Source code for juham.shelly.shelly1g3

import json
from typing import Any, Dict
from typing_extensions import override
from influxdb_client_3 import Point
from juham.base import Base, MqttMsg
from juham.base.time import epoc2utc, timestamp
from juham.shelly.jshelly import JShelly


[docs] class Shelly1G3(JShelly): """Shelly Plus 1 smart relay time series record. Listens MQTT messages from dht22 (am2302) temperature sensors attached to Shelly 1 PM Add on module and writes them to time series database. """ shelly_topic = "/events/rpc" # source topic def __init__(self, name: str = "shelly1g3-humidity") -> None: super().__init__(name) 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 """ self.info(f"on_sensor() event {params}") 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")
[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.info( f"Humidity reading { self.humidity_topic + sensor_id} {humidity} published" ) try: point = ( Point("ylakerta_humidity") .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["_shelly1g3"] = { "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 "_shelly1g3" in data: for key, value in data["_shelly1g3"].items(): setattr(self, key, value)