Combine MQTT Switch and Binary Sensor

I have a working MQTT switch and separate non-MQTT binary sensor that I’m trying to combine into the cover component with no success.

The goal would be to get the open / close status from the binary sensor. When it’s off the door is closed and when on the door is open. Otherwise the MQTT switch seems to be working just fine.

I’ve tried the following with it always showing an unknown status:

cover:
  - platform: mqtt
    name: garage_door_left
    device_class: garage
    state_topic: "garage/door"
    command_topic: "garage/button"
    payload_open: "OPEN"
    payload_close: "OPEN"
    payload_stop: "OPEN"
    optimistic: false
    retain: false
    value_template: "{{ states.binary_sensor.alarm_monitor_0_18 }}"

  - platform: mqtt
    name: garage_door_left
    device_class: garage
    state_topic: "garage/door"
    command_topic: "garage/button"
    payload_open: "OPEN"
    payload_close: "OPEN"
    payload_stop: "OPEN"
    optimistic: false
    retain: false
    value_template: "{{ is_state('binary_sensor.alarm_monitor_0_18', 'on') }}"

Also tried this version of the value_template with no success.

value_template: "{{ states.binary_sensor.alarm_monitor_0_18.state }}"

Could you describe your goal with more details?
For example, how exactly do you see your combined a MQTT switch and a template binary sensor into another component?
and it would be great to see what mqtt messages are in the broker log when the door opens/closes and same for button.

I’m not familiar with covers but your code seems strange at least because
a) it’s almost identical for both sections (cover and switch?)
b) there’s no payload_open/close in mqtt switch afaik
c) your last value_template won’t work because for binary_sensor it should return True or False, not state

The end goal is combine two separate entities into one cover entity.

There is the switch which is MQTT controlled basically toggles a relay to open the door.

And then there is the state binary sensor which is currently coming in via mysensors. So two separate components that’d I’d like to present as one.

As one what? Switch? Sensor? I don’t quite get it.

Put this into the Template Editor and what does it produce?

{{ states.binary_sensor.alarm_monitor_0_18 }}

It will be on or off.

Do the same with this template:

{{ is_state('binary_sensor.alarm_monitor_0_18', 'on') }}

It produces true or false.

You need to choose one of those two templates and set the state_on and state_off topics to use the same states. For example, if you choose to use the first template, add these lines to the cover’s configuration:
state_on: “on”
state_off: “off”

 state_open: "on"
 state_closed: "off"

EDIT
Replaced incorrect options.

So it doesn’t looks like there is a state_on or off for the MQTT cover. I am wondering through if what I should do is configure the ESP MQTT nodes as a MQTT switch first. And then try to combine the MQTT switch and binary sensor into one cover template?

You are correct; my mistake. In my haste to reply to you I used the wrong options. For cover they are:

 state_open: "on"
 state_closed: "off"

I’ve corrected the error in my previous reply.

I think the challenge comes from the fact that Home Assist is expecting to get this value via the MQTT state / position_topic. Which in my case it won’t because the binary sensor is not an MQTT device. Here’s my current config.

cover:
  - platform: mqtt
    name: garage_door_right
    device_class: garage
    command_topic: "right-garage/button"
    payload_open: "OPEN"
    payload_close: "OPEN"
    payload_stop: "OPEN"
    state_open: "on"
    state_closed: "off"
    optimistic: false
    retain: false
    value_template: "{{ states.binary_sensor.alarm_monitor_0_13 }}"

I thought it might be worth trying but I agree with you, the component is waiting for a payload to arrive via the state_topic before it applies the value_template.

An easy workaround is to use a simple automation to make binary_sensor.alarm_monitor_0_13 publish its state to an MQTT topic (such as right-garage/status).

- alias: 'MQTT Alarm Monitor 13'
  hide_entity: true
  trigger:
    platform: state
    entity_id: binary_sensor.alarm_monitor_0_13
  action:
    service: mqtt.publish
    data_template:
      topic: 'right-garage/status'
      payload: "{{ 'open' if trigger.to_state.state == 'on' else 'closed' }}"

Using the automation, the cover’s configuration is simplified to this:

cover:
  - platform: mqtt
    name: garage_door_right
    device_class: garage
    state_topic: 'right-garage/status'
    command_topic: 'right-garage/button'
    payload_open: 'OPEN'
    payload_close: 'OPEN'
    payload_stop: 'OPEN'
1 Like

Thank you! That nailed it, I feel like there might be an easier way to accomplish this but it worked. Here’s the final working code set.

