ha-mqtt-autodiscovery
Configures and publishes MQTT auto-discovery messages to automatically register IoT devices and sensors with Home Assistant, defining discovery payloads with device classes, state classes, units, and device grouping for multi-sensor devices. Use when integrating custom IoT devices, creating MQTT sensors, building ESP32/ESP8266/Pi-based devices that auto-register with HA, or implementing resilient MQTT patterns with offline queuing and auto-reconnect.
What this skill does
Works with MQTT brokers (Mosquitto), paho-mqtt Python library, and Home Assistant MQTT integration.
# Home Assistant MQTT Auto-Discovery
Automatically register IoT devices and sensors with Home Assistant by publishing MQTT discovery configurations.
## Overview
MQTT auto-discovery allows devices to automatically appear in Home Assistant without manual YAML configuration. Publish a JSON config to the discovery topic and HA creates the entity automatically.
**Discovery Topic Pattern:**
```
homeassistant/{component}/{node_id}/{object_id}/config
```
**State Topic Pattern:**
```
{node_id}/{sensor_type}/state
```
## When to Use This Skill
Use this skill when you need to:
- Automatically register custom IoT devices with Home Assistant via MQTT
- Build ESP32/ESP8266/Raspberry Pi-based sensors that self-register
- Create multi-sensor devices grouped under a single device entry
- Implement resilient MQTT patterns with offline queuing and auto-reconnect
- Configure proper device classes and state classes for long-term statistics
- Avoid manual YAML configuration for frequently changing device deployments
Do NOT use when:
- You can use existing Home Assistant integrations (prefer official integrations)
- Building devices without MQTT broker infrastructure
- You need real-time control with minimal latency (consider direct API instead)
## Usage
Follow these steps to set up MQTT auto-discovery:
1. **Define sensor configurations** with device classes and units
2. **Publish discovery payloads** to discovery topics with retain=True
3. **Verify entities appear** in Home Assistant
4. **Publish sensor values** to state topics
5. **Implement resilient patterns** with auto-reconnect and offline queuing
## Quick Start
```python
import json
import paho.mqtt.client as mqtt
# Connect to MQTT broker
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.connect("192.168.68.123", 1883, 60)
# Publish discovery config
discovery_topic = "homeassistant/sensor/enviroplus_temperature/config"
config = {
"name": "Enviro+ Temperature",
"unique_id": "enviroplus_temperature",
"state_topic": "enviroplus/temperature/state",
"device_class": "temperature",
"unit_of_measurement": "°C",
"state_class": "measurement",
"device": {
"identifiers": ["enviroplus"],
"name": "Enviro+ Environmental Sensor",
"manufacturer": "Pimoroni",
"model": "Enviro+",
},
}
client.publish(discovery_topic, json.dumps(config), qos=1, retain=True)
# Publish sensor value
client.publish("enviroplus/temperature/state", "23.5", qos=1)
```
After publishing, the sensor `sensor.enviro_temperature` appears in Home Assistant automatically.
## Discovery Payload Structure
### Required Fields
```python
{
"name": "Friendly Name", # Display name in HA
"unique_id": "unique_identifier", # Must be globally unique
"state_topic": "device/sensor/state", # Topic where values are published
}
```
### Recommended Fields
```python
{
"device_class": "temperature", # Semantic type (enables icons, units)
"unit_of_measurement": "°C", # Unit for display
"state_class": "measurement", # Enables long-term statistics
"icon": "mdi:thermometer", # Custom icon (optional)
}
```
### Device Information
Group sensors under a single device:
```python
{
"device": {
"identifiers": ["device_unique_id"], # List of identifiers
"name": "Device Name",
"manufacturer": "Manufacturer",
"model": "Model Name",
"sw_version": "1.0.0",
}
}
```
## Common Sensor Types
See [references/sensor_configs.md](references/sensor_configs.md) for complete sensor configuration templates.
### Environmental Sensors
```python
# Temperature
{
"device_class": "temperature",
"unit_of_measurement": "°C",
"state_class": "measurement",
}
# Humidity
{
"device_class": "humidity",
"unit_of_measurement": "%",
"state_class": "measurement",
}
# Pressure
{
"device_class": "atmospheric_pressure",
"unit_of_measurement": "hPa",
"state_class": "measurement",
}
# Light
{
"device_class": "illuminance",
"unit_of_measurement": "lx",
"state_class": "measurement",
}
```
### Air Quality Sensors
```python
# PM2.5
{
"device_class": "pm25",
"unit_of_measurement": "µg/m³",
"state_class": "measurement",
}
# PM10
{
"device_class": "pm10",
"unit_of_measurement": "µg/m³",
"state_class": "measurement",
}
```
### Energy Monitoring
```python
# Power
{
"device_class": "power",
"unit_of_measurement": "W",
"state_class": "measurement",
}
# Energy (cumulative)
{
"device_class": "energy",
"unit_of_measurement": "kWh",
"state_class": "total_increasing",
}
```
## State Classes
| State Class | Purpose | Resets? | Statistics? |
|-------------|---------|---------|-------------|
| `measurement` | Current value (temp, power) | No | Yes (mean, min, max) |
| `total` | Monotonically increasing (odometer) | No | Yes (rate of change) |
| `total_increasing` | Cumulative with resets (daily energy) | Yes | Yes (rate of change) |
## Complete Example: Multi-Sensor Device
```python
import json
import paho.mqtt.client as mqtt
DEVICE_ID = "enviroplus"
BROKER = "192.168.68.123"
# Sensor definitions
SENSORS = {
"temperature": {
"name": "Temperature",
"device_class": "temperature",
"unit_of_measurement": "°C",
"state_class": "measurement",
},
"humidity": {
"name": "Humidity",
"device_class": "humidity",
"unit_of_measurement": "%",
"state_class": "measurement",
},
"pressure": {
"name": "Pressure",
"device_class": "atmospheric_pressure",
"unit_of_measurement": "hPa",
"state_class": "measurement",
},
"pm2_5": {
"name": "PM2.5",
"device_class": "pm25",
"unit_of_measurement": "µg/m³",
"state_class": "measurement",
},
}
def publish_discovery(client):
"""Publish discovery configs for all sensors."""
for sensor_key, config in SENSORS.items():
unique_id = f"{DEVICE_ID}_{sensor_key}"
discovery_topic = f"homeassistant/sensor/{unique_id}/config"
payload = {
"name": config["name"],
"unique_id": unique_id,
"state_topic": f"{DEVICE_ID}/{sensor_key}/state",
"device_class": config["device_class"],
"unit_of_measurement": config["unit_of_measurement"],
"state_class": config["state_class"],
"device": {
"identifiers": [DEVICE_ID],
"name": "Enviro+ Sensor",
"manufacturer": "Pimoroni",
"model": "Enviro+",
},
}
client.publish(discovery_topic, json.dumps(payload), qos=1, retain=True)
print(f"Published discovery for {config['name']}")
# Connect and publish
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.connect(BROKER, 1883, 60)
publish_discovery(client)
# Publish sample values
client.publish(f"{DEVICE_ID}/temperature/state", "23.5", qos=1)
client.publish(f"{DEVICE_ID}/humidity/state", "65", qos=1)
client.publish(f"{DEVICE_ID}/pressure/state", "1013.25", qos=1)
client.publish(f"{DEVICE_ID}/pm2_5/state", "12.3", qos=1)
client.disconnect()
```
## Resilient MQTT Pattern
For production devices, use auto-reconnect and offline queuing:
```python
from collections import deque
import paho.mqtt.client as mqtt
class ResilientMQTT:
"""MQTT client with offline queuing and auto-reconnect."""
def __init__(self, broker: str, port: int = 1883):
self.broker = broker
self.port = port
self.connected = False
self._message_queue = deque(maxlen=1000)
self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
self.client.on_connect = self._on_connect
self.client.on_disconnect = self._on_disconnect
def connect(self):
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.