thermferm/devices.c

changeset 648
62c5ed1b9cfd
parent 647
fcd85176ea2e
child 649
64cfc01ec024
equal deleted inserted replaced
647:fcd85176ea2e 648:62c5ed1b9cfd
41 extern int SIMlight; 41 extern int SIMlight;
42 42
43 #endif 43 #endif
44 44
45 45
46 #define MAXTIMINGS 100
47
48 /* 46 /*
49 * Since kernel version 4 there is a module, and a dtoverlay so that the 47 * Since kernel version 4 there is a module, and a dtoverlay so that the
50 * temperature and humidity can simply read from the /sys filesystem. 48 * temperature and humidity can simply read from the /sys filesystem.
51 * But this isn't as reliable as this userspace function, so we leave
52 * that here.
53 */ 49 */
54
55 int dht11_temperature = -1; 50 int dht11_temperature = -1;
56 int dht11_humidity = -1; 51 int dht11_humidity = -1;
57 int dht11_valid = FALSE; 52 int dht11_state = DEVPRESENT_UNDEF;
58 int dht11_present = FALSE;
59 time_t dht11_last = (time_t)0; 53 time_t dht11_last = (time_t)0;
60 54
61 55
62 56
63 /* 57 /*
64 * DHT11 sensor read. 58 * DHT11 sensor read.
65 */ 59 */
66 void dht11Read(void) 60 void dht11Read(char *address)
67 { 61 {
68 int tries, temp, hum; 62 int tries = 5, temp, hum;
69 int fd, rc, err; 63 int fd, rc, err;
70 char buffer[25]; 64 char buffer[25], *dhtpath = NULL;
71 65
72 dht11_valid = FALSE;
73 dht11_present = FALSE;
74 dht11_temperature = -1;
75 dht11_humidity = -1;
76
77 /*
78 * Read DHT11 name. This only means the kernel module is loaded,
79 * it doesn't show if the chip is really present.
80 */
81 fd = open("/sys/bus/iio/devices/iio:device0/name", O_RDONLY);
82 if (fd == -1) {
83 syslog(LOG_NOTICE, "no DHT11 device");
84 return;
85 }
86
87 memset(&buffer, 0, 25);
88 read(fd, buffer, 25);
89 close(fd);
90 buffer[strlen(buffer) - 1] = '\0';
91 syslog(LOG_NOTICE, "dht11 name %s", buffer);
92
93 tries = 5;
94 while (tries) { 66 while (tries) {
95 67
96 fd = open("/sys/bus/iio/devices/iio:device0/in_temp_input", O_RDONLY); 68 dht11_temperature = -1;
69 dht11_humidity = -1;
70 dht11_state = DEVPRESENT_UNDEF;
71 dhtpath = xstrcpy((char *)"/sys/bus/iio/devices/");
72 dhtpath = xstrcat(dhtpath, address);
73 dhtpath = xstrcat(dhtpath, (char *)"/in_temp_input");
74
75 fd = open(dhtpath, O_RDONLY);
76 if (fd < 0) {
77 /*
78 * The sensor is gone.
79 */
80 free(dhtpath);
81 dht11_state = DEVPRESENT_NO;
82 break;
83 }
97 rc = read(fd, buffer, 25); 84 rc = read(fd, buffer, 25);
98 if (rc == -1) { 85 if (rc == -1) {
99 err = errno; 86 err = errno;
87 if (err == 110) {
88 dht11_state = DEVPRESENT_NO; /* Device is gone */
89 break;
90 } else {
91 dht11_state = DEVPRESENT_ERROR;
92 }
100 syslog(LOG_NOTICE, "DHT11 read temperature: %d %s", err, strerror(err)); 93 syslog(LOG_NOTICE, "DHT11 read temperature: %d %s", err, strerror(err));
101 dht11_temperature = -1; 94 dht11_temperature = -1;
102 } else { 95 } else {
103 sscanf(buffer, "%d", &temp); 96 sscanf(buffer, "%d", &temp);
104 syslog(LOG_NOTICE, "read temp rc=%d %f", rc, temp / 1000.0); 97 syslog(LOG_NOTICE, "read temp rc=%d %f", rc, temp / 1000.0);
105 dht11_temperature = temp; 98 dht11_temperature = temp;
99 dht11_state = DEVPRESENT_YES;
106 } 100 }
107 close(fd); 101 close(fd);
108 102 free(dhtpath);
109 fd = open("/sys/bus/iio/devices/iio:device0/in_humidityrelative_input", O_RDONLY); 103 dhtpath = NULL;
110 rc = read(fd, buffer, 25); 104
111 if (rc == -1) { 105 /*
112 err = errno; 106 * Only read humidity if state is DEVPRESENT_YES
113 syslog(LOG_NOTICE, "DHT11 read temperature: %d %s", err, strerror(err)); 107 */
114 dht11_humidity = -1; 108 if (dht11_state == DEVPRESENT_YES) {
115 } else { 109 dhtpath = xstrcpy((char *)"/sys/bus/iio/devices/");
116 sscanf(buffer, "%d", &hum); 110 dhtpath = xstrcat(dhtpath, address);
117 syslog(LOG_NOTICE, "read hum rc=%d %f", rc, hum / 1000.0); 111 dhtpath = xstrcat(dhtpath, (char *)"/in_humidityrelative_input");
118 dht11_humidity = hum; 112
119 } 113 fd = open(dhtpath, O_RDONLY);
120 close(fd); 114 rc = read(fd, buffer, 25);
121 115 if (rc == -1) {
122 tries = 0; 116 err = errno;
123 } 117 if (err == 110) {
124 118 dht11_state = DEVPRESENT_NO;
125 dht11_valid = TRUE; 119 break;
126 syslog(LOG_NOTICE, "dht11 t:%d h:%d tries:%d", dht11_temperature, dht11_humidity, 6-tries); 120 } else {
121 dht11_state = DEVPRESENT_ERROR;
122 }
123 syslog(LOG_NOTICE, "DHT11 read temperature: %d %s", err, strerror(err));
124 dht11_humidity = -1;
125 } else {
126 sscanf(buffer, "%d", &hum);
127 syslog(LOG_NOTICE, "read hum rc=%d %f", rc, hum / 1000.0);
128 dht11_humidity = hum;
129 dht11_state = DEVPRESENT_YES;
130 }
131 close(fd);
132 free(dhtpath);
133 dhtpath = NULL;
134 }
135
136 if (dht11_state == DEVPRESENT_YES) {
137 break;
138 }
139 if (tries > 0)
140 tries--;
141 }
142
143 syslog(LOG_NOTICE, "dht11 t:%d h:%d tries:%d state:%d", dht11_temperature, dht11_humidity, 6-tries, dht11_state);
127 } 144 }
128 145
129 146
130 147
131 /* 148 /*
382 */ 399 */
383 int devices_detect(void) 400 int devices_detect(void)
384 { 401 {
385 struct dirent *de; 402 struct dirent *de;
386 DIR *fd; 403 DIR *fd;
387 int fi;
388 devices_list *device, *ndev; 404 devices_list *device, *ndev;
389 int found, subdevices, ival, i, rc = 0; 405 int found, subdevices, ival, i, rc = 0;
390 char buf[40]; 406 char buf[40];
391 uuid_t uu; 407 uuid_t uu;
392 #ifdef HAVE_WIRINGPI_H 408 #ifdef HAVE_WIRINGPI_H
409 425
410 if (found == FALSE) { 426 if (found == FALSE) {
411 strncpy(buf, de->d_name, 2); 427 strncpy(buf, de->d_name, 2);
412 buf[2] = '\0'; 428 buf[2] = '\0';
413 sscanf(buf, "%02x", &ival); 429 sscanf(buf, "%02x", &ival);
414 syslog(LOG_NOTICE, "Scan 1-wire %02x %d", ival, ival);
415 subdevices = 0; 430 subdevices = 0;
431
416 /* 432 /*
417 * ival is zero when a ghost sensor is detected. 433 * ival is zero when a ghost sensor is detected.
418 */ 434 */
419 if (ival > 0) 435 if (ival > 0)
420 subdevices = 1; 436 subdevices = 1;
421 if (strcmp(buf, (char *)"29") == 0)
422 subdevices = 8;
423 if (strcmp(buf, (char *)"3a") == 0) 437 if (strcmp(buf, (char *)"3a") == 0)
424 subdevices = 2; 438 subdevices = 2;
425 for (i = 0; i < subdevices; i++) { 439 for (i = 0; i < subdevices; i++) {
426 ndev = (devices_list *)malloc(sizeof(devices_list)); 440 ndev = (devices_list *)malloc(sizeof(devices_list));
427 ndev->next = NULL; 441 ndev->next = NULL;
433 if (strcmp(buf, (char *)"10") == 0) { 447 if (strcmp(buf, (char *)"10") == 0) {
434 ndev->direction = DEVDIR_IN_ANALOG; 448 ndev->direction = DEVDIR_IN_ANALOG;
435 ndev->description = xstrcpy((char *)"DS18S20 Digital thermometer"); 449 ndev->description = xstrcpy((char *)"DS18S20 Digital thermometer");
436 } else if (strcmp(buf, (char *)"22") == 0) { 450 } else if (strcmp(buf, (char *)"22") == 0) {
437 ndev->direction = DEVDIR_IN_ANALOG; 451 ndev->direction = DEVDIR_IN_ANALOG;
438 ndev->description = xstrcpy((char *)"DS1820 Digital thermometer"); 452 ndev->description = xstrcpy((char *)"DS1822 Digital thermometer");
439 } else if (strcmp(buf, (char *)"28") == 0) { 453 } else if (strcmp(buf, (char *)"28") == 0) {
440 ndev->direction = DEVDIR_IN_ANALOG; 454 ndev->direction = DEVDIR_IN_ANALOG;
441 ndev->description = xstrcpy((char *)"DS18B20 Digital thermometer"); 455 ndev->description = xstrcpy((char *)"DS18B20 Digital thermometer");
442 } else if (strcmp(buf, (char *)"3a") == 0) { 456 } else if (strcmp(buf, (char *)"3a") == 0) {
457 ndev->direction = DEVDIR_IN_BIN;
443 ndev->description = xstrcpy((char *)"DS2413 Dual channel addressable switch"); 458 ndev->description = xstrcpy((char *)"DS2413 Dual channel addressable switch");
444 ndev->direction = DEVDIR_IN_BIN;
445 } else if (strcmp(buf, (char *)"3b") == 0) { 459 } else if (strcmp(buf, (char *)"3b") == 0) {
446 ndev->direction = DEVDIR_IN_ANALOG; 460 ndev->direction = DEVDIR_IN_ANALOG;
447 ndev->description = xstrcpy((char *)"DS1825 Digital thermometer"); 461 ndev->description = xstrcpy((char *)"DS1825 Digital thermometer");
448 } else if (strcmp(buf, (char *)"42") == 0) { 462 } else if (strcmp(buf, (char *)"42") == 0) {
449 ndev->direction = DEVDIR_IN_ANALOG; 463 ndev->direction = DEVDIR_IN_ANALOG;
460 ndev->subdevice = i; 474 ndev->subdevice = i;
461 ndev->gpiopin = -1; 475 ndev->gpiopin = -1;
462 ndev->comment = xstrcpy((char *)"Auto detected device"); 476 ndev->comment = xstrcpy((char *)"Auto detected device");
463 ndev->timestamp = time(NULL); 477 ndev->timestamp = time(NULL);
464 478
479 syslog(LOG_NOTICE, "New W1 device %s, subdevice %d, %s", ndev->address, ndev->subdevice, ndev->description);
480
465 if (Config.devices == NULL) { 481 if (Config.devices == NULL) {
466 Config.devices = ndev; 482 Config.devices = ndev;
467 } else { 483 } else {
468 for (device = Config.devices; device; device = device->next) { 484 for (device = Config.devices; device; device = device->next) {
469 if (device->next == NULL) { 485 if (device->next == NULL) {
479 } 495 }
480 closedir(fd); 496 closedir(fd);
481 } 497 }
482 498
483 /* 499 /*
484 * DHT11 as kernel module. 500 * DHT11 as kernel module. The number after the @ is the hexadecimal
501 * number of the BCM gpio pin. Since we use pin 22 at connector pin 15
502 * the number is 16.
485 */ 503 */
486 if ((fi = open((char *)"/sys/bus/iio/devices/iio:device0/name", O_RDONLY))) { 504 char *dhtaddr = NULL;
487 char buffer[25]; 505 if ((fd = opendir((char *)"/sys/devices/platform/dht11@16"))) {
488 506 while ((de = readdir(fd))) {
489 memset(&buffer, 0, 25); 507 if (de->d_name[0] != '.') {
490 read(fi, buffer, 25); 508 if (strncmp(de->d_name, (char *)"iio", 3) == 0) {
491 close(fi); 509 dhtaddr = xstrcpy(de->d_name);
492 buffer[strlen(buffer) - 1] = '\0'; 510 }
511 }
512 }
513 closedir(fd);
514 }
515 syslog(LOG_NOTICE, "%s", dhtaddr);
516
517 if (dhtaddr) {
493 518
494 found = FALSE; 519 found = FALSE;
495 for (device = Config.devices; device; device = device->next) { 520 for (device = Config.devices; device; device = device->next) {
496 if (strcmp(device->address, buffer) == 0) { 521 if (strcmp(device->address, dhtaddr) == 0) {
497 found = TRUE; 522 found = TRUE;
498 break; 523 break;
499 } 524 }
500 } 525 }
501 526
512 ndev->description = xstrcpy((char *)"DHT11 temperature sensor"); 537 ndev->description = xstrcpy((char *)"DHT11 temperature sensor");
513 else 538 else
514 ndev->description = xstrcpy((char *)"DHT11 humidity sensor"); 539 ndev->description = xstrcpy((char *)"DHT11 humidity sensor");
515 ndev->value = ndev->offset = ndev->inuse = 0; 540 ndev->value = ndev->offset = ndev->inuse = 0;
516 ndev->present = DEVPRESENT_YES; 541 ndev->present = DEVPRESENT_YES;
517 ndev->address = xstrcpy(buffer); 542 ndev->address = xstrcpy(dhtaddr);
518 ndev->subdevice = i; 543 ndev->subdevice = i;
519 ndev->gpiopin = -1; 544 ndev->gpiopin = -1;
520 ndev->comment = xstrcpy((char *)"Auto detected device"); 545 ndev->comment = xstrcpy((char *)"Auto detected device");
521 ndev->timestamp = time(NULL); 546 ndev->timestamp = time(NULL);
547
548 syslog(LOG_NOTICE, "New DHT11 device %s, subdevice %d, %s", ndev->address, ndev->subdevice, ndev->description);
522 549
523 if (Config.devices == NULL) { 550 if (Config.devices == NULL) {
524 Config.devices = ndev; 551 Config.devices = ndev;
525 } else { 552 } else {
526 for (device = Config.devices; device; device = device->next) { 553 for (device = Config.devices; device; device = device->next) {
606 ndev->inuse = 0; 633 ndev->inuse = 0;
607 ndev->comment = xstrcpy((char *)"Raspberry GPIO"); 634 ndev->comment = xstrcpy((char *)"Raspberry GPIO");
608 } 635 }
609 pin++; 636 pin++;
610 637
638 syslog(LOG_NOTICE, "New GPIO device %s, subdevice %d, %s", ndev->address, ndev->subdevice, ndev->description);
639
611 if (Config.devices == NULL) { 640 if (Config.devices == NULL) {
612 Config.devices = ndev; 641 Config.devices = ndev;
613 } else { 642 } else {
614 for (device = Config.devices; device; device = device->next) { 643 for (device = Config.devices; device; device = device->next) {
615 if (device->next == NULL) { 644 if (device->next == NULL) {
686 case 8: ndev->direction = DEVDIR_OUT_BIN; 715 case 8: ndev->direction = DEVDIR_OUT_BIN;
687 ndev->address = xstrcpy((char *)"SimLight"); 716 ndev->address = xstrcpy((char *)"SimLight");
688 ndev->description = xstrcpy((char *)"Simulated light"); 717 ndev->description = xstrcpy((char *)"Simulated light");
689 break; 718 break;
690 } 719 }
720
721 syslog(LOG_NOTICE, "New Simulator device %s, subdevice %d, %s", ndev->address, ndev->subdevice, ndev->description);
691 722
692 if (Config.devices == NULL) { 723 if (Config.devices == NULL) {
693 Config.devices = ndev; 724 Config.devices = ndev;
694 } else { 725 } else {
695 for (device = Config.devices; device; device = device->next) { 726 for (device = Config.devices; device; device = device->next) {
894 925
895 break; 926 break;
896 927
897 case DEVTYPE_DHT: 928 case DEVTYPE_DHT:
898 /* 929 /*
899 * Make sure we don't read the sensor within 2 seconds. 930 * Don't read these to often, 2 seconds minimum delay.
900 * But we use 30 seconds interval. 931 * But we use 30 seconds interval.
901 */ 932 */
902 now = time(NULL); 933 now = time(NULL);
903 if ((int)(now - dht11_last) > 30) { 934 if ((int)(now - dht11_last) > 30) {
904 if (device->subdevice == 0) { 935 if (device->subdevice == 0) {
905 /* Read once during subdevice 0 */ 936 /* Read once during subdevice 0 */
906 dht11Read(); 937 dht11Read(device->address);
907 pthread_mutex_lock(&mutexes[LOCK_DEVICES]); 938 pthread_mutex_lock(&mutexes[LOCK_DEVICES]);
908 if (dht11_valid) { 939 device->present = dht11_state;
940 if (dht11_state == DEVPRESENT_YES) {
909 device->value = dht11_temperature; 941 device->value = dht11_temperature;
910 device->timestamp = time(NULL); 942 device->timestamp = time(NULL);
911 device->present = DEVPRESENT_YES;
912 } else {
913 device->present = DEVPRESENT_ERROR;
914 } 943 }
915 pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); 944 pthread_mutex_unlock(&mutexes[LOCK_DEVICES]);
916 } else if (device->subdevice == 1) { 945 } else if (device->subdevice == 1) {
917 /* Data already present */ 946 /* Data already present */
918 pthread_mutex_lock(&mutexes[LOCK_DEVICES]); 947 pthread_mutex_lock(&mutexes[LOCK_DEVICES]);
919 if (dht11_valid) { 948 device->present = dht11_state;
949 if (dht11_state == DEVPRESENT_YES) {
920 device->value = dht11_humidity; 950 device->value = dht11_humidity;
921 device->timestamp = time(NULL); 951 device->timestamp = time(NULL);
922 device->present = DEVPRESENT_YES;
923 } else {
924 device->present = DEVPRESENT_ERROR;
925 } 952 }
926 pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); 953 pthread_mutex_unlock(&mutexes[LOCK_DEVICES]);
927 dht11_last = now; /* Okay for a new reading. */ 954 dht11_last = now; /* Okay for a new reading. */
928 } 955 }
929 } 956 }

mercurial