How to debounce an automation?

I would like to set up some redundant bridges on my network, namely RF433 to MQTT ones.

The problem is that each of the bridges will catch the RF433 message (from a wall switch for instance) and forward it, on its own topic, to MQTT - to be retrieved and processed by HA afterwards.

These wall switches have only one message: “I was pressed”. I then toggle the relevant electrical switch.

When receiving two such messages in a short time, the switch will likely be toggled twice.

Is there a debounce mechanism in HA - where I could say "discard this event if a previous one was triggered in the last n ms"?

3 Likes

It looks like it is enough to add a delay: "00:00:01" at the end of the action section.

1 Like

You could have used the last triggered attribute. I use this condition to stop multiple messages if people press my doorbell repeatedly:

  condition:
    condition: template
    value_template: "{{ (as_timestamp(now()) - as_timestamp(state_attr('automation.doorbell_alert', 'last_triggered') | default(0)) | int > 5)}}"

This way the automation wont alert me any more than every 6 seconds.

11 Likes

Thank you for that solution. Is there an advantage of this vs. the delay? (the one difference I see is that in your case the thread is finished while mine is hanging for a second)

Yeah that’s the advantage.

I like the plan to create redundant 433MHZ receivers but what’s the plan to keep the lights in sync with Home Assistant? The lights don’t report their state, only that they’ve changed state. Does HA remember their states after restarting?

