thermometers/thermometers.c

changeset 144
3446371e0bdb
parent 51
a03b6dac5398
child 145
1396350141cf
equal deleted inserted replaced
143:54f9b5d39e4c 144:3446371e0bdb
21 *****************************************************************************/ 21 *****************************************************************************/
22 22
23 #include "thermometers.h" 23 #include "thermometers.h"
24 24
25 25
26 #define STATUS_CONNECTING 0 26 static int my_shutdown = FALSE;
27 #define STATUS_CONNACK_RECVD 1
28 #define STATUS_WAITING 2
29
30 /* Global variables for use in callbacks. */
31 static int qos = 0;
32 static int status = STATUS_CONNECTING;
33 static int mid_sent = 0;
34 static int last_mid = -1;
35 static int last_mid_sent = -1;
36 static bool connected = true;
37 static bool disconnect_sent = false;
38 static bool connect_lost = false;
39 static bool my_shutdown = false;
40 static pid_t pgrp, mypid; 27 static pid_t pgrp, mypid;
41 28
42 extern bool debug; 29 extern int debug;
43 extern sys_config Config; 30 extern sys_config Config;
44 #ifdef HAVE_WIRINGPI_H 31 #ifdef HAVE_WIRINGPI_H
45 extern int lcdHandle; 32 extern int lcdHandle;
46 #endif 33 #endif
47 34
70 case SIGTERM: syslog(LOG_NOTICE, "Got SIGTERM, shutting down"); 57 case SIGTERM: syslog(LOG_NOTICE, "Got SIGTERM, shutting down");
71 break; 58 break;
72 default: syslog(LOG_NOTICE, "die() on signal %d", onsig); 59 default: syslog(LOG_NOTICE, "die() on signal %d", onsig);
73 } 60 }
74 61
75 my_shutdown = true; 62 my_shutdown = TRUE;
76 }
77
78
79
80 void my_connect_callback(struct mosquitto *mosq, void *obj, int result)
81 {
82 if (connect_lost) {
83 connect_lost = false;
84 syslog(LOG_NOTICE, "Reconnect: %s", mosquitto_connack_string(result));
85 }
86
87 if (!result) {
88 status = STATUS_CONNACK_RECVD;
89 } else {
90 syslog(LOG_NOTICE, "my_connect_callback: %s\n", mosquitto_connack_string(result));
91 }
92 }
93
94
95
96 void my_disconnect_callback(struct mosquitto *mosq, void *obj, int rc)
97 {
98 if (my_shutdown) {
99 syslog(LOG_NOTICE, "Acknowledged DISCONNECT from %s", Config.mosq_host);
100 connected = false;
101 } else {
102 /*
103 * The remove server was brought down. We must keep running
104 */
105 syslog(LOG_NOTICE, "Received DISCONNECT from %s, connection lost", Config.mosq_host);
106 connect_lost = true;
107 }
108 }
109
110
111
112 void my_publish_callback(struct mosquitto *mosq, void *obj, int mid)
113 {
114 last_mid_sent = mid;
115 }
116
117
118
119 void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str)
120 {
121 syslog(LOG_NOTICE, "MQTT: %s", str);
122 printf("MQTT: %s\n", str);
123 } 63 }
124 64
125 65
126 66
127 #ifdef HAVE_WIRINGPI_H 67 #ifdef HAVE_WIRINGPI_H
153 c = getopt_long(argc, argv, "dh", long_options, &option_index); 93 c = getopt_long(argc, argv, "dh", long_options, &option_index);
154 if (c == -1) 94 if (c == -1)
155 break; 95 break;
156 96
157 switch (c) { 97 switch (c) {
158 case 'd': debug = true; 98 case 'd': debug = TRUE;
159 break; 99 break;
160 case 'h': help(); 100 case 'h': help();
161 return 1; 101 return 1;
162 } 102 }
163 } 103 }
266 206
267 207
268 208
269 int server(void) 209 int server(void)
270 { 210 {
271 char *id = NULL, *state = NULL;
272 struct mosquitto *mosq = NULL;
273 char hostname[256], buf[1024]; 211 char hostname[256], buf[1024];
274 int temp, rc, deviation, keepalive = 60; 212 int temp, rc = 0, deviation;
275 #ifdef HAVE_WIRINGPI_H 213 #ifdef HAVE_WIRINGPI_H
276 int lcdupdate; 214 int lcdupdate;
277 #endif 215 #endif
278 unsigned int max_inflight = 20;
279 char err[1024];
280 w1_therm *tmp1, *old1; 216 w1_therm *tmp1, *old1;
281 char *device, *alias, line[60], *p = NULL; 217 char *device, *alias, line[60], *p = NULL;
282 FILE *fp; 218 FILE *fp;
283
284 /*
285 * Initialize mosquitto communication
286 */
287 mosquitto_lib_init();
288 219
289 /* 220 /*
290 * Build MQTT id 221 * Build MQTT id
291 */ 222 */
292 hostname[0] = '\0'; 223 hostname[0] = '\0';
293 gethostname(hostname, 256); 224 gethostname(hostname, 256);
294 hostname[255] = '\0'; 225 hostname[255] = '\0';
295 226
296 id = xstrcpy((char *)"thermometers/");
297 id = xstrcat(id, hostname);
298 if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH) {
299 /*
300 * Enforce maximum client id length of 23 characters
301 */
302 id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0';
303 }
304
305 mosq = mosquitto_new(id, true, NULL);
306 if(!mosq) {
307 switch(errno) {
308 case ENOMEM:
309 syslog(LOG_NOTICE, "mosquitto_new: Out of memory");
310 break;
311 case EINVAL:
312 syslog(LOG_NOTICE, "mosquitto_new: Invalid id");
313 break;
314 }
315 mosquitto_lib_cleanup();
316 return 1;
317 }
318
319 if (debug) {
320 mosquitto_log_callback_set(mosq, my_log_callback);
321 }
322
323 /*
324 * Set our will
325 */
326 state = xstrcpy((char *)"clients/");
327 state = xstrcat(state, hostname);
328 state = xstrcat(state, (char *)"/thermometers/state");
329 sprintf(buf, "0");
330 if ((rc = mosquitto_will_set(mosq, state, strlen(buf), buf, qos, true))) {
331 if (rc == MOSQ_ERR_INVAL) {
332 syslog(LOG_NOTICE, "mosquitto_will_set: input parameters invalid");
333 } else if (rc == MOSQ_ERR_NOMEM) {
334 syslog(LOG_NOTICE, "mosquitto_will_set: Out of Memory");
335 } else if (rc == MOSQ_ERR_PAYLOAD_SIZE) {
336 syslog(LOG_NOTICE, "mosquitto_will_set: invalid payload size");
337 }
338 mosquitto_lib_cleanup();
339 return rc;
340 }
341
342 mosquitto_max_inflight_messages_set(mosq, max_inflight);
343 mosquitto_connect_callback_set(mosq, my_connect_callback);
344 mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
345 mosquitto_publish_callback_set(mosq, my_publish_callback);
346
347 if ((rc = mosquitto_connect(mosq, Config.mosq_host, Config.mosq_port, keepalive))) {
348 if (rc == MOSQ_ERR_ERRNO) {
349 strerror_r(errno, err, 1024);
350 syslog(LOG_NOTICE, "mosquitto_connect: error: %s", err);
351 } else {
352 syslog(LOG_NOTICE, "mosquitto_connect: unable to connect (%d)", rc);
353 }
354 mosquitto_lib_cleanup();
355 return rc;
356 }
357 syslog(LOG_NOTICE, "Connected with %s:%d", Config.mosq_host, Config.mosq_port);
358
359 /* 227 /*
360 * Initialise is complete, report our presence state 228 * Initialise is complete, report our presence state
361 */ 229 */
362 mosquitto_loop_start(mosq);
363 sprintf(buf, "1");
364 rc = mosquitto_publish(mosq, &mid_sent, state, strlen(buf), buf, qos, 1);
365 #ifdef HAVE_WIRINGPI_H 230 #ifdef HAVE_WIRINGPI_H
366 // setBacklight(0); 231 // setBacklight(0);
367 #endif 232 #endif
368 233
369 /*
370 * Report alias names
371 */
372 for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) {
373 old1 = tmp1->next;
374
375 alias = xstrcpy((char *)"/raw/");
376 alias = xstrcat(alias, hostname);
377 alias = xstrcat(alias, (char *)"/thermometers/w1/");
378 alias = xstrcat(alias, tmp1->master);
379 alias = xstrcat(alias, (char *)"/");
380 alias = xstrcat(alias, tmp1->name);
381 alias = xstrcat(alias, (char *)"/alias");
382
383 sprintf(buf, "%s", tmp1->alias);
384 if ((rc = mosquitto_publish(mosq, &mid_sent, alias, strlen(buf), buf, qos, 1))) {
385 if (rc == MOSQ_ERR_NO_CONN)
386 mosquitto_reconnect(mosq);
387 else
388 syslog(LOG_NOTICE, "mainloop: error %d from mosquitto_publish", rc);
389 }
390
391 free(alias);
392 alias = NULL;
393 }
394
395 if (debug) 234 if (debug)
396 fprintf(stdout, (char *)"Enter loop, connected %d\n", connected); 235 fprintf(stdout, (char *)"Enter loop\n");
397 236
398 do { 237 do {
399 if (status == STATUS_CONNACK_RECVD) {
400 #ifdef HAVE_WIRINGPI_H 238 #ifdef HAVE_WIRINGPI_H
401 lcdupdate = FALSE; 239 lcdupdate = FALSE;
402 #endif 240 #endif
403 241
404 /* 242 /*
457 (tmp1->lastval && (temp > (tmp1->lastval - deviation)) && (temp < (tmp1->lastval + deviation)))) { 295 (tmp1->lastval && (temp > (tmp1->lastval - deviation)) && (temp < (tmp1->lastval + deviation)))) {
458 /* 296 /*
459 * Temperature is changed and valid, update and publish this. 297 * Temperature is changed and valid, update and publish this.
460 */ 298 */
461 sprintf(buf, "%.1f", temp / 1000.0); 299 sprintf(buf, "%.1f", temp / 1000.0);
462 if ((rc = mosquitto_publish(mosq, &mid_sent, alias, strlen(buf), buf, qos, 1))) {
463 if (rc == MOSQ_ERR_NO_CONN)
464 mosquitto_reconnect(mosq);
465 else
466 syslog(LOG_NOTICE, "mainloop: error %d from mosquitto_publish", rc);
467 }
468 } else { 300 } else {
469 syslog(LOG_NOTICE, "deviation error deviation=%d, old=%d new=%d", deviation, tmp1->lastval, temp); 301 syslog(LOG_NOTICE, "deviation error deviation=%d, old=%d new=%d", deviation, tmp1->lastval, temp);
470 if (debug) { 302 if (debug) {
471 fprintf(stdout, "deviation error deviation=%d, old=%d new=%d\n", deviation, tmp1->lastval, temp); 303 fprintf(stdout, "deviation error deviation=%d, old=%d new=%d\n", deviation, tmp1->lastval, temp);
472 } 304 }
506 lcdPuts(lcdHandle, buf); 338 lcdPuts(lcdHandle, buf);
507 } 339 }
508 #endif 340 #endif
509 341
510 if (my_shutdown) { 342 if (my_shutdown) {
511 /*
512 * Final publish 0 to clients/<hostname>/thermometers/state
513 */
514 sprintf(buf, "0");
515 mosquitto_publish(mosq, &mid_sent, state, strlen(buf), buf, qos, true);
516 last_mid = mid_sent;
517 status = STATUS_WAITING;
518 #ifdef HAVE_WIRINGPI_H 343 #ifdef HAVE_WIRINGPI_H
519 lcdClear(lcdHandle); 344 lcdClear(lcdHandle);
520 lcdPosition(lcdHandle, 0, 0); 345 lcdPosition(lcdHandle, 0, 0);
521 lcdPuts(lcdHandle, "Shuting down ..."); 346 lcdPuts(lcdHandle, "Shuting down ...");
522 #endif 347 #endif
523 } 348 }
524 349
525 usleep(100000); 350 usleep(100000);
526 351
527 } else if (status == STATUS_WAITING) { 352 } while (! my_shutdown);
528 if (debug)
529 fprintf(stdout, (char *)"Waiting\n");
530 if (last_mid_sent == last_mid && disconnect_sent == false) {
531 mosquitto_disconnect(mosq);
532 disconnect_sent = true;
533 }
534 usleep(100000);
535 }
536 rc = MOSQ_ERR_SUCCESS;
537
538 } while (rc == MOSQ_ERR_SUCCESS && connected);
539 353
540 if (debug) 354 if (debug)
541 fprintf(stdout, (char *)"Out of loop\n"); 355 fprintf(stdout, (char *)"Out of loop\n");
542 356
543 mosquitto_loop_stop(mosq, false);
544 mosquitto_destroy(mosq);
545 mosquitto_lib_cleanup();
546
547 #ifdef HAVE_WIRINGPI_H 357 #ifdef HAVE_WIRINGPI_H
548 stopLCD(); 358 stopLCD();
549 #endif 359 #endif
550 360
551 return rc; 361 return rc;

mercurial