MQTT Device Trigger combined with action/choose syntax

I’ve a couple of Xiaomi Aqara/Opple switches with 6 buttons. I use these buttons to toggle lights (single click), dim a specific light (long press) and some other automations (double/triple clicks). These switches are connected to Zigbee2MQTT which publishes the devices/actions to Home Assistant via MQTT.

My problem is that I need a lot of automations for each switch. For example, I need an automation for each button to toggle a specific light.

I was wondering if I could use the new action/choose syntax in my action block. I’ve seen some examples using a condition check inside the choose block but I’m not sure if that’s possible in my case.

This is an example of one of my existing automations:

alias: 'Bedroom opple4 button 3 single click'
trigger:
  platform: device
  domain: mqtt
  device_id: c663968060344434aa2b7ac329a6af92 
  discovery_id: 0x04cf8cdf3c794243 action_button_3_single
  type: click
  subtype: button_3_single
action:
  - service: light.toggle
    data:
      entity_id: light.bedroom_light

I would like to have some kind of choose/condition in the action block to support all buttons with their corresponding light.

So my goal is to have one single automation to toggle a light with each button:

Button Light
Button 1 Light1
Button 2 Light2
Button 3 Light3
Button 4 Light4
Button 5 Light5
Button 6 Light6

Can someone explain to me if this is possible?

1 Like

I wanted to do the exact same thing with an IKEA Tradfri remote and could finally figure out a nice way by listening on the mqtt-topic directly:

- alias: 'MyRemote fired'
  mode: parallel
  trigger:
    - platform: mqtt
      topic: 'zigbee2mqtt/0xxxxxxx'
  condition:
    - condition: template
      value_template: "{{ trigger.payload_json.action in ['arrow_left_click','arrow_left_hold',arrow_right_click] }}" # add more button-actions here
  action:
     - choose:
       - conditions: "{{ trigger.payload_json.action == 'arrow_left_click' }}"
         sequence:
           - service: light.toggle
             entity_id: light.yeelight2
       - conditions: "{{ trigger.payload_json.action == 'arrow_left_hold' }}"
         sequence:
           - service: light.toggle
             entity_id: light.yeelight1
       - conditions: "{{ trigger.payload_json.action == 'arrow_right_click' }}"
         sequence:
           - service: light.toggle
             entity_id: light.yeelight3
       # ... more conditions for other button-actions

The topic propagates a JSON with the field action, I think this should be the case for your Opples, too, as we both work with z2m.
The condition is to avoid activations in case that the remote just sends updates for link-/battery-quality withput any user-interaction. An improvement at this point could be - to beautify/simplify this even more - to let the condition-template check for the “key-substrings” like trigger.payload_json.action in ['toggle','click','hold','release'], but unfortunately this didn’t work out. Probably somebody has an idea where the mistake is.

Just to document my pretty long journey on this, here another approach inspired by tinkerer on Discord, which I could not get to work:

- alias: 'MyRemote fired'
  mode: parallel
  trigger:
    - platform: state
      entity_id: sensor.myremote_action
  condition:
    - condition: template
      value_template: >-
        {% if (state_attr(trigger.to_state.entity_id, 'action') != None) %}
          true
        {% endif %}
  action:
     - choose:
       - conditions: "{{ is_state_attr('sensor.remotekueche_action', 'action' ,'arrow_left_click') }}"
         sequence:
           - service: light.toggle
             entity_id: light.yeelight2
       - conditions: "{{ is_state_attr('sensor.remotekueche_action', 'action', 'toggle') }}"
         sequence:
           - service: light.toggle
             entity_id: light.yeelight1
       # ... more conditions for other buttons

Probably this piece of code helps somebody inanother situation…

did you saw this blueprint? Zigbee2mqtt - Aqara Opple switch 3 bands.

For future reference, if there is only one type of service call and only the entity names change, then instead of using choose it can be done like this:

- alias: 'MyRemote fired'
  mode: parallel
  trigger:
  - platform: mqtt
    topic: 'zigbee2mqtt/0xxxxxxx'
  action:
  - service: light.toggle
    entity_id: >
      {% set modes = {'arrow_left_click': 'yeelight2', 'arrow_left_hold': 'yeelight1', 'arrow_right_click': 'yeelight3'}
      {% if trigger.payload_json.action in modes.keys() %} light.{{ modes[trigger.payload_json.action] }}
      {% else %} none
      {% endif %}

The modes dictionary is used determine which entity to use based on the received payload action.
This automation doesn’t need a condition. If the received payload action doesn’t exist in the modes dictionary then the entity is none. The light.toggle service will fail silently when given an entity called none.

FWIW, the same technique could be used even when different kinds of service calls are needed (i.e. one payload action calls one kind of service whereas another payload action calls a different service).