# HG changeset patch # User Michiel Broek # Date 1713376496 -7200 # Node ID b2265c7e57071bfa83b61423b666f9ee2b3034e7 # Parent d48733bf1529fd3dce1b0f49e9ab2eaf2a9cfc31 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. diff -r d48733bf1529 -r b2265c7e5707 thermferm/Makefile --- 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 diff -r d48733bf1529 -r b2265c7e5707 thermferm/devices.c --- 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"); diff -r d48733bf1529 -r b2265c7e5707 thermferm/devices.h --- 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 *); diff -r d48733bf1529 -r b2265c7e5707 thermferm/server.c --- 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; } diff -r d48733bf1529 -r b2265c7e5707 thermferm/websocket.c --- 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); diff -r d48733bf1529 -r b2265c7e5707 www/js/fermenter.js --- 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 + '}');