Source code for juham_shelly.shellydht22

import json
from typing import Any, Dict
from typing_extensions import override

from masterpiece.mqtt import MqttMsg
from juham_core.timeutils import epoc2utc, timestamp
from .shelly import Shelly


[docs] class ShellyDHT22(Shelly): """Shelly Plus add-on with DHT22 humidity, temperature sensor. Listens MQTT messages from dht22 (am2302) humidity sensor attached to Shelly add-on module and writes them to time series database. """ _DHT22: str = "_dht22" shelly_topic = "/events/rpc" # source topic def __init__(self, name: str, mqtt_prefix: str) -> None: super().__init__(name, mqtt_prefix) self.relay_started: float = 0 self.temperature_topic = self.make_topic_name("temperature/") # target topic self.humidity_topic = self.make_topic_name("humidity/") # target topic
[docs] @override def on_connect(self, client: object, userdata: Any, flags: int, rc: int) -> None: super().on_connect(client, userdata, flags, rc) if rc == 0: self.subscribe(self.mqtt_prefix + self.shelly_topic)
[docs] @override def on_message(self, client: object, userdata: Any, msg: MqttMsg) -> None: # optimize out excessive notifications tsnow = timestamp() self.relay_started = tsnow m = json.loads(msg.payload.decode()) mth = m["method"] if mth == "NotifyStatus": params = m["params"] self.on_sensor(params) else: self.warning("Unknown method " + mth, str(m))
[docs] def on_sensor(self, params: dict[str, Any]) -> None: """Map Shelly Plus 1GM specific event to juham format and post it to temperature topic. Args: params (dict): message from Shelly Plus 1 wifi relay """ ts = params["ts"] for key, value in params.items(): if key.startswith("humidity:"): self.on_value(ts, key, value, "humidity", "rh") elif key.startswith("temperature:"): self.on_value(ts, key, value, "temperature", "tC") else: # self.warning( # f"Unknown msg {self.name} {self.mqtt_prefix}: {key}", value # ) pass
[docs] def on_value( self, ts: float, key: str, value: dict[str, Any], attr: str, unit: str ) -> None: sensor_id = key.split(":")[1] humidity = value[unit] msg = { "sensor": sensor_id, "timestamp": ts, attr: float(humidity), } self.publish(self.humidity_topic + sensor_id, json.dumps(msg), 1, True) # self.debug( # f"Sensor reading {self.humidity_topic}{sensor_id} {attr} = {humidity}" # ) try: point = ( self.measurement(self.name) .tag("sensor", sensor_id) .field(attr, humidity) .time(epoc2utc(ts)) ) self.write(point) except Exception as e: self.error(f"Writing to influx failed {str(e)}")
[docs] @override def to_dict(self) -> Dict[str, Any]: data: Dict[str, Any] = super().to_dict() data[self._DHT22] = { "shelly_topic": self.shelly_topic, "temperature_topic": self.temperature_topic, } return data
[docs] @override def from_dict(self, data: Dict[str, Any]) -> None: super().from_dict(data) if self._DHT22 in data: for key, value in data[self._DHT22].items(): setattr(self, key, value)