From 1064b265cab2fa1c8c7cfd5f1095a57e99d61c9d Mon Sep 17 00:00:00 2001 From: f34rdotcom <=> Date: Thu, 24 May 2018 05:27:41 +0000 Subject: [PATCH] Added support for on_chime. Clerification on_bypass return value. Version bump. --- alarmdecoder/decoder.py | 35 +++++++++++++++++++++++++++++++++-- setup.py | 2 +- test/test_ad2.py | 14 ++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/alarmdecoder/decoder.py b/alarmdecoder/decoder.py index d927554..87098b4 100644 --- a/alarmdecoder/decoder.py +++ b/alarmdecoder/decoder.py @@ -45,6 +45,7 @@ class AlarmDecoder(object): on_low_battery = event.Event("This event is called when the device detects a low battery.\n\n**Callback definition:** *def callback(device, status)*") on_panic = event.Event("This event is called when the device detects a panic.\n\n**Callback definition:** *def callback(device, status)*") on_relay_changed = event.Event("This event is called when a relay is opened or closed on an expander board.\n\n**Callback definition:** *def callback(device, message)*") + on_chime_changed = event.Event("This event is called when chime state changes.\n\n**Callback definition:** *def callback(device, message)*") # Mid-level Events on_message = event.Event("This event is called when standard panel :py:class:`~alarmdecoder.messages.Message` is received.\n\n**Callback definition:** *def callback(device, message)*") @@ -144,6 +145,7 @@ class AlarmDecoder(object): self._battery_timeout = AlarmDecoder.BATTERY_TIMEOUT self._fire_timeout = AlarmDecoder.FIRE_TIMEOUT self._power_status = None + self._chime_status = None self._ready_status = None self._alarm_status = None self._bypass_status = {} @@ -154,7 +156,7 @@ class AlarmDecoder(object): self._panic_status = False self._relay_status = {} self._internal_address_mask = 0xFFFFFFFF - + self.last_fault_expansion = 0 self.fault_expansion_time_limit = 30 # Seconds @@ -614,6 +616,7 @@ class AlarmDecoder(object): if isinstance(message, Message) and not self._ignore_message_states: self._update_armed_ready_status(message) self._update_power_status(message) + self._update_chime_status(message) self._update_alarm_status(message) self._update_zone_bypass_status(message) self._update_battery_status(message) @@ -650,6 +653,32 @@ class AlarmDecoder(object): return self._power_status + def _update_chime_status(self, message=None, status=None): + """ + Uses the provided message to update the Chime state. + + :param message: message to use to update + :type message: :py:class:`~alarmdecoder.messages.Message` + :param status: chime status, overrides message bits. + :type status: bool + + :returns: bool indicating the new status + """ + chime_status = status + if isinstance(message, Message): + chime_status = message.chime_on + + if chime_status is None: + return + + if chime_status != self._chime_status: + self._chime_status, old_status = chime_status, self._chime_status + + if old_status is not None: + self.on_chime_changed(status=self._chime_status) + + return self._chime_status + def _update_alarm_status(self, message=None, status=None, zone=None, user=None): """ Uses the provided message to update the alarm state. @@ -692,7 +721,9 @@ class AlarmDecoder(object): :param zone: zone associated with bypass event :type zone: int - :returns: bool indicating the new status + :returns: dictionary {Zone:True|False,...} + Zone can be None if LRR CID Bypass checking is disabled + or we do not know what zones but know something is bypassed. """ bypass_status = status if isinstance(message, Message): diff --git a/setup.py b/setup.py index b76f57b..c4441f9 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ if sys.version_info < (3,): extra_requirements.append('future==0.14.3') setup(name='alarmdecoder', - version='1.13.3', + version='1.13.4', description='Python interface for the AlarmDecoder (AD2) family ' 'of alarm devices which includes the AD2USB, AD2SERIAL and AD2PI.', long_description=readme(), diff --git a/test/test_ad2.py b/test/test_ad2.py index 8cf3e48..9c5191c 100644 --- a/test/test_ad2.py +++ b/test/test_ad2.py @@ -20,6 +20,7 @@ class TestAlarmDecoder(TestCase): self._panicked = False self._relay_changed = False self._power_changed = False + self._chime_changed = False self._ready_changed = False self._alarmed = False self._bypassed = False @@ -48,6 +49,7 @@ class TestAlarmDecoder(TestCase): self._decoder.on_relay_changed += self.on_relay_changed self._decoder.on_power_changed += self.on_power_changed self._decoder.on_ready_changed += self.on_ready_changed + self._decoder.on_chime_changed += self.on_chime_changed self._decoder.on_alarm += self.on_alarm self._decoder.on_alarm_restored += self.on_alarm_restored self._decoder.on_bypass += self.on_bypass @@ -84,6 +86,9 @@ class TestAlarmDecoder(TestCase): def on_ready_changed(self, sender, *args, **kwargs): self._ready_changed = kwargs['status'] + def on_chime_changed(self, sender, *args, **kwargs): + self._chime_changed = kwargs['status'] + def on_alarm(self, sender, *args, **kwargs): self._alarmed = True @@ -255,6 +260,15 @@ class TestAlarmDecoder(TestCase): msg = self._decoder._handle_message(b'[0000000000000000----],000,[f707000600e5800c0c020000]," "') self.assertFalse(self._ready_changed) + def test_chime_changed_event(self): + msg = self._decoder._handle_message(b'[0000000000000000----],000,[f707000600e5800c0c020000]," "') + self.assertFalse(self._chime_changed) # Not set first time we hit it. + + msg = self._decoder._handle_message(b'[0000000010000000----],000,[f707000600e5800c0c020000]," "') + self.assertTrue(self._chime_changed) + + msg = self._decoder._handle_message(b'[0000000000000000----],000,[f707000600e5800c0c020000]," "') + self.assertFalse(self._chime_changed) def test_alarm_event(self): msg = self._decoder._handle_message(b'[0000000000100000----],000,[f707000600e5800c0c020000]," "')