/
mb-listener.c
389 lines (365 loc) · 12.1 KB
/
mb-listener.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "wiringPi.h"
#include "MQTTClient.h"
#include "MQTTClientPersistence.h"
#include "time.h"
//MQTT definitions
//IMPORTANT:
//To get ONLY the last message 'RETAIN FLAG' should be SET when publishing, also the QOS should be set to 0 when publishing to the LED on/off topic
#define QOS 2
#define TIMEOUT 10000L
//wiringPi definitions
#define LED_1 02 //GPIO numbers for the LED inputs
#define LED_2 03
#define LED_3 04
#define SWITCH_1 21 //Reed Switch input GPIO pins
#define SWITCH_2 13
#define SWITCH_3 16
#define TRUE 1
#define FALSE 0
#define debounceDelay 50 //Delay until the signal settles down
#define interruptDelay 10 //Delay for the next interrupt. High the number lesser the bounce interrupts that it will catch. Controls the sensitivity of the interrupt
#define LOCK_KEY 0 //Memeory lock key. More info at http://wiringpi.com/reference/priority-interrupts-and-threads/
int boxStatus_1 = 0; //Global variables for box status
int boxStatus_2 = 0;
int boxStatus_3 = 0;
int threadFlag = 0;
//Queue structure
typedef struct Queue
{
int capacity;
int size;
int front;
int rear;
int *elements;
}Queue;
Queue *Q;
FILE *dataStream;
int count = 1; //Only for debuging purposes
//Function Prototypes
void connlost(void*, char*);
void delivered(void *context, MQTTClient_deliveryToken dt);
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message);
void connlost(void *context, char *cause);
volatile MQTTClient_deliveryToken deliveredtoken;
// Create Que function
Queue * createQueue(int maxElements)
{
/* Create a Queue */
Queue *Q;
Q = (Queue *)malloc(sizeof(Queue));
/* Initialise its properties */
Q->elements = (int *)malloc(sizeof(int)*maxElements);
Q->size = 0;
Q->capacity = maxElements;
Q->front = 0;
Q->rear = -1;
/* Return the pointer */
return Q;
}
// Delete values from the que
void dequeue(Queue *Q)
{
/* If Queue size is zero then it is empty. So we cannot pop */
if(Q->size==0)
{
printf("Queue is Empty\n");
return;
}
/* Removing an element is equivalent to incrementing index of front by one */
else
{
Q->size--;
Q->front++;
/* As we fill elements in circular fashion */
if(Q->front==Q->capacity)
{
Q->front=0;
}
}
return;
}
//Return the value in front
int front(Queue *Q)
{
if(Q->size==0)
{
printf("Queue is Empty\n");
exit(0);
}
/* Return the element which is at the front*/
return Q->elements[Q->front];
}
//Add values to the que
void enqueue(Queue *Q,int element)
{
/* If the Queue is full, we cannot push an element into it as there is no space for it.*/
if(Q->size == Q->capacity)
{
printf("Queue is Full\n");
}
else
{
Q->size++;
Q->rear = Q->rear + 1;
/* As we fill the queue in circular fashion */
if(Q->rear == Q->capacity)
{
Q->rear = 0;
}
/* Insert the element in its rear side */
Q->elements[Q->rear] = element;
}
return;
}
//Interrupt fuction 1 for switch 1
void interruptFunc_1(void){
printf("$Time: %f\n",(float)(clock()/1000000.0F)*1000);
printf("Interrupt Occured 1\n");
delay(interruptDelay); //Level of sensitivity of the interrupt(higher the delay less the sensitiveness)
boxStatus_1 = digitalRead(SWITCH_1);
printf("Interrupt End 1\n");
printf("$Time: %f\n",(float)(clock()/1000000.0F)*1000);
}
//Interrupt fuction 2 for switch 2
void interruptFunc_2(void){
printf("Interrupt Occured 2\n");
delay(interruptDelay); //Level of sensitivity of the interrupt(higher the delay less$
boxStatus_2 = digitalRead(SWITCH_2);
printf("Interrupt End 2\n");
}
//Interrupt fuction 3 for switch 3
void interruptFunc_3(void){
printf("Interrupt Occured 3\n");
delay(interruptDelay); //Level of sensitivity of the interrupt(higher the delay less$
boxStatus_3 = digitalRead(SWITCH_3);
printf("Interrupt End 3\n");
}
//Lock the thread and add data to the Que name ‘Q’ (Lock in due accessing the Que)
void publishBoxStatus(int drawer,int boxStatus){
piLock(LOCK_KEY);
enqueue(Q,drawer+boxStatus);
piUnlock(LOCK_KEY);
}
//LED switch case
void lightLED(char LED){
switch(LED){
case '1' : digitalWrite(LED_1,HIGH); break;
case '2' : digitalWrite(LED_2,HIGH); break;
case '3' : digitalWrite(LED_3,HIGH); break;
case '4' : digitalWrite(LED_1,LOW); break;
case '5' : digitalWrite(LED_2,LOW); break;
case '6' : digitalWrite(LED_3,LOW); break;
default : printf("Invalid MQTT message\n message: ");break;
}
}
//Default function in MQTT paho (Delivery token is received. Only works in QoS 2)
void delivered(void *context, MQTTClient_deliveryToken dt)
{
printf("Message with token value %d delivery confirmed\n", dt);
deliveredtoken = dt;
}
//Default function in MQTT paho (Runs when msg is received)
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
int i;
char* payloadptr;
char messageText[message->payloadlen];
printf("Message arrived\n");
printf(" topic: %s\n", topicName);
printf(" message: ");
payloadptr = message->payload;
for(i=0; i < message->payloadlen; i++)
{
// putchar(*payloadptr++);
messageText[i] = *payloadptr++;
}
messageText[i] = '\0';
lightLED(messageText[0]);
printf("%s",messageText);
putchar('\n');
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
//Default function in MQTT paho (Runs when the MQTT connection is lost)
void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}
// Thread that publishes the data using MQTT in the Que
PI_THREAD (mqttStream)
{
/* //Creating the MQTT stream
char *buffer = NULL;
size_t length = 0;
off_t eob;
dataStream = open_memstream(&buffer, &length);
if (dataStream == NULL)
{
printf("MQTT data stream ERROR!\n");
exit(-1);
}
*/
//Queue initialization
Q = createQueue(10);
//MQTT pub data from the file
char PAYLOAD[3];
char ADDRESS[50];
char CLIENTID[23];
char TOPIC[80];
char PORT[5];
FILE* fp = fopen("input_pub.config","r");
fscanf(fp,"%s",ADDRESS);
fscanf(fp,"%s",CLIENTID);
fscanf(fp,"%s",TOPIC);
fscanf(fp,"%s",PORT);
sprintf(ADDRESS,"%s:%s",ADDRESS,PORT);
fclose(fp);
//For ever loop which publises data. More info at http://www.eclipse.org/paho/files/mqttdoc/Cclient/index.html
while(1)
{
if(Q->size != 0)
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_USER, NULL);
conn_opts.keepAliveInterval = 100;
conn_opts.cleansession = 0;
MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(-1);
}
piLock(LOCK_KEY);
sprintf(PAYLOAD,"%i. %i",count,front(Q));
dequeue(Q);
count++;
piUnlock(LOCK_KEY);
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 1;
deliveredtoken = 1;
printf("$Time: %f\n",(float)(clock()/1000000.0F)*1000);
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
printf("Waiting for publication of %s\n" "on topic %s for client with ClientID: %s\n", PAYLOAD, TOPIC, CLIENTID);
//delay(50);
while(deliveredtoken != token);
//Not getting a token
printf("$Time: %f\n",(float)(clock()/1000000.0F)*1000);
MQTTClient_disconnect(client, 100);
printf("$Time: %f\n",(float)(clock()/1000000.0F)*1000);
MQTTClient_destroy(&client);
printf("Message Sent\n");
printf("################################################################\n");
}
}
}
int main(int argc, char* argv[])
{
//Getting input from the file for subscribing
char ADDRESS[50];
char CLIENTID[23];
char TOPIC[80];
char PORT[5];
FILE* fp = fopen("input_sub.config","r");
fscanf(fp,"%s",ADDRESS);
fscanf(fp,"%s",CLIENTID);
fscanf(fp,"%s",TOPIC);
fscanf(fp,"%s",PORT);
sprintf(ADDRESS,"%s:%s",ADDRESS,PORT);
fclose(fp);
//WiringPi setup
wiringPiSetupGpio ();
pinMode (LED_1, OUTPUT);
pinMode (LED_2, OUTPUT);
pinMode (LED_3, OUTPUT);
//pinMode (SWITCH_1, INPUT);
//pinMode (SWITCH_2, INPUT);
//pinMode (SWITCH_3, INPUT);
//Pull up input pins
pullUpDnControl (SWITCH_1, PUD_UP);
pullUpDnControl (SWITCH_2, PUD_UP);
pullUpDnControl (SWITCH_3, PUD_UP);
//Set Interrupts
wiringPiISR(SWITCH_1,INT_EDGE_BOTH,&interruptFunc_1);
wiringPiISR(SWITCH_2,INT_EDGE_BOTH,&interruptFunc_2);
wiringPiISR(SWITCH_3,INT_EDGE_BOTH,&interruptFunc_3);
//Pull down the non ground pins
pullUpDnControl (19, PUD_DOWN);
pullUpDnControl (26, PUD_DOWN);
//Lights Initialization
digitalWrite(LED_1,HIGH);
digitalWrite(LED_2,LOW);
digitalWrite(LED_3,LOW);
delay(100);
digitalWrite(LED_1,LOW);
digitalWrite(LED_2,HIGH);
digitalWrite(LED_3,LOW);
delay(100);
digitalWrite(LED_1,LOW);
digitalWrite(LED_2,LOW);
digitalWrite(LED_3,HIGH);
delay(100);
digitalWrite(LED_1, LOW);
digitalWrite(LED_2, LOW);
digitalWrite(LED_3, LOW);
//MQTT Setup for subscribing
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc;
int ch;
MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_USER, NULL);
conn_opts.keepAliveInterval = 100;
conn_opts.cleansession = 0;
MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(-1);
}
printf("Subscribing to topic %s\nfor client %s using QoS %d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
MQTTClient_subscribe(client, TOPIC, QOS);
//Start the new thread
if(piThreadCreate(mqttStream) != 0)
{
printf("ERROR in creating MQTT streaming thread");
}
//Main loop
int previousBoxStatus_1,previousBoxStatus_2,previousBoxStatus_3;
previousBoxStatus_1 = boxStatus_1;
previousBoxStatus_2 = boxStatus_2;
previousBoxStatus_3 = boxStatus_3;
do
{
//if the previous mode is not the status now publish else do nothing
if(previousBoxStatus_1 != boxStatus_1){
delay(debounceDelay); //Time delay after an interrupt for the signal to be stable
publishBoxStatus(10,boxStatus_1);
previousBoxStatus_1 = boxStatus_1;
}
if(previousBoxStatus_2 != boxStatus_2){
delay(debounceDelay); //Time delay after an interrupt for the signal to be stable
publishBoxStatus(20,boxStatus_2);
previousBoxStatus_2 = boxStatus_2;
}
if(previousBoxStatus_3 != boxStatus_3){
delay(debounceDelay); //Time delay after an interrupt for the signal to be stable
publishBoxStatus(30,boxStatus_3);
previousBoxStatus_3 = boxStatus_3;
}
// ch = getchar();
} while(ch!='Q' && ch != 'q');
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}