Do not trig automation too often ("debounce")

Hi,

Here is my setup : An RF button (part of a doorbell), an RTLSDR dongle and rtl_433 running. rtl_433 detects the RF signal from the button and publish an MQTT message for each data frame it detects. As the button sends the same frame multiple times each time the button is pressed, rtl_433 publishes the message several times too.

I want to write an automation that trigs when the button is pushed. My issue is that the automation is triggered multiple times too.

Is there a way to “debounce” the trigger, so that the automation won’t be executed more than once in a very short time?

Here is my automation so far:

- id: '1550948583732'
  alias: test2
  trigger:
  - platform: mqtt
    topic: /rtl_433
  condition:
  - condition: template
    value_template: '{% if states.automation.test2.attributes.last_triggered  %} {{(as_timestamp(now())-    as_timestamp(states.automation.test2.attributes.last_triggered))
  > 10 }}  {% else %}  true {% endif %}'
  action:
  - alias: ''
    data:
      entity_id: light.tradfri_bulb
    service: light.toggle
  - data:
      payload: test
      topic: /test
    service: mqtt.publish

It trigs on a new message in topic ‘/rtl_433’. The first condition tries to filter the trigger during 10s. Then, there are 2 actions : toggle light and publish a new message in topic ‘/test’.

This automation toggles the light 3 times, and publish 3 messages on MQTT (because rtl_433 published 3 messages too…), and I would like it to trig only once.

Any ideas?

Thanks

try this for the template:

value_template: '{{((as_timestamp(now()) - as_timestamp(states.automation.test2.attributes.last_triggered)) / 60) | int > 10 }}'

I’ve just tried it (without the division by 60, which seems to convert seconds to minutes), with similar behavior (the automation is still triggered 3 times).

My guess is that rtl_433 publishes 3 messages very fast (within 200ms), which will trigger the automation as fast and that somehow pass throught the condition.
I’ve seen several warning in the documentation about using ‘now()’ in conditions. Could it be the issue?

I’m really not sure but you could try this instead to eliminate it:

value_template: '{{(as_timestamp(strptime(states.sensor.date_time.state, '%Y-%m-%d, %H:%M')) - as_timestamp(states.automation.test2.attributes.last_triggered)) | int > 10 }}'

You’ll have to create the date_time sensor if you don’t already have it.

And sorry about the /60 for some reason I was thinking you wanted it to be minutes instead of seconds.

I still observe the same results, except than the minimum delay is 1 minutes, since the time_date sensor is accurate to the minute.

When I publish manually in the topic ‘rtl_433’ as if it was published by the tool, it works perfectly (the automation is triggered once, than nothing happen for a minute, and the the automation is triggered again).
So, the issue comes from the fact that the messages are posted too quickly. Why? I don’t know. Are multiple automations run in parallel?

I still hope to find a solution in Home-Assistant to cover this use can. Else, I’ll write a little python program that’ll do the filter at the source, before publishing in MQTT.

Btw, @finity thanks a lot for your help !

I think the issue is that the automation’s state in the state machine takes a while to update after the automation is triggered. So if the second trigger comes too fast the condition won’t see the new last_triggered from the previous run yet.

Another way to solve this problem is to use a timer as a trigger filter. Use the original trigger to start a timer, and then trigger the original automation when the timer becomes active. Something like this:

- alias: test2 trigger filter
  trigger:
  - platform: mqtt
    topic: /rtl_433
  action:
  - service: timer.start
    entity_id: timer.test2
- id: '1550948583732'
  alias: test2
  trigger:
  - platform: state
    entity_id: timer.test2
    to: active
  action:
  ...

The idea is when the first trigger comes in the timer’s state will change to active, which will trigger the original automation. If another trigger comes in before the timer finishes, it will just be restarted and its state will stay active. Once no more triggers come in long enough for the timer to finish, it will change to idle. Then it will be ready for the next sequence.

@pnbruckner Thank you, that seem to do the trick!

Here is my config:

I added the timer in configuration.yaml:

timer:
  doorbell_debouncer:
  duration: '00:00:03'

And the automation.yaml

- id: '1550948583733'
  alias: test2triggerfilter
  trigger:
  - platform: mqtt
    topic: /rtl_433
  action:
  - service: timer.start
    entity_id: timer.doorbell_debouncer

- id: '1550948583732'
  alias: doorbell_automation
  trigger:
  - platform: state
    entity_id: timer.doorbell_debouncer
    to: active
  action:
  - alias: ''
    data:
      entity_id: light.tradfri_bulb
    service: light.toggle
  - data:
      payload: test
      topic: /test
    service: mqtt.publish
1 Like

Hi this is an interesting solution, however is it somehow possible to forward the payload of the original message from the filter to the real automation? I want to process mqtt data in the main function.

Sure, just store it in an input_text.