I have installed a ESP32 nodemcu with a CC1101 to read the wmbus data from my IPERL watermeter. In principle it seems to work but my ESPHome sensors are not updated.
I am using ESPHome 2025.2.2 with the Szczepan’s esphome custom component ( esphome-components/components/wmbus/wmbus.cpp at main · SzczepanLeon/esphome-components and an AES key from my water provider.
The ESPHome log contains this if it receives data from the iperl:
[10:04:56][V][rxLoop:167]: Have 56 bytes from CC1101 Rx, RSSI: -27 dBm LQI: 128
[10:04:56][D][mbus:035]: Received T1 A frame
[10:04:56][V][mbus:046]: Frame: 37271C9B273434D59659C38E6AC5935B2A744E635A596356599C652F43726A9D2564D99A36338BC59393C5C6B299A5A3D269A94DA5A99A55 (56) [RAW]
[10:04:56][VV][3of6:095]: Decode 3 out of 6 OK.
[10:04:56][V][mbus:053]: Frame: 1E44AE4C1100042268070EFC7A16001005D93C1E6FC951A61B23D527D46EA60BCAAF760FA9 (37) [with CRC]
[10:04:56][V][mbus:096]: Validating CRC for Block1
[10:04:56][V][crc:031]: calculated: 0x0EFC, read: 0x0EFC
[10:04:56][V][mbus:116]: Validating CRC for Block2
[10:04:56][V][crc:031]: calculated: 0xD46E, read: 0xD46E
[10:04:56][V][mbus:116]: Validating CRC for Block3
[10:04:56][V][crc:031]: calculated: 0x0FA9, read: 0x0FA9
[10:04:56][V][mbus:063]: Frame: 1E44AE4C1100042268077A16001005D93C1E6FC951A61B23D527A60BCAAF76 (31) [without CRC]
[10:04:56][VV][wmbus:056]: Have data from RF ...
[10:04:56][V][Telegram.cpp:1131]: (wmbus) parseDLL @0 31
[10:04:56][V][Telegram.cpp:1178]: (wmbus) parseELL @10 21
[10:04:56][V][Telegram.cpp:1333]: (wmbus) parseNWL @10 21
[10:04:56][V][Telegram.cpp:1391]: (wmbus) parseAFL @10 21
[10:04:56][V][Telegram.cpp:2078]: (wmbus) parseTPL @10 21
[10:04:56][I][wmbus:104]: iperl [0x22040011] RSSI: -27dBm T: 1E44AE4C1100042268077A16001005D93C1E6FC951A61B23D527A60BCAAF76 (31) T1 A
[10:04:56][W][component:237]: Component wmbus took a long time for an operation (105 ms).
[10:04:56][W][component:238]: Components should block for at most 30 ms.
If I put a telegram and my key into the analyzer on https://wmbusmeters.org I’m getting this:
telegram=|1E44AE4C1100042268077A150010052F2F_04136CDC0300023B00002F2F2F2F|
Auto driver : iperl
Similar driver : topaseskr 06/06
Using driver : iperl 00/00
000 : 1e length (30 bytes)
001 : 44 dll-c (from meter SND_NR)
002 : ae4c dll-mfct (SEN)
004 : 11000422 dll-id (22040011)
008 : 68 dll-version
009 : 07 dll-type (Water meter)
010 : 7a tpl-ci-field (EN 13757-3 Application Layer (short tplh))
011 : 15 tpl-acc-field
012 : 00 tpl-sts-field (OK)
013 : 1005 tpl-cfg 0510 (AES_CBC_IV nb=1 cntn=0 ra=0 hc=0 )
015 : 2f2f decrypt check bytes (OK)
017 : 04 dif (32 Bit Integer/Binary Instantaneous value)
018 : 13 vif (Volume l)
019 C!: 6CDC0300 ("total_m3":253.036)
023 : 02 dif (16 Bit Integer/Binary Instantaneous value)
024 : 3B vif (Volume flow l/h)
025 C!: 0000 ("max_flow_m3h":0)
027 : 2F skip
028 : 2F skip
029 : 2F skip
030 : 2F skip
{
"_":"telegram",
"media":"water",
"meter":"iperl",
"name":"",
"id":"22040011",
"max_flow_m3h":0,
"total_m3":253.036,
"timestamp":"2025-03-23T08:04:30Z"
}
Sometimes I’m also receiving data that cannot be decoded. Maybe from another meter or some other device I guess.
[09:38:28][V][rxLoop:167]: Have 332 bytes from CC1101 Rx, RSSI: -97 dBm LQI: 194
[09:38:28][D][mbus:035]: Received T1 A frame
[09:38:28][V][mbus:041]: Frame: D0E2F4697E080830185D62122208890901B0D614C81BE001E028DCAD88942315EF84A1CB24410039A021084F81F96E09C681B000202713689FAA20FC8BF509DCEF9B4021050888C818838832343120585BF0C6808A30D7254321F2078A4032D50D030AE2505503023C1A94C1046025004933180ADD8C6A802A0B2E21444A323FE3A840D52040800611894412682469400509C1710600DD40D1B143A6D165104665D498F8D43741AAFB8F83A96D7115182B3E026321230BD88270A42F4280116A49D0C190432C8B70 [RAW]
[09:38:28][V][mbus:043]: 4AB3DA18F6AFC00B68996025C0F01AF500BC2EC90088195289FECA982E9D1A06860F770703D601E8C41E8872349A0EC55F270C93382C887E11054B14404BC745944623A116E951A34890476008080C2080411A791594602E22CA0EEC6090DE45E3513876064EC4053D18EE006B1CE20069E843C1832E01721C9DCBCCA434C621074E7318 (332) [RAW]
[09:38:28][V][3of6:083]: Decode 3 out of 6 failed..
So there are telegrams can be properly decoded. But all my ESPHome sensors are always unavailable and I cannot find out why.
This is my ESPHome .yaml:
substitutions:
## device settings
device_name_short: "water-meter-esp"
device_description: "Wasserzähler ESP32, IPERL"
projectname: "IPERL 868.Watermeter"
appversion: "1.0"
## all watermeters wmid: "0"
wmid: !secret watermeterId
## logger settings
log_level: "VERY_VERBOSE" # not that logging need memory, so in production mode use "WARN"
log_wmbus: "VERY_VERBOSE" # Loglevel for wmbus meters component
log_baudrate: "0" # 0 disable uart logger messages
## ----------------------------------------------------------------
## APPLICATION ESPHOME
## ----------------------------------------------------------------
esphome:
name: ${device_name_short}
comment: ${device_description}
# Automatically add the mac address to the name
# so you can use a single firmware for all devices
name_add_mac_suffix: false
project:
name: ${projectname}
version: ${appversion}
build_path: ./build/${device_name_short}
on_boot:
priority: 200
then:
- globals.set:
id: boot_counter
value: !lambda "return id(boot_counter)+=1;"
- logger.log:
level: INFO
tag: "system"
format: "BOOTMESSAGE:${device_name_short} API is connected, Device ready!"
- component.update: bootcounter
on_shutdown:
priority: 700
then:
- logger.log:
level: ERROR
tag: "system"
format: "BOOTMESSAGE:${device_name_short} is down!"
esp32:
board: esp32dev
framework:
type: arduino
## ----------------------------------------------------------------
## EXTERNAL COMPONENTS
## ----------------------------------------------------------------
external_components:
# uses the latest version from SzczepanLeon
# https://github.com/SzczepanLeon/esphome-components
# You can make ESPHome check the repository every time by setting this option to 0s
- source: github://SzczepanLeon/esphome-components@main
refresh: 0s
components: [wmbus]
## ----------------------------------------------------------------
## Global variables
## ----------------------------------------------------------------
globals:
- id: boot_counter
type: int
restore_value: yes
initial_value: "0"
- id: last_value
type: float
restore_value: yes
initial_value: "0.00"
## ---------------------------------------------------
## WIFI Settings
## ---------------------------------------------------
wifi:
networks:
- ssid: !secret ssid3_name
password: !secret ssid3_pswd
priority: 0
domain: !secret domain
## ---------------------------------------------------
## mDNS Component
## ---------------------------------------------------
mdns:
# if mDNS is disabled, they will no longer be able to automatically find your devices.
disabled: false
captive_portal:
## ---------------------------------------------------
## LOGGER COMPONENT
## ---------------------------------------------------
logger:
id: appslogger
level: ${log_level}
baud_rate: ${log_baudrate}
logs:
wmbus: ${log_wmbus}
wMBus-lib: ${log_wmbus}
## ---------------------------------------------------
## OTA COMPONENT
## ---------------------------------------------------
ota:
platform: esphome
password: !secret ota_pswd
## ---------------------------------------------------
## COMPONENT WEBSERVER
## ---------------------------------------------------
web_server:
port: 80
# version: 2
# js_url: !secret webserver_jsurl
api:
encryption:
key: !secret api_encryption_key
## ---------------------------------------------------
## SNTP COMPONENT
## ---------------------------------------------------
time:
- platform: sntp
id: time_sntp
timezone: Europe/Berlin
servers:
- 0.at.pool.ntp.org
- 0.pool.ntp.org
- 1.pool.ntp.org
on_time_sync:
then:
- logger.log:
tag: "system"
level: INFO
format: "Synchronized sntp clock"
## ------------------------------------------------------------------
## WMBUS CC1101 --> ESP32 az-delivery-devkit-v4
## ------------------------------------------------------------------
##
##
## o 1 (3.3V)
## |
## ╭――x――x――x――x――x――x――x――x――x――x――x――x――x――x――x――x――x――x――x――o―╮
## | |
## | |
## - | 5v az-delivery-devkit-v4 | -- ANT
## | |
## | 16 17 5 18 19 23 |
## ╰――x――x――x――x――x――x――x――x――o――x――o――o――o――o――o――o――o――o――o――o―╯
## | | | | | | |
## o | | o | | ╰-o - 2 (GND)
## 7 o | 4 o o
## GDO0 6 | CLK 5 3
## GD02 o MISO M0SI
## 8
## CSN
##
## ------------------------------------------------------------------
wmbus:
mosi_pin: GPIO23 ## SI: braun
miso_pin: GPIO19 ## SO: grün
clk_pin: GPIO18 ## SCLK: violett
cs_pin: GPIO05 ## CSN: orange
gdo0_pin: GPIO16 ## GD00: gelb (rx)
gdo2_pin: GPIO17 ## GD02: weiss (tx)
# all_drivers: true
log_all: true
# frequency: 868.950
## ---------------------------------------------------
## SWITCHES
## ---------------------------------------------------
switch:
# reset boot counter value
- platform: template
name: Device Boot Counter reset
turn_on_action:
then:
- lambda: |-
id(boot_counter) = 0;
id(bootcounter).publish_state(id(boot_counter));
- logger.log:
level: WARN
tag: "system"
format: "${device_name_short} reset boot counter o.k!"
- component.update: bootcounter
- platform: restart
name: "Restart"
id: restart_switch
## ---------------------------------------------------
## SENSORS
## ---------------------------------------------------
sensor:
- platform: wmbus
# Meter ID (usually from sticker). Can be specified as decimal or hex.
# only hex is working for my watermeter !
# see: https://github.com/SzczepanLeon/esphome-components/issues/6
# edit watermeterid in the secrets file
meter_id: !secret watermeterId
type: iperl
key: !secret watermeter_key
# add_prefix: true
sensors:
- name: "CC1101 LQI"
field: "lqi"
id: wmbus_cc1101_lqi
entity_category: "diagnostic"
unit_of_measurement: "lqi"
state_class: "measurement"
- name: "RSSI"
field: "rssi"
id: wmbus_cc1101_rssi
unit_of_measurement: "dbm"
- name: "Wasser Gesamt"
field: "total"
id: "water_total"
unit_of_measurement: "m³"
state_class: total_increasing
device_class: "water"
accuracy_decimals: 3
on_value:
then:
- text_sensor.template.publish:
id: cold_water_last_update
state: !lambda 'return id(time_sntp).now().strftime("%Y-%m-%d %H:%M:%S");'
- name: "Wasser Max Flow"
field: "max_flow"
id: "water_max_flow"
unit_of_measurement: "m³h"
state_class: measurement
device_class: "water"
accuracy_decimals: 3
# Wifi quality RSSI, internal used to calculate the Wifi quality RSSI in percentage
- platform: wifi_signal
id: wifi_signal_db
update_interval: 60s
internal: true
disabled_by_default: true
# Wifi quality RSSI in percentage
# Received Signal Strength (RSSI) is a measure of incoherent
## (raw) RF power in a channel.
- platform: copy # Reports the WiFi signal strength in %
source_id: wifi_signal_db
name: "Device WLAN Signal"
filters:
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
unit_of_measurement: "%"
entity_category: "diagnostic"
# device boot counter
- platform: template
name: Device Boot counter
id: bootcounter
icon: mdi:counter
accuracy_decimals: 0
state_class: "measurement"
entity_category: "diagnostic"
lambda: return (id(boot_counter));
text_sensor:
- platform: version
name: "ESPHome Version"
- platform: template
name: "Wasserzähler Letztes Update"
id: cold_water_last_update