Wed, 24 Apr 2024 20:36:06 +0200
Finished save fermenter uit edit.
/***************************************************************************** * Copyright (C) 2014..2024 * * Michiel Broek <mbroek at mbse dot eu> * * This file is part of the mbsePi-apps * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * mbsePi-apps is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with thermferm; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ #include "thermferm.h" #include "delay.h" #include "devices.h" #include "rc-switch.h" #include "panel.h" #include "xutil.h" #include "websocket.h" int my_devices_shutdown = 0; int my_devices_state = 0; extern sys_config Config; 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 extern int SIMcooling; extern int SIMheating; extern int SIMfan; extern int SIMlight; #endif void devices_ws(void); /* * Since kernel version 4 there is a module, and a dtoverlay so that the * temperature and humidity can simply read from the /sys filesystem. */ int dht11_temperature = -1; int dht11_humidity = -1; int dht11_state = DEVPRESENT_UNDEF; time_t dht11_next; /* * DHT11 sensor read. * Called at 30 seconds interval if all is well. * If last read was an error, the interval is 2 seconds. */ void dht11Read(char *address) { int temp, hum; int fd, rc, err, oldstate; char buffer[25], *dhtpath = NULL; dht11_temperature = -1; dht11_humidity = -1; oldstate = dht11_state; dhtpath = xstrcpy((char *)"/sys/bus/iio/devices/"); dhtpath = xstrcat(dhtpath, address); dhtpath = xstrcat(dhtpath, (char *)"/in_temp_input"); fd = open(dhtpath, O_RDONLY); if (fd < 0) { /* * The sensor is gone. */ err = errno; syslog(LOG_NOTICE, "DHT11 open temperature: %d %s", err, strerror(err)); free(dhtpath); dht11_state = DEVPRESENT_NO; return; } rc = read(fd, buffer, 25); if (rc == -1) { err = errno; if (err == 110) { dht11_state = DEVPRESENT_NO; /* Device is gone */ } else { dht11_state = DEVPRESENT_ERROR; } syslog(LOG_NOTICE, "DHT11 read temperature: %s", strerror(err)); } else { sscanf(buffer, "%d", &temp); dht11_temperature = temp; dht11_state = DEVPRESENT_YES; } close(fd); free(dhtpath); dhtpath = NULL; /* * Only read humidity if state is DEVPRESENT_YES */ if (dht11_state == DEVPRESENT_YES) { dhtpath = xstrcpy((char *)"/sys/bus/iio/devices/"); dhtpath = xstrcat(dhtpath, address); dhtpath = xstrcat(dhtpath, (char *)"/in_humidityrelative_input"); fd = open(dhtpath, O_RDONLY); rc = read(fd, buffer, 25); if (rc == -1) { err = errno; if (err == 110) { dht11_state = DEVPRESENT_NO; } else { dht11_state = DEVPRESENT_ERROR; } syslog(LOG_NOTICE, "DHT11 read humidity: %s", strerror(err)); dht11_temperature = -1; /* Make invalid */ } else { sscanf(buffer, "%d", &hum); dht11_humidity = hum; dht11_state = DEVPRESENT_YES; } close(fd); free(dhtpath); dhtpath = NULL; } if (oldstate != dht11_state) syslog(LOG_NOTICE, "dht11 t:%d h:%d state:%d", dht11_temperature, dht11_humidity, dht11_state); } /* * Read one byte from a 1-wire device like a DS2413 */ int read_w1(char *address, char *file) { char *addr = NULL; int fn = -1, rc = -1, retries = 5; uint8_t val; addr = xstrcpy((char *)"/sys/bus/w1/devices/"); addr = xstrcat(addr, address); addr = xstrcat(addr, (char *)"/"); addr = xstrcat(addr, file); if ((fn = open(addr, O_RDONLY)) >= 0) { if ((lseek(fn, 0L, SEEK_SET)) == 0) { while (retries--) { if ((read(fn, &val, 1)) == 1) { rc = (int)val; goto leave; } } syslog(LOG_NOTICE, "read_w1() read %s fatal: %s", addr, strerror(errno)); } else { syslog(LOG_NOTICE, "read_w1() lseek %s: %s", addr, strerror(errno)); } } else { syslog(LOG_NOTICE, "read_w1() open %s: %s", addr, strerror(errno)); } leave: if (fn != -1) { if ((close(fn)) == -1) { syslog(LOG_NOTICE, "read_w1() close %s: %s", addr, strerror(errno)); } } free(addr); return rc; } /* * Write a byte to a 1-wire device like a DS2413 */ int write_w1(char *address, char *file, uint8_t val) { char *addr = NULL; int fn = -1, rc = -1, retries = 5; addr = xstrcpy((char *)"/sys/bus/w1/devices/"); addr = xstrcat(addr, address); addr = xstrcat(addr, (char *)"/"); addr = xstrcat(addr, file); if ((fn = open(addr, O_WRONLY)) >= 0) { if ((lseek(fn, 0L, SEEK_SET)) == 0) { while (retries--) { if ((write(fn, &val, 1)) == 1) { rc = 0; goto leave; } } syslog(LOG_NOTICE, "write_w1() write %s fatal: %s", addr, strerror(errno)); } else { syslog(LOG_NOTICE, "write_w1() lseek %s: %s", addr, strerror(errno)); } } else { syslog(LOG_NOTICE, "write_w1() open %s: %s", addr, strerror(errno)); } leave: if (fn != -1) { if ((close(fn)) == -1) { syslog(LOG_NOTICE, "write_w1() close %s: %s", addr, strerror(errno)); } } free(addr); return rc; } int device_out(char *uuid, int value) { devices_list *device; time_t now, my_timestamp; int my_value, test_value; #ifdef HAVE_WIRINGPI_H int rc, i; char buf[40]; #endif if (uuid == NULL) return 0; now = time(NULL); // pthread_mutex_lock(&mutexes[LOCK_DEVICES]); for (device = Config.devices; device; device = device->next) { if (! strcmp(uuid, device->uuid)) { /* * Execute command if different then the old value. But also * every 2 minutes because commands can have temporary * disconnects, or have radio problems. */ my_timestamp = device->timestamp; my_value = device->value; if ((device->type == DEVTYPE_W1) && (device->direction == DEVDIR_OUT_BIN)) { test_value = (value == 0) ? 0 : 1; } else { test_value = value; } if ((test_value != my_value) || (((int)now - (int)my_timestamp) >= 120)) { #ifdef HAVE_WIRINGPI_H rc = 0; if ((device->type == DEVTYPE_RC433) && (device->gpiopin != -1) && (device->present == DEVPRESENT_YES)) { snprintf(buf, 39, "%s,%d", device->address, value ? 1:0); for (i = 0; i < strlen(buf); i++) if (buf[i] == '-') buf[i] = ','; // pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); enableTransmit(device->gpiopin); rc = toggleSwitch(buf); disableTransmit(); // pthread_mutex_lock(&mutexes[LOCK_DEVICES]); syslog(LOG_NOTICE, "RC433 command %s rc=%d", buf, rc); device->value = value; device->timestamp = time(NULL); devices_ws(); // pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); return rc; } if ((device->type == DEVTYPE_GPIO) && (device->gpiopin != -1) && (device->present == DEVPRESENT_YES)) { } #endif if ((device->type == DEVTYPE_W1) && (device->direction == DEVDIR_OUT_BIN) && (device->present == DEVPRESENT_YES)) { if (strncmp(device->address, (char *)"3a", 2) == 0) { syslog(LOG_NOTICE, "DS2413 PIO%c value=%d (%s)", (device->subdevice == 0) ? 'A' : 'B', (value == 0) ? 0 : 1, device->comment); // pthread_mutex_lock(&mutexes[LOCK_DEVICES]); if (device->value != (value == 0) ? 0 : 1) { device->value = (value == 0) ? 0 : 1; device->timestamp = time(NULL); devices_ws(); } // pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); } } #ifdef USE_SIMULATOR if ((device->type == DEVTYPE_SIM) && (device->direction == DEVDIR_OUT_BIN) && (device->present == DEVPRESENT_YES)) { if ((strcmp((char *)"SimCooler", device->address) == 0) || (strcmp((char *)"SimHeater", device->address) == 0) || (strcmp((char *)"SimFan" , device->address) == 0) || (strcmp((char *)"SimLight" , device->address) == 0)) { if (value != device->value) { syslog(LOG_NOTICE, "SIM %s value=%d", device->address, value); device->value = value; device->timestamp = time(NULL); if (strcmp((char *)"SimCooler", device->address) == 0) SIMcooling = value; if (strcmp((char *)"SimHeater", device->address) == 0) SIMheating = value; if (strcmp((char *)"SimFan", device->address) == 0) SIMfan = value; if (strcmp((char *)"SimLight", device->address) == 0) SIMlight = value; devices_ws(); } } } #endif } else { // pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); return 0; } // if ((test_value != my_value) || (((int)now - (int)my_timestamp) >= 120)) } // if (! strcmp(uuid, device->uuid)) } // for (device = Config.devices; device; device = device->next) // pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); return 0; } /* * Returns DEVPRESENT_NO if failed. * Returns DEVPRESENT_YES if success, value contains new value. */ int device_in(char *uuid, int *value) { devices_list *device; int tmp, present; if (uuid == NULL) return DEVPRESENT_UNDEF; for (device = Config.devices; device; device = device->next) { if (! strcmp(uuid, device->uuid)) { present = device->present; if (present == DEVPRESENT_YES) { tmp = device->value + device->offset; } else { tmp = 0; } *value = tmp; return present; } } return DEVPRESENT_NO; } /* * Return json data for one device. */ char *device_json(devices_list *device) { 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); 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 *)"\""); 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 *)"}"); 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); 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; } /* * Auto detect hotplugged or known to be present devices */ int devices_detect(void) { struct dirent *de; DIR *fd; w1_list *dev_w1; devices_list *device, *ndev; int found, subdevices, i, rc = 0; uuid_t uu; #ifdef HAVE_WIRINGPI_H int pin; char buf[40]; #endif /* * Scan for 1-wire devices. These are already detected by the * one-wire thread that is already running. So we just check * these detected devices. */ for (dev_w1 = w1_devices; dev_w1; dev_w1 = dev_w1->next) { found = FALSE; for (device = Config.devices; device; device = device->next) { if (strcmp(device->address, dev_w1->address) == 0) { found = TRUE; break; } } if (found == FALSE) { subdevices = (strcmp(dev_w1->family, (char *)"3a") == 0) ? 2:1; for (i = 0; i < subdevices; i++) { ndev = (devices_list *)malloc(sizeof(devices_list)); ndev->next = NULL; ndev->uuid = malloc(37); uuid_generate(uu); uuid_unparse(uu, ndev->uuid); ndev->type = DEVTYPE_W1; ndev->direction = DEVDIR_IN_ANALOG; if (strcmp(dev_w1->family, (char *)"10") == 0) { ndev->description = xstrcpy((char *)"DS18S20 Digital thermometer"); } else if (strcmp(dev_w1->family, (char *)"22") == 0) { ndev->description = xstrcpy((char *)"DS1822 Digital thermometer"); } else if (strcmp(dev_w1->family, (char *)"28") == 0) { ndev->description = xstrcpy((char *)"DS18B20 Digital thermometer"); } else if (strcmp(dev_w1->family, (char *)"3a") == 0) { ndev->description = xstrcpy((char *)"DS2413 Dual channel addressable switch"); ndev->direction = DEVDIR_IN_BIN; } else if (strcmp(dev_w1->family, (char *)"3b") == 0) { ndev->description = xstrcpy((char *)"DS1825 Digital thermometer"); } else if (strcmp(dev_w1->family, (char *)"42") == 0) { ndev->description = xstrcpy((char *)"DS28EA00 Digital thermometer"); } else { ndev->description = xstrcpy((char *)"Unknown device family "); ndev->direction = DEVDIR_UNDEF; } ndev->value = ndev->offset = ndev->inuse = 0; ndev->present = DEVPRESENT_YES; ndev->address = xstrcpy(dev_w1->address); ndev->subdevice = i; ndev->gpiopin = -1; ndev->comment = xstrcpy((char *)"Auto detected device"); ndev->timestamp = time(NULL); syslog(LOG_NOTICE, "New W1 device %s, subdevice %d, %s", ndev->address, ndev->subdevice, ndev->description); if (Config.devices == NULL) { Config.devices = ndev; } else { for (device = Config.devices; device; device = device->next) { if (device->next == NULL) { device->next = ndev; break; } } } rc++; } } } /* * DHT11 as kernel module. The number after the @ is the hexadecimal * number of the BCM gpio pin. Since we use pin 22 at connector pin 15 * the number is 16. */ char *dhtaddr = NULL; if ((fd = opendir((char *)"/sys/devices/platform/dht11@16"))) { while ((de = readdir(fd))) { if (de->d_name[0] != '.') { if (strncmp(de->d_name, (char *)"iio", 3) == 0) { dhtaddr = xstrcpy(de->d_name); } } } closedir(fd); } if (dhtaddr) { found = FALSE; for (device = Config.devices; device; device = device->next) { if (strcmp(device->address, dhtaddr) == 0) { found = TRUE; break; } } if (found == FALSE) { for (i = 0; i < 2; i++) { ndev = (devices_list *)malloc(sizeof(devices_list)); ndev->next = NULL; ndev->uuid = malloc(37); uuid_generate(uu); uuid_unparse(uu, ndev->uuid); ndev->type = DEVTYPE_DHT; ndev->direction = DEVDIR_IN_ANALOG; if (i == 0) ndev->description = xstrcpy((char *)"DHT11 temperature sensor"); else ndev->description = xstrcpy((char *)"DHT11 humidity sensor"); ndev->value = ndev->offset = ndev->inuse = 0; ndev->present = DEVPRESENT_YES; ndev->address = xstrcpy(dhtaddr); ndev->subdevice = i; ndev->gpiopin = -1; ndev->comment = xstrcpy((char *)"Auto detected device"); ndev->timestamp = time(NULL); syslog(LOG_NOTICE, "New DHT11 device %s, subdevice %d, %s", ndev->address, ndev->subdevice, ndev->description); if (Config.devices == NULL) { Config.devices = ndev; } else { for (device = Config.devices; device; device = device->next) { if (device->next == NULL) { device->next = ndev; break; } } } rc++; } } } #ifdef HAVE_WIRINGPI_H if (piBoardRev() == 2) { /* * Support rev B and newer boards only */ found = FALSE; for (device = Config.devices; device; device = device->next) { if (device->type == DEVTYPE_GPIO) { found = TRUE; break; } } if (found == FALSE) { /* * There were no GPIO devices found. */ subdevices = 12; pin = 0; for (i = 0; i < subdevices; i++) { if (i == 8) pin = 17; ndev = (devices_list *)malloc(sizeof(devices_list)); ndev->next = NULL; ndev->uuid = malloc(37); uuid_generate(uu); uuid_unparse(uu, ndev->uuid); ndev->type = DEVTYPE_GPIO; ndev->value = digitalRead(pin); ndev->offset = 0; ndev->present = DEVPRESENT_YES; ndev->address = xstrcpy((char *)"GPIO"); snprintf(buf, 39, "Raspberry GPIO %d", i); ndev->description = xstrcpy(buf); ndev->subdevice = i; ndev->gpiopin = pin; ndev->timestamp = time(NULL); if (i == 0) { ndev->direction = DEVDIR_INTERN; ndev->inuse = 1; ndev->comment = xstrcpy((char *)"433 Mhz transmitter"); } else if (i == 3) { ndev->direction = DEVDIR_INTERN; ndev->inuse = 1; ndev->comment = xstrcpy((char *)"DHT11 sensor"); } else if (i == PANEL_LED) { ndev->direction = DEVDIR_OUT_BIN; ndev->inuse = 1; ndev->comment = xstrcpy((char *)"Frontpanel LED"); } else if (i == PANEL_ENTER) { ndev->direction = DEVDIR_IN_BIN; ndev->inuse = 1; ndev->comment = xstrcpy((char *)"Frontpanel Enter key"); } else if (i == PANEL_DOWN) { ndev->direction = DEVDIR_IN_BIN; ndev->inuse = 1; ndev->comment = xstrcpy((char *)"Frontpanel Down key"); } else if (i == PANEL_UP) { ndev->direction = DEVDIR_IN_BIN; ndev->inuse = 1; ndev->comment = xstrcpy((char *)"Frontpanel Up key"); } else if (i == 7) { ndev->direction = DEVDIR_INTERN; ndev->inuse = 1; ndev->comment = xstrcpy((char *)"1-Wire bus"); } else { ndev->direction = DEVDIR_IN_BIN; ndev->inuse = 0; ndev->comment = xstrcpy((char *)"Raspberry GPIO"); } pin++; syslog(LOG_NOTICE, "New GPIO device %s, subdevice %d, %s", ndev->address, ndev->subdevice, ndev->description); if (Config.devices == NULL) { Config.devices = ndev; } else { for (device = Config.devices; device; device = device->next) { if (device->next == NULL) { device->next = ndev; break; } } } rc++; } } } #endif #ifdef USE_SIMULATOR found = 0; for (device = Config.devices; device; device = device->next) { if (device->type == DEVTYPE_SIM) { found++; } } /* * Create simulated devices, or upgrade with new devices. */ subdevices = 9; for (i = found; i < subdevices; i++) { ndev = (devices_list *)malloc(sizeof(devices_list)); ndev->next = NULL; ndev->uuid = malloc(37); uuid_generate(uu); uuid_unparse(uu, ndev->uuid); ndev->type = DEVTYPE_SIM; ndev->value = ndev->offset = 0; ndev->present = DEVPRESENT_YES; ndev->subdevice = i; ndev->gpiopin = -1; ndev->comment = xstrcpy((char *)"Auto detected device"); ndev->timestamp = time(NULL); ndev->inuse = 0; switch (i) { case 0: ndev->direction = DEVDIR_IN_ANALOG; ndev->address = xstrcpy((char *)"SimRoomTemp"); ndev->description = xstrcpy((char *)"Simulated room temperature"); break; case 1: ndev->direction = DEVDIR_IN_ANALOG; ndev->address = xstrcpy((char *)"SimAirTemp"); ndev->description = xstrcpy((char *)"Simulated air temperature"); break; case 2: ndev->direction = DEVDIR_IN_ANALOG; ndev->address = xstrcpy((char *)"SimBeerTemp"); ndev->description = xstrcpy((char *)"Simulated beer temperature"); break; case 3: ndev->direction = DEVDIR_OUT_BIN; ndev->address = xstrcpy((char *)"SimHeater"); ndev->description = xstrcpy((char *)"Simulated heater"); break; case 4: ndev->direction = DEVDIR_OUT_BIN; ndev->address = xstrcpy((char *)"SimCooler"); ndev->description = xstrcpy((char *)"Simulated cooler"); break; case 5: ndev->direction = DEVDIR_IN_ANALOG; ndev->address = xstrcpy((char *)"SimRoomHum"); ndev->description = xstrcpy((char *)"Simulated room humidity"); break; case 6: ndev->direction = DEVDIR_IN_ANALOG; ndev->address = xstrcpy((char *)"SimChillerTemp"); ndev->description = xstrcpy((char *)"Simulated Chiller temperature"); break; case 7: ndev->direction = DEVDIR_OUT_BIN; ndev->address = xstrcpy((char *)"SimFan"); ndev->description = xstrcpy((char *)"Simulated fan"); break; case 8: ndev->direction = DEVDIR_OUT_BIN; ndev->address = xstrcpy((char *)"SimLight"); ndev->description = xstrcpy((char *)"Simulated light"); break; } syslog(LOG_NOTICE, "New Simulator device %s, subdevice %d, %s", ndev->address, ndev->subdevice, ndev->description); if (Config.devices == NULL) { Config.devices = ndev; } else { for (device = Config.devices; device; device = device->next) { if (device->next == NULL) { device->next = ndev; break; } } } rc++; } #endif return rc; } void *my_devices_loop(void *threadid) { devices_list *device; w1_list *dev_w1; #ifdef USE_SIMULATOR simulator_list *simulator; #endif int found; time_t now; bool changed; my_devices_state = 1; syslog(LOG_NOTICE, "Thread my_devices_loop started"); dht11_next = time(NULL); /* * Loop forever until the external shutdown variable is set. */ for (;;) { changed = false; /* * Process all devices. */ for (device = Config.devices; device; device = device->next) { if (my_devices_shutdown) break; switch (device->type) { case DEVTYPE_W1: /* * Only tested with DS18B20 but from the kernel source this * should work with all 1-wire thermometer sensors. */ if ((strncmp(device->address, (char *)"10", 2) == 0) || (strncmp(device->address, (char *)"22", 2) == 0) || (strncmp(device->address, (char *)"28", 2) == 0) || (strncmp(device->address, (char *)"3b", 2) == 0) || (strncmp(device->address, (char *)"42", 2) == 0)) { found = FALSE; for (dev_w1 = w1_devices; dev_w1; dev_w1 = dev_w1->next) { if (strcmp(device->address, dev_w1->address) == 0) { found = TRUE; if ((dev_w1->value == -1) || (dev_w1->value < -55000)) { 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) { syslog(LOG_NOTICE, "sensor %s value ok %d", device->address, dev_w1->value); changed = true; device->present = DEVPRESENT_YES; } if (device->value != dev_w1->value) { changed = true; device->value = dev_w1->value; device->timestamp = time(NULL); } } } } if (found == FALSE) { if (device->present != DEVPRESENT_NO) { 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]); } } } /* if temperature sensor */ break; case DEVTYPE_DHT: /* * Don't read these to often, 2 seconds minimum delay. * Delay 30 seconds if last update was successfull, * else delay 2 seconds. */ now = time(NULL); if ((int)(now >= dht11_next)) { if (device->subdevice == 0) { /* Read once during subdevice 0 */ dht11Read(device->address); // pthread_mutex_lock(&mutexes[LOCK_DEVICES]); device->present = dht11_state; if (dht11_state == DEVPRESENT_YES) { 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) { /* Data already present, valid or not. */ // pthread_mutex_lock(&mutexes[LOCK_DEVICES]); device->present = dht11_state; if (dht11_state == DEVPRESENT_YES) { if (device->value != dht11_humidity) { changed = true; device->value = dht11_humidity; device->timestamp = time(NULL); } dht11_next = now + 29; } else { dht11_next = now + 1; } // pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); } } break; #ifdef HAVE_WIRINGPI_H case DEVTYPE_GPIO: if (device->direction == DEVDIR_IN_BIN) { // pthread_mutex_lock(&mutexes[LOCK_DEVICES]); 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; #endif #ifdef USE_SIMULATOR case DEVTYPE_SIM: // pthread_mutex_lock(&mutexes[LOCK_DEVICES]); if (Config.simulators) { int val; simulator = Config.simulators; if (device->subdevice == 0) { 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) { 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) { 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) { 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) { 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]); break; #endif default: break; } if (my_devices_shutdown) break; /* * Delay a bit after procesing a device. */ mDelay(10); } if (my_devices_shutdown) break; /* * Delay a bit after all devices */ mDelay(50); if (changed) { devices_ws(); } mDelay(50); } syslog(LOG_NOTICE, "Thread my_devices_loop stopped"); my_devices_state = 0; return 0; }