One-wire thread is now the first to start. The devices_detect() function now uses the detected one-wire linked list instead of scan the sysfs. Base code for ds2413 added in the state table, needs rework.

Wed, 03 Apr 2024 12:14:45 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 03 Apr 2024 12:14:45 +0200
changeset 656
ca47c742a25d
parent 655
780cc08df263
child 657
38162f374842

One-wire thread is now the first to start. The devices_detect() function now uses the detected one-wire linked list instead of scan the sysfs. Base code for ds2413 added in the state table, needs rework.

thermferm/devices.c file | annotate | diff | comparison | revisions
thermferm/one-wire.c file | annotate | diff | comparison | revisions
thermferm/thermferm.c file | annotate | diff | comparison | revisions
--- a/thermferm/devices.c	Tue Apr 02 15:29:16 2024 +0200
+++ b/thermferm/devices.c	Wed Apr 03 12:14:45 2024 +0200
@@ -33,6 +33,8 @@
 extern sys_config	Config;
 extern int		my_shutdown;
 extern pthread_mutex_t  mutexes[5];
+extern w1_list		*w1_devices;
+
 
 #ifdef USE_SIMULATOR
 
@@ -393,99 +395,77 @@
 {
     struct dirent	*de;
     DIR			*fd;
+    w1_list		*dev_w1;
     devices_list	*device, *ndev;
-    int			found, subdevices, ival, i, rc = 0;
-    char		buf[40];
+    int			found, subdevices, i, rc = 0;
     uuid_t		uu;
 #ifdef HAVE_WIRINGPI_H
     int			pin;
 #endif
 
     /*
-     * Scan for 1-wire devices
+     * 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.
      */
-    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;
+    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) {
+	    for (i = 0; i < dev_w1->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;
+			}
 		    }
 		}
-
-		if (found == FALSE) {
-		    strncpy(buf, de->d_name, 2);
-		    buf[2] = '\0';
-		    sscanf(buf, "%02x", &ival);
-		    subdevices = 0;
-
-		    /*
-		     * ival is zero when a ghost sensor is detected.
-		     */
-		    if (ival > 0)
-		    	subdevices = 1;
-		    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->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 *)"DS1822 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->direction = DEVDIR_IN_BIN;
-			    ndev->description = xstrcpy((char *)"DS2413 Dual channel addressable switch");
-			} 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);
-
-			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++;
-		    }
-		}
+		rc++;
 	    }
 	}
-	closedir(fd);
     }
 
     /*
--- a/thermferm/one-wire.c	Tue Apr 02 15:29:16 2024 +0200
+++ b/thermferm/one-wire.c	Wed Apr 03 12:14:45 2024 +0200
@@ -23,6 +23,8 @@
 #include "thermferm.h"
 #include "statetbl.h"
 #include "one-wire.h"
+#include "devices.h"
+#include "delay.h"
 #include "xutil.h"
 
 
@@ -61,20 +63,22 @@
 SM_DECL(one_wire,(char *)"one-wire")
 SM_STATES
     Scan,
+    Read2413,
     Reading,
     Missing
 SM_NAMES
     (char *)"Scan",
+    (char *)"Read2413",
     (char *)"Reading",
     (char *)"Missing"
 SM_EDECL
 
-    int			found, i;
+    int			found, i, rc;
     FILE		*fp;
-//    devices_list	*device, *ndev;
+    devices_list	*device;
     w1_list		*dev_w1, *n_w1, *cur_w1 = NULL;
     char		buffer[25], w1type[10];
-    uuid_t		uu;
+    uint8_t		state, output;
 
 SM_START(Scan)
 
@@ -94,8 +98,6 @@
     }
     while ((fgets(buffer, 25, fp))) {
 	buffer[strlen(buffer)-1] = '\0';
-//	syslog(LOG_NOTICE, "device %d %s", strlen(buffer), buffer);
-
 	strncpy(w1type, buffer, 2);
 	w1type[2] = '\0';
 
@@ -149,6 +151,58 @@
 	}
     }
     fclose(fp);
+    SM_PROCEED(Read2413);
+
+SM_STATE(Read2413)
+
+    if (my_shutdown) {
+	SM_SUCCESS;
+    }
+
+    for (dev_w1 = w1_devices; dev_w1; dev_w1 = dev_w1->next) {
+	if (strcmp(dev_w1->family, "3a") == 0) {
+	    syslog(LOG_NOTICE, "ds2413 %s", dev_w1->address);
+	    for (i = 0; i < 2; i++) {
+		for (device = Config.devices; device; device = device->next) {
+		    if ((strcmp(dev_w1->address, device->address) == 0) && (device->subdevice == i) && (device->direction == DEVDIR_IN_BIN)) {
+			/*
+			 * First make sure that if this device is configured as input
+			 * to drive the output high.
+			 * TODO: This must be made different. Check state and fix only if wrong.
+			 */
+			if ((rc = read_w1(device->address, (char *)"state")) >= 0) {
+			    state = (unsigned int)rc;
+			    output = ((state & 0x02) >> 1) + ((state & 0x08) >> 2);         /* Both latch states    */
+			    if (i == 0) {
+				output = (output & 0xfe);
+				output |= 0x01;
+			    } else if (i == 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) {
+			    pthread_mutex_lock(&mutexes[LOCK_DEVICES]);
+			    /*
+			     * 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);
+			    pthread_mutex_unlock(&mutexes[LOCK_DEVICES]);
+			}
+			mDelay(20);
+		    }
+		}
+	    }
+	}
+    }
+
     SM_PROCEED(Reading);
 
 SM_STATE(Reading)
--- a/thermferm/thermferm.c	Tue Apr 02 15:29:16 2024 +0200
+++ b/thermferm/thermferm.c	Wed Apr 03 12:14:45 2024 +0200
@@ -1037,6 +1037,18 @@
     }
     mqtt_connect();
 
+    /*
+     * First scan the one-wire bus
+     */
+    rc = pthread_create(&threads[t], NULL, my_one_wire_loop, (void *)t );
+    if (rc) {
+	fprintf(stderr, "my_one_wire_loop thread didn't start rc=%d\n", rc);
+	syslog(LOG_NOTICE, "my_one_wire_loop thread didn't start rc=%d", rc);
+    } else {
+	t++;
+	mDelay(250);	/* Wait a while to detect the devices */
+    }
+
     if ((rc = devices_detect())) {
 	syslog(LOG_NOTICE, "Detected %d new devices", rc);
 	wrconfig();
@@ -1066,14 +1078,6 @@
 	t++;
     }
 
-    rc = pthread_create(&threads[t], NULL, my_one_wire_loop, (void *)t );
-    if (rc) {
-	fprintf(stderr, "my_one_wire_loop thread didn't start rc=%d\n", rc);
-	syslog(LOG_NOTICE, "my_one_wire_loop thread didn't start rc=%d", rc);
-    } else {
-	t++;
-    }
-
 #ifdef USE_SIMULATOR
     rc = pthread_create(&threads[t], NULL, my_simulator_loop, (void *)t );
     if (rc) {

mercurial