Connect Home Assistant lights to MQTT

PUBLISHED ON MAR 2, 2019 — HOWTO

It’s relatively easy to control equipment connected through MQTT from Home Assistant. However, to make Home Assistant-controlled devices available over MQTT requires a bit more work and I have not found a good guide on how to connect them. I wanted to find a generic pattern that makes it easy to add more lights possible to control through MQTT.

Core idea

This article shows how to make a light in Home Assistant available to switch on and off through MQTT, and to update the state of the MQTT topic based on the device state. A topic will be made into a Light in Home Assistant, and an existing Light in Home Assistant will be connected to it. The state will be updated between them: When one state changes to on or off, the other will be changed too.

The system can enter a “twitching” state if/when the switching occurs too frequently, and the state is changed faster than the system can update itself. This has happened on my Raspberry Pi when pushing the system, but not in normal use.

What is to be connected

The devices I connected for this article are two IKEA TRÅDFRI bulbs, connected through the IKEA Gateway, controlled mainly with an IKEA remote control. The IKEA Gateway is connected to Home Automation and two lights were connected to MQTT: lights.koksbordet (Swedish for kitchen table) and lights.bedroom_tablelamp. I am a beginner with Home Assistant, having using OpenHAB for a long time, and still do, in parallel with Home Assistant.

The configuration for how to connect to the MQTT broker and to the IKEA TRÅDFRI gateway is left out from the article. The lamps from the IKEA TRÅDFRI were discovered automatically and not added in the configuration files.

Lights and how to include files

Three key parts of the Home Automation configuration is covered: Light devices, Automation rules and the main configuration file. I have put my lights and automation configuration in external files: lights.yaml and automation.yaml. This is accomplished by adding below two rows to the configuration.yaml file:

automation: !include automations.yaml
light: !include light.yaml

Making an MQTT topic into a light

I used a simple MQTT topic with 1 representing the on state, and a 0 the off state. When sending 1 to MQTT topic indoors/kitchen/table, the kitchen table lamp is expected to light up, and turn off when we send a 0.

The MQTT configuration for the kitchen table lamp MQTT topic is listed below. On state change, it will send the new state to the MQTT topic, 0 or 1. On receiving either value on the topic, the corresponding Home Assistant state for the light will be set.

Two MQTT topics are defined, one for the kitchen table lamp, and one for the bedroom tablelamp. The Home Assistant light names are used, with a suffix of _mqtt. The _mqtt suffix is used in the automation rule to identify the link between MQTT light and connected Home Assistant Light:

  • light.koksbordet_mqtt
  • light.bedroom_tablelight_mqtt

The MQTT configuration for the two lights is straightforward.

# The light.yaml file for the two Trådfri lamps
---
- platform: mqtt
  name: 'koksbordet_mqtt'
  command_topic: "indoors/kitchen/table"
  state_topic: "indoors/kitchen/table"
  payload_on: 1
  payload_off: 0
  
- platform: mqtt
  name: 'bedroom_tablelamp_mqtt'
  command_topic: "indoors/bedroom/tablelamp"
  state_topic: "indoors/bedroom/tablelamp"
  payload_on: 1
  payload_off: 0

The TRÅDFRI gateway and the lamps

The IKEA TRÅDFRI gateway has two lamps, each connected to an IKEA TRÅDFRI remote control to change color and brightness. Turning the light on and off is the only thing we will do in this article.

The two lights are named without the _mqtt prefix above:

  • light.koksbordet
  • light.bedroom_tablelamp

Both are connected to the IKEA TRÅDFRI gateway.

Automation rules to connect lights and MQTT

The connection between lights and MQTT took me a long time to figure out as started in the wrong end, connecting lights and switches, and trying out templating, rather than figuring out the automations. Once I learned the automations part, it was quite straightforward to connect the lights with MQTT. What I wanted next was to make it easy to add new lights in the future, to the list of entities in entity_id:.

I am down to one code block where I need to add each “real” light and each MQTT light twice, once for on, and once for off. It’s good enough for now.

The first part of automations.yaml deals with turning on and off the MQTT light when the “real” lights change state. Using the powerful Home Assistant automation templating, the triggering entity_id can be reused in the action section. I use the Jinja2 string concatenation character + to bind the trigger entity id together with the suffix _mqtt for selecting the light to turn on.

Turning on/off the MQTT light from the TRÅDFRI light

As all the MQTT entities we have defined have an _mqtt suffix, the automation template action will find it when triggering the turn_on/turn_off service. Add the entitiy_ids that should trigger their respective MQTT lights to entity_id:.

- alias: 'Make lights switch on MQTT shadows'
  trigger:
    # Multiple entities for which you want to trigger shadow state.
    - platform: state
      entity_id: light.koksbordet, light.bedroom_tablelamp
      to: 'on'
  action:
    - service: light.turn_on
      data_template:
        entity_id: "{{ trigger.entity_id + '_mqtt' }}"

- alias: 'Make lights switch off MQTT shadows'
  trigger:
    # Multiple entities for which you want to trigger shadow state.
    - platform: state
      entity_id: light.koksbordet, light.bedroom_tablelamp
      to: 'off'
  action:
    - service: light.turn_off
      data_template:
        entity_id: "{{ trigger.entity_id + '_mqtt' }}"

Turning on/off the TRÅDFRI light based on MQTT

The other direction is needed too, to ensure the lights will receive the state changes from MQTT. Jinja2 is used here too, this time it’s the replace() function that is used, to remove the _mqtt suffix of the triggering entity_id. This way, the “real” lamp will assume the state of the MQTT corresponding lamp.

- alias: 'Make MQTT shadows switch lights'
  trigger:
    # Multiple entities for which you want to trigger shadow state.
    - platform: state
      entity_id: light.koksbordet_mqtt, light.bedroom_tablelamp_mqtt
      to: 'on'
  action:
    - service: light.turn_on
      data_template:
        entity_id: "{{ trigger.entity_id | replace('_mqtt', '') }}"

- alias: 'Make MQTT shadows switch lights'
  trigger:
    # Multiple entities for which you want to trigger shadow state.
    - platform: state
      entity_id: light.koksbordet_mqtt, light.bedroom_tablelamp_mqtt
      to: 'off'
  action:
    - service: light.turn_off
      data_template:
        entity_id: "{{ trigger.entity_id | replace('_mqtt', '') }}"

Conclusion

The templating solution for automation makes it easy to add the functionality to a large number of lamps by just adding them to automations.yaml and not have to copy the automation code to many places. Using Jinja2 and trigger.entity_id to find the corresponding light simplified the configuration tremendeously.

The use of MQTT enables OpenHAB and Home Assistant to share state and have the lights configured in both platforms and in sync, which is a great use case for an event driven architecture.