Updated dependencies. Devices json data is created in de devices source for all places where it is needed. Added devices_ws function to broadcast all devices, to be used when any device is changed. The devices loop detects changes in input values and calls devices_ws if so. The server uses the general devices json data.

Wed, 17 Apr 2024 19:54:56 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 17 Apr 2024 19:54:56 +0200
changeset 684
b2265c7e5707
parent 683
d48733bf1529
child 685
819553a2b97e

Updated dependencies. Devices json data is created in de devices source for all places where it is needed. Added devices_ws function to broadcast all devices, to be used when any device is changed. The devices loop detects changes in input values and calls devices_ws if so. The server uses the general devices json data.

thermferm/Makefile file | annotate | diff | comparison | revisions
thermferm/devices.c file | annotate | diff | comparison | revisions
thermferm/devices.h file | annotate | diff | comparison | revisions
thermferm/server.c file | annotate | diff | comparison | revisions
thermferm/websocket.c file | annotate | diff | comparison | revisions
www/js/fermenter.js file | annotate | diff | comparison | revisions
--- a/thermferm/Makefile	Wed Apr 17 15:03:01 2024 +0200
+++ b/thermferm/Makefile	Wed Apr 17 19:54:56 2024 +0200
@@ -56,7 +56,7 @@
 # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
 # Dependencies generated by make depend
 delay.o: delay.h thermferm.h
-devices.o: thermferm.h delay.h devices.h rc-switch.h panel.h xutil.h
+devices.o: thermferm.h delay.h devices.h rc-switch.h panel.h xutil.h websocket.h
 futil.o: thermferm.h futil.h
 lcd-buffer.o: thermferm.h lcd-buffer.h lcd-pcf8574.h slcd.h panel.h
 lcd-pcf8574.o: thermferm.h lcd-pcf8574.h slcd.h
@@ -70,7 +70,7 @@
 server.o: rdconfig.h thermferm.h delay.h devices.h server.h lcd-buffer.h xutil.h mqtt.h
 simulator.o: thermferm.h delay.h simulator.h
 slcd.o: thermferm.h slcd.h futil.h xutil.h
-thermferm.o: lock.h rdconfig.h server.h thermferm.h devices.h delay.h simulator.h lcd-pcf8574.h lcd-buffer.h slcd.h panel.h one-wire.h futil.h xutil.h pid.h mqtt.h statetbl.h
-websocket.o: thermferm.h xutil.h websocket.h
+thermferm.o: lock.h rdconfig.h server.h thermferm.h devices.h delay.h simulator.h lcd-pcf8574.h lcd-buffer.h slcd.h panel.h one-wire.h futil.h xutil.h pid.h mqtt.h statetbl.h websocket.h
+websocket.o: thermferm.h xutil.h devices.h websocket.h
 xutil.o: thermferm.h xutil.h
 # End of generated dependencies
--- a/thermferm/devices.c	Wed Apr 17 15:03:01 2024 +0200
+++ b/thermferm/devices.c	Wed Apr 17 19:54:56 2024 +0200
@@ -26,6 +26,7 @@
 #include "rc-switch.h"
 #include "panel.h"
 #include "xutil.h"
+#include "websocket.h"
 
 
 int			my_devices_shutdown = 0;
@@ -35,6 +36,10 @@
 extern pthread_mutex_t  mutexes[5];
 extern w1_list		*w1_devices;
 
+extern const char	DEVTYPE[8][6];
+extern const char	DEVPRESENT[4][6];
+extern const char	DEVDIR[7][11];
+
 
 #ifdef USE_SIMULATOR
 
@@ -361,6 +366,83 @@
 }
 
 
