juham_shelly.shellymotion — juham-shelly documentation

# Source code for juham_shelly.shellymotion

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

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

    class ShellyMotion(Shelly):
        """Shelly Motion 2 - a wifi motion sensor with light and temperature metering."""

        shelly_topic = "shellies/shellymotion2/info"  # source topic

        def __init__(self, name: str = "shellymotion") -> None:
            super().__init__(name)
            self.motion_topic = self.make_topic_name("motion")

        @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.shelly_topic)

        @override
        def on_message(self, client: object, userdata: Any, msg: MqttMsg) -> None:
            if msg.topic == self.shelly_topic:
                m = json.loads(msg.payload.decode())
                self.on_sensor(m)
            else:
                super().on_message(client, userdata, msg)

        def on_sensor(self, m: dict[str, Any]) -> None:
            """Handle motion sensor event. This method reads the incoming event,
            translates it, and publishes it to the Juham topic. It also writes the
            attributes to the time series database.

            Args:
                m (dict): MQTT event from Shelly motion sensor
            """

            tmp = m["tmp"]
            sensor_id = self.name
            roomtemperature = tmp["value"]
            sensor = m["sensor"]
            vibration = sensor["vibration"]
            motion = sensor["motion"]
            timestamp = m["unixtime"]

            msg = {
                "sensor": sensor_id,
                "ts": timestamp,
                "temperature": int(roomtemperature),
                "motion": motion,
                "vibration": vibration,
            }
            point = (
                self.measurement("motion")
                .tag("sensor", sensor_id)
                .field("motion", motion)
                .field("vibration", vibration)
                .field("roomtemp", roomtemperature)
                .field("timestamp", int(timestamp))
                .time(epoc2utc(timestamp))
            )
            if "illuminance" in sensor:
                msg["illumination"] = sensor["illuminance"]
                point.field("illumination", sensor["illuminance"])

            self.publish(self.motion_topic, json.dumps(msg), 1, True)
            self.write(point)

        @override
        def to_dict(self) -> Dict[str, Any]:
            data: Dict[str, Any] = super().to_dict()
            data["_shellymotion"] = {
                "shelly_topic": self.shelly_topic,
                "motion_topic": self.motion_topic,
            }
            return data

        @override
        def from_dict(self, data: Dict[str, Any]) -> None:
            super().from_dict(data)
            if "_shellymotion" in data:
                for key, value in data["_shellymotion"].items():
                    setattr(self, key, value)