MQTT: Birth-Message + Last Will auf {MQTT_TOPIC}/status

- "online" (retained) beim (Re-)Connect via on_connect-Callback
- "offline" automatisch durch Broker bei Verbindungsabbruch (LWT)
- Abnehmer (n8n / Home Assistant) sehen jederzeit den Live-Zustand
- README um Status-/Availability-Topic ergaenzt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 14:37:32 +02:00
parent d593f9e8af
commit 394c72d6d9
2 changed files with 18 additions and 0 deletions

View File

@@ -138,6 +138,10 @@ Datenbank wie **NocoDB** ablegen.
- Die Events werden auf dem Topic `{MQTT_TOPIC}/crossing` mit **QoS 1**
(nicht retained) publiziert.
- Zusätzlich gibt es ein **Status-/Availability-Topic** `{MQTT_TOPIC}/status`
(retained): Beim Verbinden sendet die App `online` (Birth-Message), bei einem
Verbindungsabbruch publiziert der Broker automatisch `offline` (Last Will /
LWT). So lässt sich jederzeit erkennen, ob der Counter läuft.
- Das Payload ist JSON, z. B.:
```json
{

14
app.py
View File

@@ -73,9 +73,20 @@ MQTT_PASS = os.environ.get("MQTT_PASS")
MQTT_TOPIC = os.environ.get("MQTT_TOPIC", "vehiclecounter/cam1")
CAMERA_ID = os.environ.get("CAMERA_ID", "cam1")
# Availability-/Status-Topic: "online" beim Verbinden (Birth-Message),
# "offline" automatisch via Last Will (LWT), falls die Verbindung abreisst.
STATUS_TOPIC = f"{MQTT_TOPIC}/status"
# Zeitzone fuer den Zeitstempel (DST-aware). Standard Europe/Berlin.
LOCAL_TZ = ZoneInfo(os.environ.get("TZ_NAME", "Europe/Berlin"))
def _on_mqtt_connect(client, userdata, flags, *args):
"""Birth-Message: nach jedem (Re-)Connect 'online' (retained) senden."""
client.publish(STATUS_TOPIC, "online", qos=1, retain=True)
print(f"[mqtt] connected -> {STATUS_TOPIC} online", flush=True)
# paho-mqtt 2.x verlangt die CallbackAPIVersion, 1.x kennt sie nicht.
try:
_mqtt = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
@@ -83,6 +94,9 @@ except AttributeError:
_mqtt = mqtt.Client()
if MQTT_USER:
_mqtt.username_pw_set(MQTT_USER, MQTT_PASS)
_mqtt.on_connect = _on_mqtt_connect
# Last Will: Broker publiziert das, sobald die Verbindung unsauber abbricht.
_mqtt.will_set(STATUS_TOPIC, "offline", qos=1, retain=True)
try:
# async + loop_start -> blockiert den App-Start nicht, wenn der Broker weg ist
_mqtt.connect_async(MQTT_HOST, MQTT_PORT, keepalive=60)