update
This commit is contained in:
parent
5242eeabb2
commit
b8549ac286
@ -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]
|
||||||
|
240
code/main.py
240
code/main.py
@ -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()
|
||||||
|
@ -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 = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user