Tutorial: Eine MQTT-Discovery-Nachricht veröffentlichen, die im Energie-Dashboard ankommt

Inhalt
Ein Gerät, das sich über MQTT anmeldet, tut das mit einer einzigen Nachricht. Sie landet auf einem Topic, auf dem Home Assistant ohnehin lauscht, sie trägt JSON, und sie muss retained sein – sonst existiert sie nur bis zum nächsten Neustart einer der beiden Seiten.
Eine Entität auf diesem Weg zu erzeugen, ist eine Sache von sechs Zeilen. Diese Entität als Energiequelle akzeptiert zu bekommen, ist eine Sache von drei weiteren – und genau dort sitzt die Arbeit: Jedes der drei Felder wird stillschweigend übergangen, wenn es falsch steht, und das Symptom ist immer dieselbe leere Auswahlliste.

Das Topic bestimmt, wo die Entität auftaucht
Discovery läuft über ein Topic-Muster, nicht über einen Anmeldeaufruf. Home Assistant abonniert einen Präfix, und alles, was darunter in der richtigen Form veröffentlicht wird, wird zur Entität.
homeassistant/sensor/kellerzaehler/energie/config
│ │ │ │
Praefix Komponente node_id object_id
Der Präfix lautet homeassistant, solange er in der MQTT-Integration nicht geändert wurde. Die Komponente bestimmt den Entitätstyp und muss zu dem passen, was die Nutzlast beschreibt – ein sensor für einen Messwert, ein binary_sensor für einen Ja-Nein-Zustand, ein switch für etwas Schaltbares.
Node ID und Object ID sind freier Text und dienen allein dazu, das Topic eindeutig zu halten. Sie sind nicht die Entitäts-ID: Die entsteht später aus dem Namen, und ein nachträglich geändertes Topic erzeugt eine zweite Entität, statt die erste umzubenennen.
Die kleinste Nutzlast, die wirklich funktioniert
Vier Schlüssel genügen, damit eine Entität existiert. Ein Name, das Topic, auf dem die Messwerte eintreffen, eine Einheit und eine Kennung, die Neustarts übersteht.
{
"name": "Kellerzähler",
"state_topic": "haus/keller/zaehler",
"unit_of_measurement": "kWh",
"unique_id": "kellerzaehler_energie"
}
Von diesen vieren lohnt sich vor allem unique_id. Ohne diesen Schlüssel erscheint die Entität zwar, lässt sich aber nicht umbenennen, keinem Bereich zuordnen und im Energie-Dashboard überhaupt nicht auswählen. Die Kennung muss in der gesamten Installation eindeutig sein, weshalb sich die Topic-Bestandteile gut als Grundlage eignen.
Ein device-Block ist freiwillig und rechnet sich sofort: Entitäten mit derselben Kennung werden zu einem Gerät zusammengefasst, und ein Gerät mit acht Messwerten ist deutlich angenehmer als acht lose Entitäten.
"device": {
"identifiers": ["kellerzaehler"],
"name": "Kellerzähler",
"manufacturer": "Eastron",
"model": "SDM630"
}
Die drei Felder, die das Energie-Dashboard liest
Eine Entität mit einer Zahl darin ist noch keine Energiequelle. Drei Felder müssen zusammenpassen, bevor sie in der Auswahlliste erscheint, und alle drei beschreiben etwas Verschiedenes.
| Feld | Nötiger Wert | Aussage |
|---|---|---|
| device_class | energy | Die Zahl ist eine Energiemenge, keine Leistung |
| unit_of_measurement | Wh, kWh, MJ oder GJ | Die Einheit, in der diese Menge gezählt wird |
| state_class | total_increasing | Der Wert zählt ausschließlich aufwärts |
Am häufigsten passen die ersten beiden nicht zusammen. Ein Zähler, der Watt meldet, ist ein Leistungssensor: device_class power, state_class measurement, Einheit W. Dieser Sensor ist nützlich und richtig, und er wird nie als Energiequelle erscheinen, weil Leistung keine Energie ist. Was das Energie-Dashboard sucht, ist der Zählerstand, der sich aufsummiert.
Das dritte Feld entscheidet, wie ein Zählerwechsel behandelt wird. Mit total_increasing gilt ein plötzlich kleinerer Wert als neuer Zähldurchgang und nicht als negativer Verbrauch, und die Statistik läuft weiter. Mit total braucht derselbe Sprung einen last_reset-Zeitstempel zur Deutung, und ohne ihn wird aus der betroffenen Stunde ein Ausschlag. Für einen physischen Zähler, der vorwärts läuft und gelegentlich von vorn beginnt, ist total_increasing die ehrliche Wahl.
Von Hand veröffentlichen
Nichts daran braucht ein Gerät. Ein einziger Befehl erzeugt die Entität, und derselbe Befehl mit anderem Inhalt aktualisiert sie.
mosquitto_pub -h 192.168.1.10 -u ha -P geheim -r \
-t "homeassistant/sensor/kellerzaehler/energie/config" \
-m '{
"name": "Kellerzähler",
"state_topic": "haus/keller/zaehler",
"unit_of_measurement": "kWh",
"device_class": "energy",
"state_class": "total_increasing",
"unique_id": "kellerzaehler_energie",
"device": { "identifiers": ["kellerzaehler"], "name": "Kellerzähler" }
}'
mosquitto_pub -h 192.168.1.10 -u ha -P geheim -r \
-t "haus/keller/zaehler" -m "18234.7"
Der Schalter -r ist der, der vergessen wird, und er gehört aus zwei verschiedenen Gründen an beide Nachrichten. Auf dem Config-Topic sorgt er dafür, dass die Beschreibung einen Neustart von Home Assistant übersteht – sonst verschwindet die Entität, bis das Gerät sich zufällig erneut meldet. Auf dem State-Topic sorgt er dafür, dass die Entität direkt nach einem Neustart einen Wert hat, statt bis zum nächsten Messwert als nicht verfügbar dazustehen.
Ein Hinweis zur Nutzlastgrösse: Firmware, die Discovery spricht, sendet meist abgekürzte Schlüssel – stat_t, dev_cla, stat_cla, unit_of_meas, uniq_id, dev. Beide Schreibweisen funktionieren und lassen sich sogar mischen. Von Hand geschriebene Nutzlasten bleiben in der Langform lesbarer.
Wenn die Entität erscheint und leer bleibt
Eine Entität, die existiert und nichts anzeigt, ist fast immer ein Topic-Versatz: Das state_topic in der Nutzlast und das Topic, auf dem der Wert veröffentlicht wird, unterscheiden sich um ein Zeichen. Ein Abonnement mit Platzhalter zeigt beide Seiten gleichzeitig.
mosquitto_sub -h 192.168.1.10 -u ha -P geheim -v -t "haus/#"
Kommt der Wert an, steckt aber in einer grösseren JSON-Nachricht, holt ihn ein value_template heraus – "value_template": "{{ value_json.total_kwh }}". Ohne das bekommt die Entität das ganze Objekt und meldet es als unbekannt.
Und eine Warnung vor einem Feld, das hilfreich aussieht: expire_after setzt die Entität auf nicht verfügbar, wenn innerhalb der angegebenen Sekunden kein Wert eintrifft. Bei einem Schalter ist das nützlich. Bei einem Energiezähler reisst es Löcher in die Langzeitstatistik, denn jede Lücke beendet einen Zähldurchgang. Ein Zähler, der alle fünfzehn Minuten meldet, fährt ohne dieses Feld besser.
Beim letzten Schritt hilft Geduld. Die Langzeitstatistik entsteht in Fünf-Minuten-Abschnitten, und das Energie-Dashboard fasst stundenweise zusammen. Ein frisch erzeugter Sensor bleibt deshalb leer, bis die erste volle Stunde vorüber ist. Das ist kein Fehler, und erneutes Veröffentlichen der Nutzlast beschleunigt es nicht.
Ein Gerät entfernen, ohne eine Leiche zu hinterlassen
Ein Löschen der Entität in der Oberfläche wirkt bis zum nächsten Neustart – dann erzeugt die retained Config-Nachricht sie wieder. Das Entfernen muss dort geschehen, wo das Anlegen geschah.
mosquitto_pub -h 192.168.1.10 -u ha -P geheim -r \
-t "homeassistant/sensor/kellerzaehler/energie/config" -m ""
Eine leere retained Nutzlast auf dem Config-Topic löscht Entität und gespeicherte Nachricht zugleich. Das State-Topic behält seinen eigenen retained Wert und wird am besten genauso geleert – sonst erbt das nächste Gerät auf diesem Topic einen Messwert, der zu etwas anderem gehört.