MQTT "events" and automations

I’m trying to get a system working using MQTT auto discovery. The device being controlled is kind of annoying. I can send commands to it, and wait for a response, but I’m unable to monitor the device itself (making an MQTT switch inappropriate.)

My “solution” is to use an MQTT button to send commands to the device (which works) and have the device use MQTT events (MQTT Event - Home Assistant) to send the response back (which is either “success” or “failure.”

My MQTT autodiscovery config to the response event is similar to this:

{
  "name": "command_result",
  "device": {
     // stuff deleted
  },
  // availability stuff here
  "retain": false,
  "state_topic": "homeassistant/event/some-identifier/command_result/state",
  "event_types": [
    "success",
    "failure"
  ]
}

This appears to work. My device is absolutely sending an “event_type”:“failure” payload to the proper topic whenever the command fails. However, I’m finding that I can’t use an automation to handle “failure” responses. As a simple case, here’s an automation that should give me a notification if the command ever fails:

alias: TESTING
description: ""
trigger:
  - platform: state
    entity_id:
      - event.some-identifiercommand_result
    attribute: event_type
    to: failure
condition: []
action:
  - service: notify.notify
    data:
      message: Failed to cancel starting the vehicle
mode: single

This only works once. If the command fails multiple times, the MQTT event never fires again. I can see why: The payload of the topic never changes… it’s always “failure”. So, I guess I need some other kind of automation action, but what?

I believe that my usage of the MQTT event is correct, based on the example in the docs. That example uses a doorbell and has “press” and “hold” event types. Obviously, if someone presses it (without holding), it could trigger an automation. However, if it’s pressed a second time, the event type would still be seen by HA as “press” and therefore no change would be detected!

Please help

1 Like

Shouldn’t you be triggering on event, not state?

I don’t see any “action” in the automations page for triggering on an event. The closest I see is a “manual event”, but when I select that, there aren’t any options for selecting the MQTT event…

I tried to set up a “manual event”… this is very cumbersome to use, but:

trigger:
  - platform: event
    event_type: event.some-identifiercommand_result
    event_data:
      event_data: failure

This doesn’t work. It’s confusing because there’s a field in the UI for filling in the “event_data”, but I can’t just put “failure” in there. If I try, I get an error: " expected dict for dictionary value @ data[‘event_data’]"

I never thought a simple button type event would be so annoying. Using the documentation for MQTT-event, how would an automation be set up for that doorbell that as event types of “press” and “hold” ?

Going into developer-tools → events, I can see the event listed on the right, but when I use the tool to “listen” to the event, it never fires when the MQTT topic is pubished.

It does “fire” when I use the “fire event” button on the same page.

Am I doing something wrong (or are MQTT events broken?)

Your state trigger will only fire once on repeated failure events - i.e. when it changes from something else to “failure”. This is the same for ALL state triggers, not just MQTT.

What you can do however, if you want to use a state trigger, is to publish a dummy value to the topic in your action block.

action:
  - service: notify.notify
    data:
      message: Failed to cancel starting the vehicle
  - service: mqtt.publish
    data:
      topic: "homeassistant/event/some-identifier/command_result/state"
      payload: "reset"

Syntax I think is right - or you can persist with the event trigger.

I think I might have to resort to clearing the state… I’m unsure why this MQTT event isn’t working whatsoever. The MQTT plugin see’s the message. HA’s own logbook shows:

blah blah some-identifiercommand_result detected an event

… but a “manual event” automation that doesn’t filter on event_data isn’t firing, and the event isn’t showing when I “listen to events” on the developer page.

I just hate doing things the “wrong” way. It seems like I must be doing something wrong, but I have no idea what.

This is frustrating. I might be encountering a bug with HA events, or I just might be not doing things correctly… :frowning:

I’m considering submitting a bug report, but I’d really hate to bug (no pun intended) the folks working on HA if the only problem is my lack of knowledge.

(Searching google, I’ve found exactly ZERO other people trying to use mqtt-events.)

Show us the raw event JSON: dev tools, then listen for the event.

The structure is typically more like this:

    - platform: event
      event_type: <type>
      event_data:
        event: <event>
        payload:
          <some_key>: <some_value>

As already mentioned: changes to the existing state doesn’t cause a state trigger to fire. This is not a limitation of MQTT: it’s how all states in HA behave, which is why you need to hook into the raw event bus.

The “raw” event? You mean what I’m publishing to MQTT?

To topic: “homeassistant/event/some-identifier/command_result/state”
Payload: “{ ‘event_data’ : ‘failure’ }”

As I mentioned, that doesn’t cause anything whatsoever to show up in the event listener in dev-tools, nor does it trigger an automation (even when the automation doesn’t filter on event_data) It does cause an entry in the logbook to show up similar to “blah blah some-identifiercommand_result detected an event”

Even when I use the dev tools to listen for ALL events (using “*” as the event to subscribe to) I don’t see the MQTT event being fired. (I do see the related state_changed event, but no event type corresponding to the MQTT name)

Show it to us.

I’m not Gary, obviously, but I’m trying to do something very similar and can’t figure out how to use mqtt events either.

I’m trying to listen to mqtt events from Zigbee2Tasmota with a config like this:

- event:
  - name: "Button Press Event"
    unique_id: tradfri_switch_1_event
    state_topic: "tele/tasmota_zigbeebridge/tradfri_switch_1/SENSOR"
    value_template: >
      { "event_type":
        {% if value_json.ZbReceived.tradfri_switch_1.Power is defined %}
          {% if value_json.ZbReceived.tradfri_switch_1.Power == 1 %}
            "turn_on"
          {% else %}
            "turn_off"
          {% endif %}
        {% else %}
          "unknown"
        {% endif %}
      }

    event_types:
      - "turn_on"
      - "turn_off"
      - "unknown"
    device_class: "button"
    device:
      name: "Tradfri Remote 1"
      identifiers: "tradfri_switch_1"
      manufacturer: "IKEA"
      model: "TRADFRI remote control"

I don’t see any mqtt events in the dev tools either. The state_changed event I see in the dev tools is this:

event_type: state_changed
data:
  entity_id: event.tradfri_remote_1_button_press_event
  old_state:
    entity_id: event.tradfri_remote_1_button_press_event
    state: "2024-01-07T14:35:19.863+00:00"
    attributes:
      event_types:
        - turn_on
        - turn_off
        - unknown
      event_type: turn_on
      device_class: button
      friendly_name: Tradfri Remote 1 Button Press Event
    last_changed: "2024-01-07T14:35:19.863706+00:00"
    last_updated: "2024-01-07T14:35:19.863706+00:00"
    context:
      id: 01...TJ
      parent_id: null
      user_id: null
  new_state:
    entity_id: event.tradfri_remote_1_button_press_event
    state: "2024-01-07T14:36:13.488+00:00"
    attributes:
      event_types:
        - turn_on
        - turn_off
        - unknown
      event_type: turn_on
      device_class: button
      friendly_name: Tradfri Remote 1 Button Press Event
    last_changed: "2024-01-07T14:36:13.488366+00:00"
    last_updated: "2024-01-07T14:36:13.488366+00:00"
    context:
      id: 01...MQ
      parent_id: null
      user_id: null
origin: LOCAL
time_fired: "2024-01-07T14:36:13.488366+00:00"
context:
  id: 01...MQ
  parent_id: null
  user_id: null

Now I could listen to the state_changed event instead of an mqtt event in my automation like this:

alias: Tradfri Test
description: ""
trigger:
  - platform: event
    event_type: state_changed
    event_data:
      entity_id: event.tradfri_remote_1_button_press_event
condition: []
action:
  - service: counter.increment
    metadata: {}
    data: {}
    target:
      entity_id: counter.test_counter
mode: single

But unfortunately, I can’t figure out how to listen to the event types defined in the mqtt event definition. Adding them to event_data just breaks the automation.

I think I’m also hindered by my lack of understanding of how mqtt events are supposed to be used and why the event generated is of type state_changed (when the ikea remote doesn’t have a state).

I also tried to configure the remote as a mqtt device trigger, but unfortunately the config isn’t persisent across HA reboots (and I don’t understand why). To make it stick I could apparently post to the config mqtt topics with the retain flag set, but then I’m a bit reluctant to distribute my config across configuration.yaml and the mqtt broker. I’d rather have it in one place.

Got stuck on this myself as well. I fully expected there to be some trigger based directly on the fact that the event was received, but if there is, I didn’t understand it.

I finally got a glimmer of understanding when I found this snippet on the event docs:

So, the solution is looking at the entity which was created when you defined the “event”, e.g.:

- event: 
    unique_id: "shelly_switch_keuken_switch_licht_event"
    device_class: "button"
    device: {
      identifiers: "shelly_switch_keuken",
      name: "Schakelaar keuken"
    }
    qos: 2
    state_topic: "shellies/shelly_switch_keuken/events/rpc"
    value_template: |
      { {% for element in value_json.params.events %}
      {% if element.component == "input:0" %}
      "event_type": "{{ element.event }}"
      {% endif %}
      {% endfor %} }
    event_types: 
      - single_push
      - double_push
      - long_push

This leads to the following entity appearing in hass:
image

The “state” of this entity is the timestamp of the most recently received message. Any time an event is received, there’ll be a “state” change - because of course the timestamp changed. You can use this as your trigger.

Then, in the automation, you can filter on the type of event if necessary:

Hope it helps someone :slight_smile:

2 Likes

So the solution is to simply just do a state trigger on the event entity? Thanks! That’s not obvious at all from the docs.