This commit is contained in:
Nils Schulte 2021-01-17 22:41:25 +01:00
parent 5242eeabb2
commit b8549ac286
3 changed files with 44 additions and 210 deletions

View File

@ -69,6 +69,7 @@ class HomieDevice:
self._extensions = getattr(settings, "EXTENSIONS", []) self._extensions = getattr(settings, "EXTENSIONS", [])
self._bc_enabled = getattr(settings, "BROADCAST", False) self._bc_enabled = getattr(settings, "BROADCAST", False)
self._wifi = getattr(settings, "WIFI_CREDENTIALS", False) self._wifi = getattr(settings, "WIFI_CREDENTIALS", False)
self._wifi_rescan_delay = getattr(settings, "WIFI_RESCAN_DELAY", MAIN_DELAY)
self.first_start = True self.first_start = True
self.stats_interval = getattr(settings, "DEVICE_STATS_INTERVAL", 60) self.stats_interval = getattr(settings, "DEVICE_STATS_INTERVAL", 60)
@ -326,7 +327,7 @@ class HomieDevice:
wifi_cfg = get_wifi_credentials(self._wifi) wifi_cfg = get_wifi_credentials(self._wifi)
if wifi_cfg is None: if wifi_cfg is None:
self.dprint("No WiFi found. Rescanning...") self.dprint("No WiFi found. Rescanning...")
await sleep_ms(MAIN_DELAY) await sleep_ms(self._wifi_rescan_delay)
else: else:
self.dprint("Connect to SSID: {}".format(wifi_cfg[0])) self.dprint("Connect to SSID: {}".format(wifi_cfg[0]))
self.mqtt._ssid = wifi_cfg[0] self.mqtt._ssid = wifi_cfg[0]

View File

@ -1,217 +1,49 @@
from waterlevel_sensor import WaterLevelSensor from homie.device import HomieDevice
import bme280 from machine import Pin, I2C
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
import settings import settings
import uasyncio as asyncio # import uasyncio as asyncio
from time import ticks_ms, ticks_add, ticks_diff # from time import ticks_ms, ticks_add, ticks_diff
import gc from plant_node import PlantNode
from bmp280_node import BMP280Node
class PlantNode(HomieNode): from plant_box_control_panel import PlantBoxControlPanel
from waterlevel_sensor import WaterLevelSensor
def __init__( import bme280
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
def main(): def main():
global plantNode 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 # Homie device setup
plantNode = PlantNode()
homie = HomieDevice(settings) homie = HomieDevice(settings)
homie.add_node(plantNode) homie.add_node(plantNode)
homie.add_node(bmp280Node)
homie.add_node(controlNode)
# run forever # run forever
homie.run_forever() homie.run_forever()

View File

@ -18,8 +18,9 @@ with open("wifi-credentials", 'r') as f:
WIFI_CREDENTIALS[lines[i].replace("\n", "")] = lines[i+1].replace("\n", "") WIFI_CREDENTIALS[lines[i].replace("\n", "")] = lines[i+1].replace("\n", "")
WIFI_SSID, WIFI_PASSWORD = list(WIFI_CREDENTIALS.items())[0] 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 # MQTT settings
@ -65,15 +66,15 @@ DEVICE_ID = "pflanzen-geraet1" # get_unique_id()
DEVICE_NAME = "Pflanzen Gießer" DEVICE_NAME = "Pflanzen Gießer"
# Time in seconds the device updates device properties # 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 # Subscribe to broadcast topic is enabled by default. To disable broadcast
# messages set BROADCAST to False # messages set BROADCAST to False
# BROADCAST = True # BROADCAST = True
# Enable build-in extensions # Enable build-in extensions
from homie.constants import EXT_MPY from homie.constants import EXT_MPY, EXT_STATS
EXTENSIONS = [EXT_MPY] EXTENSIONS = [EXT_MPY, EXT_STATS]
# from homie.constants import EXT_MPY, EXT_FW, EXT_STATS # from homie.constants import EXT_MPY, EXT_FW, EXT_STATS
# EXTENSIONS = [ # EXTENSIONS = [