Working reading thermometers and sending data to a MQTT server.

Thu, 24 Apr 2014 15:12:48 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Thu, 24 Apr 2014 15:12:48 +0200
changeset 11
f78f313b1d34
parent 10
5600a1789644
child 12
102c44bb8c9d

Working reading thermometers and sending data to a MQTT server.

thermometers/main.c file | annotate | diff | comparison | revisions
--- a/thermometers/main.c	Wed Apr 23 21:29:37 2014 +0200
+++ b/thermometers/main.c	Thu Apr 24 15:12:48 2014 +0200
@@ -28,20 +28,15 @@
 #define STATUS_CONNACK_RECVD 1
 #define STATUS_WAITING 2
 
-/* Global variables for use in callbacks. See sub_client.c for an example of
- * using a struct to hold variables for use in callbacks. */
-static char *topic = NULL;
-//static char *message = NULL;
-//static long msglen = 0;
-static int qos = 0;
-//static int retain = 0;
-static int status = STATUS_CONNECTING;
-static int mid_sent = 0;
-static int last_mid = -1;
-static int last_mid_sent = -1;
-static bool connected = true;
-static bool disconnect_sent = false;
-static bool shutdown = false;
+/* Global variables for use in callbacks. */
+static int		qos = 0;
+static int		status = STATUS_CONNECTING;
+static int		mid_sent = 0;
+static int		last_mid = -1;
+static int		last_mid_sent = -1;
+static bool		connected = true;
+static bool		disconnect_sent = false;
+static bool		shutdown = false;
 
 extern bool		debug;
 extern sys_config	Config;
@@ -108,8 +103,6 @@
 
 void my_publish_callback(struct mosquitto *mosq, void *obj, int mid)
 {
-    fprintf(stdout, (char *)"my_publish_callback mid=%d\n", mid);
-
     last_mid_sent = mid;
 }
 
@@ -178,10 +171,12 @@
     char                *id = NULL, *state = NULL;
     struct mosquitto    *mosq = NULL;
     char                hostname[256], buf[1024];
-    int                 rc, keepalive = 60;
+    int                 temp, rc, deviation, keepalive = 60;
     unsigned int        max_inflight = 20;
     char                err[1024];
     w1_therm		*tmp1, *old1;
+    char		*device, *alias, line[60], *p = NULL;
+    FILE		*fp;
 
     /*
      * Initialize mosquitto communication
@@ -265,7 +260,6 @@
      * Initialise is complete, report our presence state
      */
     mosquitto_loop_start(mosq);
-
     sprintf(buf, "1");
     rc = mosquitto_publish(mosq, &mid_sent, state, strlen(buf), buf, qos, 1);
 
@@ -273,17 +267,89 @@
     do {
 	if (status == STATUS_CONNACK_RECVD) {
 	    /*
-	     * Sleep just log enough to keep the system load low.
-	     */
-//	    usleep(1);
-	    /*
 	     * Here send our sensors values
 	     */
 	    for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) {
 		old1 = tmp1->next;
-		fprintf(stdout, "s: %s\n", tmp1->name);
+
+		/*
+		 * Build path and alias topic
+		 */
+		device = xstrcpy((char *)"/sys/bus/w1/devices/");
+		device = xstrcat(device, tmp1->master);
+		device = xstrcat(device, (char *)"/");
+		device = xstrcat(device, tmp1->name);
+		device = xstrcat(device, (char *)"/w1_slave");
+		alias = xstrcpy((char *)"sensor/temperature/");
+		alias = xstrcat(alias, hostname);
+		alias = xstrcat(alias, (char *)"/");
+		alias = xstrcat(alias, tmp1->master);
+		alias = xstrcat(alias, (char *)"/");
+		alias = xstrcat(alias, tmp1->alias);
+
+		/*
+		 * Read sensor data
+		 */
+		if ((fp = fopen(device, "r"))) {
+		    /*
+		     * The output looks like:
+		     * 72 01 4b 46 7f ff 0e 10 57 : crc=57 YES
+		     * 72 01 4b 46 7f ff 0e 10 57 t=23125
+		     */
+		    fgets(line, 50, fp);
+		    line[strlen(line)-1] = '\0';
+		    if ((line[36] == 'Y') && (line[37] == 'E')) {
+			/*
+			 * CRC is Ok, continue
+			 */
+		    	fgets(line, 50, fp);
+			line[strlen(line)-1] = '\0';
+			strtok(line, (char *)"=");
+			p = strtok(NULL, (char *)"=");
+			rc = sscanf(p, "%d", &temp);
+			if ((rc == 1) && (tmp1->lastval != temp)) {
+			    /*
+			     * It is possible to have read errors or extreme values.
+			     * This can happen with bad connections so we compare the
+			     * value with the previous one. If the difference is too
+			     * much, we don't send that value. That also means that if
+			     * the next value is ok again, it will be marked invalid too.
+			     */
+			    deviation = (temp + tmp1->lastval) / 10;
+			    if ((tmp1->lastval == 0) ||
+				(tmp1->lastval && (temp > (tmp1->lastval - deviation)) && (temp < (tmp1->lastval + deviation)))) {
+			    	/*
+			    	 * Temperature is changed and valid, update and publish this.
+			    	 */
+			    	sprintf(buf, "%.1f", temp / 1000.0);
+			    	if ((rc = mosquitto_publish(mosq, &mid_sent, alias, strlen(buf), buf, qos, 0))) {
+			            if (rc == MOSQ_ERR_NO_CONN)
+				    	mosquitto_reconnect(mosq);
+			    	    else
+				    	syslog(LOG_NOTICE, "mainloop: error %d from mosquitto_publish", rc);
+			    	}
+			    } else {
+				if (debug)
+				    syslog(LOG_NOTICE, "deviation error deviation=%d, old=%d new=%d", deviation, tmp1->lastval, temp);
+			    }
+			    tmp1->lastval = temp;
+			}
+		    } else {
+			syslog(LOG_NOTICE, "sensor %s/%s CRC error", tmp1->master, tmp1->name);
+		    }
+		    fclose(fp);
+		    tmp1->present = 1;
+		} else {
+		    tmp1->present = 0;
+		    printf("sensor %s is missing\n", tmp1->name);
+		}
+
+		free(device);
+		device = NULL;
+		free(alias);
+		alias = NULL;
 	    }
-	    usleep(15000000);
+	    usleep(1000000);
 
 	    if (shutdown) {
 		/*
@@ -291,7 +357,6 @@
 		 */
 		sprintf(buf, "0");
 		mosquitto_publish(mosq, &mid_sent, state, strlen(buf), buf, qos, true);
-		free(topic);
 		last_mid = mid_sent;
 		status = STATUS_WAITING;
 	    }

mercurial