--- 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");