Thu, 02 Apr 2015 23:24:32 +0200
Added ARCHIVE GET file download command.
/***************************************************************************** * Copyright (C) 2014..2015 * * 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 "devices.h" #include "rc-switch.h" #include "panel.h" #include "xutil.h" extern int debug; extern sys_config Config; extern int my_shutdown; #ifdef HAVE_WIRINGPI_H #define MAXTIMINGS 100 int dht11_pin = -1; int dht11_temperature = -1; int dht11_humidity = -1; int dht11_valid = FALSE; time_t dht11_last = (time_t)0; static uint8_t sizecvt(const int read_value) { /* * digitalRead() and friends from wiringpi are defined as returning a value * < 256. However, they are returned as int() types. This is a safety function */ if (read_value > 255 || read_value < 0) { syslog(LOG_NOTICE, "invalid data from wiringPi library"); } return (uint8_t)read_value; } /* * DHT11 sensor read. */ void dht11Read(void) { int tries = 5; unsigned short got_correct_data = 0; if (dht11_pin == -1) return; while (tries && !got_correct_data) { uint8_t laststate = HIGH; uint8_t counter = 0; uint8_t j = 0, i = 0; int dht11_dat[5] = {0,0,0,0,0}; /* * Select output mode to send the start signal. */ pinMode(dht11_pin, OUTPUT); digitalWrite(dht11_pin, HIGH); usleep(1000); /* * Low for at least 18 milliseconds */ digitalWrite(dht11_pin, LOW); usleep(20000); digitalWrite(dht11_pin, HIGH); pinMode(dht11_pin, INPUT); /* * Detect change and read data */ for (i=0; i<MAXTIMINGS; i++) { counter = 0; delayMicroseconds(10); while (sizecvt(digitalRead(dht11_pin)) == laststate) { counter++; delayMicroseconds(1); if (counter == 255) { break; } } laststate = sizecvt(digitalRead(dht11_pin)); if (counter == 255) break; /* * ignore first 3 transitions */ if ((i >= 4) && (i%2 == 0)) { // shove each bit into the storage bytes dht11_dat[(int)((double)j/8)] <<= 1; if (counter > 16) dht11_dat[(int)((double)j/8)] |= 1; j++; } } /* * If there is no sensor, j = 0 */ if ((counter == 255) && (j == 0)) { if (dht11_temperature != -1) { syslog(LOG_NOTICE, "dht11 sensor disappeared"); } else { syslog(LOG_NOTICE, "dht11 sensor not present"); } dht11_temperature = -1; dht11_humidity = -1; dht11_valid = FALSE; return; } /* * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte * print it out if data is good */ if ((j >= 40) && (dht11_dat[4] == ((dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF))) { got_correct_data = 1; int h = dht11_dat[0] + dht11_dat[1]; int t = (dht11_dat[2] & 0x7F) + dht11_dat[3]; if ((dht11_dat[2] & 0x80) != 0) t *= -1; dht11_temperature = t; dht11_humidity = h; dht11_valid = TRUE; } else { tries--; if (tries == 0) syslog(LOG_NOTICE, "dht11 data checksum was wrong 5 times"); usleep(100000); } } } #endif 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; // } else { // syslog(LOG_NOTICE, "read_w1() read %s try=%d: %s", addr, retries, strerror(errno)); } } 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; } 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; // } else { // syslog(LOG_NOTICE, "write_w1() write %s try=%d: %s", addr, retries, strerror(errno)); } } 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 rc, my_value, test_value; #ifdef HAVE_WIRINGPI_H int i; char buf[40]; #endif if (uuid == NULL) return 0; now = time(NULL); #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif 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] = ','; piUnlock(LOCK_DEVICES); enableTransmit(device->gpiopin); rc = toggleSwitch(buf); disableTransmit(); piLock(LOCK_DEVICES); syslog(LOG_NOTICE, "RC433 command %s rc=%d", buf, rc); if (debug) fprintf(stdout, "RC433 command %s rc=%d\n", buf, rc); device->value = value; device->timestamp = time(NULL); piUnlock(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); if (debug) fprintf(stdout, "DS2413 PIO%c value=%d (%s)\n", (device->subdevice == 0) ? 'A' : 'B', (value == 0) ? 0 : 1, device->comment); device->value = (value == 0) ? 0 : 1; device->timestamp = time(NULL); } } } } #ifdef USE_SIMULATOR if ((device->type == DEVTYPE_SIM) && (device->direction == DEVDIR_OUT_BIN) && (device->present == DEVPRESENT_YES)) { } #endif } else { #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif return 0; } } } #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif return 0; } /* * Auto detect hotplugged or known to be present devices */ int devices_detect(void) { struct dirent *de; DIR *fd; devices_list *device, *ndev; int found, subdevices, ival, i, rc = 0; char buf[40]; uuid_t uu; #ifdef HAVE_WIRINGPI_H int pin; #endif /* * Scan for 1-wire devices */ if ((fd = opendir((char *)"/sys/bus/w1/devices"))) { while ((de = readdir(fd))) { if (de->d_name[0] != '.') { found = FALSE; for (device = Config.devices; device; device = device->next) { if (strcmp(device->address,de->d_name) == 0) { found = TRUE; break; } } if (found == FALSE) { strncpy(buf, de->d_name, 2); buf[2] = '\0'; sscanf(buf, "%02x", &ival); syslog(LOG_NOTICE, "Scan 1-wire %02x %d", ival, ival); subdevices = 1; if (strcmp(buf, (char *)"29") == 0) subdevices = 8; if (strcmp(buf, (char *)"3a") == 0) subdevices = 2; for (i = 0; i < subdevices; i++) { ndev = (devices_list *)malloc(sizeof(devices_list)); ndev->next = NULL; ndev->version = 1; ndev->uuid = malloc(37); uuid_generate(uu); uuid_unparse(uu, ndev->uuid); ndev->type = DEVTYPE_W1; ndev->direction = DEVDIR_UNDEF; if (strcmp(buf, (char *)"10") == 0) { ndev->direction = DEVDIR_IN_ANALOG; ndev->description = xstrcpy((char *)"DS18S20 Digital thermometer"); } else if (strcmp(buf, (char *)"22") == 0) { ndev->direction = DEVDIR_IN_ANALOG; ndev->description = xstrcpy((char *)"DS1820 Digital thermometer"); } else if (strcmp(buf, (char *)"28") == 0) { ndev->direction = DEVDIR_IN_ANALOG; ndev->description = xstrcpy((char *)"DS18B20 Digital thermometer"); } else if (strcmp(buf, (char *)"29") == 0) { ndev->description = xstrcpy((char *)"DS2408 8 Channel addressable switch/LCD"); ndev->direction = DEVDIR_IN_BIN; } else if (strcmp(buf, (char *)"3a") == 0) { ndev->description = xstrcpy((char *)"DS2413 Dual channel addressable switch"); ndev->direction = DEVDIR_IN_BIN; } else if (strcmp(buf, (char *)"3b") == 0) { ndev->direction = DEVDIR_IN_ANALOG; ndev->description = xstrcpy((char *)"DS1825 Digital thermometer"); } else if (strcmp(buf, (char *)"42") == 0) { ndev->direction = DEVDIR_IN_ANALOG; ndev->description = xstrcpy((char *)"DS28EA00 Digital thermometer"); } else if (strcmp(buf, (char *)"w1") == 0) { ndev->description = xstrcpy((char *)"Master System device"); } else { ndev->description = xstrcpy((char *)"Unknown device family "); ndev->description = xstrcat(ndev->description, buf); } ndev->value = ndev->offset = ndev->inuse = 0; ndev->present = DEVPRESENT_YES; ndev->address = xstrcpy(de->d_name); ndev->subdevice = i; ndev->gpiopin = -1; ndev->comment = xstrcpy((char *)"Auto detected device"); ndev->timestamp = time(NULL); 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++; } } } } closedir(fd); } #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->version = 1; ndev->uuid = malloc(37); uuid_generate(uu); uuid_unparse(uu, ndev->uuid); ndev->type = DEVTYPE_GPIO; ndev->value = digitalRead(pin); 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 == 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++; 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 = FALSE; for (device = Config.devices; device; device = device->next) { if (device->type == DEVTYPE_SIM) { found = TRUE; break; } } if (found == FALSE) { subdevices = 5; for (i = 0; i < subdevices; i++) { ndev = (devices_list *)malloc(sizeof(devices_list)); ndev->next = NULL; ndev->version = 1; 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_ANALOG; ndev->address = xstrcpy((char *)"SimHeater"); ndev->description = xstrcpy((char *)"Simulated heater"); break; case 4: ndev->direction = DEVDIR_OUT_ANALOG; ndev->address = xstrcpy((char *)"SimCooler"); ndev->description = xstrcpy((char *)"Simulated cooler"); break; } 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; } #ifdef HAVE_WIRINGPI_H PI_THREAD (my_devices_loop) #else void *my_devices_loop(void *threadid) #endif { devices_list *device; #ifdef USE_SIMULATOR simulator_list *simulator; #endif char *addr = NULL, line[60], *p = NULL; FILE *fp; int temp, rc; #ifdef HAVE_WIRINGPI_H time_t now; #endif syslog(LOG_NOTICE, "Thread my_devices_loop started"); #ifdef HAVE_WIRINGPI_H if ((rc = piHiPri(10))) syslog(LOG_NOTICE, "my_devices_loop: piHiPri(10) rc=%d", rc); #endif /* * Loop forever until the external shutdown variable is set. */ for (;;) { /* * Process all devices. */ for (device = Config.devices; device; device = device->next) { if (my_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)) { addr = xstrcpy((char *)"/sys/bus/w1/devices/"); addr = xstrcat(addr, device->address); addr = xstrcat(addr, (char *)"/w1_slave"); if ((fp = fopen(addr, "r"))) { if (device->present != DEVPRESENT_YES) { syslog(LOG_NOTICE, "sensor %s is back", device->address); #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif device->present = DEVPRESENT_YES; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } /* * The output looks like: * 72 01 4b 46 7f ff 0e 10 57 : crc=57 YES * 72 01 4b 46 7f ff 0e 10 57 t=23125 */ fgets(line, 50, fp); line[strlen(line)-1] = '\0'; if ((line[36] == 'Y') && (line[37] == 'E')) { /* CRC is Ok, continue */ fgets(line, 50, fp); line[strlen(line)-1] = '\0'; strtok(line, (char *)"="); p = strtok(NULL, (char *)"="); rc = sscanf(p, "%d", &temp); #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if ((rc == 1) && (device->value != temp)) { device->value = temp; device->timestamp = time(NULL); } #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } else { syslog(LOG_NOTICE, "sensor %s CRC error", device->address); #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif device->present = DEVPRESENT_ERROR; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } fclose(fp); } else { if (device->present != DEVPRESENT_NO) { syslog(LOG_NOTICE, "sensor %s is missing", device->address); #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif device->present = DEVPRESENT_NO; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } } free(addr); addr = NULL; } /* if temperature sensor */ /* * DS2408 8 Channel addressable switch */ if (strncmp(device->address, (char *)"29", 2) == 0) { /* * Always read current state and set these bits * in the subdevices value. We do this even with * the output bits, they should match. */ addr = xstrcpy((char *)"/sys/bus/w1/devices/"); addr = xstrcat(addr, device->address); addr = xstrcat(addr, (char *)"/state"); if ((fp = fopen(addr, "r"))) { if (device->present != DEVPRESENT_YES) { syslog(LOG_NOTICE, "DS2408 %s is back", device->address); #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif device->present = DEVPRESENT_YES; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } fclose(fp); } else { if (device->present != DEVPRESENT_NO) { syslog(LOG_NOTICE, "DS2408 %s is missing", device->address); #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif device->present = DEVPRESENT_NO; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } } free(addr); addr = NULL; } /* * DS2413 Dual channel addressable switch */ if (strncmp(device->address, (char *)"3a", 2) == 0) { addr = xstrcpy((char *)"/sys/bus/w1/devices/"); addr = xstrcat(addr, device->address); addr = xstrcat(addr, (char *)"/state"); if ((access(addr, R_OK)) == 0) { if (device->present != DEVPRESENT_YES) { syslog(LOG_NOTICE, "DS2413 %s is back", device->address); #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif device->present = DEVPRESENT_YES; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } if ((rc = read_w1(device->address, (char *)"state")) >= 0) { #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif /* * Read PIOA or PIOB pin state bits */ if (device->subdevice == 0) device->value = (rc & 0x01) ? 0 : 1; else if (device->subdevice == 1) device->value = (rc & 0x04) ? 0 : 1; device->timestamp = time(NULL); #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } } else { if (device->present != DEVPRESENT_NO) { syslog(LOG_NOTICE, "DS2413 %s is missing", device->address); #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif device->present = DEVPRESENT_NO; #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif } } free(addr); addr = NULL; } break; #ifdef HAVE_WIRINGPI_H case DEVTYPE_DHT: /* * Make sure we don't read the sensor withing 2 seconds. */ now = time(NULL); if ((int)(now - dht11_last) > 2) { dht11_pin = device->gpiopin; dht11Read(); dht11_last = now; } if (device->subdevice == 0) { piLock(LOCK_DEVICES); if (dht11_valid) { device->value = dht11_temperature * 1000; device->timestamp = time(NULL); device->present = DEVPRESENT_YES; } else { device->present = DEVPRESENT_ERROR; } piUnlock(LOCK_DEVICES); } else if (device->subdevice == 1) { piLock(LOCK_DEVICES); if (dht11_valid) { device->value = dht11_humidity * 1000; device->timestamp = time(NULL); device->present = DEVPRESENT_YES; } else { device->present = DEVPRESENT_ERROR; } piUnlock(LOCK_DEVICES); } break; #endif #ifdef USE_SIMULATOR case DEVTYPE_SIM: #ifdef HAVE_WIRINGPI_H piLock(LOCK_DEVICES); #endif if (Config.simulators) { simulator = Config.simulators; if (device->subdevice == 0) { device->value = (int)(simulator->room_temperature * 1000); device->timestamp = time(NULL); } else if (device->subdevice == 1) { device->value = (int)(simulator->air_temperature * 1000); device->timestamp = time(NULL); } else if (device->subdevice == 2) { device->value = (int)(simulator->beer_temperature * 1000); device->timestamp = time(NULL); } } #ifdef HAVE_WIRINGPI_H piUnlock(LOCK_DEVICES); #endif break; #endif default: break; } /* * Delay a bit after procesing a device. */ usleep(10000); } /* * Delay a bit after all devices */ usleep(100000); } syslog(LOG_NOTICE, "Thread my_devices_loop stopped"); return 0; }