Trouble with MQTT Binary (Motion) Sensor

Because the payload isn’t being published as a retained message.

That’s exactly how the documentation explains its behavior (and why I said it doesn’t apply at startup).

I don’t know what “queue” you mean and the broker’s location is irrelevant. Home Assistant acts as an MQTT client so on startup it logs into the broker (wherever it’s hosted) and subscribes to all required topics (i.e. the topics of all MQTT-based entities, MQTT triggers, etc). At the moment it subscribes, it receives any payloads that were published as a retained message (i.e. it receives payloads stored on the broker).

Then you did something wrong somewhere. Where did you set the “retain flag”? It must be set on the device that publishes to zoneminder/1 and then confirmed by checking the topic with another client (like MQTT Explorer).

This isn’t useful for this application because the received payload is a JSON dictionary plus, apparently, the desired key in the dictionary doesn’t always exist.

If you’re forcing it to off on startup, what if it’s state was actually on just before Home Assistant restarted? Your automation just forced it into the wrong state.

1 Like

The entire JSON is the payload unfortunately.

Entire json is fine.
That’s what the value template and key:value do to refine the entire json to that key and then use it’s value.

key >>>  "eventtype": "event_start"   <<< value
value_template: >
        {{ iif(value_json.eventtype is defined and value_json.eventtype == 'event_start', 'ON', 'OFF') }}

What is the “Off” state json published though?? or isn’t there any or it always ‘event_start’?
It never publishes an off state…

This won’t fit your use case because of the json… tasmota pir example It does a good job of defining the other parts though.

Anyway I am just getting in the way now.

The template I posted above checks if the desired key exists (eventtype) and its associated value is event_start. If true it reports ON otherwise it reports OFF. In other words, if the value is anything other than event_start it reports OFF.

The sensor’s state will be unknown at startup if the topic doesn’t have a retained message.

1 Like

So I was bored and decided to play around with this.

If you manually publish a retained msg to your broker without the event_start, the binary sensor will start as clear in lovelace on mqtt reload or HA restarts.
You could also update your automation so that if the state was unknown or unavailable for > 5secs repuplish the manual message. Although the retained msg shouldn’t be deleted unless your broker failed…

mqtt:
  binary_sensor:
    - name: driveway_mus_motion
      unique_id: driveway_mus_motion
      device_class: motion
      state_topic: "zoneminder/1"
      value_template: >
          {{ iif(value_json.eventtype is defined and value_json.eventtype == 'event_start', 'ON', 'OFF') }}
      off_delay: 20

Capture

Retained msg --- starts as clear. Leave this as retained on your broker

{
  "name": "Driveway (MUS):(32687) Linked",
  "detection": [],
  
  "hookvalue": "1",
  "eventid": "32687",
  "monitor": "1",
  "state": "alarm"
}

Capture

retained msg --  starts as detected 

{
  "name": "Driveway (MUS):(32687) Linked",
  "detection": [],
  "eventtype": "event_start",
  "hookvalue": "1",
  "eventid": "32687",
  "monitor": "1",
  "state": "alarm"
}

Does this ever change btw?

 "detection": [],

Your suggestion forces the binary_sensor’s state to off on startup. jlw52761 stated that he has already created an automation that does this. It’s not a good solution because if the binary_sensor was on before restarting Home Assistant, it will be forced to off on startup (and no longer report the device’s true state).

The solution is to ensure the device publishing to zoneminder/1 does so as a retained message. If there’s no ability to do that then the alternative is to create a ‘middleman’ automation that subscribes to zoneminder/1, publishes whatever it receives as a retained message to a new topic, like zm/1, and then set the MQTT Sensor’s state_topic to zm/1. It’s a trivially simple automation that ensures the sensor immediately acquires a correct value on startup.

True.

Although if there was actually motion when HA restarted, then the retained message would be ignored in favour of the real message received after HA subscribed to the topic.

It wouldn’t be “ignored”. The sensor always uses the latest value published to its state_topic.

Yes… And if there is motion, it would be event_start and the state would be detected.

You’re stating the obvious so I fail to see why you had claimed a value would be “ignored”.

Each new payload published to a topic replaces the previous one. The subscriber to the topic (the MQTT Sensor) doesn’t “ignore” anything, it simply receives the latest published payload.