Automations:

- alias: 'Read in Garage Doors State On Startup'
  hide_entity: true
  trigger:
    platform: homeassistant
    event: start
  action:
    - service: mqtt.publish
      data_template:
        topic: 'right-garage/status'
        payload: "{{ 'open' if binary_sensor.alarm_monitor_0_13.to_state.state == 'on' else 'closed' }}"
    - service: mqtt.publish
      data_template:
        topic: 'center-garage/status'
        payload: "{{ 'open' if binary_sensor.alarm_monitor_0_19.to_state.state == 'on' else 'closed' }}"
    - service: mqtt.publish
      data_template:
        topic: 'left-garage/status'
        payload: "{{ 'open' if binary_sensor.alarm_monitor_0_18.to_state.state == 'on' else 'closed' }}"

- alias: 'MQTT Right Garage Publish'
  hide_entity: true
  trigger:
    platform: state
    entity_id: binary_sensor.alarm_monitor_0_13
  action:
    service: mqtt.publish
    data_template:
      topic: 'right-garage/status'
      payload: "{{ 'open' if trigger.to_state.state == 'on' else 'closed' }}"

- alias: 'MQTT Center Garage Publish'
  hide_entity: true
  trigger:
    platform: state
    entity_id: binary_sensor.alarm_monitor_0_19
  action:
    service: mqtt.publish
    data_template:
      topic: 'center-garage/status'
      payload: "{{ 'open' if trigger.to_state.state == 'on' else 'closed' }}"

- alias: 'MQTT Left Garage Publish'
  hide_entity: true
  trigger:
    platform: state
    entity_id: binary_sensor.alarm_monitor_0_18
  action:
    service: mqtt.publish
    data_template:
      topic: 'left-garage/status'
      payload: "{{ 'open' if trigger.to_state.state == 'on' else 'closed' }}"

Config

cover:
  - platform: mqtt
    name: garage_door_right
    device_class: garage
    command_topic: "right-garage/button"
    state_topic: "right-garage/status"
    payload_open: "OPEN"
    payload_close: "OPEN"
    payload_stop: "OPEN"
    optimistic: false
    retain: false

  - platform: mqtt
    name: garage_door_center
    device_class: garage
    command_topic: "center-garage/button"
    state_topic: "center-garage/status"
    payload_open: "OPEN"
    payload_close: "OPEN"
    payload_stop: "OPEN"
    optimistic: false
    retain: false

  - platform: mqtt
    name: garage_door_left
    device_class: garage
    command_topic: "left-garage/button"
    state_topic: "left-garage/status"
    payload_open: "OPEN"
    payload_close: "OPEN"
    payload_stop: "OPEN"
    optimistic: false
    retain: false
1 Like

Three garage doors! :slight_smile:

Today’s your lucky day. Here’s a single automation that can handle all three binary_sensors.

- alias: 'MQTT Garage Publish'
  hide_entity: true
  trigger:
    platform: state
    entity_id: binary_sensor.alarm_monitor_0_13, binary_sensor.alarm_monitor_0_18, binary_sensor.alarm_monitor_0_19
  action:
    service: mqtt.publish
    data_template:
      topic: >-
        {% set topics = {"13":'right', "18":'left', "19":'center'} %}
        {% set door = trigger.to_state.object_id[-2:] %}
        {{ topics[door] if door in topics.keys() else 'unknown' }}/status
      payload: "{{ 'open' if trigger.to_state.state == 'on' else 'closed' }}"
      retain: true

How it works:

  • It triggers if any one of the three binary_sensors changes state.
  • It defines a dictionary called topics where the key is the last two characters of the binary_sensor’s name (13, 18, 19) and the value is the door’s name (right, left, center).
  • It extracts the last two characters from the name of whichever binary sensor triggered the automation and assigns it to the door variable.
  • To create the topic, it uses the dictionary to find the door’s name then appends /status.

EDIT

I added retain: true to the automation. This will cause the states of the binary_sensors to be retained (stored) by the broker. That means when Home Assistant restarts it will re-subscribe to the broker and immediately receive the last known state of each binary sensor. In other words, it duplicates the functionality of the automation you created to run on startup. Therefore the four automations you currently have can be reduced to just one ‘do it all’ automation.

NOTE
You will initially need to open/close each door once so that the automation is triggered and publishes the retained state of each door.

2 Likes

@rsaturns I wanted to thank you for posting your complete, final code. This worked perfectly with my Sonoff/Espurna setup. Thanks again for the clarity and following up with your solution.