meter -> SX1262 / SX1276 / CC1101 / LR1121 -> ESPHome wmbus_radio -> MQTT RAW HEX -> backend / wmbusmeters / Home Assistant
RAW-to-MQTT wireless M-Bus / wM-Bus radio bridge for ESPHome, focused on SX1262 and SX1276, with experimental CC1101 and LR1121 support.
✅ Verified on ESPHome 2026.7.0 — clean builds on all three test boards in CI.
The ESP device is a radio receiver and MQTT publisher. It does not decode meter values on the ESP.
🌉 Together with the Home Assistant add-on
homeassistant-wmbus-mqtt-bridgethis ESP is the radio front-end of a distributed wM-Bus → Home Assistant gateway: the ESP receives and forwards RAW HEX, the add-on decrypts and decodes. Unlike a monolithic wM-Bus gateway (radio + decoder in one box), the decode side is offloaded to Home Assistant — no meter drivers and no AES keys live on the ESP. The ESP also works standalone with any MQTT backend (Node-RED, a custom script), and the add-on accepts hex from any source (rtl-wmbus, another gateway, the replay tool) — the two cooperate, but neither depends on the other.
🧱 Responsibility boundary. This firmware is an MQTT client: it publishes to a topic and its scope ends there. The broker — authentication, ACLs, TLS, network exposure and any broker-to-broker bridging for remote/distributed setups (site A → internet → site B) — is the operator's responsibility. Keep the broker on your LAN and use a tunnel/VPN or TLS broker bridging for remote access; do not expose port 1883 to the internet.
It does:
- receive T1/C1 frames and experimental S1 frames,
- validate and normalize telegrams,
- publish valid RAW HEX telegrams to MQTT,
- publish RF diagnostics.
It does not:
- choose
wmbusmetersdrivers, - decrypt AES payloads,
- create final meter-value sensors,
- replace
wmbusmeters.
Use one of the YAML examples from examples/, then read the startup log before changing anything else.
Requirements. This component builds and runs on the ESP-IDF framework (every example uses it) and publishes to absolute MQTT topics of the form
wmbus/<topic_name>/telegram— there is no configurable topic prefix.
Recommended path:
- Choose the matching board example from
examples/. - Use
topic_nameor omit it and let the component useesphome.name. - Start with
listen_mode: t1unless you know you need C1 or S1. - Start with
diagnostic_mode: normal. - Check the boot sanity report and local
Have datalogs before debugging MQTT/backend.
Recommended topic scheme:
wmbus/<device>/telegram
wmbus/<device>/rssi/<meter_id> # only with publish_rssi: true (default: false)
wmbus/<device>/diag/summary
wmbus/<device>/diag/summary_15min
wmbus/<device>/diag/meter_snapshot
wmbus/<device>/diag/boot
The backend bridge should subscribe to:
wmbus/+/telegram
Do not manually build topic paths in normal YAML. Use topic_name, or omit it and let the component use esphome.name.
wmbus_radio:
topic_name: "xiao_s3"If MQTT is unavailable, radio reception continues and frames remain visible in local logs. MQTT publishing is skipped with a throttled warning.
TLS, remote brokers and certificates belong to ESPHome's standard mqtt: configuration, not to wmbus_radio.
SX1262 board-level options are explicit. The component does not guess board wiring.
Common options:
wmbus_radio:
radio_type: SX1262
has_tcxo: true
dio2_rf_switch: true
rx_gain: boosted
long_gfsk_packets: trueAt boot, the component prints a multiline SX1262 YAML sanity report. Missing has_tcxo: true on TCXO-based boards can still allow the radio to initialize, but RX may be completely silent. Disabled long_gfsk_packets in T1/both is reported as a risk for long T1 telegrams.
Some modules gate their antenna path behind an external pin and stay roughly 30 dB deaf without it. The Seeed Wio-SX1262 is one of them - on the XIAO ESP32S3 kit that pin is GPIO38:
wmbus_radio:
radio_type: SX1262
rf_sw_pin: GPIO38This is not the same option as dio2_rf_switch, and both are needed: DIO2 selects the TX/RX direction inside the chip, rf_sw_pin decides whether the module's RF switch conducts at all. Heltec V3/V4/V4-R8 do not need it - they use the fem_* pins.
Normal SX1276 boards do not need a TCXO option. Some boards expose a dedicated TCXO enable pin. Configure it explicitly only when your board documentation says so.
Example for LILYGO T3 V3.0 TCXO OLED LoRa32:
wmbus_radio:
radio_type: SX1276
tcxo_pin: GPIO12tcxo_pin, when configured, is driven HIGH before SX1276 radio initialization.
CC1101 support is experimental and requires explicit opt-in plus dual IRQ wiring. Single-IRQ CC1101 wiring is not supported.
wmbus_radio:
radio_type: CC1101
cc1101_allow_experimental: true
gdo0_pin: GPIOxx
gdo2_pin: GPIOyySilicon revisions: modules reporting VERSION=0x14 and VERSION=0x04 are both accepted. The revision byte is logged, but it does not gate startup — an unrecognised value produces a warning and the receiver still starts. What decides whether the radio is usable is the register self-check (GDO mapping, packet mode, RF profile), and a completely silent SPI bus (VERSION reading 0x00 or 0xFF) still fails setup.
LR1121 support is experimental and requires explicit opt-in. It has decoded real T1, C1 and S1 traffic on the Waveshare ESP32-S3-LR1121-HF board (SKU 34011), but it has not run for weeks and has never been compared against another radio in the same position.
wmbus_radio:
radio_type: LR1121
lr1121_allow_experimental: true
cs_pin: GPIO42
reset_pin: GPIO39
irq_pin: GPIO38
busy_pin: GPIO41
tcxo_voltage: 3.0v
payload_length: 255tcxo_voltage: 3.0v is measured, not assumed: at 1.8v the chip reports
HF_XOSC_START and never reaches the receive path. payload_length: 255 is
needed because NES frames are 245 raw bytes.
HF_XOSC_START in the boot log is normal and is not a fault — it latches when the
chip enters STDBY_XOSC, both calibrations afterwards come back clean, and the
driver explains this in the log.
This board has no USB-serial bridge, so logger: needs
hardware_uart: USB_SERIAL_JTAG or nothing will appear on the console. It also
has more than one u.FL socket, and only one of them is the sub-GHz path — the
wrong socket gives perfect silence with no error anywhere.
Main documentation lives in docs/. Examples live in examples/.
Start here:
docs/START_HERE.mddocs/CONFIG_REFERENCE_MINIMAL.mddocs/RADIO_OPTIONS_MINIMAL.mddocs/ON_FRAME.mddocs/TROUBLESHOOTING.mddocs/DIAGNOSTIC.mdexamples/README.md
Deeper notes:
Older detailed README content was moved to docs/README_FULL.md.
This project is intentionally RAW-only and is not a general ESPHome/Home Assistant support desk.
Before opening an issue, read SUPPORT.md.
Most radiowy Wireless M-Bus / wM-Bus RAW-to-MQTT dla ESPHome, ukierunkowany na SX1262 i SX1276, z eksperymentalną obsługą CC1101 i LR1121.
✅ Zweryfikowano na ESPHome 2026.7.0 — czyste kompilacje na wszystkich trzech płytkach testowych w CI.
Urządzenie ESP jest odbiornikiem radiowym i publisherem MQTT. Nie dekoduje wartości liczników na ESP.
🌉 Razem z dodatkiem Home Assistant
homeassistant-wmbus-mqtt-bridgeten ESP jest radiowym frontendem rozproszonego gatewaya wM-Bus → Home Assistant: ESP odbiera i przekazuje RAW HEX, add-on deszyfruje i dekoduje. W odróżnieniu od monolitycznej bramki wM-Bus (radio + dekoder w jednym pudełku) dekodowanie jest przeniesione na Home Assistant — na ESP nie ma driverów ani kluczy AES. ESP działa też samodzielnie z dowolnym backendem MQTT (Node-RED, własny skrypt), a add-on przyjmuje hex z dowolnego źródła (rtl-wmbus, inny gateway, narzędzie replay) — współpracują, ale żadna strona nie zależy od drugiej.
🧱 Granica odpowiedzialności. To firmware jest klientem MQTT: publikuje na temat i jego zakres tam się kończy. Broker — uwierzytelnianie, ACL, TLS, ekspozycja sieciowa oraz ewentualny mostek broker-broker dla instalacji zdalnych/rozproszonych (lokalizacja A → internet → lokalizacja B) — jest odpowiedzialnością operatora. Trzymaj broker w LAN, a do dostępu zdalnego użyj tunelu/VPN albo mostka brokera z TLS; nie wystawiaj portu 1883 do internetu.
Robi:
- odbiera ramki T1/C1 oraz eksperymentalne ramki S1,
- waliduje i normalizuje telegramy,
- publikuje poprawne telegramy RAW HEX do MQTT,
- publikuje diagnostykę RF.
Nie robi:
- nie wybiera driverów
wmbusmeters, - nie deszyfruje payloadów AES,
- nie tworzy końcowych sensorów z wartościami liczników,
- nie zastępuje
wmbusmeters.
Użyj jednego z przykładów YAML z examples/, a potem najpierw przeczytaj log startowy, zanim zaczniesz zmieniać kolejne rzeczy.
Wymagania. Komponent buduje się i działa na frameworku ESP-IDF (używa go każdy przykład) i publikuje na bezwzględne tematy MQTT w postaci
wmbus/<topic_name>/telegram— nie ma konfigurowalnego prefiksu tematu.
Zalecana ścieżka:
- Wybierz przykład z
examples/pasujący do używanej płytki. - Użyj
topic_namealbo pomiń tę opcję i pozwól komponentowi użyćesphome.name. - Zacznij od
listen_mode: t1, chyba że wiesz, że potrzebujesz C1 albo S1. - Zacznij od
diagnostic_mode: normal. - Sprawdź boot sanity report oraz lokalne logi
Have data, zanim zaczniesz debugować MQTT/backend.
Zalecany schemat topiców:
wmbus/<device>/telegram
wmbus/<device>/rssi/<meter_id> # tylko przy publish_rssi: true (domyślnie: false)
wmbus/<device>/diag/summary
wmbus/<device>/diag/summary_15min
wmbus/<device>/diag/meter_snapshot
wmbus/<device>/diag/boot
Backend bridge powinien subskrybować:
wmbus/+/telegram
W normalnym YAML-u nie składaj topiców ręcznie. Użyj topic_name albo pomiń tę opcję, a komponent użyje esphome.name.
wmbus_radio:
topic_name: "xiao_s3"Jeżeli MQTT jest niedostępne, odbiór radiowy działa dalej, a ramki nadal są widoczne lokalnie w logach. Publikacja MQTT jest pomijana z ograniczanym czasowo ostrzeżeniem.
TLS, zdalne brokery i certyfikaty należą do standardowej konfiguracji mqtt: ESPHome, a nie do wmbus_radio.
Opcje sprzętowe SX1262 są jawne. Komponent nie zgaduje okablowania płytki.
Typowe opcje:
wmbus_radio:
radio_type: SX1262
has_tcxo: true
dio2_rf_switch: true
rx_gain: boosted
long_gfsk_packets: truePodczas startu komponent wypisuje wieloliniowy raport sanity YAML dla SX1262. Brak has_tcxo: true na płytkach z TCXO może nadal pozwolić na inicjalizację radia, ale RX może być całkowicie martwy. Wyłączone long_gfsk_packets w T1/both jest raportowane jako ryzyko dla długich telegramów T1.
Część modułów bramkuje swój tor antenowy zewnętrznym wyprowadzeniem i bez niego pracuje z czułością niższą o około 30 dB. Moduł Seeed Wio-SX1262 jest jednym z nich — w zestawie z XIAO ESP32-S3 tym wyprowadzeniem jest GPIO38:
wmbus_radio:
radio_type: SX1262
rf_sw_pin: GPIO38To nie jest ta sama opcja co dio2_rf_switch i potrzebne są obie: DIO2 wybiera kierunek TX/RX wewnątrz układu, a rf_sw_pin decyduje, czy przełącznik RF modułu w ogóle przewodzi. Płytki Heltec V3/V4/V4-R8 tej opcji nie wymagają — korzystają z wyprowadzeń fem_*.
Zwykłe płytki SX1276 nie wymagają opcji TCXO. Niektóre płytki mają osobny pin włączający TCXO. Ustaw go jawnie tylko wtedy, gdy wynika to z dokumentacji płytki.
Przykład dla LILYGO T3 V3.0 TCXO OLED LoRa32:
wmbus_radio:
radio_type: SX1276
tcxo_pin: GPIO12Jeżeli tcxo_pin jest skonfigurowany, komponent ustawia go w stan HIGH przed inicjalizacją SX1276.
Obsługa CC1101 jest eksperymentalna i wymaga jawnego włączenia oraz podłączenia dwóch linii IRQ. Konfiguracja single-IRQ dla CC1101 nie jest wspierana.
wmbus_radio:
radio_type: CC1101
cc1101_allow_experimental: true
gdo0_pin: GPIOxx
gdo2_pin: GPIOyyRewizje układu: akceptowane są moduły zgłaszające zarówno VERSION=0x14, jak i VERSION=0x04. Bajt rewizji trafia do logu, ale nie blokuje startu — nierozpoznana wartość daje ostrzeżenie, a odbiornik i tak rusza. O używalności radia decyduje autotest rejestrów (mapowanie GDO, tryb pakietu, profil RF), a całkowicie milcząca magistrala SPI (VERSION równe 0x00 albo 0xFF) nadal przerywa uruchomienie.
Obsługa LR1121 jest eksperymentalna i wymaga jawnego włączenia. Na płytce Waveshare ESP32-S3-LR1121-HF (SKU 34011) zdekodowała realny ruch T1, C1 i S1, ale nie chodziła tygodniami i nigdy nie była porównana z innym radiem w tym samym miejscu.
wmbus_radio:
radio_type: LR1121
lr1121_allow_experimental: true
cs_pin: GPIO42
reset_pin: GPIO39
irq_pin: GPIO38
busy_pin: GPIO41
tcxo_voltage: 3.0v
payload_length: 255tcxo_voltage: 3.0v jest zmierzone, nie założone: przy 1.8v układ zgłasza
HF_XOSC_START i nie dochodzi do odbioru. payload_length: 255 jest potrzebne,
bo ramki NES mają 245 bajtów surowych.
HF_XOSC_START w logu startowym jest normalny i nie jest usterką — zatrzaskuje się
przy wejściu w STDBY_XOSC, obie kalibracje po nim wracają czyste, a sterownik
tłumaczy to w logu.
Płytka nie ma mostka USB-UART, więc logger: wymaga
hardware_uart: USB_SERIAL_JTAG, inaczej na konsoli nie pojawi się nic. Ma też
więcej niż jedno gniazdo u.FL, a torem sub-GHz jest tylko jedno z nich — złe
gniazdo daje idealną ciszę bez żadnego błędu.
Główna dokumentacja jest w docs/. Przykłady są w examples/.
Zacznij tutaj:
docs/START_HERE_PL.mddocs/CONFIG_REFERENCE_MINIMAL.mddocs/RADIO_OPTIONS_MINIMAL.mddocs/ON_FRAME_PL.mddocs/TROUBLESHOOTING_PL.mddocs/DIAGNOSTIC_PL.mdexamples/README_PL.md
Głębsze notatki:
docs/CHIP_SELECTION_PL.mddocs/BENCHMARKS_PL.mddocs/RX_PIPELINE_PL.md- Release notes: GitHub Releases
Starszy szczegółowy opis README przeniesiono do docs/README_FULL_PL.md.
Ten projekt jest celowo RAW-only i nie jest ogólnym helpdeskiem ESPHome/Home Assistant.
Przed otwarciem issue przeczytaj SUPPORT.md.