You are missing the point.
This has removed his unknown state, so fixes his original concern of the card showing On on unknown state.

If the state was motion when HA stops it should have started whatever automation was trying to triggered, before it died.

If HA crashed mid automation it was never going to act…

The state now briefly starts as unknown, then immediately flicks to clear.
HA is now subscribed.

If there is motion, there will be a new message with event_start, which will immediately update the state from clear to detected, which has updated the any triggers to start an automation or whatever.

With all due respect, you don’t appear to understand how Home Assistant uses MQTT with an MQTT Binary Sensor. If configured correctly, there’s no need for an automation to force the entity’s state to a default value.

For reference, I have several MQTT Binary Sensors (and other MQTT-based entities like lights, switches, sensors, locks, thermostat, etc) that always report the correct state on startup (over three years of operation). None require automations to set their state on startup.

What automation did I use?

I didn’t.

I was suggesting he could update his current automation to resend the message if the broker died. The rest of the automation can be deleted.

All you’re offering are unnecessary band-aids when the solution is to simply use retained messages correctly.

If you send every message retained…
It will work sure.
If HA crashes and 5 hours later I restart it do I want a motion detection from 5 hours ago?

The way I used the retained message was to send 1 single retained message. That is all that ever needed to be sent(excluding broker failure and losing that retained message, which was the automation suggestion)

The rest of the messages can be not retained and what I posted earlier is the result. If the retained message cannot be set on the device. This is the option to use.

I didn’t mean for his automation to be used at all.

While Home Assistant is offline, the broker continues to receive payloads published to topics. Whenever Home Assistant starts, it reconnects to the broker, subscribes to all required topics, and immediately receives the most recently published payload (assuming it was published as a retained message).

The scenario you described requires both Home Assistant and the broker to be offline. jlw52761 would have to let us know if having both offline for long periods of time is a common occurrence in his operating environment.

Well yes I suppose it would actually be the broker failed in that case. Seeing as it’s a separate unit. I was thinking more along the lines of built-in broker and the whole machine crashes.

It was a rhetorical question really.
In some cases I might like to know there was movement detected before a crash, if I was using it for security, I probably would.

If I was using it to set scenes in rooms I want the actual now state, so this would be fine. The movement in the room would start the trigger.

Edit.

So we are clear…
I am presuming the motion sensor only sends ON states. If it never actually sends OFF states, then a retained ON is going to be the last message. It could have been sent many hours ago.

The problem to avoid is having the unknown state. A retained ON would do that, but it could also be stale. Without any retained message the unknown state stays active until there is actually motion as no OFF state is sent. The way I set it up removes the unknown, by setting the state immediately to OFF. Any new messages will be ONs, because ON is all that is ever sent.

That’s why the off_delay resets it to OFF, but it doesn’t reset unknown.

Technically speaking, a state value of unknown isn’t a problem but a truthful report of the current situation. If a binary_sensor entity has not received any information from the device, the entity’s state is neither on or off, it’s unknown; it doesn’t know which of the two nominal states is the actual current state so it reports unknown (this additional state was added several versions ago). The other non-nominal state is unavailable.

To avoid an unknown state on startup, the device must supply the entity with one of the two nominal states. The common method is to ensure the device publishes its state as a retained message. The argument that the value might be “stale” only applies to the atypical situation where the broker has ceased to function for a significant period of time. Otherwise, it works for typical situations like merely restarting Home Assistant and/or the broker.

Where does the Off state come from… If it never publishes Off.

If I was in a room a few hours ago. A retained On is sent.

I restart HA, I get an On state from a few hours ago.

If the device never publishes an “off” message, then the MQTT Binary Sensor should employ the off_delay option. In that specific situation, the use of retained message isn’t recommended. It’s something I explained in a different post related to receiving multiplexed payloads:

I didn’t see jlw52761 reply to your question if the device publishes an “off” message of any kind. What I did see written is that the payload may at times fail to contain the eventtype key. It’s unclear if that implicitly indicates an “off” message or if it’s just one of the quirks of the device’s behavior. The template I suggested assumes the key’s absence implies an “off” message. If the key exists in the payload but its value is anything other than event_start the template will also interpret it as an “off” message.

Anyway, we’re discussing a lot of hypothetical operational edge-cases but we don’t know all the details of the device jlw52761 is using. :man_shrugging: