Gas meter reading with a USB direct connection

Einen Gaszähler per Reedkontakt in Homeassistant per USB einbinden

Vorwort :
This is how i solved the problem. You might find more clever ways or solutions that fit better to what you need. Consider this as a inspiration. Full english translation might follow if i find the time.

Aufgabenstellung :

  • Einen reed-relais Lesekopf für einen Gaszähler, der seine Daten per MQTT in Homeassistant sichtbar macht.
  • Der Lesekopf ist per USB direkt an den Homeassitant server angebunden. Ohne Umwege über esp-home, Tasmota oder ähnliches.
  • KISS in HW, keine extra Netzteile, keine cloud, keine externen Accounts bei Viessmann, etx…

Lösung :
Die Signalkette ist:
Reed Relais Sensor à Lesekopf USB à VZLogger (Container) à Mosquitto MQTT Broker (Container)à Homeassistant (Container)
grafik

Ergebnis :
Fancy Schmancy Homeassistant Graphen und Sensoren als Ausgangsbasis für Automatisierungen
grafik
grafik

Wir brauchen folgendes Zeug:

Software:

  1. Openmediavault auf einem Server um die Container zu hosten openmediavault - The open network attached storage solution
  2. VZLogger container GitHub - StefanSchoof/volkszaehler.org-config: My docker volkszaehler setup
  3. Mosquitto MQTT broker container Mosquitto Docker Configuration - Ultimate Guide | Cedalo
  4. Homeassistant container GitHub - tomaae/homeassistant-openmediavault: OpenMediaVault integration for Home Assistant

Hardware :
5. hardware:controllers:gaszaehler_lesekopf [wiki.volkszaehler.org]

Vorraussetzung**:**

  • Openmediavault läuft als Homeserver, Docker/Compose ist eingerichtet
  • Der Lesekopf ist direkt per USB mit dem Homeserver verbunden

Umsetzung, Detail, ich versuche die Reihenfolge einzuhalten

1. Am Gaszähler den Lesekopf installieren.
Bei meinem Zähler war es notwendig, das Reedkontakt direkt mit doppelseitigem Klebeband auf in der Nähe der letzten Nachkommastelle zu platzieren. Der Magnet sitzt auf der letzten Nachkommastelle des Gählers, im „Bauch“ der Ziffer 6. Die Aussparung unterhalb der Anzeige, die zur Aufnahme eines solchen Reedkontakts gedacht ist, hat bei mir nicht funktioniert.

Die LED in meinem Lesekopf war sehr hilfreich bei der Suche nach der richtigen Position des Reedkontakts

grafik

