From 943361453a3149ce0c144c2c283c64b47e79576d Mon Sep 17 00:00:00 2001 From: Pierre Gironde Date: Tue, 26 May 2026 08:30:44 +0200 Subject: [PATCH] feat: add debounce_seconds parameter to EventDispatcher for event trigger management --- eventhandler.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/eventhandler.py b/eventhandler.py index 73d4023..4c2e736 100644 --- a/eventhandler.py +++ b/eventhandler.py @@ -42,6 +42,9 @@ import json # : # reset_data: # optional — latch reset filter # : +# debounce_seconds: # optional — ignore re-triggers within +# # this delay (seconds). Useful for +# # buttons that fire duplicate events. # # Usage: # handler = EventHandler(ad_api, self.args['events_to_listen'], my_callback) @@ -57,7 +60,7 @@ import json # ============================================================================= class EventDispatcher: - def __init__(self,ad_api,event_name,callback,event_data,reset_data,event_context): + def __init__(self,ad_api,event_name,callback,event_data,reset_data,event_context,debounce_seconds=None): self.ad_api = ad_api event_data = self._resolve_zha_device_name(event_data) reset_data = self._resolve_zha_device_name(reset_data) @@ -67,6 +70,8 @@ class EventDispatcher: self.reset_data = reset_data self.waiting_for_reset = False self.event_context = event_context + self.debounce_seconds = debounce_seconds + self._last_trigger_time = None if event_data == None: self.ad_api.listen_event(self.on_event,event_name) else: @@ -159,6 +164,13 @@ class EventDispatcher: #special threatment for event if match_event_data and not self.waiting_for_reset: + if self.debounce_seconds is not None: + import time + now = time.monotonic() + if self._last_trigger_time is not None and (now - self._last_trigger_time) < self.debounce_seconds: + return False + self._last_trigger_time = now + if self.reset_data != None: self.waiting_for_reset = True @@ -173,7 +185,7 @@ class EventDispatcher: class EventHandler: def __init__(self, ad_api,events_block,callback,event_context = None): #event_context is passed back to the CB has a context def register_event_with_params(event_block,callback,event_context): - self.add_dispatcher(event_block['event_name'],callback,event_block['event_data'] if 'event_data' in event_block else None, event_block['reset_data'] if 'reset_data' in event_block else None,event_context) + self.add_dispatcher(event_block['event_name'],callback,event_block['event_data'] if 'event_data' in event_block else None, event_block['reset_data'] if 'reset_data' in event_block else None,event_context, event_block.get('debounce_seconds')) self.__ad_api = ad_api self.event_dispatchers = [] @@ -185,7 +197,7 @@ class EventHandler: for event_block in events_block.values(): register_event_with_params(event_block,callback,event_context) - def add_dispatcher(self,event_name,callback,event_data = None,reset_data = None ,event_context = None): + def add_dispatcher(self,event_name,callback,event_data = None,reset_data = None ,event_context = None, debounce_seconds = None): self.__ad_api.log_info(f'Registering dispatcher {callback.__name__} for event "{event_name}" ({event_data})') - dispatcher = EventDispatcher(self.__ad_api,event_name,callback,event_data,reset_data,event_context) + dispatcher = EventDispatcher(self.__ad_api,event_name,callback,event_data,reset_data,event_context,debounce_seconds) self.event_dispatchers.append(dispatcher) \ No newline at end of file