Skip to content

Add Home Assistant MQTT Discovery support - #708

Draft
OKDaG wants to merge 1 commit into
volkszaehler:masterfrom
OKDaG:feat/ha-mqtt-discovery
Draft

Add Home Assistant MQTT Discovery support#708
OKDaG wants to merge 1 commit into
volkszaehler:masterfrom
OKDaG:feat/ha-mqtt-discovery

Conversation

@OKDaG

@OKDaG OKDaG commented May 15, 2026

Copy link
Copy Markdown

Summary

Adds opt-in Home Assistant MQTT Discovery to the existing MQTT client. When enabled,
vzlogger publishes retained discovery configs (<prefix>/sensor/vzlogger_<uuid>/config)
for each channel on first reading, letting Home Assistant auto-create sensors with the
correct unit_of_measurement, device_class and state_class derived from the
channel's OBIS identifier.

Why

Today every Home Assistant user running vzlogger needs to hand-write a YAML sensor
block per channel just to give the raw smartmeter/reading/chnN/raw topic a unit
and a meaningful name. Doing this once inside vzlogger removes that boilerplate and
makes the readings show up in HA as proper Energy / Power / Voltage / Current sensors
out of the box.

Design notes

  • Opt-in. ha_discovery.enabled defaults to false — no behaviour change for
    existing setups.
  • No new dependencies. Discovery JSON is built with the already-linked libjson-c.
  • Lazy publish. The discovery config is sent once per channel, hooked next to the
    existing per-channel announce flow in MqttClient::publish(). Channels without
    readings never produce discovery topics.
  • Static OBIS map with 18 common SML codes (1.8.0/1.8.1/1.8.2, 2.8.0/2.8.1/2.8.2,
    16.7.0, 1.7.0, 2.7.0, 36/56/76.7.0, 32/52/72.7.0, 31/51/71.7.0). Unknown OBIS codes
    fall back to a unit-less generic sensor.
  • value_template is only emitted when mqtt.timestamp=true (JSON payload);
    otherwise the raw numeric payload is consumed directly by HA.
  • Separate translation unit (src/mqtt_ha_discovery.cpp) for the metadata lookup
    and config-JSON assembly so they can be unit-tested without a broker.
  • One HA device per vzlogger process (vzlogger by default, configurable via
    device_name / device_identifier). Per-meter grouping would require a
    ChannelMeter back-reference and is intentionally left as a follow-up to keep
    this PR contained.

Config

"mqtt": {
    "enabled": true,
    "host": "",
    "topic": "smartmeter/reading",
    "ha_discovery": {
        "enabled": true,             // opt in
        "prefix": "homeassistant",   // optional, HA discovery prefix
        "device_name": "vzlogger",   // optional, HA device name
        "device_identifier": ""      // optional, defaults to mqtt.id or device_name
    }
}

Tests

Adds tests/ut_mqtt_ha_discovery.cpp with 6 gtest cases covering:

  • Lookup of known OBIS metadata (energy import, active power)
  • Lookup of unknown OBIS returns nullptr
  • Discovery-JSON shape for a known OBIS (verifies name, unique_id, state_topic,
    unit_of_measurement, device_class, state_class, device.*)
  • Unknown-meta path omits unit_of_measurement, device_class, state_class
  • timestamp: true adds the value_template

All existing tests still pass.

Test plan

  • docker build --build-arg build_test=on . succeeds
  • vzlogger_unit_tests, mock_metermap, mock_MeterW1therm, mock_MeterOMS,
    mock_MeterS0 — 5/5 passing via make test
  • MqttHaDiscovery.* — 6/6 passing
  • ./check-formatting.sh clean (verified in an ubuntu:latest container with
    clang-format-20)
  • Smoke-tested against a real Mosquitto broker and Home Assistant 2025.x; sensors
    appear under the vzlogger device with correct units (Wh / W) and the Energy
    Dashboard picks up the total_increasing energy sensors.

Adds an opt-in `ha_discovery` block under the existing `mqtt` config. When
enabled, vzlogger publishes retained MQTT Discovery configs
(`<prefix>/sensor/vzlogger_<uuid>/config`) for each channel on first reading,
letting Home Assistant auto-create sensors with the correct unit,
device_class and state_class derived from the channel's OBIS identifier.

- Default off; no behaviour change for existing setups.
- No new dependencies; uses the already-linked libjson-c.
- Lazy publish, integrated next to the existing per-channel announce flow.
- 18 common SML OBIS codes mapped (energy import/export, active power per
  phase, voltage and current per phase). Unknown codes fall back to a
  generic unit-less sensor.
- All channels grouped under one HA device per vzlogger process; per-meter
  grouping would require a Channel->Meter back-reference and is left as a
  follow-up.
- Metadata lookup and config-JSON assembly live in their own translation
  unit (mqtt_ha_discovery.cpp) so they can be unit-tested without a broker.

Includes 6 gtest cases covering OBIS lookup and discovery JSON assembly.
Example config snippet added to etc/vzlogger.conf.
@r00t-

r00t- commented May 16, 2026

Copy link
Copy Markdown
Contributor

thanks for your contribution!

  • this very much looks like it was at least partially generated with an LLM, i don't know if other project members have an opinion, but i would personally very much prefer if that was noted/detailed in the commits and MR
  • not your fault, but it would be so much better if mqtt was an api instead of hardcoded, so this code could live in an MQTT api instead of in the root (see mqtt should be implemented as an API, not hardcoded into vzlogger core #550 )
    (that would probably also solve the "One HA device per vzlogger process" issue.)
  • i'm personally not a user of Home Assistant or mqtt and won't be able to test this. any takers?

@OKDaG

OKDaG commented Jun 3, 2026

Copy link
Copy Markdown
Author

LLM was partly involved creating the PR text.
LLM was involved creating the PR for issue #550

@OKDaG
OKDaG marked this pull request as draft June 3, 2026 09:43
@OKDaG

OKDaG commented Jun 3, 2026

Copy link
Copy Markdown
Author

Will adjust this PR if 550 is accepted.

@narc-Ontakac2
narc-Ontakac2 force-pushed the master branch 6 times, most recently from 32c98ac to 2a4d18e Compare July 24, 2026 11:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants