Neuer Wasserzähler (Wireless M-Bus und Home Assistant)

,

wie sieht deine Config aus? Der Fehlermeldung nach würde ich mal auf einen falschen “board” eintrag tippen.

So einen Fehler hatte ich bislang nicht. Ab und an brach ESPhome beim flashen reproduzierbar ab. Dann hatte ich über die ArduinoIDE eine File geflasht. Danach ging es wieder wie immer.

So. Auf Basis von @manfred52 habe ich mal den Heltec V2 soweit eingebunden.

Im Wesentlichen stellt sich jetzt eine Frage, da ich keinen Key habe und folgenden Werte bekomme, ob das erstmal so passt?

Mein Wasseranbieter will 80.- für den Key haben. Finde ich leicht unverschämt …

 `{`
 `    "_":"telegram",`
 `    "media":"water",`
 `    "meter":"hydrus",`
 `    "name":"",`
 `    "id":"<gelöscht>",`
 `    "status":"OK",`
 `    "timestamp":"2026-05-24T11:59:42Z"`
 `}`
esphome:

  name: wasserzaehler
  friendly_name: Wasserzaehler

esp32:
board: heltec_wifi_lora_32_V2
framework:
type: esp-idf
# sram1_as_iram: true


logger:
level: INFO

api:
#  encryption:
#   key: "xxxxx" 

ota:

  - platform: esphome
password: "xxxxxxxx"


wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password

manual_ip:
static_ip: 192.168.6.79
gateway: 192.168.6.1
subnet: 255.255.255.0
power_save_mode: none

ap:
ssid: "WasserzaehlerHotspot"
password: "xxxxxxxx"


time:
  - platform: homeassistant

web_server:
port: 80
version: 3


globals:
  - id: frame_counter
type: int
restore_value: no
initial_value: "0"

  - id: Lasters
type: int
restore_value: no
initial_value: "0"


i2c:
sda: GPIO4
scl: GPIO15
scan: true


font:
  - file: "gfonts://Roboto"
id: font1
size: 12


spi:
clk_pin: GPIO5
miso_pin: GPIO19
mosi_pin: GPIO27


external_components:

  - source:
type: git
url: https://github.com/IoTLabs-pl/ESPHome-Components
ref: v1.0.6
components:
      - wmbus_common
      - wmbusa_radio
      - wmbus_meter
      - socket_transmitter
refresh: 0s


wmbus_common:
drivers: all


wmbus_radio:
id: radio_component
radio_type: SX1276
cs_pin: GPIO18
reset_pin: GPIO14
irq_pin: GPIO35

on_frame:
    - then:
        - lambda: |-
            id(frame_counter) += 1;
            id(last_rssi) = frame->rssi();
        - logger.log:

level: WARN
format: "Meter ID: %s"
args: ["frame->meter_id().c_str()"]
        - logger.log:
level: WARN
format: "Frame: https://wmbusmeters.org/analyze/%s"
args: ["frame->as_hex().c_str()"]

wmbus_meter:
  - id: wasserzaehler_kg
meter_id: "0xxxxxxxxxxx"
type: izar
key: "0000000000000000"

text_sensor:
  - platform: wifi_info
ip_address:
name: "Wasserzaehler ESP IP"

id: esp32_ip
entity_category: diagnostic

  - platform: wmbus_meter
parent_id: wasserzaehler_kg
field: current_status
name: "Wasserzaehler Status"
icon: mdi:information-outline

  - platform: wmbus_meter
parent_id: wasserzaehler_kg
field: timestamp
name: "Wasserzaehler Letztes Telegramm"
entity_category: diagnostic

sensor:

  - platform: wmbus_meter
parent_id: wasserzaehler_kg
field: total_m3
id: wasser_total_m3
name: "Wasserzaehler Gesamtverbrauch"
unit_of_measurement: "m³"
accuracy_decimals: 2
device_class: water
state_class: total_increasing
icon: mdi:water

  - platform: wmbus_meter
parent_id: wasserzaehler_kg
field: target_m3
name: "Wasserzaehler Stichtagswert"
unit_of_measurement: "m³"
accuracy_decimals: 2
device_class: water
state_class: total
icon: mdi:counter

  - platform: wmbus_meter
parent_id: wasserzaehler_kg
field: flow_temperature_c
id: wasser_flow_temp
name: "Wasserzaehler Wassertemperatur"
unit_of_measurement: "°C"
accuracy_decimals: 0
device_class: temperature
state_class: measurement

  - platform: wmbus_meter
parent_id: wasserzaehler_kg
field: external_temperature_c
id: wasser_external_temp
name: "Wasserzaehler Umgebungstemperatur"
unit_of_measurement: "°C"
accuracy_decimals: 0
device_class: temperature
state_class: measurement

  - platform: wmbus_meter
parent_id: wasserzaehler_kg
field: rssi_dbm
id: wasser_rssi
name: "Wasserzaehler RSSI"
unit_of_measurement: "dBm"
accuracy_decimals: 0
device_class: signal_strength
state_class: measurement
entity_category: diagnostic


display:

  - platform: ssd1306_i2c
model: "SSD1306 128x64"
reset_pin: GPIO16
address: 0x3C
update_interval: 30s
lambda: |-

      if (!isnan(id(wasser_total_m3).state)) {
        it.printf(0, 0, id(font1), "Gesamt: %.2f m3", id(wasser_total_m3).state);
      } else {
        it.printf(0, 0, id(font1), "Gesamt: --.-- m3");
      }

      if (!isnan(id(wasser_flow_temp).state)) {
        it.printf(0, 28, id(font1), "Wasser: %.0f C", id(wasser_flow_temp).state);
      } else {
        it.printf(0, 28, id(font1), "Wasser: -- C");
      }

      if (!isnan(id(wasser_external_temp).state)) 
        it.printf(0, 42, id(font1), "Umgbg.: %.0f C", id(wasser_external_temp).state);
      } else {
        it.printf(0, 42, id(font1), "Umgbg.: -- C");
      }

:crayon:by HarryP: Post formatiert

ich geh mal davon aus der Code Ersteller meinte mit Kg eher Kellergeschoß satt Kilogramm ….

Hallo Samhain,

status:OK ohne Werte ist erstmal nicht ungewöhnlich – aber ob das an einem fehlenden Key, am Driver (izar vs. das von wmbusmeters selbst gemeldete hydrus) oder an etwas anderem liegt, lässt sich aus dem dekodierten JSON allein nicht sagen.

Kannst du das RAW-Telegramm posten – den Hex-String aus der Frame: …/analyze/<hex>-Zeile in deinem Log? Damit sieht man eindeutig, ob’s verschlüsselt ist und welcher Driver wirklich passt, bevor du über die 80 € nachdenkst.

Moin alle zusammen, ich habe mich hier extra angemeldet um mich primär für eure Beiträge zu bedanken.

Ich möchte euch auch gerne etwas zurückgeben. Ich konnte mit Hilfe von euch den Heltec WiFi LoRa 32 v4 einbinden. Aktuelle warte ich noch auf den Key (mal schauen ob die Stadt diesen herausgibt)

Aber nach dem kompilieren konnte ich schon meine Zählernummer im Log sehen und auch die verschlüsselten Telegramme.

Anbei ist das mein YAML, ich habe es aus allen euren Kommentaren zusammengeschrieben und ein wenig auf mein Board angepasst.

# Board: Heltec WiFi LoRa 32 (V4) (Heltec)
substitutions:
  meter_id: "1"                    #<---hier meter id einfügen
  meter_key: "1234567890123456"    #<---hier key einfügen

external_components:
  - source: github://SzczepanLeon/esphome-components@main
    components: [ wmbus_common, wmbus_radio, wmbus_meter ]

output:
  - platform: gpio
    pin: 2
    id: fem_csd
  - platform: gpio
    pin: 7
    id: vfem_pwr
  - platform: gpio
    pin: 46
    id: fem_mode
  - platform: gpio
    pin: 36
    id: vext_pin

esphome:
  name: heltec-wifi-lora-32-v4
  friendly_name: Heltec WiFi LoRa 32 V4
  # LoRa helpers
  on_boot:
    priority: 600
    # Für das FEM (front end module) zuständig um das Signal zu boosten
    then:
      - output.turn_on: fem_csd     # SET HIGH
      - output.turn_on: vfem_pwr    # SET HIGH
      - output.turn_on: fem_mode    # SET HIGH (Mode Gain ON)

esp32:
  variant: esp32s3
  #board: heltec_wifi_lora_32_V4 -> not existing yet
  flash_size: 16MB
  cpu_frequency: 240MHZ
  framework:
    type: esp-idf
    advanced:
      loop_task_stack_size: 32768

#enable logging
logger:
    id: component_logger
    level: DEBUG

#enable home assistant    
api:
  encryption:
    key: "API-Key"

ota:
  - platform: esphome
    
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: Heltec WiFi LoR Fallback Hotspot
    password: "Fallback-Passwort"
    
captive_portal:
  
web_server:
    version: 3

time:
  - platform: homeassistant    

# SPI bus für das LoRa radio
spi:
  clk_pin: 9
  mosi_pin: 10
  miso_pin: 11

# I2C für das OLED Display
i2c:
  - id: bus_a
    sda: 17
    scl: 18

