Ankündigung

Einklappen
Keine Ankündigung bisher.

ESPHome Sensor / Wasserzähler / SSE Stream Plugin

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    ESPHome Sensor / Wasserzähler / SSE Stream Plugin

    Hallo zusammen,

    ich habe mir in der Bucht einen Sensor für meinen Wasserzähler gekauft "Komplettsystem Reed-Kontakt ESPHome für Wasserzähler wie ZENNER MNK", welcher über WLAN auf einer Webseite (SSE Streaming) den Zählerstand für ESPHome zur Verfügung stellt. (soll keine Werbung sein, bin nicht beteiligt ;-) )
    Hierfür habe ich - zugegeben, mit Unterstützung von Copilot - ein Plugin für SmartHomeNG erstellt.

    Ich stelle das hier mal ein. Evtl. kann jemand damit was anfangen. Ich habe nichts anderes gefunden. Vielleicht gibt es auch elegantere Lösungen, aber es funktioniert.
    Wenn nicht, einfach ignorieren .

    /plugins/esphome_sse/__init__.py:
    Code:
    import threading
    import requests
    import json
    import time
    
    from lib.model.smartplugin import SmartPlugin
    
    
    class ESPHomeSSE(SmartPlugin):
        PLUGIN_VERSION = "1.1.0"
    
        def __init__(self, sh, *args, **kwargs):
            super().__init__()
            self._sh = sh
    
            self._host = self.get_parameter_value('host')
            self._port = self.get_parameter_value('port')
            self._events_path = self.get_parameter_value('events_path')
    
            self._base_url = f"http://{self._host}:{self._port}{self._events_path}"
    
            self.logger.info(f"ESPHomeSSE Plugin initialisiert, URL: {self._base_url}")
    
            self._items_by_id = {}
            self._alive = False
            self._thread = None
    
        def run(self):
            self._alive = True
            self._thread = threading.Thread(target=self._sse_loop, name="ESPHomeSSE", daemon=True)
            self._thread.start()
            self.logger.info("ESPHomeSSE Plugin gestartet")
    
        def stop(self):
            self._alive = False
            self.logger.info("ESPHomeSSE Plugin gestoppt")
    
        def parse_item(self, item):
            esphome_id = item.conf.get('esphome_id')
            if esphome_id:
                self.logger.info(f"Item {item.id()} mit esphome_id={esphome_id} registriert")
                self._items_by_id[esphome_id] = item
            return None
    
        def _sse_loop(self):
            self.logger.warning("ESPHome SSE Thread gestartet")
    
            while self._alive:
                try:
                    self.logger.debug(f"Verbinde zu {self._base_url}")
                    with requests.get(
                        self._base_url,
                        headers={"Accept": "text/event-stream"},
                        stream=True,
                        timeout=60
                    ) as r:
    
                        if r.status_code != 200:
                            self.logger.warning(f"SSE HTTP Status {r.status_code}, warte 5s")
                            time.sleep(5)
                            continue
    
                        current_event = None
    
                        for raw_line in r.iter_lines(decode_unicode=True):
                            if not self._alive:
                                break
    
                            if not raw_line:
                                continue
    
                            # Beispiel:
                            # event: state
                            if raw_line.startswith("event:"):
                                current_event = raw_line.split(":", 1)[1].strip()
                                continue
    
                            # Beispiel:
                            # data: {"id":"sensor-water", ...}
                            if raw_line.startswith("data:"):
                                data_str = raw_line[5:].strip()
    
                                # leere data-Zeilen ignorieren
                                if not data_str:
                                    continue
    
                                # Nur "state"-Events verarbeiten
                                if current_event != "state":
                                    continue
    
                                try:
                                    payload = json.loads(data_str)
                                except Exception as e:
                                    self.logger.warning(f"Konnte JSON nicht parsen: {data_str} ({e})")
                                    continue
    
                                sensor_id = payload.get("id")
                                value = payload.get("value")
    
                                if sensor_id in self._items_by_id:
                                    item = self._items_by_id[sensor_id]
    
                                    try:
                                        fvalue = float(value)
                                    except Exception:
                                        self.logger.warning(f"Value nicht float-konvertierbar: {value}")
                                        continue
    
                                    item(fvalue, self.get_shortname())
                                    self.logger.info(f"Item {item.id()} von {sensor_id} aktualisiert: {fvalue}")
    
                except Exception as e:
                    self.logger.warning(f"SSE Fehler: {e}, neuer Versuch in 5s")
                    time.sleep(5)
    /plugins/esphome_sse/plugin.yaml:
    Code:
    plugin:
      plugin_name: esphome_sse
      class_name: ESPHomeSSE
      description: "ESPHome SSE Plugin fuer Wasserzaehler"
      author: "ooUrmeloo"
      version: "1.0"
      sh_minversion: "1.9"
      multi_instance: False
    
    parameters:
      host:
        type: str
        description: "IP oder Hostname des ESPHome Geraets"
        default: "192.168.178.167"
    
      port:
        type: int
        description: "Port des ESPHome HTTP Servers"
        default: 80
    
      events_path:
        type: str
        description: "Pfad fuer SSE Events"
        default: "/events"
    
    item_attributes:
      esphome_id:
        type: str
        description: "ID des ESPHome Sensors (z.B. sensor-water)"
    
    ​
    Eintrag /etc/plugin.yaml:
    Code:
    esphome_sse:
        plugin_name: esphome_sse
        class_name: ESPHomeSSE
        plugin_enabled: true
        host: 192.168.xxx.xxx
        port: 80
        events_path: /events
    item:
    Code:
    wasserzaehler:
        zaehler:
            type: num
            esphome_id: sensor-water
    
    ​

    #2
    Ich hatte auch mal angefangen ein (generelles) Plugin für ESPHome zu schreiben. Ich habe dann aber die Abkürzung genommen. Ich habe das Device konfiguriert, um das MQTT Protokoll zu nutzen und habe die entsprechenden Items von SmartHomeNG für MQTT konfiguriert.
    Viele Grüße
    Martin

    There is no cloud. It's only someone else's computer.

    Kommentar


      #3
      Zitat von Msinn Beitrag anzeigen
      Ich hatte auch mal angefangen ein (generelles) Plugin für ESPHome zu schreiben. Ich habe dann aber die Abkürzung genommen. Ich habe das Device konfiguriert, um das MQTT Protokoll zu nutzen und habe die entsprechenden Items von SmartHomeNG für MQTT konfiguriert.
      Das ging bei mir leider nicht (oder ich wusste nicht, wie), weil ich keinen direkten Zugriff auf die Software / Firmware des Zählers habe - Zukaufteil, komplett "eingepackt".

      Kommentar

      Lädt...
      X