+/*
+ * Return json data for one device.
+ */
+char *device_json(devices_list *device, bool full)
+{
+    char	*payload;
+    char	vbuf[64];
+
+    payload = xstrcpy((char *)"{\"uuid\":\"");
+    payload = xstrcat(payload, device->uuid);
+    payload = xstrcat(payload, (char *)"\",\"type\":\"");
+    payload = xstrcat(payload, (char *)DEVTYPE[device->type]);
+    payload = xstrcat(payload, (char *)"\",\"direction\":\"");
+    payload = xstrcat(payload, (char *)DEVDIR[device->direction]);
+    payload = xstrcat(payload, (char *)"\",\"address\":\"");
+    payload = xstrcat(payload, device->address);
+    payload = xstrcat(payload, (char *)"\",\"subdevice\":");
+    snprintf(vbuf, 63, "%d", device->subdevice);
+    payload = xstrcat(payload, vbuf);
+    payload = xstrcat(payload, (char *)",\"value\":");
+    snprintf(vbuf, 63, "%d", device->value);
+    payload = xstrcat(payload, vbuf);
+    if (full) {
+    	payload = xstrcat(payload, (char *)",\"offset\":");
+    	snprintf(vbuf, 63, "%d", device->offset);
+    	payload = xstrcat(payload, vbuf);
+    }
+    payload = xstrcat(payload, (char *)",\"present\":\"");
+    payload = xstrcat(payload, (char *)DEVPRESENT[device->present]);
+    payload = xstrcat(payload, (char *)"\"");
+    if (full) {
+    	payload = xstrcat(payload, (char *)",\"gpiopin\":");
+    	snprintf(vbuf, 63, "%d", device->gpiopin);
+    	payload = xstrcat(payload, vbuf);
+    }
+    payload = xstrcat(payload, (char *)",\"inuse\":");
+    snprintf(vbuf, 63, "%d", device->inuse);
+    payload = xstrcat(payload, vbuf);
+    payload = xstrcat(payload, (char *)",\"description\":\"");
+    payload = xstrcat(payload, device->description);
+    if (full) {
+    	payload = xstrcat(payload, (char *)"\",\"comment\":\"");
+    	payload = xstrcat(payload, device->comment);
+    }
+    payload = xstrcat(payload, (char *)"\",\"timestamp\":");
+    snprintf(vbuf, 63, "%ld", (long)device->timestamp);
+    payload = xstrcat(payload, vbuf);
+    payload = xstrcat(payload, (char *)"}");
+
+    return payload;
+}
+
+
+
+void devices_ws(void)
+{
+    bool		comma = false;
+    char		*payload = NULL, *payloadu = NULL;
+    devices_list	*device;
+
+    payload = xstrcpy((char *)"{\"type\":\"device\",\"metric\":[");
+    for (device = Config.devices; device; device = device->next) {
+	if (comma)
+	    payload = xstrcat(payload, (char *)",");
+	payloadu = device_json(device, false);
+	payload = xstrcat(payload, payloadu);
+	comma = true;
+	free(payloadu);
+	payloadu = NULL;
+    }
+    payload = xstrcat(payload, (char *)"]}");
+    syslog(LOG_NOTICE, "%s", payload);
+    ws_broadcast(payload);
+    free(payload);
+    payload = NULL;
+}
+
 
 
 /*
@@ -696,6 +778,7 @@
 #endif
     int			found;
     time_t		now;
+    bool		changed;
 
     my_devices_state = 1;
     syslog(LOG_NOTICE, "Thread my_devices_loop started");
@@ -706,6 +789,7 @@
      */
     for (;;) {
 
+	changed = false;
     	/*
     	 * Process all devices.
     	 */
@@ -733,12 +817,18 @@
 					if (device->present != DEVPRESENT_ERROR)
 					    syslog(LOG_NOTICE, "sensor %s value error %d, keep %d", device->address, dev_w1->value, device->value);
 					device->present = DEVPRESENT_ERROR;
+					changed = true;
 				    } else {
-					if (device->present != DEVPRESENT_YES)
+					if (device->present != DEVPRESENT_YES) {
 					    syslog(LOG_NOTICE, "sensor %s value ok %d", device->address, dev_w1->value);
-					device->value = dev_w1->value;
-					device->timestamp = time(NULL);
-					device->present = DEVPRESENT_YES;
+					    changed = true;
+					    device->present = DEVPRESENT_YES;
+					}
+					if (device->value != dev_w1->value) {
+					    changed = true;
+					    device->value = dev_w1->value;
+					    device->timestamp = time(NULL);
+					}
 				    }
 				}
 			    }
