Browse Source

Ready and Arm change events were happening on the same message causing one message to be missing status bits of the other. Refactor to a new routine to avoid breaking anyone. New routine processes all state logic first for both ready and arm bits then calls event functions last.

pyserial_fix
f34rdotcom 6 years ago
parent
commit
a05de69a3a
1 changed files with 48 additions and 5 deletions
  1. +48
    -5
      alarmdecoder/decoder.py

+ 48
- 5
alarmdecoder/decoder.py View File

@@ -609,11 +609,10 @@ class AlarmDecoder(object):
:type message: :py:class:`~alarmdecoder.messages.Message`, :py:class:`~alarmdecoder.messages.ExpanderMessage`, :py:class:`~alarmdecoder.messages.LRRMessage`, or :py:class:`~alarmdecoder.messages.RFMessage` :type message: :py:class:`~alarmdecoder.messages.Message`, :py:class:`~alarmdecoder.messages.ExpanderMessage`, :py:class:`~alarmdecoder.messages.LRRMessage`, or :py:class:`~alarmdecoder.messages.RFMessage`
""" """
if isinstance(message, Message) and not self._ignore_message_states: if isinstance(message, Message) and not self._ignore_message_states:
self._update_armed_ready_status(message)
self._update_power_status(message) self._update_power_status(message)
self._update_ready_status(message)
self._update_alarm_status(message) self._update_alarm_status(message)
self._update_zone_bypass_status(message) self._update_zone_bypass_status(message)
self._update_armed_status(message)
self._update_battery_status(message) self._update_battery_status(message)
self._update_fire_status(message) self._update_fire_status(message)


@@ -738,6 +737,52 @@ class AlarmDecoder(object):


return bypass_status return bypass_status


def _update_armed_ready_status(self, message=None):
"""
Uses the provided message to update the armed state
and ready state at once as they can change in the same
message and we want both events to have the same states.
:param message: message to use to update
:type message: :py:class:`~alarmdecoder.messages.Message`

"""

arm_status = None
stay_status = None
ready_status = None

send_ready = False
send_arm = False

if isinstance(message, Message):
arm_status = message.armed_away
stay_status = message.armed_home
ready_status = message.ready

if arm_status is None or stay_status is None or ready_status is None:
return

self._armed_stay, old_stay = stay_status, self._armed_stay
self._armed_status, old_arm = arm_status, self._armed_status
self._ready_status, old_ready_status = ready_status, self._ready_status

if old_arm is not None:
if arm_status != old_arm or stay_status != old_stay:
send_arm = True

if old_ready_status is not None:
if ready_status != old_ready_status:
send_ready = True

if send_ready:
self.on_ready_changed(status=self._ready_status)

if send_arm:
if self._armed_status or self._armed_stay:
self.on_arm(stay=stay_status)
else:
self.on_disarm()

def _update_armed_status(self, message=None, status=None, status_stay=None): def _update_armed_status(self, message=None, status=None, status_stay=None):
""" """
Uses the provided message to update the armed state. Uses the provided message to update the armed state.
@@ -757,10 +802,8 @@ class AlarmDecoder(object):
if isinstance(message, Message): if isinstance(message, Message):
arm_status = message.armed_away arm_status = message.armed_away
stay_status = message.armed_home stay_status = message.armed_home

if arm_status is None or stay_status is None: if arm_status is None or stay_status is None:
return return

self._armed_status, old_status = arm_status, self._armed_status self._armed_status, old_status = arm_status, self._armed_status
self._armed_stay, old_stay = stay_status, self._armed_stay self._armed_stay, old_stay = stay_status, self._armed_stay
if arm_status != old_status or stay_status != old_stay: if arm_status != old_status or stay_status != old_stay:
@@ -815,7 +858,7 @@ class AlarmDecoder(object):
last_status = self._fire_status last_status = self._fire_status
if isinstance(message, Message): if isinstance(message, Message):
# Quirk in Ademco panels. The fire bit drops on "SYSTEM LO BAT" messages. # Quirk in Ademco panels. The fire bit drops on "SYSTEM LO BAT" messages.
# needs to be done for different languages.
# FIXME: does not support non english panels.
if self.mode == ADEMCO and message.text.startswith("SYSTEM"): if self.mode == ADEMCO and message.text.startswith("SYSTEM"):
fire_status = last_status fire_status = last_status
else: else:


Loading…
Cancel
Save