Tutoriales

Guía de configuración MQTT en ESPHome: discovery, birth/will y brokers externos

Configura el componente mqtt: de ESPHome: broker y credenciales, topic_prefix, discovery de Home Assistant, mensajes birth y will, TLS, on_message y pruebas.

Actualizado · 9 min de lectura

Guía de configuración MQTT en ESPHome: discovery, birth/will y brokers externos

ESPHome habla MQTT con un solo bloque de YAML. Añade mqtt: con la dirección de un broker y cada sensor, switch y luz del dispositivo publicará su estado y aceptará comandos en topics predecibles, sin escribir C++. Funciona con Home Assistant mediante MQTT discovery, e igual de bien sin Home Assistant, alimentando Node-RED, Grafana o tu propio backend desde cualquier broker.

Esta guía cubre una configuración completa contra un broker externo, la estructura de topics que genera ESPHome, el discovery, los mensajes birth y will, TLS, suscripciones personalizadas y cómo verificar cada parte desde el navegador.

Una configuración mínima que funciona

livingroom.yaml
esphome:
  name: livingroom

esp32:
  board: esp32dev
  framework:
    type: esp-idf

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

logger:

ota:
  - platform: esphome
    password: !secret ota_password

mqtt:
  broker: broker.connectmq.com
  port: 1883
  username: !secret mqtt_user
  password: !secret mqtt_password
  client_id: esphome-livingroom
  topic_prefix: testmqtt/esphome/livingroom
  discovery: false

sensor:
  - platform: wifi_signal
    name: "WiFi Signal"
    update_interval: 30s
  - platform: uptime
    name: "Uptime"

switch:
  - platform: gpio
    pin: GPIO2
    name: "Relay"
    id: relay
secrets.yaml
wifi_ssid: "your-ssid"
wifi_password: "your-wifi-password"
ota_password: "change-me"
mqtt_user: "username"
mqtt_password: "password"

Flashéalo con esphome run livingroom.yaml. En el log deberías ver Connecting to MQTT... seguido de MQTT Connected!.

Hay tres ajustes que conviene definir explícitamente en lugar de fiarse de los valores por defecto:

  • topic_prefix usa por defecto el nombre del nodo (livingroom). En un broker compartido eso choca con el salón de todos los demás. Un prefijo único como testmqtt/esphome/livingroom mantiene tus topics como tuyos.
  • client_id debe ser único por dispositivo. Dos dispositivos con el mismo ID se desconectan mutuamente en bucle. Si lo omites, ESPHome genera uno a partir del nombre y la MAC, lo cual está bien; simplemente no copies nunca uno fijo entre archivos YAML.
  • discovery: false mientras pruebas en un broker público o compartido, para no publicar mensajes de configuración de Home Assistant en un espacio de nombres que leen otras personas. Actívalo cuando uses tu propio broker.

Los topics que genera ESPHome

Cada entidad recibe un topic de estado, y las entidades controlables un topic de comando. El object ID es el nombre de la entidad en minúsculas, con los espacios sustituidos por guiones bajos:

EntidadTopicDirección
Disponibilidadtestmqtt/esphome/livingroom/statusdispositivo → broker (online / offline)
Sensor WiFi Signaltestmqtt/esphome/livingroom/sensor/wifi_signal/statedispositivo → broker
Sensor Uptimetestmqtt/esphome/livingroom/sensor/uptime/statedispositivo → broker
Estado del switch Relaytestmqtt/esphome/livingroom/switch/relay/statedispositivo → broker (ON / OFF)
Comando del switch Relaytestmqtt/esphome/livingroom/switch/relay/commandbroker → dispositivo (ON / OFF / TOGGLE)
Logstestmqtt/esphome/livingroom/debugdispositivo → broker

Puedes sobrescribir cualquiera por entidad con state_topic: y command_topic: cuando necesites encajar en un diseño de topics existente. La opción log_topic: controla el topic de depuración; ponla a null para dejar de publicar logs por MQTT, lo que ahorra ancho de banda en dispositivos con mucha actividad.

Mensajes birth, will y shutdown

ESPHome envía un mensaje birth tras conectarse y registra un Last Will en el broker. Por defecto ambos van a <topic_prefix>/status, retained, con los payloads online y offline. Eso es lo que usa Home Assistant para la disponibilidad de las entidades. Puedes personalizarlos:

Custom availability
mqtt:
  # ...
  birth_message:
    topic: testmqtt/esphome/livingroom/availability
    payload: "connected"
    retain: true
  will_message:
    topic: testmqtt/esphome/livingroom/availability
    payload: "lost"
    retain: true
  shutdown_message:
    topic: testmqtt/esphome/livingroom/availability
    payload: "shutdown"
    retain: true
  keepalive: 30s

El will lo publica el broker, no el dispositivo, aproximadamente 1,5 × keepalive después de que el dispositivo deje de responder. El mensaje shutdown lo envía el propio dispositivo antes de un reinicio planificado o una actualización OTA, así puedes distinguir "reinicio intencionado" de "se quedó sin corriente". Los tiempos se explican en MQTT Last Will, y el flag retained en mensajes retenidos.

Discovery de Home Assistant

Con discovery: true (el valor por defecto), ESPHome publica un mensaje de configuración retained por entidad bajo <discovery_prefix>/<component>/<node>/<object_id>/config. La integración MQTT de Home Assistant se suscribe a ese prefijo y crea las entidades automáticamente.

