diff --git a/code/lib/homie/device.py b/code/lib/homie/device.py index 869dff6..1879edb 100644 --- a/code/lib/homie/device.py +++ b/code/lib/homie/device.py @@ -69,6 +69,7 @@ class HomieDevice: self._extensions = getattr(settings, "EXTENSIONS", []) self._bc_enabled = getattr(settings, "BROADCAST", False) self._wifi = getattr(settings, "WIFI_CREDENTIALS", False) + self._wifi_rescan_delay = getattr(settings, "WIFI_RESCAN_DELAY", MAIN_DELAY) self.first_start = True self.stats_interval = getattr(settings, "DEVICE_STATS_INTERVAL", 60) @@ -326,7 +327,7 @@ class HomieDevice: wifi_cfg = get_wifi_credentials(self._wifi) if wifi_cfg is None: self.dprint("No WiFi found. Rescanning...") - await sleep_ms(MAIN_DELAY) + await sleep_ms(self._wifi_rescan_delay) else: self.dprint("Connect to SSID: {}".format(wifi_cfg[0])) self.mqtt._ssid = wifi_cfg[0] diff --git a/code/main.py b/code/main.py index d2aa373..a2ec824 100644 --- a/code/main.py +++ b/code/main.py @@ -1,217 +1,49 @@ -from waterlevel_sensor import WaterLevelSensor -import bme280 -import sh1106 -from homie.constants import BOOLEAN, FALSE, TRUE, FLOAT -from homie.property import HomieProperty -from homie.node import HomieNode -from homie.device import HomieDevice, await_ready_state -from machine import Pin, ADC, I2C +from homie.device import HomieDevice +from machine import Pin, I2C import settings -import uasyncio as asyncio -from time import ticks_ms, ticks_add, ticks_diff +# import uasyncio as asyncio +# from time import ticks_ms, ticks_add, ticks_diff -import gc - -class PlantNode(HomieNode): - - def __init__( - self, - name="Planze", - pin_watering=Pin(13, Pin.OUT, value=0), - pin_moisture=Pin(34), - pin_water_tank=Pin(23), - i2c=I2C(scl=Pin(18), sda=Pin(19)), - interval=60*5, - interval_watering=0.1): - super().__init__(id="plant", name=name, type="watering") - self.i2c = i2c - self.display = sh1106.SH1106_I2C( - i2c=i2c, width=128, height=64) - - # Update Interval - self.interval = interval - self.interval_watering = interval_watering - self.interval_changed = False - self.property_interval = HomieProperty( - id="update_interval", - name="Aktualisierungsrate", - datatype=FLOAT, # TODO ISO8601 - settable=True, - on_message=self._set_interval, - unit="s", - ) - self.add_property(self.property_interval) - - # WaterLevelSensor - self.waterlevel_sensor = WaterLevelSensor() - self.property_waterlevel = HomieProperty( - id="waterlevel", - name="Wassertankstand", - datatype=FLOAT, - unit="L", - ) - self.add_property(self.property_waterlevel) - self.property_waterlevel_percent = HomieProperty( - id="waterlevel_percent", - name="Wassertankstand [%]", - datatype=FLOAT, - format="0.00:100.00", - unit="%", - ) - self.add_property(self.property_waterlevel_percent) - # self.property_waterlevel_max_value = HomieProperty( - # id="waterlevel_max", - # name="Wassertankstandsensor Max-Wert", - # settable=True, - # datatype=FLOAT, - # default=1, - # unit="#", - # on_message=self._set_waterlevel_max_value - # ) - # self.add_property(self.property_waterlevel_max_value) - # self.property_waterlevel_min_value = HomieProperty( - # id="waterlevel_min", - # name="Wassertankstandsensor Min-Wert", - # settable=True, - # datatype=FLOAT, - # default=0, - # unit="#", - # on_message=self._set_waterlevel_min_value - # ) - # self.add_property(self.property_waterlevel_min_value) - self.property_waterlevel_volume_liter = HomieProperty( - id="waterlevel_volume_max", - name="Wassertankgröße", - settable=True, - datatype=FLOAT, - unit="L", - on_message=self._set_waterlevel_volume - ) - self.add_property(self.property_waterlevel_volume_liter) - - # Moisture - self.adc = ADC(pin_moisture) - self.adc.atten(ADC.ATTN_11DB) - self.property_moisture = HomieProperty( - id="moisture", - name="Feuchte", - datatype=FLOAT, - format="0.00:100.00", - unit="%", - ) - self.add_property(self.property_moisture) - - # BMP280 - self.bmp280 = bme280.BME280(i2c=self.i2c) - self.property_temerature = HomieProperty( - id="temperature", - name="Temperatur", - datatype=FLOAT, - unit="°C", - ) - self.add_property(self.property_temerature) - self.property_pressure = HomieProperty( - id="pressure", - name="Druck", - datatype=FLOAT, - unit="Pa", - ) - self.add_property(self.property_pressure) - - # Watering Motor - self.pin_watering_motor = pin_watering - self.pin_watering_motor.init(mode=Pin.OUT, value=0) - self.property_water_power = HomieProperty( - id="power", - name="Bewässerung", - settable=True, - datatype=BOOLEAN, - default=FALSE, - on_message=self.toggle_motor, - ) - self.add_property(self.property_water_power) - - self.property_watering_max_duration = HomieProperty( - id="watering_duration_max", - name="Bewässerungszeit", - settable=True, - datatype=FLOAT, - default=3, - unit="s", - ) - self.add_property(self.property_watering_max_duration) - - asyncio.create_task(self.update_data()) - - @await_ready_state - async def update_data(self): - while True: - self.property_moisture.value = "{:1.2f}".format( - (4096 - self.adc.read()) / 40.96) - - self.property_waterlevel_percent.value = "{:1.0f}".format( - self.waterlevel_sensor.level_percent) - self.property_waterlevel.value = "{:1.2f}".format( - self.waterlevel_sensor.level) - self.property_waterlevel_volume_liter.value = "{:1.4f}".format( - self.waterlevel_sensor.volume) - - self.property_pressure.value = "{:1.0f}".format( - self.bmp280.pressure * 100) # hPa = 100 Pa - self.property_temerature.value = "{:1.2f}".format( - self.bmp280.temperature) - - # TODO ISO8601 self.property_interval.value = "PT{:1.3f}S".format(self.interval) - self.property_interval.value = "{:1.3f}".format(self.interval) - - # We don't simply wait the update interval, as it can change while waiting. - last_update = ticks_ms() - wait_till = ticks_add(last_update, int(self.interval * 1000.0)) - while ticks_diff(ticks_ms(), wait_till) < 0: - watering = self.pin_watering_motor.value() == 1 - if watering or self.interval_changed: - self.interval_changed = False - wait_till = ticks_add( - last_update, - int(self.interval if not watering else self.interval_watering) * 1000) - sleep_for = min(int(self.interval_watering * 1000.0), - ticks_diff(wait_till, ticks_ms())) - await asyncio.sleep_ms(sleep_for) - - def toggle_motor(self, topic, payload, retained): - ONOFF = {FALSE: 0, TRUE: 1} - v = ONOFF[payload] - self.pin_watering_motor(v) - if v == 1: - asyncio.create_task(self.stop_motor()) - - def stop_motor(self): - await asyncio.sleep_ms( - int(float(self.property_watering_max_duration.value) * 1000)) - self.pin_watering_motor.value(0) - self.property_water_power.value = FALSE - - def _set_waterlevel_min_value(self, topic, payload, retained): - self.waterlevel_sensor.value_min = float(payload) - - def _set_waterlevel_max_value(self, topic, payload, retained): - self.waterlevel_sensor.value_max = float(payload) - - def _set_waterlevel_volume(self, topic, payload, retained): - self.waterlevel_sensor.volume = float(payload) - - def _set_interval(self, topic, payload, retained): - self.interval = float(payload) - self.interval_changed = True +from plant_node import PlantNode +from bmp280_node import BMP280Node +from plant_box_control_panel import PlantBoxControlPanel +from waterlevel_sensor import WaterLevelSensor +import bme280 def main(): global plantNode + i2c = I2C(scl=Pin(18), sda=Pin(19)) + + wls = WaterLevelSensor( + power_pin=Pin(26), + adc_pin=Pin(35),) + bmp280 = bme280.BME280(i2c=i2c) + + plantNode = PlantNode( + id="pflanze1", + name="Planze", + pin_watering=Pin(13, Pin.OUT, value=0), + pin_moisture=Pin(34), + pin_water_tank=Pin(23), + waterlevel_sensor=wls) + + bmp280Node = BMP280Node( + id="bmp280", + name="Enviroment-Sensor", + bmp280=bmp280) + + controlNode = PlantBoxControlPanel( + id="control", name="Benutzeroberfläche", + i2c=i2c, waterlevel_sensor=wls, bmp280=bmp280, + pin_clk=Pin(15), pin_dt=Pin(16), pin_sw=Pin(17)) + # Homie device setup - plantNode = PlantNode() homie = HomieDevice(settings) homie.add_node(plantNode) + homie.add_node(bmp280Node) + homie.add_node(controlNode) # run forever homie.run_forever() diff --git a/code/settings.py b/code/settings.py index 06ba2c6..e4892b7 100644 --- a/code/settings.py +++ b/code/settings.py @@ -18,8 +18,9 @@ with open("wifi-credentials", 'r') as f: WIFI_CREDENTIALS[lines[i].replace("\n", "")] = lines[i+1].replace("\n", "") WIFI_SSID, WIFI_PASSWORD = list(WIFI_CREDENTIALS.items())[0] -# WIFI_CREDENTIALS = None -# print(WIFI_CREDENTIALS) + +# The delay until wifi is rescanned to keep UI somewhat responsive +WIFI_RESCAN_DELAY = 10000 ### # MQTT settings @@ -65,15 +66,15 @@ DEVICE_ID = "pflanzen-geraet1" # get_unique_id() DEVICE_NAME = "Pflanzen Gießer" # Time in seconds the device updates device properties -DEVICE_STATS_INTERVAL = 60 +DEVICE_STATS_INTERVAL = 600 # Subscribe to broadcast topic is enabled by default. To disable broadcast # messages set BROADCAST to False # BROADCAST = True # Enable build-in extensions -from homie.constants import EXT_MPY -EXTENSIONS = [EXT_MPY] +from homie.constants import EXT_MPY, EXT_STATS +EXTENSIONS = [EXT_MPY, EXT_STATS] # from homie.constants import EXT_MPY, EXT_FW, EXT_STATS # EXTENSIONS = [