From cf9c94053d7084815841b67e4e634ea9ddeb635b Mon Sep 17 00:00:00 2001 From: f34rdotcom Date: Sun, 4 Aug 2019 16:53:51 -0700 Subject: [PATCH] Ok that did not work on some panels. Back to timers ;(. Sorry fire will take 30 seconds to clear. At least its not flopping back and forth anymore. --- alarmdecoder/decoder.py | 59 ++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/alarmdecoder/decoder.py b/alarmdecoder/decoder.py index e280ad5..c87e069 100644 --- a/alarmdecoder/decoder.py +++ b/alarmdecoder/decoder.py @@ -93,6 +93,8 @@ class AlarmDecoder(object): BATTERY_TIMEOUT = 30 """Default timeout (in seconds) before the battery status reverts.""" + FIRE_TIMEOUT = 30 + """Default tTimeout (in seconds) before the fire status reverts.""" # Attributes address = 18 @@ -141,6 +143,7 @@ class AlarmDecoder(object): self._ignore_message_states = ignore_message_states self._ignore_lrr_states = ignore_lrr_states self._battery_timeout = AlarmDecoder.BATTERY_TIMEOUT + self._fire_timeout = AlarmDecoder.FIRE_TIMEOUT self._power_status = None self._chime_status = None self._ready_status = None @@ -152,6 +155,7 @@ class AlarmDecoder(object): self._armed_stay = False self._exit = False self._fire_status = False + self._fire_status_timeout = 0 self._battery_status = (False, 0) self._panic_status = False self._relay_status = {} @@ -216,6 +220,25 @@ class AlarmDecoder(object): """ self._battery_timeout = value + @property + def fire_timeout(self): + """ + Retrieves the timeout for restoring the fire status, in seconds. + + :returns: fire status timeout + """ + return self._fire_timeout + + @fire_timeout.setter + def fire_timeout(self, value): + """ + Sets the timeout for restoring the fire status, in seconds. + + :param value: timeout in seconds + :type value: int + """ + self._fire_timeout = value + @property def internal_address_mask(self): """ @@ -893,21 +916,38 @@ class AlarmDecoder(object): fire_status = status last_status = self._fire_status + last_update = self._fire_status_timeout # Quirk in Ademco panels. Fire bit goes on/off if other alarms are on or a system fault if isinstance(message, Message): if self.mode == ADEMCO: - # ignore sticky bit on these messages :( - if (not message.text.startswith("SYSTEM") and - not message.text.startswith("CHECK") and - message.system_fault != 3): - - # if we did not have an alarm and we do now send event + # if we did not have an alarm and we do now send event + if message.fire_alarm and message.fire_alarm != self._fire_status: fire_status = message.fire_alarm - else: - # Keep the current fire state do not update for SYSTEM messages. - fire_status = self._fire_status + # if we had an alarm and the sticky bit was cleared then clear the alarm + ## ignore sticky bit on these messages :( + if (not message.text.startswith("SYSTEM") and + not message.text.startswith("CHECK")): + if self._fire_status and not message.alarm_event_occurred: + # fire restore + fire_status = False + + # if we had a fire event and it went away and we still have a sticky alarm bit + # then it is not gone yet just restore it + if not message.fire_alarm and self._fire_status: + if message.alarm_event_occurred: + fire_status = self._fire_status + + # if we had an alarm already and we get it again extend the timeout + if message.fire_alarm and message.fire_alarm == self._fire_status: + self._fire_status = message.fire_alarm + self._fire_status_timeout = time.time() + + # if we timeout with an alarm set restore it + if self._fire_status: + if time.time() > last_update + self._fire_timeout: + fire_status = False else: fire_status = message.fire_alarm @@ -915,6 +955,7 @@ class AlarmDecoder(object): if fire_status != self._fire_status: if fire_status is not None: self._fire_status = fire_status + self._fire_status_timeout = time.time() self.on_fire(status=fire_status) return self._fire_status