I plan to set the initial state of the lamps to off when HA starts (I used to do that with AppDaemon, now I need to find out how to do this with HA as I am moving back to HA for the simple automations). The restart, long term, will be a rare event and I prefer to start with a clean state (and, should HA restart in the middle of the night, I prefer not to light everything up.

I then use toggle to change the state of the switches (and not specifically on or off)

- id: hass_startup
  alias: 'Hass startup'
  initial_state: true
  trigger:
    platform: homeassistant
    event: start

Thank you @tom_l, my last comment was a reply to @123 but the time it took me to make a coffee - the solution to the startup problem was there thanks to you :slight_smile:

1 Like

Apologies but can you explain your strategy in more detail? With the ability to only toggle the states, and not set them to a desired state (ON/OFF), I have difficulty envisioning how your proposed technique can maintain synchronization between a light’s actual state and HA’s tracking of that state (after a reboot).

Here’s the scenario:

  • Light #1 is ON. Light #2 is OFF
  • HA restarts and your automation sets the initial state of both lights to OFF. This is only HA’s representation of the light’s state; actual states remain #1 is ON and #2 is OFF.
  • " I then use toggle to change the state of the switches (and not specifically on or off )"
  • The result of the previous step is: #1 is OFF and #2 is ON.

Is the desired outcome?

To take your example:

  • Light #1 is ON. Light #2 is OFF
  • HA reboots and (in an automation which is triggered as in @tom_l response) sets as part of the action the state of both lights to off. The lights are now actually off and, collaterally, HA knows they are off (but it is not important)
  • from now on, only toggle is sent to devices

We do not need to keep the state of the lights to switch them on or off (the state is important for the UI, though).

Please let me know if this is not clear.

Perhaps this is the part I don’t understand. How can the action make the lights “actually off” when, and maybe this is the part I misunderstood, you can only transmit a command to toggle their state and not to explicitly set their state to on or off. If you can set their state explicitly, great!

Indeed, the state is important to the UI. Unless you don’t plan to use the UI, all is well. Otherwise, when out of sync, the UI will show lights are off when they are actually on (or vice-versa).

If you wish, you can keep track of a light’s state by leveraging MQTT’s ability to retain a topic’s message. Upon restart, Home Assistant re-subscribes to the topic and re-initializes itself with the light’s last-known state. If that interests you, let me know and I can elaborate.

When you call the service, you can use homeassistant.turn_off to explicitly turn the entity off (and turn_on to set to on and toggle to flip the state).

EDIT: the code I use could be helpful

- id: hass_startup
  alias: HASS starts
  initial_state: true
  trigger:
    platform: homeassistant
    event: start
  action:
    - service: homeassistant.turn_off
      data:
        entity_id:
          - light.ch2_lampe_pixar
          - light.ch2_lampe_entree
          - light.ch1_lampe_bureau

Almost all of my automations and devices are based on MQTT.
I also use it for a lot of other development (I am a big fan of buses).

And indeed, HA will catch up with the retained state.

I think my misunderstanding is self-inflicted. I read waaay too much into what you stated here:

I incorrectly interpreted that into meaning the switches are very limited in terms of control and acknowledgement, with the ability to be controlled only by a toggle command and to respond not with their current state but just acknowledgement of being pressed.

Based on your replies, I see now that the RF switches are able to be controlled by explicit turn_on and turn_off commands (and not only toggle). That makes all the difference in being able to set them to a known state after a reboot (as opposed to the potentially ambiguous toggle).

tl;dr
My mistake, carry on.

It may be me who was not clear enough. This is also due to the duality of the word “switch”:

  • I have RF433 wall switches which send a unique code when they are pressed. They are just buttons so the code has no other meaning than “I was pressed”
  • this RF433 signal is intercepted by a RF433 to MQTT bridge (the one I want to duplicate to have redundancy). It then sends the code above to a MQTT topic (as payload) .
  • HA listens in the automation to that topic, and depending on the code (in the payload), toggles a specific electrical switch (a Sonoff Basic, which gets its orders via MQTT) - this is the mapping wall switch ↔ electrical switch. The “electrical switch” has usually a lamp behind.

This is a really great idea @WoJWoJ! I’ve got window and door sensors all over my house and a single Sonoff Bridge that sometimes misses a door or window closure. When it does, the entities state never goes to ‘off’ and when the sun sets my speakers tell me that the door or window is still open. This happens regularly enough to be annoying…

I’ve been trying to think of a way to make it more robust but haven’t come up with anything. I was searching the automation threads looking for something else and came across this one as an excellent find. I think this should work! I wonder if you’ve implemented it and have it working. Did you implement it for a similar reason?

So far, only two complaints about 433MHz stuff.

  1. No encryption on transmission so someone could fairly easily spoof packets
  2. Occasionally packets are missed causing the problem I outlined above

Other than that, I LOVE 433 and how cheap it was to outfit my whole house with door, window, and moisture sensors. I also wouldn’t want to accidentally miss a moisture sensor going off! :sweat_smile:

I have 2 Sonoff rf bridges for redundancy. They go through the same demux script to keep the sensors synchronized. Worked well for the last 2 years.

That’s way cool! Care to share it? I’ve been using this demux python script I found on the community a long time ago and it works great:

d = { # list all sensors in a dict...
      'CODE_GOES_HERE': ['Front_Door', 'ON', 'true']
}

p = data.get('payload')

if p is not None:
  if p in d.keys():
    service_data = {'topic':'433/{}'.format(d[p][0]), 'payload':'{}'.format(d[p][1]), 'qos':0, 'retain':'{}'.format(d[p][2])}
  else:
    service_data = {'topic':'433/unknown', 'payload':'{}'.format(p), 'qos':0, 'retain':'false'}
    logger.warning('<rfbridge_demux> Received unknown RF command: {}'.format(p))
  hass.services.call('mqtt', 'publish', service_data, False)

I actually bought two Sonoff Bridges so I could play around with the second one. Subsequently got the system working and never messed with the second one cause I couldn’t think of anything to use it for :exploding_head:

More or less the same demux script, except I flashed my rf bridges with openmqttgateway instead of tasmota.

- id: '1565365902888'
  alias: rfbridge_demultiplexer
  trigger:
  - platform: mqtt
    topic: home/OpenMQTTGateway1/SRFBtoMQTT
  - platform: mqtt
    topic: home/OpenMQTTGateway/SRFBtoMQTT
  action:
  - data_template:
      payload: '{{trigger.payload_json.value}}'
    service: python_script.rfbridge_demux
  mode: parallel
  max: 10