From b9575f8b6e289867a9fa551872579c7117a18688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Balzarotti?= Date: Tue, 21 Feb 2023 13:58:12 +0100 Subject: [PATCH] do not crash when SHT sensor library is missing --- sensors.py | 78 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/sensors.py b/sensors.py index d567ce9..4ca3293 100644 --- a/sensors.py +++ b/sensors.py @@ -4,12 +4,21 @@ from collections import deque import re from os.path import exists -import RPi.GPIO as GPIO -GPIO.setmode(GPIO.BCM) +try: + import RPi.GPIO as GPIO + GPIO.setmode(GPIO.BCM) + rpi = True +except: + rpi = False -# SHT40 -import board -import adafruit_sht4x +try: + # SHT40 + import board + import adafruit_sht4x + enable_sht = True +except: + print("Adafruit SHT4X not available!") + enable_sht = False # TODO client: add a way to disable live plotting? server: stop # sending data periodically to everybody! @@ -39,7 +48,8 @@ class GPIOState(Sensor): try: self.value = GPIO.input(self.pin) except: - self.value = None + print(f"Could not read pin {self.pin}") + self.value = 0 self.time = perf_counter() return (self.time, self.transform(self.value)) @@ -67,27 +77,53 @@ class Temperature1W(Sensor): return (time, None) return (time, int(re.search("t=([0-9]+)", content[1]).group(1)) / 1000.0) +if enable_sht: + i2c = board.I2C() # uses board.SCL and board.SDA + sht = adafruit_sht4x.SHT4x(i2c) + print('Serial: ', hex(sht.serial_number)) + SHT40_DEFAULT = adafruit_sht4x.Mode.NOHEAT_HIGHPRECISION + sht.mode = SHT40_DEFAULT + class SHT40(Sensor): - def __init__(self, what): + def __init__(self, what, every=60): + if what not in ("Temperature", "Humidity"): + print("ERROR: invalid sensor value: ", what) + return self.measure = what - self.i2c = board.I2C() # uses board.SCL and board.SDA - self.sht = adafruit_sht4x.SHT4x(i2c) - print('Serial: ', hex(self.sht.serial_number)) - # FIXME: - self.sht.mode = adafruit_sht4x.Mode.NOHEAT_HIGHPRECISION + if not enable_sht: + return + self.heat_every = every + if self.measure != "Temperature": + self.last_heat = perf_counter() + self.heatmode = adafruit_sht4x.Mode.HIGHHEAT_1S + self.standardmode = SHT40_DEFAULT + # mode: adafruit_sht4x.Mode.string[sht.mode] # Can also set the mode to enable heater # sht.mode = adafruit_sht4x.Mode.LOWHEAT_100MS # modes = [adafruit_sht4x.Mode.HIGHHEAT_1S, # adafruit_sht4x.Mode.LOWHEAT_100MS, # adafruit_sht4x.Mode.NOHEAT_HIGHPRECISION] + def is_temperature(self): + return self.measure == "Temperature" + + def is_humidity(self): + return self.measure == "Humidity" + + def reset_mode(self): + sht.mode = self.standardmode def read(self): time = perf_counter() + reset = False + if self.is_humidity(): + timediff = time - self.last_heat + if timediff > self.heat_every: + reset = True + sht.mode = self.heatmode temperature, relative_humidity = sht.measurements - # print("Temperature: %0.1f C" % temperature) - # print("Humidity: %0.1f %%" % (relative_humidity)) - # print("") - return (time, temerature if self.measure == 'Temperature' else relative_humidityg) + if reset: + self.reset_mode() + return (time, temperature if self.measure == 'Temperature' else relative_humidity) class Sensors(): def __init__(self, history=2621440): @@ -102,6 +138,9 @@ class Sensors(): "Scan for new sensors" def scan(self): + # Read something like this from a stored prefs json + # sensors_names_map = {} + # Then, scan, apply existing names and use placholders for new sensors # FIXME: should scan, apply stored data and return this self.available_sensors = { 'T_food': Temperature1W('28-06214252b671'), @@ -123,8 +162,11 @@ class Sensors(): def read(self): for sensor in self.available_sensors.keys(): - time, value = self.available_sensors[sensor].read() - self.values[sensor] = (str(self.perf_datetime(time)), value) + try: + time, value = self.available_sensors[sensor].read() + self.values[sensor] = (str(self.perf_datetime(time)), value) + except Exception as e: + print("Error reading sensors", sensor, ": ", e) self.history.append(self.value_tuple()) def get_sensor_value(self, sensor_name):