Discovery on your own broker
mqtt:
  broker: broker.connectmq.com
  port: 1883
  username: !secret mqtt_user
  password: !secret mqtt_password
  discovery: true
  discovery_prefix: homeassistant
  discovery_retain: true

Lo que debes saber:

  • El prefijo debe coincidir. Home Assistant escucha en homeassistant salvo que lo hayas cambiado en las opciones de la integración MQTT. Si cambias uno, cambia ambos.
  • Los mensajes de discovery son retained. Si renombras o eliminas una entidad, la configuración antigua sigue en el broker. Bórrala publicando un mensaje retained vacío en el topic de configuración antiguo.
  • Un mismo broker para ambos. Home Assistant debe conectarse al mismo broker que el dispositivo. Para la parte de Home Assistant, lee Home Assistant MQTT.

Suscribirse y publicar desde YAML

ESPHome puede reaccionar a cualquier topic, no solo a sus propios topics de comando, y publicar mensajes arbitrarios:

Custom subscriptions and publishes
mqtt:
  # ...
  on_message:
    - topic: testmqtt/esphome/livingroom/cmd/toggle
      qos: 1
      then:
        - switch.toggle: relay
  on_json_message:
    topic: testmqtt/esphome/livingroom/cmd/json
    then:
      - if:
          condition:
            lambda: 'return x["relay"] == "on";'
          then:
            - switch.turn_on: relay
          else:
            - switch.turn_off: relay

interval:
  - interval: 60s
    then:
      - mqtt.publish:
          topic: testmqtt/esphome/livingroom/heartbeat
          payload: "alive"
          qos: 0
          retain: false

on_json_message parsea el payload con ArduinoJson y lo expone como x. Mantén los payloads pequeños: los mensajes muy grandes pueden superar el buffer del cliente en placas con poca memoria.

Usar TLS con un broker externo

En ESP32, añade el certificado de la CA del broker y cambia al puerto 8883:

TLS on ESP32
mqtt:
  broker: broker.connectmq.com
  port: 8883
  username: !secret mqtt_user
  password: !secret mqtt_password
  certificate_authority: |
    -----BEGIN CERTIFICATE-----
    ... root CA of your broker's certificate chain ...
    -----END CERTIFICATE-----

Usa la CA raíz de la cadena que presenta el broker, no el certificado del servidor. El framework ESP-IDF es la opción recomendada para MQTT sobre TLS en ESP32. El soporte en ESP8266 es mucho más limitado (solo fingerprints con el framework Arduino), así que para dispositivos donde TLS es crítico elige un ESP32, o mantén los ESP8266 en una red local de confianza. Nuestra guía de TLS en ESP32 explica cómo extraer el certificado correcto con openssl s_client.

Prueba cada parte desde el navegador

  1. Abre el cliente MQTT online, conéctate a broker.connectmq.com en el puerto 8084 (ruta /mqtt) y suscríbete a testmqtt/esphome/livingroom/#.
  2. Deberías ver status = online (retained) y los estados de wifi_signal y uptime cada 30 segundos.
  3. Publica ON en testmqtt/esphome/livingroom/switch/relay/command. El relé conmuta y switch/relay/state informa ON.
  4. Publica cualquier cosa en testmqtt/esphome/livingroom/cmd/toggle para probar on_message.
  5. Apaga la placa. Tras aproximadamente 1,5 × keepalive, el will pone status en offline. Si en su lugar la reinicias desde el dashboard, verás primero el mensaje shutdown.

Observa tu nodo ESPHome en el cliente online

Si una entidad no aparece en el topic esperado, pega el topic y tu filtro en el topic matcher para detectar una errata en el prefijo.

Referencia rápida de problemas

Mensaje de logCausa probable
MQTT Disconnected: TCP disconnected.Host o puerto incorrectos, firewall, puerto TLS usado sin certificate_authority
MQTT Disconnected: Not Authorized.Usuario o contraseña incorrectos, o una ACL deniega al cliente
MQTT Disconnected: Identifier Rejected.Client ID rechazado o duplicado
El dispositivo se reinicia a los 15 minutosSe alcanzó reboot_timeout porque el broker es inaccesible

Para un diagnóstico paso a paso, lee ESPHome MQTT no conecta.

Configurar ESPHome para MQTT es sobre todo una cuestión de nombres: un prefijo de topic y un client ID únicos, el discovery activado solo donde vive Home Assistant y topics de disponibilidad en los que puedas confiar. Acierta con eso, verifica el estado, los comandos y el will desde el cliente online, y el mismo YAML pasará de tu broker de pruebas a producción cambiando un hostname y un secreto.

Preguntas frecuentes

¿Puedo usar ESPHome con MQTT y la API nativa a la vez?

Sí. Los componentes api: y mqtt: son independientes. Muchas instalaciones mantienen la API nativa para Home Assistant y añaden MQTT para que otros sistemas (Node-RED, un registrador de datos, otra sede) lean los mismos sensores.

¿Por qué mi dispositivo ESPHome se reinicia cada 15 minutos?

El componente mqtt: tiene reboot_timeout, de 15 minutos por defecto: si no puede alcanzar el broker durante ese tiempo, el dispositivo se reinicia. Arregla la conexión o pon reboot_timeout: 0s para desactivarlo en dispositivos que deben seguir funcionando sin conexión.

¿En qué topics publica ESPHome?

Por defecto en <topic_prefix>/<component_type>/<object_id>/state, donde topic_prefix es el nombre del nodo y object_id es el nombre de la entidad en minúsculas con guiones bajos. Las entidades controlables escuchan en la misma ruta terminada en /command.