IoT 05.07.2026 2 min read by Ulrich Emmerich

Connect a Python service to Home Assistant via MQTT

Publish Python measurements to Home Assistant with MQTT Discovery, Paho MQTT 2.x, confirmed delivery, retained messages, and availability handling.

MQTT Home Assistant Python LAN-Server
Connect a Python service to Home Assistant via MQTT

Create MQTT entities automatically

A Python script can publish measurements to a broker and describe the corresponding Home Assistant entity through MQTT Discovery. No additional sensor block is needed in configuration.yaml.

Prerequisites

  • the Home Assistant MQTT integration
  • a reachable broker, such as the Mosquitto add-on
  • a dedicated broker account with suitable topic permissions
  • a Python virtual environment on the LAN server

Port 1883 is normally unencrypted and should remain on a trusted LAN. Use TLS or a VPN across untrusted networks.

Install Paho MQTT


python3 -m venv /opt/lanserver/venv
/opt/lanserver/venv/bin/pip install paho-mqtt

Publish discovery and state

Home Assistant Core 2026.4 ignores the old MQTT object_id option. default_entity_id proposes an ID; unique_id lets Home Assistant manage the entity in its registry.


import json
import os
import paho.mqtt.client as mqtt

BROKER = "HOME-ASSISTANT-IP"
USER = os.environ["MQTT_USER"]
PASSWORD = os.environ["MQTT_PASSWORD"]

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.username_pw_set(USER, PASSWORD)
client.connect(BROKER, 1883, keepalive=60)

config_topic = "homeassistant/sensor/lanserver/temperature/config"
state_topic = "lanserver/sensor/temperature"
availability_topic = "lanserver/status"
config = {
    "name": "Temperature",
    "unique_id": "lanserver_temperature_01",
    "default_entity_id": "sensor.lanserver_temperature",
    "state_topic": state_topic,
    "availability_topic": availability_topic,
    "unit_of_measurement": "°C",
    "device_class": "temperature",
    "state_class": "measurement",
    "value_template": "{{ value_json.temperature }}",
    "device": {
        "identifiers": ["lanserver_01"],
        "name": "LAN server",
        "manufacturer": "DIY"
    }
}

client.loop_start()
client.publish(config_topic, json.dumps(config), qos=1, retain=True).wait_for_publish()
client.publish(availability_topic, "online", qos=1, retain=True).wait_for_publish()
client.publish(state_topic, json.dumps({"temperature": 42.5}), qos=1, retain=True).wait_for_publish()
client.disconnect()
client.loop_stop()

Credentials belong in a protected systemd environment file. Retained discovery survives a Home Assistant restart; retained state restores the last value but may be stale. Availability gives that old value context. A short timer job cannot truthfully claim that a permanent process remains online.

Schedule with systemd


# /etc/systemd/system/mqtt-sensor.service
[Unit]
Description=MQTT sensor update

[Service]
Type=oneshot
EnvironmentFile=/etc/lanserver/mqtt.env
ExecStart=/opt/lanserver/venv/bin/python /opt/lanserver/mqtt_sensor.py

# /etc/systemd/system/mqtt-sensor.timer
[Unit]
Description=Update MQTT sensor every five minutes

[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
Persistent=true

[Install]
WantedBy=timers.target

systemctl daemon-reload
systemctl enable --now mqtt-sensor.timer

Troubleshooting

Check both topics with an MQTT client, verify ACLs and exact topic spelling, inspect journalctl -u mqtt-sensor.service, and deliberately clear obsolete retained discovery messages with an empty retained payload.

Sources and technical documentation

Links marked with * are affiliate links. As an Amazon Associate I earn from qualifying purchases.

More articles about IoT