fix: ignore stale callbacks from rescheduled timers
- Add generation counters to SmartCondition and EventSensor timers. - Preserve pending changes and the retention period when timers are restarted. - Silently cancel timers that have already expired. - Add regression tests for stale callbacks and expiry during cancellation.
This commit is contained in:
1 parent
1a148d4e3f
commit
54c525c843
4 files changed
+228
-9
No files matched your search
+11
-3
@@ -757,20 +757,28 @@ class EventSensor(VirtualSensorBase):
|
||||
|
||||
self.retain_time = self.yaml_block['retain_time']
|
||||
self.cb_handle = None
|
||||
self._timer_generation = 0
|
||||
|
||||
self.event_handlers = []
|
||||
if "activation_events" in self.yaml_block:
|
||||
self.event_handlers.append(EventHandler(self.ad_api, self.yaml_block["activation_events"], self.on_activation_event,logger_interface = self.logger_interface))
|
||||
|
||||
def on_activation_event(self, event_name, data, kwargs):
|
||||
self._timer_generation += 1
|
||||
self.output_sensor.set_state(state = 'on')
|
||||
if self.cb_handle is not None:
|
||||
self.ad_api.cancel_timer(self.cb_handle)
|
||||
self.cb_handle = self.ad_api.run_in(self.on_retain_time_elapsed, self.retain_time)
|
||||
self.ad_api.cancel_timer(self.cb_handle, silent=True)
|
||||
self.cb_handle = self.ad_api.run_in(
|
||||
self.on_retain_time_elapsed, self.retain_time,
|
||||
generation=self._timer_generation,
|
||||
)
|
||||
|
||||
def on_retain_time_elapsed(self, kwargs):
|
||||
self.output_sensor.set_state(state = 'off')
|
||||
# Cancellation cannot retract a callback already queued by AppDaemon.
|
||||
if kwargs.get('generation') != self._timer_generation:
|
||||
return
|
||||
self.cb_handle = None
|
||||
self.output_sensor.set_state(state = 'off')
|
||||
|
||||
def generate_sensor_name(self,virtual_sensor_name):
|
||||
return f"binary_sensor.{virtual_sensor_name}"
|
||||
|
||||
Reference in new issue
Block a user