brewco/devices.c

changeset 434
eb724767860d
child 435
4b1ed6897d80
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brewco/devices.c	Wed Nov 25 22:49:35 2015 +0100
@@ -0,0 +1,795 @@
+/*****************************************************************************
+ * 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 "brewco.h"
+#include "devices.h"
+#include "xutil.h"
+
+
+extern int		debug;
+extern sys_config	Config;
+extern int		my_shutdown;
+
+#ifdef USE_SIMULATOR
+
+/*extern*/ int	SIM_hlt_temp = 0;
+/*extern*/ int	SIM_mlt_temp = 0;
+
+#endif
+
+
+
+/*
+ * 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			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)) {
+		    if ((strcmp((char *)"SimHLTheater", device->address) == 0) || (strcmp((char *)"SimMLTheater", device->address) == 0)) {
+			if (value != device->value) {
+			    syslog(LOG_NOTICE, "SIM %s value=%d", device->address, value);
+			    if (debug)
+			    	fprintf(stdout, "SIM %s value=%d\n", device->address, value);
+			}
+			device->value = value;
+			if (strcmp((char *)"SimHLTheater", device->address) == 0)
+			    SIM_hlt_temp = value;
+			if (strcmp((char *)"SimMLTheater", device->address) == 0)
+			    SIM_mlt_temp = value;
+		    }
+		}
+#endif
+	    } else {
+#ifdef HAVE_WIRINGPI_H
+		piUnlock(LOCK_DEVICES);
+#endif
+		return 0;
+	    }
+	}
+    }
+#ifdef HAVE_WIRINGPI_H
+    piUnlock(LOCK_DEVICES);
+#endif
+
+    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;
+
+#ifdef HAVE_WIRINGPI_H
+    piLock(LOCK_DEVICES);
+#endif
+
+    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;
+	    }
+#ifdef HAVE_WIRINGPI_H
+	    piUnlock(LOCK_DEVICES);
+#endif
+	    *value = tmp;
+	    return present;
+	}
+    }
+
+#ifdef HAVE_WIRINGPI_H
+    piUnlock(LOCK_DEVICES);
+#endif
+
+    return DEVPRESENT_NO;
+}
+
+
+
+
+/*
+ * 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 *)"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->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 == PANEL_RETURN) {
+		    ndev->direction = DEVDIR_IN_BIN;
+		    ndev->inuse = 1;
+		    ndev->comment = xstrcpy((char *)"Frontpanel Return");
+		} 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 *)"SimHLTtemp");
+			ndev->description = xstrcpy((char *)"Simulated HLT temperature");
+			break;
+		case 2:	ndev->direction = DEVDIR_IN_ANALOG;
+			ndev->address = xstrcpy((char *)"SimMLTtemp");
+			ndev->description = xstrcpy((char *)"Simulated MLT temperature");
+			break;
+		case 3:	ndev->direction = DEVDIR_OUT_ANALOG;
+			ndev->address = xstrcpy((char *)"SimHLTheater");
+			ndev->description = xstrcpy((char *)"Simulated HLT heater");
+			break;
+		case 4:	ndev->direction = DEVDIR_OUT_ANALOG;
+			ndev->address = xstrcpy((char *)"SimMLTheater");
+			ndev->description = xstrcpy((char *)"Simulated MLT heater");
+			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 */
+			/*
+			 * 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
+				}
+				/*
+				 * First make sure that if this device is configured as input
+				 * to drive the output high.
+				 */
+				if (device->direction == DEVDIR_IN_BIN) {
+				    uint8_t state, output;
+
+				    if ((rc = read_w1(device->address, (char *)"state")) >= 0) {
+					state = (unsigned int)rc;
+					output = ((state & 0x02) >> 1) + ((state & 0x08) >> 2);		/* Both latch states	*/
+					if (device->subdevice == 0) {
+					    output = (output & 0xfe);
+					    output |= 0x01;
+					} else if (device->subdevice == 1) {
+					    output = (output & 0xfd);
+					    output |= 0x02;
+					} else {
+					    output = 0xff;
+					}
+					write_w1(device->address, (char *)"output", output);
+				    }
+				}
+				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_GPIO:
+			if (device->direction == DEVDIR_IN_BIN) {
+			    piLock(LOCK_DEVICES);
+			    device->value = digitalRead(device->gpiopin);
+			    device->offset = 0;
+			    device->timestamp = time(NULL);
+			    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->hlt_temperature * 1000);
+			    	device->timestamp = time(NULL);
+			    } else if (device->subdevice == 2) {
+			    	device->value = (int)(simulator->mlt_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;
+}
+
+
+

mercurial