# HG changeset patch # User Michiel Broek # Date 1712139285 -7200 # Node ID ca47c742a25d7dc537e9b93590f03dbe41daeadf # Parent 780cc08df263276ed3bbe365e5ca0df9ae6b56a1 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. diff -r 780cc08df263 -r ca47c742a25d thermferm/devices.c --- 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); } /* diff -r 780cc08df263 -r ca47c742a25d thermferm/one-wire.c --- 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) diff -r 780cc08df263 -r ca47c742a25d thermferm/thermferm.c --- 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) {