@@ -748,6 +838,7 @@
 				    syslog(LOG_NOTICE, "sensor %s is missing", device->address);
 //				    pthread_mutex_lock(&mutexes[LOCK_DEVICES]);
 				    device->present = DEVPRESENT_NO;
+				    changed = true;
 //				    pthread_mutex_unlock(&mutexes[LOCK_DEVICES]);
 				}
 			    }
@@ -770,8 +861,11 @@
 //				pthread_mutex_lock(&mutexes[LOCK_DEVICES]);
 				device->present = dht11_state;
 			    	if (dht11_state == DEVPRESENT_YES) {
-				    device->value = dht11_temperature;
-				    device->timestamp = time(NULL);
+				    if (device->value != dht11_temperature) {
+					changed = true;
+				    	device->value = dht11_temperature;
+				    	device->timestamp = time(NULL);
+				    }
 			    	}
 //				pthread_mutex_unlock(&mutexes[LOCK_DEVICES]);
 			    } else if (device->subdevice == 1) {
@@ -779,8 +873,11 @@
 //				pthread_mutex_lock(&mutexes[LOCK_DEVICES]);
 				device->present = dht11_state;
 			    	if (dht11_state == DEVPRESENT_YES) {
-				    device->value = dht11_humidity;
-				    device->timestamp = time(NULL);
+				    if (device->value != dht11_humidity) {
+					changed = true;
+				    	device->value = dht11_humidity;
+				    	device->timestamp = time(NULL);
+				    }
 				    dht11_next = now + 29;
 			    	} else {
 				    dht11_next = now + 1;
@@ -794,9 +891,12 @@
 		case DEVTYPE_GPIO:
 			if (device->direction == DEVDIR_IN_BIN) {
 //			    pthread_mutex_lock(&mutexes[LOCK_DEVICES]);
-			    device->value = digitalRead(device->gpiopin);
-			    device->offset = 0;
-			    device->timestamp = time(NULL);
+			    if (device->value != digitalRead(device->gpiopin)) {
+				changed = true;
+			    	device->value = digitalRead(device->gpiopin);
+			    	device->offset = 0;
+			    	device->timestamp = time(NULL);
+			    }
 //			    pthread_mutex_unlock(&mutexes[LOCK_DEVICES]);
 			}
 			break;
@@ -806,22 +906,44 @@
 		case DEVTYPE_SIM:
 //			pthread_mutex_lock(&mutexes[LOCK_DEVICES]);
 			if (Config.simulators) {
+			    int		val;
+
 			    simulator = Config.simulators;
 			    if (device->subdevice == 0) {
-			    	device->value = (int)((int)(simulator->room_temperature * 1000) / 500) * 500;
-			    	device->timestamp = time(NULL);
+				val = (int)((int)(simulator->room_temperature * 1000) / 500) * 500;
+				if (device->value != val) {
+			    	    device->value = val;
+			    	    device->timestamp = time(NULL);
+				    changed = true;
+				}
 			    } else if (device->subdevice == 1) {
-			    	device->value = (int)((int)(simulator->air_temperature * 1000) / 62.5) * 62.5;
-			    	device->timestamp = time(NULL);
+				val = (int)((int)(simulator->air_temperature * 1000) / 62.5) * 62.5;
+				if (device->value != val) {
+			    	    device->value = val;
+			    	    device->timestamp = time(NULL);
+				    changed = true;
+				}
 			    } else if (device->subdevice == 2) {
-			    	device->value = (int)((int)(simulator->beer_temperature * 1000) / 62.5) * 62.5;
-			    	device->timestamp = time(NULL);
+				val = (int)((int)(simulator->beer_temperature * 1000) / 62.5) * 62.5;
+				if (device->value != val) {
+			    	    device->value = val;
+			    	    device->timestamp = time(NULL);
+				    changed = true;
+				}
 			    } else if (device->subdevice == 5) {
-				device->value = (int)((int)(simulator->room_humidity * 1000) / 500) * 500;
-				device->timestamp = time(NULL);
+				val = (int)((int)(simulator->room_humidity * 1000) / 500) * 500;
+				if (device->value != val) {
+				    device->value = val;
+				    device->timestamp = time(NULL);
+				    changed = true;
+				}
 			    } else if (device->subdevice == 6) {
-				device->value = (int)((int)(simulator->chiller_temperature * 1000) / 62.5) * 62.5;
-				device->timestamp = time(NULL);
+				val = (int)((int)(simulator->chiller_temperature * 1000) / 62.5) * 62.5;
+				if (device->value != val) {
+				    device->value = val;
+				    device->timestamp = time(NULL);
+				    changed = true;
+				}
 			    }
 			}
 //			pthread_mutex_unlock(&mutexes[LOCK_DEVICES]);
@@ -843,7 +965,11 @@
 	/*
 	 * Delay a bit after all devices
 	 */
-	mDelay(100);
+	mDelay(50);
+	if (changed) {
+	    devices_ws();
+	}
+	mDelay(50);
     }
 
     syslog(LOG_NOTICE, "Thread my_devices_loop stopped");
--- a/thermferm/devices.h	Wed Apr 17 15:03:01 2024 +0200
+++ b/thermferm/devices.h	Wed Apr 17 19:54:56 2024 +0200
@@ -6,6 +6,9 @@
 
 int device_out(char *uuid, int value);
 int device_in(char *uuid, int *value);
+
+char *device_json(devices_list *device, bool full);
+
 int devices_detect(void);
 
 void *my_devices_loop(void *);
--- a/thermferm/server.c	Wed Apr 17 15:03:01 2024 +0200
+++ b/thermferm/server.c	Wed Apr 17 19:54:56 2024 +0200
@@ -343,7 +343,7 @@
     }
 
     if (strcmp(opt, (char *)"JSON") == 0) {
-	char	*payload = NULL, vbuf[64];
+	char	*payload = NULL, *payloadu = NULL, vbuf[64];
 	bool	comma = false;
 
 	if (param == NULL) {
@@ -352,25 +352,11 @@
 	    for (device = Config.devices; device; device = device->next) {
 		if (comma)
 		    payload = xstrcat(payload, (char *)",");
-		payload = xstrcat(payload, (char *)"{\"uuid\":\"");
-		payload = xstrcat(payload, device->uuid);
-		payload = xstrcat(payload, (char *)"\",\"address\":\"");
-		payload = xstrcat(payload, device->address);
-		payload = xstrcat(payload, (char *)"\",\"subdevice\":");
-		snprintf(vbuf, 63, "%d", device->subdevice);
-		payload = xstrcat(payload, vbuf);
-		payload = xstrcat(payload, (char *)",\"inuse\":");
-		snprintf(vbuf, 63, "%d", device->inuse);
-		payload = xstrcat(payload, vbuf);
-		payload = xstrcat(payload, (char *)",\"comment\":\"");
-		payload = xstrcat(payload, device->comment);
-		payload = xstrcat(payload, (char *)"\",\"direction\":\"");
-		payload = xstrcat(payload, (char *)DEVDIR[device->direction]);
-		payload = xstrcat(payload, (char *)"\",\"value\":");
-		snprintf(vbuf, 63, "%d", device->value + device->offset);
-		payload = xstrcat(payload, vbuf);
-		payload = xstrcat(payload, (char *)"}");
+		payloadu = device_json(device, false);
+		payload = xstrcat(payload, payloadu);
 		comma = true;
+		free(payloadu);
+		payloadu = NULL;
 	    }
 	    payload = xstrcat(payload, (char *)"]");
 	    srv_send(s, payload);
@@ -386,39 +372,12 @@
 		    payload = xstrcat(payload, device->address);
 		    payload = xstrcat(payload, (char *)"-");
 		    payload = xstrcat(payload, vbuf);
-		    payload = xstrcat(payload, (char *)"\",\"metric\":{\"uuid\":\"");
-		    payload = xstrcat(payload, device->uuid);
-		    payload = xstrcat(payload, (char *)"\",\"type\":\"");
-		    payload = xstrcat(payload, (char *)DEVTYPE[device->type]);
-		    payload = xstrcat(payload, (char *)"\",\"direction\":\"");
-		    payload = xstrcat(payload, (char *)DEVDIR[device->direction]);
-		    payload = xstrcat(payload, (char *)"\",\"address\":\"");
-		    payload = xstrcat(payload, device->address);
-		    payload = xstrcat(payload, (char *)"\",\"subdevice\":");
-		    snprintf(vbuf, 63, "%d", device->subdevice);
-		    payload = xstrcat(payload, vbuf);
-		    payload = xstrcat(payload, (char *)",\"value\":");
-		    snprintf(vbuf, 63, "%d", device->value);
-		    payload = xstrcat(payload, vbuf);
-		    payload = xstrcat(payload, (char *)",\"offset\":");
-		    snprintf(vbuf, 63, "%d", device->offset);
-		    payload = xstrcat(payload, vbuf);
-		    payload = xstrcat(payload, (char *)",\"present\":\"");
-		    payload = xstrcat(payload, (char *)DEVPRESENT[device->present]);
-		    payload = xstrcat(payload, (char *)"\",\"gpiopin\":");
-		    snprintf(vbuf, 63, "%d", device->gpiopin);
-		    payload = xstrcat(payload, vbuf);
-		    payload = xstrcat(payload, (char *)",\"inuse\":");
-		    snprintf(vbuf, 63, "%d", device->inuse);
-		    payload = xstrcat(payload, vbuf);
-		    payload = xstrcat(payload, (char *)",\"description\":\"");
-		    payload = xstrcat(payload, device->description);
-		    payload = xstrcat(payload, (char *)"\",\"comment\":\"");
-		    payload = xstrcat(payload, device->comment);
-		    payload = xstrcat(payload, (char *)"\",\"timestamp\":");
-		    snprintf(vbuf, 63, "%ld", (long)device->timestamp);
-		    payload = xstrcat(payload, vbuf);
-		    payload = xstrcat(payload, (char *)"}}");
+		    payload = xstrcat(payload, (char *)"\",\"metric\":");
+		    payloadu = device_json(device, true);
+		    payload = xstrcat(payload, payloadu);
+		    free(payloadu);
+		    payloadu = NULL;
+		    payload = xstrcat(payload, (char *)"}");
 	    	    srv_send(s, (char *)"213 Device json record follows:");
 		    srv_send(s, payload);
 	    	    free(payload);
@@ -427,6 +386,7 @@
 		    return 0;
 		}
 	    }
+	    srv_send(s, (char *)"{}");
 	    srv_send(s, (char *)"440 No such device");
             return 0;
 	}
--- a/thermferm/websocket.c	Wed Apr 17 15:03:01 2024 +0200
+++ b/thermferm/websocket.c	Wed Apr 17 19:54:56 2024 +0200
@@ -415,7 +415,7 @@
     	else
             ringbuffer_head++;
 
-//    	syslog(LOG_NOTICE, "ws: broadcast buffer=%d  len=%d", ringbuffer_head, len);
+    	syslog(LOG_NOTICE, "ws: broadcast buffer=%d  len=%d", ringbuffer_head, len);
 
     	lws_callback_on_writable_all_protocol(context, &protocols[0]);
     	err = pthread_mutex_unlock(&ws_mutex);
--- a/www/js/fermenter.js	Wed Apr 17 15:03:01 2024 +0200
+++ b/www/js/fermenter.js	Wed Apr 17 19:54:56 2024 +0200
@@ -435,7 +435,7 @@
   var msg = evt.data;
   var obj = JSON.parse(msg);
 
-//  console.log('ws got ' + msg);
+  console.log('ws got ' + msg);
 
   if (obj.ping) {
    websocket.send('{"pong":' + obj.ping + '}');

mercurial