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 /* |
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; |
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) { |
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 } |