Skip to content

1.4.0: MQTT with Home Assistant, German SML, Belgian and Luxembourg P1, water and thermal subdevices - #8

Merged
ichnograph merged 9 commits into
masterfrom
release-1.4
Aug 1, 2026
Merged

1.4.0: MQTT with Home Assistant, German SML, Belgian and Luxembourg P1, water and thermal subdevices#8
ichnograph merged 9 commits into
masterfrom
release-1.4

Conversation

@ichnograph

Copy link
Copy Markdown
Contributor

Rollup of the three reviewed feature branches plus their integration, replacing #5, #6, and #7.

Contents

  • MQTT sink with Home Assistant discovery (MQTT.Enabled): every source appears in HA as a device with typed sensors; grid, gas, water, and solar slot into the Energy dashboard. Includes the QuestDB heat power unit fix (readings were 1000x too small since the gombus migration; expect a step change in that history).
  • German SML meters (Grid.Reader: sml): EMH, ISKRA MT681, EasyMeter Q3A/B, eBZ DD3 SM, Holley DTZ541 over an IR head, with both CRC variants and factory-state tolerance.
  • Belgian Fluvius eMUCS: auto-detected; gas on its Belgian OBIS code (non-temperature-corrected), decimal currents fixed, capacity tariff demand fields in three new grid columns (schema migration v2).
  • Luxembourg Smarty and Austrian Sagemcom meters: AES-128-GCM telegram decryption via Grid.DecryptionKey, validated against a real published frame.
  • Water and thermal P1 subdevices (Grid.Water, Grid.Thermal): same capture-time dedup and per-sink tables as gas; slave e-meters documented as skipped.

Integration work in this rollup

  • MQTT writers and HA discovery for the new water and thermal readings (the MQTT branch predated them).
  • Grid reader factory handles reader selection and decryption together; keys are rejected with the SML reader.
  • Config validation restructured; changelog carries the full 1.4.0 section, so the release gate passes at tag time.

Coverage 82.7%, lint 0 issues, race suite green, gitleaks clean. The databases job exercises the v2 grid migration and all new subdevice tables against real databases.

The writer divided power by 1000 and max power by 100, assuming the
milliwatt units of the M-Bus library used before the gombus migration.
The domain values have been plain watts since then, so QuestDB heat
power readings were three orders of magnitude off. The other sinks
already stored watts.
Publishes every reading as JSON under a configurable topic prefix and
announces retained Home Assistant discovery configs, so each meter
shows up as a device with typed sensors and the energy and gas
sensors slot into the Energy dashboard without any YAML. Availability
rides a last-will status topic; the broker connection registers as a
health check. One shared client per process, created lazily by the
first enabled sink builder.
A new sml grid reader for the meters common in Germany (EMH, ISKRA
MT681, EasyMeter Q3A/Q3B, eBZ DD3 SM, Holley DTZ541), selected with
Grid.Reader: sml. The meters push SML frames unsolicited at 9600 8N1;
the reader validates transport frames (CRC-16/X-25, with the Kermit
fallback Holley firmware needs) and extracts OBIS values by scanning
value-list entries instead of parsing the full SML tree, which keeps
it robust against the vendor quirks the reference implementations
document.

Only the total energy counter is required: factory-state meters hide
everything else until the owner enters the meter PIN and enables the
extended info mode. Signed power maps to usage or output by sign, and
both vendor conventions for per-phase registers are accepted. Gas
over M-Bus is a DSMR feature, so Grid.Gas requires the dsmr reader.
Belgium (Fluvius eMUCS) works without configuration: the version line
moved, subdevice gas publishes non-temperature-corrected volume on a
different code, water meters are dispatched by device type and
skipped, currents carry decimals the old parser silently dropped to
zero, and the capacity tariff demand values (current average and
running-month maximum) are parsed into three new grid columns added
as a second schema migration.

Luxembourg Smarty meters and the Austrian DSOs using the same
Sagemcom construction encrypt the telegram with AES-128-GCM. The
reader detects encrypted frames per frame, decrypts with
Grid.DecryptionKey (Grid.AuthenticationKey defaults to the fixed
Luxembourg value; Austrians supply their own), verifies the tag, and
feeds the plaintext through the normal DSMR path. Telegrams with
plain totals instead of tariff registers are now accepted.
Verified against the published Fluvius and Smarty test telegrams and
a real captured encrypted frame with its key.
The fixed Luxembourg authentication key is printed in the Luxmetering
specification and the test decryption key was published by NEXXTLAB
for exactly this purpose; neither is a secret.
Water meters (common on Belgian P1) and thermal meters follow the
same path as gas: identified by device type, deduplicated on the
meter's capture time, stored to their own table in every sink in the
units the telegram carries (m3 and GJ). Slave electricity meters are
skipped; they are better read from their own P1 port.
# Conflicts:
#	CHANGELOG.md
#	README.md
#	cmd/meterlogger/source_grid.go
#	documentation/README.md
#	documentation/configuration.md
#	internal/config/config.go
# Conflicts:
#	CHANGELOG.md
#	internal/config/load_test.go
Merging the three feature branches left one real gap: the MQTT sink
predates the water and thermal subdevice support, so it gains writers
and Home Assistant discovery for both (water as a water device class
total, thermal energy in GJ). Also resolves the merge seams: the grid
reader factory now applies decryption in the dsmr case and rejects
keys with sml, config validation extracts the grid subdevice checks,
and the changelog gains the 1.4.0 section.
@ichnograph
ichnograph merged commit 0d8ba40 into master Aug 1, 2026
9 checks passed
@ichnograph
ichnograph deleted the release-1.4 branch August 1, 2026 21:56
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.

1 participant