Created
March 22, 2026 23:51
-
-
Save k0ff33/39b9aec2c35b33f96c7a65b85b89fc83 to your computer and use it in GitHub Desktop.
ESPhome configuration for wmbus-reader on Lilygo T3 LoRa32 V1.6.1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| esphome: | |
| name: wmbus-reader | |
| friendly_name: wM-Bus Reader | |
| esp32: | |
| board: ttgo-lora32-v1 | |
| framework: | |
| type: esp-idf | |
| advanced: | |
| loop_task_stack_size: 16384 | |
| wifi: | |
| ssid: !secret wifi_ssid | |
| password: !secret wifi_password | |
| ap: | |
| ssid: "wMBus Fallback" | |
| password: "wmbus-reader" | |
| captive_portal: | |
| api: | |
| time: | |
| - platform: homeassistant | |
| ota: | |
| - platform: esphome | |
| logger: | |
| level: DEBUG | |
| baud_rate: 115200 | |
| external_components: | |
| - source: github://k0ff33/esphome-components@main | |
| components: [wmbus_radio, wmbus_common, wmbus_meter] | |
| # ── SPI bus (SX1278, LilyGo T3 v1.6.1) ────────────────────────────────────── | |
| spi: | |
| clk_pin: GPIO5 | |
| mosi_pin: GPIO27 | |
| miso_pin: GPIO19 | |
| # ── wM-Bus common: active drivers ──────────────────────────────────────────── | |
| wmbus_common: | |
| drivers: | |
| - apator162 | |
| - amiplus | |
| # ── wM-Bus radio ───────────────────────────────────────────────────────────── | |
| wmbus_radio: | |
| radio_type: SX1276 # SX1278 (868 MHz) is the same driver as SX1276 | |
| cs_pin: GPIO18 | |
| irq_pin: GPIO33 # DIO1 — FIFO-not-empty interrupt; DIO0 (GPIO26) is RxDone/PayloadReady only | |
| reset_pin: GPIO23 | |
| has_tcxo: false # T3 v1.6.1 has no TCXO | |
| # Scan mode: logs every frame so you can discover meter IDs. | |
| # Paste the hex data at https://wmbusmeters.org/analyze/ to decode and find your meter ID. | |
| on_frame: | |
| - then: | |
| - logger.log: | |
| format: "RSSI: %ddBm T: %s (%d)" | |
| args: [frame->rssi(), frame->as_hex().c_str(), frame->data().size()] | |
| # ── Meter definitions ───────────────────────────────────────────────────────── | |
| wmbus_meter: | |
| - id: water_meter | |
| meter_id: 0x00000000 | |
| type: apator162 | |
| key: "00000000000000000000000000000000" | |
| mode: | |
| - T1 | |
| - C1 | |
| - id: garden_water_meter | |
| meter_id: 0x00000000 | |
| type: apator162 | |
| key: "00000000000000000000000000000000" | |
| mode: | |
| - T1 | |
| - C1 | |
| - id: elec_meter | |
| meter_id: 0x00000000 | |
| type: amiplus | |
| key: !secret pge_key | |
| mode: | |
| - T1 | |
| - C1 | |
| # ── Sensors ─────────────────────────────────────────────────────────────────── | |
| sensor: | |
| - platform: wmbus_meter | |
| parent_id: water_meter | |
| id: water_total | |
| field: total_m3 | |
| name: "Water Total" | |
| state_class: total_increasing | |
| device_class: water | |
| unit_of_measurement: "m³" | |
| filters: | |
| - heartbeat: 60s | |
| - platform: wmbus_meter | |
| parent_id: garden_water_meter | |
| id: garden_water_total | |
| field: total_m3 | |
| name: "Garden Water Total" | |
| state_class: total_increasing | |
| device_class: water | |
| unit_of_measurement: "m³" | |
| filters: | |
| - heartbeat: 60s | |
| - platform: wmbus_meter | |
| parent_id: elec_meter | |
| id: elec_power | |
| field: current_power_consumption_kw | |
| name: "Power" | |
| device_class: power | |
| state_class: measurement | |
| unit_of_measurement: "kW" | |
| accuracy_decimals: 3 | |
| filters: | |
| - heartbeat: 60s | |
| - platform: wmbus_meter | |
| parent_id: elec_meter | |
| id: elec_total | |
| field: total_energy_consumption_kwh | |
| name: "Energy Total" | |
| state_class: total_increasing | |
| device_class: energy | |
| unit_of_measurement: "kWh" | |
| filters: | |
| - heartbeat: 60s | |
| - platform: wmbus_meter | |
| parent_id: elec_meter | |
| id: elec_tariff1 | |
| field: total_energy_consumption_tariff_1_kwh | |
| name: "Energy Tariff 1 (Day)" | |
| state_class: total_increasing | |
| device_class: energy | |
| unit_of_measurement: "kWh" | |
| filters: | |
| - heartbeat: 60s | |
| - platform: wmbus_meter | |
| parent_id: elec_meter | |
| id: elec_tariff2 | |
| field: total_energy_consumption_tariff_2_kwh | |
| name: "Energy Tariff 2 (Night)" | |
| state_class: total_increasing | |
| device_class: energy | |
| unit_of_measurement: "kWh" | |
| filters: | |
| - heartbeat: 60s | |
| # ── Diagnostics ── | |
| - platform: wmbus_meter | |
| parent_id: water_meter | |
| id: water_rssi | |
| field: rssi_dbm | |
| name: "Water RSSI" | |
| device_class: signal_strength | |
| state_class: measurement | |
| unit_of_measurement: "dBm" | |
| entity_category: diagnostic | |
| filters: | |
| - heartbeat: 60s | |
| - platform: wmbus_meter | |
| parent_id: garden_water_meter | |
| id: garden_water_rssi | |
| field: rssi_dbm | |
| name: "Garden Water RSSI" | |
| device_class: signal_strength | |
| state_class: measurement | |
| unit_of_measurement: "dBm" | |
| entity_category: diagnostic | |
| filters: | |
| - heartbeat: 60s | |
| - platform: wifi_signal | |
| id: wifi_signal_db | |
| name: "WiFi Signal" | |
| entity_category: diagnostic | |
| update_interval: 60s | |
| text_sensor: | |
| - platform: wifi_info | |
| ip_address: | |
| id: wifi_ip | |
| # ── Display: 0.96" SSD1306 128x64 OLED ─────────────────────────────────────── | |
| i2c: | |
| sda: GPIO21 | |
| scl: GPIO22 | |
| frequency: 400kHz | |
| font: | |
| - file: "gfonts://Roboto Mono" | |
| id: f10 | |
| size: 10 | |
| display: | |
| - platform: ssd1306_i2c | |
| model: "SSD1306 128x64" | |
| address: 0x3C | |
| update_interval: 5s | |
| lambda: |- | |
| // Row 0 — WiFi IP | |
| if (id(wifi_ip).state != "") { | |
| it.printf(0, 0, id(f10), "IP: %s", id(wifi_ip).state.c_str()); | |
| } else { | |
| it.print(0, 0, id(f10), "WiFi: connecting..."); | |
| } | |
| // Row 1 — WiFi signal strength | |
| if (!isnan(id(wifi_signal_db).state)) { | |
| it.printf(0, 12, id(f10), "WiFi: %d dBm", (int)id(wifi_signal_db).state); | |
| } else { | |
| it.print(0, 12, id(f10), "WiFi: ---"); | |
| } | |
| // Row 2 — Water total | |
| if (!isnan(id(water_total).state)) { | |
| it.printf(0, 24, id(f10), "W: %.3f m3", id(water_total).state); | |
| } else { | |
| it.print(0, 24, id(f10), "Water: scanning..."); | |
| } | |
| // Row 3 — Garden water total | |
| if (!isnan(id(garden_water_total).state)) { | |
| it.printf(0, 36, id(f10), "G: %.3f m3", id(garden_water_total).state); | |
| } else { | |
| it.print(0, 36, id(f10), "Garden: scanning..."); | |
| } | |
| // Row 4 — Current power / Energy | |
| if (!isnan(id(elec_power).state)) { | |
| it.printf(0, 48, id(f10), "%.2fkW %.0fkWh", id(elec_power).state, id(elec_total).state); | |
| } else { | |
| it.print(0, 48, id(f10), "Power: scanning..."); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment