Source code for juham.shelly.shellyplus1

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

from juham.base import Base
from juham.base import JMqtt, MqttMsg
from juham.base.time import epoc2utc, timestamp
from juham.shelly.jshelly import JShelly


[docs] class ShellyPlus1(JShelly): """Shelly Plus 1 smart relay time series record. Listens MQTT messages from DS18B20 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 = "shellyplus1-a0a3b3c309c4") -> None: super().__init__(name) self.relay_started: float = 0 self.temperature_topic = self.make_topic_name("temperature/") # 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: 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 1 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("temperature:"): sensor_id = key.split(":")[1] temperature_reading = value # temperature_id = temperature_reading["id"] temperature_celsius = temperature_reading["tC"] msg = { "sensor": sensor_id, "timestamp": ts, "temperature": int(temperature_celsius), } self.publish( self.temperature_topic + sensor_id, json.dumps(msg), 1, True ) self.debug( f"Temperature reading { self.temperature_topic + sensor_id} published" ) try: point = ( Point("boiler") .tag("sensor", sensor_id) .field("s" + sensor_id, temperature_celsius) .time(epoc2utc(ts)) ) self.write(point) self.debug( f"Temperature { str(sensor_id)} { str(temperature_celsius)} recorded", "", ) 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["_shellyplus1"] = { "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 "_shellyplus1" in data: for key, value in data["_shellyplus1"].items(): setattr(self, key, value)