# LoRa Radio Configuration SX1262
wmbus_radio:
  radio_type: SX1262
  cs_pin: 8
  reset_pin: 12
  irq_pin: 14
  busy_pin: 13           # Reset Pin fürs timing
  rx_gain: BOOSTED       # BOOSTED (default) oder POWER_SAVING
  rf_switch: true        # Wenn DIO2 den RF switch steuert
  has_tcxo: true         # Wenn DIO3 einen externen TCXO steuert
  on_frame:
    - then:
        - logger.log:
            format: "RSSI: %ddBm T: %s (%d)"
            args: [ frame->rssi(), frame->as_hex().c_str(), frame->data().size() ]    

wmbus_common: 
    drivers:
      - multical21

# Definition des Wasserzaehlers
wmbus_meter:
  - id: wasserzaehler
    meter_id: ${meter_id}
    type: multical21
    key: "${meter_key}" 
    mode:
      - C1
      - T1

# OLED Display
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    reset_pin: 21
    i2c_id: bus_a
    address: 0x3C
    lambda: |-
      it.printf(0, 0, id(font1), "Wasserzaehler");
      it.printf(0, 16, id(font1), "Zaehler:");
      it.printf(72, 16, id(font1), "%.3f l", id(wasser_total_m3).state);
      it.printf(0, 32, id(font1), "Temperatur:");
      it.printf(72, 32, id(font1), "%.0f °C", id(wasser_flow_temp).state);
      it.printf(0, 48, id(font1), "Status:");
      it.printf(72, 48, id(font1), "%s", id(wasser_status).state.c_str());
      
font:
  - file: "gfonts://Roboto"
    id: font1
    size: 13

text_sensor:
  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: current_status
    name: "Wasserzaehler current_Status"

  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: status
    id: wasser_status
    name: "Wasserzaehler Status"

  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: time_dry
    name: "Wasserzaehler Trockenlauf"

  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: time_reversed
    name: "Wasserzaehler Rücklauf"

  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: time_bursting
    name: "Wasserzaehler Rohrburch"

  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: time_leaking
    name: "Wasserzaehler Leckage"

sensor:
  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: total_m3
    id: wasser_total_m3
    name: "Wasserzaehler Gesamtverbrauch"
    unit_of_measurement: "m³"
    accuracy_decimals: 2
    device_class: water
    state_class: total_increasing
    icon: mdi:water

  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: target_m3
    name: "Wasserzaehler Stichtagswert"
    unit_of_measurement: "m³"
    accuracy_decimals: 2
    device_class: water
    state_class: total
    icon: mdi:counter

  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: flow_temperature_c
    id: wasser_flow_temp
    name: "Wasserzaehler Wassertemperatur"
    unit_of_measurement: "°C"
    accuracy_decimals: 0
    device_class: temperature
    state_class: measurement
  
  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: external_temperature_c
    name: "Wasserzaehler Umgebungstemperatur"
    unit_of_measurement: "°C"
    accuracy_decimals: 0
    device_class: temperature
    state_class: measurement
  
  - platform: wmbus_meter
    parent_id: wasserzaehler
    field: rssi_dbm
    id: wasser_rssi
    name: "Wasserzaehler RSSI"
    unit_of_measurement: "dBm"
    accuracy_decimals: 0
    device_class: signal_strength
    state_class: measurement
    entity_category: diagnostic
    

Vielen Dank. Der Heltec V4 empfängt tadellos. Nur können die Telegramme von Hydrus nicht von den wmbus-Komponenten dekodiert werden. Auf der WMBusmeters-Website funktioniert es; da sind wohl unterschiedliche Versionen von WMBus im Umlauf. Letztendlich habe ich dann die Distributed-Version von Kustonium installiert, bei der die Telegramme aus HA dekodiert werden.

1 „Gefällt mir“

Kurzer Hinweis, falls hier noch jemand am Wireless-M-Bus-Weg verzweifelt: Es gibt für den Multical 21 auch eine Alternative über den optischen IR-Port statt Funk — spart einem das Beantragen des Auslese-/Verschlüsselungskeys beim Wasserversorger komplett, weil man direkt am Zähler ausliest.

Braucht nur einen günstigen USB-IR-Lese-/Schreibkopf (ca. 15–20 €, z. B. von AliExpress) und diese HACS-Integration: GitHub - mallewski/ha-multical_21: Custom component that integrates the Kamstrup multical 21 water meter into Home Assistant. · GitHub

Einrichtung komplett über die UI, unterstützt mittlerweile auch mehrere Zähler gleichzeitig und einen Wechsel des seriellen Ports ohne Neueinrichtung. Nachteil gegenüber wM-Bus: Der Rechner mit Home Assistant muss direkt am Zähler stehen bzw. per Kabel erreichbar sein, kein Auslesen aus der Ferne per Funk.