Mastering Custom MQTT Device Integration in Home Assistant: Beyond Discovery for Unique Sensors and Actuators

Represent Mastering Custom MQTT Device Integration in Home Assistant: Beyond Discovery for Unique Sensors and Actuators article
5m read

While Home Assistant's MQTT Discovery is a marvel, automatically configuring many devices for plug-and-play integration, there are often scenarios where it falls short. Perhaps you're building a highly customized ESP32-based sensor that publishes data in a unique JSON format, integrating a legacy industrial sensor with an MQTT gateway, or simply want unparalleled control over how your device data is represented. This is where mastering custom MQTT device integration becomes invaluable.

By manually defining MQTT entities in your Home Assistant configuration, you gain granular control over topics, payloads, state parsing, command structures, and availability. This guide will walk you through the process, empowering you to bring virtually any MQTT-enabled device into your Home Assistant ecosystem.

Prerequisites: Your MQTT Broker

Before diving into custom configurations, ensure you have an MQTT broker running and accessible by Home Assistant. The Mosquitto Broker add-on is a popular choice for Home Assistant OS/Supervised installations, or you can run one independently. Verify Home Assistant is connected to your broker via its MQTT integration.

Core MQTT Concepts for Custom Integrations

  • Topics: Hierarchical strings (e.g., home/living_room/temperature) used to identify data streams. Clients subscribe to topics to receive messages and publish to topics to send messages.
  • Payloads: The actual data transmitted over a topic. This can be plain text (e.g., ON, 25.5) or structured data like JSON (e.g., {"temperature": 25.5, "humidity": 60}).
  • Quality of Service (QoS): Defines message delivery guarantees. For most smart home uses, QoS 0 (at most once) or QoS 1 (at least once) is sufficient.
  • Retain Flag: If set to true, the broker will store the last message on a topic and send it immediately to any new subscribers. Crucial for stateful devices that report their status infrequently (e.g., door sensors).

Manual MQTT Entity Configuration: Step-by-Step

All custom MQTT entities are configured in your configuration.yaml file or a separate YAML file included via !include. Remember to restart Home Assistant after making changes.

1. MQTT Sensors: Reading Data

MQTT sensors display a numerical or string value from a published topic. They are fundamental for integrating environmental sensors, power meters, and other data sources.

Basic Temperature Sensor

Imagine an ESP32 publishing temperature to my_devices/bedroom/temp as plain text.

mqtt:
  sensor:
    - name: "Bedroom Temperature"
      state_topic: "my_devices/bedroom/temp"
      unit_of_measurement: "°C"
      value_template: "{{ value | float }}"
      device_class: "temperature"
      state_class: "measurement"

Sensor with Complex JSON Payload

What if your device publishes {"temp": 25.1, "hum": 62.3} to my_devices/weather_station?

mqtt:
  sensor:
    - name: "Outdoor Temperature"
      state_topic: "my_devices/weather_station"
      unit_of_measurement: "°C"
      value_template: "{{ value_json.temp | float }}"
      device_class: "temperature"
      state_class: "measurement"
    - name: "Outdoor Humidity"
      state_topic: "my_devices/weather_station"
      unit_of_measurement: "%"
      value_template: "{{ value_json.hum | float }}"
      device_class: "humidity"
      state_class: "measurement"

You can also extract attributes:

mqtt:
  sensor:
    - name: "Advanced Weather Station"
      state_topic: "my_devices/weather_station"
      value_template: "{{ value_json.temp | float }}" # Primary state
      json_attributes_topic: "my_devices/weather_station"
      json_attributes_template: "{{ value_json | tojson }}" # All JSON as attributes

2. MQTT Binary Sensors: On/Off States

Ideal for door/window sensors, motion detectors, or any device reporting a true/false state.

Door Sensor Example

Device publishes OPEN or CLOSED to my_devices/front_door/status.

mqtt:
  binary_sensor:
    - name: "Front Door Sensor"
      state_topic: "my_devices/front_door/status"
      payload_on: "OPEN"
      payload_off: "CLOSED"
      device_class: "door"
      qos: 1
      # Optional: set an availability topic for robustness
      # availability_topic: "my_devices/front_door/lwt"
      # payload_available: "online"
      # payload_not_available: "offline"

3. MQTT Switches: Controlling On/Off Devices

For smart plugs, relays, or any device that can be toggled.

Custom Relay Switch

To turn on, publish 1 to my_devices/porch_light/set. To turn off, publish 0.

mqtt:
  switch:
    - name: "Porch Light"
      command_topic: "my_devices/porch_light/set"
      state_topic: "my_devices/porch_light/state" # Device publishes its current state here
      payload_on: "1"
      payload_off: "0"
      state_on: "1" # How the device reports its ON state
      state_off: "0" # How the device reports its OFF state
      optimistic: false # Set to true if device doesn't report state back
      qos: 1
      retain: true # Device can subscribe to this to get last state on reboot

4. MQTT Lights: Advanced Lighting Control

Offers extensive control for RGB, dimmable, or white temperature lights.

Dimmable White Light

Publish brightness (0-255) to my_devices/desk_lamp/brightness/set.

