Thu, 11 Apr 2024 14:57:32 +0200
Only log temperature error once. Only log temperature Ok again once. Do not log changed temperature.
/***************************************************************************** * 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" 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; #ifdef USE_SIMULATOR extern int SIMcooling; extern int SIMheating; extern int SIMfan; extern int SIMlight; #endif /* * 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; char buffer[25], *dhtpath = NULL; dht11_temperature = -1; dht11_humidity = -1; dht11_state = DEVPRESENT_UNDEF; 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: %d %s", err, 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: %d %s", err, 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; } 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); // 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) { /* * DS2413. First read state so that we can preserve the state of * the "other" PIO channel. To make things a bit more complicated * the bits in the state register differ from the output register. */ // uint8_t state, output; // if ((rc = read_w1(device->address, (char *)"state")) >= 0) { // state = (unsigned int)rc; // output = (state & 0x01) + ((state & 0x04) >> 1); // if (device->subdevice == 0) { // output = (output & 0xfe); // output |= (value == 0) ? 0x01 : 0x00; // } else if (device->subdevice == 1) { // output = (output & 0xfd); // output |= (value == 0) ? 0x02 : 0x00; // } else { // output = 0xff; // } // if ((write_w1(device->address, (char *)"output", output)) == 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]); device->value = (value == 0) ? 0 : 1; device->timestamp = time(NULL); // 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; } } #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 0; // pthread_mutex_lock(&mutexes[LOCK_DEVICES]); 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; } // pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); *value = tmp; return present; } } // pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); return DEVPRESENT_NO; } /* * 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 // char *addr = NULL, line1[60], line2[60], *p = NULL; // FILE *fp; int found; time_t now; my_devices_state = 1; syslog(LOG_NOTICE, "Thread my_devices_loop started"); #ifdef HAVE_WIRINGPI_H // if ((rc = piHiPri(50))) // syslog(LOG_NOTICE, "my_devices_loop: piHiPri(50) rc=%d", rc); #endif dht11_next = time(NULL); /* * Set the temperature sensors to 12 bits resolution and write it in EEPROM */ // for (device = Config.devices; device; device = device->next) { // if ((device->type == DEVTYPE_W1) && // ((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))) { // addr = xstrcpy((char *)"/sys/bus/w1/devices/"); // addr = xstrcat(addr, device->address); // addr = xstrcat(addr, (char *)"/w1_slave"); // if ((fp = fopen(addr, "w"))) { // rc = fprintf(fp, "12\n0\n"); // According to the kernel documentation. Seems to work. // fclose(fp); // if (rc != 5) { // syslog(LOG_NOTICE, "Program 12 bits resolution error rc=%d for %s", rc, addr); // } // } // free(addr); // addr = NULL; // } // } /* * Loop forever until the external shutdown variable is set. */ for (;;) { /* * Process all devices. */ for (device = Config.devices; device; device = device->next) { if (my_devices_shutdown) break; //syslog(LOG_NOTICE, "device type %d address %s-%d comment %s", device->type, device->address, device->subdevice, device->comment); 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) { // syslog(LOG_NOTICE, "sensor %s value %d", dev_w1->address, dev_w1->value); 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; } else { 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; } } } 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; // 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) { 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) { 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]); 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) { simulator = Config.simulators; if (device->subdevice == 0) { device->value = (int)((int)(simulator->room_temperature * 1000) / 500) * 500; device->timestamp = time(NULL); } else if (device->subdevice == 1) { device->value = (int)((int)(simulator->air_temperature * 1000) / 62.5) * 62.5; device->timestamp = time(NULL); } else if (device->subdevice == 2) { device->value = (int)((int)(simulator->beer_temperature * 1000) / 62.5) * 62.5; device->timestamp = time(NULL); } else if (device->subdevice == 5) { device->value = (int)((int)(simulator->room_humidity * 1000) / 500) * 500; device->timestamp = time(NULL); } else if (device->subdevice == 6) { device->value = (int)((int)(simulator->chiller_temperature * 1000) / 62.5) * 62.5; device->timestamp = time(NULL); } } // 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(100); } syslog(LOG_NOTICE, "Thread my_devices_loop stopped"); my_devices_state = 0; return 0; }