Source code for juham.web.homewizardwatermeter

import json
from typing import Any, Dict, Optional, cast, 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.web.rcloud import RCloud, RCloudThread


class HomeWizardThread(RCloudThread):
    """Thread that reads HomeWizard's water meter sensor."""

    def __init__(self, client: Optional[JMqtt] = None) -> None:
        """Construct HomeWizard water meter acquisition thread.

        Args:
            topic (str, optional): MQTT topic to post the sensor readings. Defaults to None.
            interval (float, optional): Interval specifying how often the sensor is read. Defaults to 60 seconds.
            url (str, optional): url for reading watermeter. Defaults to None.
        """
        super().__init__(client)

    def init(self, topic: str = "", url: str = "", interval: float = 60) -> None:
        """Initialize thread for reading HomeWizard sensor and publishing
        the readings to Mqtt network.

        Args:
            topic (str, optional): Mqtt topic to publish the readings
            url (str, optional): HomeWizard url for reading sensor data.
            interval (float, optional): Update interval. Defaults to 60.
        """
        self._sensor_topic = topic
        self._interval = interval
        self._device_url = url

    @override
    def make_weburl(self) -> str:
        return self._device_url

    @override
    def update_interval(self) -> float:
        return self._interval

    @override
    def process_data(self, data: Any) -> None:
        super().process_data(data)
        data = data.json()
        msg = json.dumps(data)
        self.publish(self._sensor_topic, msg, qos=1, retain=False)


[docs] class HomeWizardWaterMeter(RCloud): """Homewizard watermeter sensor.""" workerThreadId = HomeWizardThread.get_class_id() url = "http://192.168.86.70/api/v1/data" update_interval = 60 def __init__( self, name: str = "homewizardwatermeter", topic: str = "", url: str = "", interval: float = 60.0, ) -> None: """Create Homewizard water meter sensor. Args: name (str, optional): name identifying the sensor. Defaults to 'homewizardwatermeter'. topic (str, optional): Juham topic to publish water consumption readings. Defaults to None. url (str, optional): Homewizard url from which to acquire water consumption readings. Defaults to None. interval (float, optional): Frequency at which the watermeter is read. Defaults to None. """ super().__init__(name) self.active_liter_lpm: float = -1 self.update_ts: float = 0.0 if topic != "": self.topic = topic if url != "": self.url = url if interval > 0.0: self.interval = interval self.sensor_topic = self.make_topic_name("watermeter")
[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.sensor_topic)
[docs] @override def on_message(self, client: object, userdata: Any, msg: MqttMsg) -> None: if msg.topic == self.sensor_topic: em = json.loads(msg.payload.decode()) self.on_sensor(em) else: super().on_message(client, userdata, msg)
[docs] def on_sensor(self, em: dict[str, Any]) -> None: """Handle data coming from the watermeter sensor. Writes the sensor telemetry to time series. Args: em (dict): data from the sensor """ active_liter_lpm = float(em["active_liter_lpm"]) total_liter_m3 = float(em["total_liter_m3"]) ts = timestamp() if (active_liter_lpm != self.active_liter_lpm) or (ts > self.update_ts + 60.0): point = ( Point("watermeter") .tag("sensor", "0") .field("total_liter", total_liter_m3) .field("active_lpm", active_liter_lpm) .time(epoc2utc(timestamp())) ) self.write(point) self.info("Water consumption " + str(total_liter_m3)) self.update_ts = ts self.active_liter_lpm = active_liter_lpm
[docs] @override def run(self) -> None: self.worker = cast( HomeWizardThread, Base.instantiate(HomeWizardWaterMeter.workerThreadId) ) self.worker.init(self.sensor_topic, self.url, self.update_interval) super().run()
[docs] @override def to_dict(self) -> Dict[str, Any]: data: Dict[str, Any] = super().to_dict() data["_homewizardwatermeter"] = { "topic": self.sensor_topic, "url": self.url, "interval": self.update_interval, } return data
[docs] @override def from_dict(self, data: Dict[str, Any]) -> None: super().from_dict(data) if "_homewizardwatermeter" in data: for key, value in data["_homewizardwatermeter"].items(): setattr(self, key, value)