mqtt:
  light:
    - name: "Desk Lamp"
      unique_id: "desk_lamp_custom_mqtt"
      schema: "json"
      state_topic: "my_devices/desk_lamp/state"
      command_topic: "my_devices/desk_lamp/command"
      brightness_scale: 255
      brightness_command_topic: "my_devices/desk_lamp/brightness/set"
      brightness_state_topic: "my_devices/desk_lamp/brightness/state"
      brightness_value_template: "{{ value | int }}"
      on_command_type: "brightness"
      # Example JSON command for on/off/brightness
      # Command: { "state": "ON", "brightness": 128 }
      # State: { "state": "ON", "brightness": 128 }

The json schema is powerful, allowing a single topic to carry multiple light attributes.

mqtt:
  light:
    - name: "Living Room RGBW Light"
      unique_id: "living_room_rgbw_custom_mqtt"
      schema: "json"
      state_topic: "my_devices/living_room_light/state"
      command_topic: "my_devices/living_room_light/command"
      brightness: true
      color_mode: true
      supported_color_modes: ["rgb", "color_temp", "brightness"]
      effect: true
      effect_list: ["flash", "fade", "smooth"]
      optimistic: false
      qos: 0
      retain: true

Your device would then expect and publish JSON like:

# Command to turn on:
{ "state": "ON" }

# Command to set brightness and color:
{ "state": "ON", "brightness": 128, "color": { "r": 255, "g": 0, "b": 0 } }

# Device state update:
{ "state": "ON", "brightness": 150, "color": { "r": 200, "g": 50, "b": 10 } }

5. MQTT Covers: Blinds, Gates, etc.

For controlling devices like blinds, garage doors, or gates that have open/close/stop actions or position.

Simple Blind Control

mqtt:
  cover:
    - name: "Bedroom Blinds"
      command_topic: "my_devices/bedroom_blinds/command"
      state_topic: "my_devices/bedroom_blinds/state"
      payload_open: "OPEN"
      payload_close: "CLOSE"
      payload_stop: "STOP"
      state_open: "OPEN"
      state_closed: "CLOSED"
      optimistic: false # Set to true if device doesn't report state back

Cover with Position

mqtt:
  cover:
    - name: "Garage Door"
      command_topic: "my_devices/garage_door/set"
      state_topic: "my_devices/garage_door/status"
      position_topic: "my_devices/garage_door/position"
      set_position_topic: "my_devices/garage_door/set_position"
      value_template: "{{ value_json.state }}"
      position_open: 100
      position_closed: 0
      qos: 1
      retain: true
      optimistic: false

Your device would publish {"state": "open", "position": 100} or {"state": "closed", "position": 0} to my_devices/garage_door/status and expect position commands on my_devices/garage_door/set_position.

Best Practices for a Robust Custom MQTT Ecosystem

  • Consistent Topic Structure: Design a logical, hierarchical topic structure (e.g., area/device_type/device_name/attribute) to keep your MQTT network organized.
  • Leverage availability_topic: This is crucial for knowing if your custom device is online. Devices should publish online to this topic on boot and use MQTT's Last Will and Testament (LWT) feature to publish offline if they disconnect unexpectedly.
  • Use retain: true for State Topics: For stateful entities (switches, binary sensors, lights), setting the retain flag on their state topics ensures that Home Assistant receives the current state immediately upon restart or reconnect, preventing "unknown" states.
  • Jinja2 Templating for Payload Parsing: Master Jinja2's value_template and json_attributes_template. They are essential for extracting specific values from complex JSON payloads and transforming them into the format Home Assistant expects.
  • Define unique_id: While not strictly necessary for basic functionality, adding a unique_id allows you to manage the entity from the Home Assistant UI (e.g., rename, disable) without editing YAML, and also avoids conflicts.
  • QoS Levels: For critical commands (e.g., garage door), consider QoS 1 or 2 to ensure delivery. For sensor readings, QoS 0 is often sufficient.
  • Security: Always enable authentication (username/password) on your MQTT broker and use SSL/TLS if your broker is exposed outside your local network.

Troubleshooting Tips

  • MQTT Explorer/Client: Use a tool like MQTT Explorer, MQTT.fx, or even the Home Assistant MQTT integration's built-in listener to subscribe to your device's topics and verify that messages are being published correctly and with the expected payloads.
  • Home Assistant Logs: Check Home Assistant's logs (Settings > System > Logs) for configuration errors related to your MQTT entities. Look for warnings or errors indicating invalid YAML, template issues, or connection problems.
  • Broker Logs: Review your MQTT broker's logs for client connection issues or authentication failures.
  • Payload Mismatch: Ensure your value_template or state_on/state_off values exactly match the payloads sent by your device, including case sensitivity.
  • Retain Flag Issues: If devices show "unknown" states after Home Assistant restarts, check if the retain flag is set correctly on the device's state messages.

Conclusion

Mastering custom MQTT device integration opens up a vast realm of possibilities within Home Assistant. It allows you to connect unique, DIY, or legacy devices that don't conform to standard protocols or discovery mechanisms. By understanding the core concepts of MQTT, leveraging Jinja2 templating, and adhering to best practices, you can build an incredibly robust, flexible, and truly personalized smart home ecosystem that goes far beyond off-the-shelf solutions.

Avatar picture of NGC 224
Written by:

NGC 224

Author bio: DIY Smart Home Creator

There are no comments yet
loading...