2. Erkennt das System den USB-Lesekopf?
Usb Kabel des Lesekopf in einen USB Port des Homeserver stöpseln
Auf der Konsole, als root im host System rausfinden wie der angemeldet wird.
Der Befehl

		ls -l /dev/serial/{by-path,by-id}/*

Sollte uns, unter anderem, eine Ausgabe wie z.B. das hier erzeugen

/dev/serial/by-id/usb-Silicon_Labs_USB-Gaszaehler-Kopf_001DE071-if00-port0 → …/…/ttyUSB0

Die Ausgabe brauchen wir in der VZLogger config, um dem Container mitzuteilen wo die Daten herkommen.
Wenn der Lesekopf richtig erkannt wird, sollte der Befehl

	strace -ttt -e read cat < /dev/ttyUSB0

diese Ausgabe erzeugen, wenn ihr mit einem starken Magneten testhalber um den Reedkontakt rumfuchtelt

1705761295.886147 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@>\2\0\0\0\0\0"..., 832) = 832
1705761295.889327 read(0, "\0", 131072) = 1
1705761319.616911 read(0, "\0", 131072) = 1
1705761320.055179 read(0, "\0", 131072) = 1
1705761320.437988 read(0, "\0", 131072) = 1
1705761320.837171 read(0, "\0", 131072) = 1
1705761321.237010 read(0, "\0", 131072) = 1
1705761321.638733 read(0, "\0", 131072) = 1

Der Lesekopf sendet also immer nur stumpf „1“ jedes Mal wenn der Reedkontakt geschlossen wird.
Wenn das läuft, ist die HW in Ordnung.

3. VZlogger Container aufsetzen in Openmediavault Compose:
Aus dem Volkszählerprojekt ist lediglich der VzLogger notwendig. Also VZLogger und Volkszähler nicht verwechseln.
Mein compose file sieht so aus
Hierbei ist im Abschnitt devices: darauf zu achten, daß der Pfad entsprechend der Ausgabe oben angepasst wird.
Ggf. müssen noch die Volumes angepasst werden, das ist aber von euerer lokalen Installation von Docker/compose in Openmediavault abhängig

---
version: "2"
services:
  vzlogger:
    container_name: vzlogger
    image: stefanschoof/vzlogger:latest
    volumes:
      - /data/vzlogger/:/etc
      - /data/vzlogger/:/var/log
    ports:
      - 8081:8081
    devices:
      - /dev/ttyUSB0:/dev/ttyUSB0 #gas
    restart: unless-stopped

Ob der Ports Parameter notwendig ist, weiß ich nicht mehr, spielt jedenfalls später keine Rolle mehr.
Den Container im Openmediavault starten

4. VZlogger Container konfigurieren und starten
Konfigurieren daß er die Reekontakt-Pulse als Gaszähler ausgibt und MQTT „spricht“
Das vzlogger.conf file anlegen.
Meines sieht so aus, nach meinem Verständnis kann das einfach übernommen werden.
Achtung: das MQTT Topic darf nicht geändert werden.
Die IP ist die IP eures Openmediavault Heimservers, auf dem wir ja auch den MQTT broker installieren werden.
Die uuid ist bei mir ein Überbleibsel aus einer alten Volkszähler Installation. Ob es auch ohne geht, habe ich nicht ausprobiert. Sollte so aber funktionieren.

{
    "retry": 0,            // how long to sleep between failed requests, in seconds
    "daemon": true,        // run periodically
    "verbosity": 0,         // between 0 and 15
    //"log": "/var/log/vzlogger/vzlogger.log",     // path to logfile, optional


    "local": {
        "enabled": false,   // should we start the local HTTPd for serving live readings?
        "port": 8081,       // the TCP port for the local HTTPd
        "index": true,      // should we provide a index listing of available channels if no UUID was requested?
        "timeout": 30,      // timeout for long polling comet requests, 0 disables comet, in seconds
        "buffer": 600       // how long to buffer readings for the local interface, in seconds
    },

  "mqtt": {
    "enabled": true,
    "host": "192.168.178.46",
    "port": 1883,
    "id": "vzlogger",
    "cafile": "",
    "capath": "",
    "certfile": "",
    "keyfile": "",
    "keypass": "",
    "keepalive": 30,
    "topic": "vzlogger/data",
    "id": "gas",
    "user": "vzlogger",
    "pass": "supergeheim",
    "retain": false,
    "rawAndAgg": false,
    "qos": 0,
    "timestamp": false
  },

    "meters": [
           
//Gaszähler
 {
            "enabled": true,               // disabled meters will be ignored
            "skip": false,                  // if enabled, errors when opening meter will lead to meter being ignored
            "protocol": "s0",
            "aggtime": -1,
            "aggfixedinterval": false,
            "device": "/dev/ttyUSB0",   // oder /dev/ttyAMA0
            "channel": {
                "identifier": "Impulse",    // s0 meter knows "Impulse" and "Power"
                "uuid": "d0f1dae0-a270-11ed-8b4c-f51368103fd6",
                //"middleware": "http://localhost/middleware.php",
                "middleware": "null",

                "aggmode": "none",
                "duplicates": 0
            }
        }



     ]
 }


Den Container im Openmediavault starten, das logfile motzt ggf. rum wegen irgendwelcher Zugriffe, aber das konnte ich ignorieren:

grafik
Außerdem wird in dem Log wahrscheinlich noch ein paar weitere Fehler auftauchen, die ich aber allesamt ignoriert habe.

5. Den MQTT Broker Mosquitto MQTT Container anlegen, konfigurieren und starten
Damit der ZVlogger von oben die Möglichkeit Daten abzuliefern, müssen wir noch einen Moquitto Container aufsetzen. Mein Compose File sieht so aus:

---
# https://mosquitto.org/
version: "2"
services:
  mqtt:
    container_name: mqtt
    image: eclipse-mosquitto:latest
    volumes:
      - /data/mqtt/config/:/mosquitto/config/
      - /data/mqtt/data:/mosquitto/data
      - /data/mqtt/log:/mosquitto/log
    ports:
      - 1883:1883
      - 9001:9001
    restart: unless-stopped

Außerdem muss die mosquitto conf ggf. angepasst werden
Meine sieht so aus, mosquitto ist so konfiguriert, daß es keine Passwörter erwartet:

retry_interval 20
sys_interval 10
user mosquitto
max_inflight_messages 40
max_queued_messages 200
queue_qos0_messages false
message_size_limit 0
allow_zero_length_clientid true
persistent_client_expiration 3m
allow_duplicate_messages false
autosave_interval 60
autosave_on_changes false

persistence false
persistence_file mosquitto.db
persistence_location /config/data/

# Port to use for the default listener.
listener 1883

listener 9001
protocol websockets

log_dest stderr
log_type error
connection_messages true
log_timestamp true

# include_dir /config/conf.d

# If the password.mqtt file is empty, this has no effect.
allow_anonymous true

# DO NOT CHANGE THIS LINE BELOW!!!
#password_file /config/passwords.mqtt

6. In Homeassistant Sensoren, Templates und Verbrauchszähler anlegen
In der configuration.yaml den Sensor anlegen der die MQTT Pakete entgegennimmt
Dieser Sensor ist erstmal sehr doof, sein Stand ist ja immer nur „1“, da ja in dem Datenpaket nichts anderes enthalten ist.

mqtt:
   sensor:
      name: "gaszaehlerMQTT"
      device_class: 'gas'
      state_topic: "vzlogger/data/chn0/raw"
      force_update: true
      unit_of_measurement: "m³"
      state_class: total_increasing
      icon: 'mdi:fire'
      unique_id: 'GaszaehlerMQTT'

Dann legen wir in der GUI von Homeassistant einen Verbrauchszähler an.
Das geht unter Einstellungenà Geräte und Dienste à Helferà Helfer erstellen à Verbrauchszähler
Für die Einstellungen: Der wird nie zurückgesetzt und kann nicht rückwärts zählen.
Sein Input Sensor heitß, wie gerade in der configuration.yaml angelegt: gaszaehlerMQTT
Der Verbrauchszähler heißt bei mir sensor.verbrauchzahlergas
Seine Aufgabe ist es, bei jedem Datenpaket um eins hochzuzählen
grafik

Dummerweise lässt sich der Verbrauchszähler noch nicht im Energy Dashboard hinzufügen.
Dafür legen wir nun noch ein Template in der configuration.yaml an, daß den gerade angelegten Verbrauchszähler in kWh umrechnet und den bisherigen Zählerstand addiert.
Dieser Sensor ist später der Input für das Engergie dashboard.

In der configuration.yaml wird also ein stetig hochzählender Sensor, der aus dem Verbrauchszähler kWh errechnet, hinzugefügt:

- sensor:
      - name: "GaszahlerTemplatekWh"
        unique_id: GaszahlerTemplatekWh
        state: "{{ states ('sensor.verbrauchzahlergas') | float * 0.01 *0.9384 * 11.540 }}"
        unit_of_measurement: "kWh"
        icon: "mdi:gas-station"
        device_class: energy
        state_class: total_increasing

Dabei ist:
0.01 für 0.01m³ pro Zählerumdrehung
0.9384 für die Zustandszahl in eurem Gasnetz (siehe letzte Gasrechnung)
11.540 für den Brennwert des Gas‘ das bei euch eingespeist wird (siehe letzte Gasrechnung)

Ein weiterer Sensor für den Stand des Gaszählers:

- sensor:
      - name: "GaszahlerStandm3"
        unique_id: Gaszahlerm3
        state: "{{ states ('sensor.verbrauchzahlergas') | float * 0.01 + 4711}}"
        unit_of_measurement: "m³"
        icon: "mdi:gas-station"
        device_class: gas
        state_class: total_increasing

Dabei ist:
0.01 für 0.01m³ pro Zählerumdrehung
4711 der aktuelle Stand eures Gaszählers, also der Offset von dem aus aufsummiert wird.

7. Ins Energiedashboard hinzufügen
Im Energiedashboard sollte nun der GaszahlerTemplatekWh als Gasquelle mit der Einheit kWh auswählbar sein.
Beachtet, daß es zwei Stunden dauern kann bis da was sichtbar ist.

Inspiration zu diesem Beitrag war dieser Bericht. Vielen Dank dafür.
Stromzähler via IR-Lesekopf auslesen und Daten in Home Assistant erfassen – Antary

1 Like