Browse Source

changed fire handeling to just use Fire bit and remove SYSTEM BATTERY LOW messages to avoid Ademco quirk. Removed processing of LRR messages as default behavior to avoid over processing of events from section #1 and LRR.

pyserial_fix
f34rdotcom 6 years ago
parent
commit
77c3bdb7d0
2 changed files with 27 additions and 65 deletions
  1. +21
    -50
      alarmdecoder/decoder.py
  2. +6
    -15
      test/test_ad2.py

+ 21
- 50
alarmdecoder/decoder.py View File

@@ -123,7 +123,7 @@ class AlarmDecoder(object):
version_flags = ""
"""Device flags enabled"""

def __init__(self, device, ignore_message_states=False):
def __init__(self, device, ignore_message_states=False, ignore_lrr_states=True):
"""
Constructor

@@ -132,12 +132,15 @@ class AlarmDecoder(object):
:type device: Device
:param ignore_message_states: Ignore regular panel messages when updating internal states
:type ignore_message_states: bool
:param ignore_lrr_states: Ignore LRR panel messages when updating internal states
:type ignore_lrr_states: bool
"""
self._device = device
self._zonetracker = Zonetracker(self)
self._lrr_system = LRRSystem(self)

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
@@ -146,10 +149,7 @@ class AlarmDecoder(object):
self._bypass_status = {}
self._armed_status = None
self._armed_stay = False
self._fire_status = (False, 0)
self._fire_alarming = False
self._fire_alarming_changed = 0
self._fire_state = FireState.NONE
self._fire_status = False
self._battery_status = (False, 0)
self._panic_status = False
self._relay_status = {}
@@ -470,8 +470,6 @@ class AlarmDecoder(object):
if self._internal_address_mask & msg.mask > 0:
if not self._ignore_message_states:
self._update_internal_states(msg)
else:
self._update_fire_status(status=None)

self.on_message(message=msg)

@@ -519,7 +517,8 @@ class AlarmDecoder(object):
"""
msg = LRRMessage(data)

self._lrr_system.update(msg)
if not self._ignore_lrr_states:
self._lrr_system.update(msg)
self.on_lrr_message(message=msg)

return msg
@@ -812,54 +811,26 @@ class AlarmDecoder(object):

:returns: boolean indicating the new status
"""
is_lrr = status is not None
fire_status = status
last_status = self._fire_status
if isinstance(message, Message):
fire_status = message.fire_alarm

last_status, last_update = self._fire_status

if self._fire_state == FireState.NONE:
# Always move to a FIRE state if detected
if fire_status == True:
self._fire_state = FireState.ALARM
self._fire_status = (fire_status, time.time())

self.on_fire(status=FireState.ALARM)

elif self._fire_state == FireState.ALARM:
# If we've received an LRR CANCEL message, move to ACKNOWLEDGED
if is_lrr and fire_status == False:
self._fire_state = FireState.ACKNOWLEDGED
self._fire_status = (fire_status, time.time())
self.on_fire(status=FireState.ACKNOWLEDGED)
# Quirk in Ademco panels. The fire bit drops on "SYSTEM LO BAT" messages.
# needs to be done for different languages.
if self.mode == ADEMCO and message.text.startswith("SYSTEM"):
fire_status = last_status
else:
# Handle bouncing status changes and timeout in order to revert back to NONE.
if last_status != fire_status or fire_status == True:
self._fire_status = (fire_status, time.time())
if fire_status == False and time.time() > last_update + self._fire_timeout:
self._fire_state = FireState.NONE
self.on_fire(status=FireState.NONE)

elif self._fire_state == FireState.ACKNOWLEDGED:
# If we've received a second LRR FIRE message after a CANCEL, revert back to FIRE and trigger another event.
if is_lrr and fire_status == True:
self._fire_state = FireState.ALARM
self._fire_status = (fire_status, time.time())

self.on_fire(status=FireState.ALARM)
else:
# Handle bouncing status changes and timeout in order to revert back to NONE.
if last_status != fire_status or fire_status == True:
self._fire_status = (fire_status, time.time())
fire_status = message.fire_alarm

if fire_status is None:
return

if fire_status != True and time.time() > last_update + self._fire_timeout:
self._fire_state = FireState.NONE
self.on_fire(status=FireState.NONE)
if fire_status != self._fire_status:
self._fire_status, old_status = fire_status, self._fire_status

return self._fire_state == FireState.ALARM
if old_status is not None:
self.on_fire(status=self._fire_status)

return self._fire_status

def _update_panic_status(self, status=None):
"""


+ 6
- 15
test/test_ad2.py View File

@@ -304,32 +304,23 @@ class TestAlarmDecoder(TestCase):
self.assertFalse(self._battery)

def test_fire_alarm_event(self):
self._fire = FireState.NONE
msg = self._decoder._handle_message(b'[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertTrue(self._fire) # Not set the first time we hit it.

msg = self._decoder._handle_message(b'[0000000000000100----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._fire, FireState.ALARM)

# force the timeout to expire.
with patch.object(time, 'time', return_value=self._decoder._fire_status[1] + 35):
msg = self._decoder._handle_message(b'[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._fire, FireState.NONE)
self.assertTrue(self._fire)

def test_fire_lrr(self):
self._fire = FireState.NONE
self._fire = False

msg = self._decoder._handle_message(b'!LRR:095,1,CID_1110,ff') # Fire: Non-specific

self.assertIsInstance(msg, LRRMessage)
self.assertEquals(self._fire, FireState.ALARM)
self.assertTrue(self._fire)

msg = self._decoder._handle_message(b'!LRR:001,1,CID_1406,ff') # Open/Close: Cancel
self.assertIsInstance(msg, LRRMessage)
self.assertEquals(self._fire, FireState.ACKNOWLEDGED)

# force the timeout to expire.
with patch.object(time, 'time', return_value=self._decoder._fire_status[1] + 35):
msg = self._decoder._handle_message(b'[0000000000000000----],000,[f707000600e5800c0c020000]," "')
self.assertEquals(self._fire, FireState.NONE)
self.assertFalse(self._fire)

def test_hit_for_faults(self):
self._decoder._handle_message(b'[0000000000000000----],000,[f707000600e5800c0c020000],"Hit * for faults "')


Loading…
Cancel
Save