From 3b2c17257d6302c598a95ec4d9a8bbc8f48af2e2 Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Mon, 29 Apr 2024 20:20:55 -0700 Subject: [PATCH] DSC fire/panic state update fixes * Set the `alarm_fire_zone` and `alarm_in_memory` attributes based on keypad LED state updates from the EVL * Clear the `panic` and `fire` attributes on 650, 651, 653, and 655 * Clear the `armed_*`, `alarm`, and `entry/exit_delay` attributes on 656 and 657 updates. --- .../envisalink_new/pyenvisalink/dsc_client.py | 62 ++++++++++--------- .../pyenvisalink/dsc_envisalinkdefs.py | 32 ++++++++-- 2 files changed, 62 insertions(+), 32 deletions(-) diff --git a/custom_components/envisalink_new/pyenvisalink/dsc_client.py b/custom_components/envisalink_new/pyenvisalink/dsc_client.py index 73bf5a6..703beb9 100644 --- a/custom_components/envisalink_new/pyenvisalink/dsc_client.py +++ b/custom_components/envisalink_new/pyenvisalink/dsc_client.py @@ -276,10 +276,6 @@ def handle_partition_state_change(self, code, data): result = {STATE_CHANGE_PARTITION: [partitionNumber]} if code == "655": - # Clear any fire or panic status - status["fire"] = False - status["panic"] = False - if self._alarmPanel._zoneBypassEnabled: """Partition was disarmed so any zone bypasses will have been reset""" cleared_zones = self.clear_zone_bypass_state() @@ -376,34 +372,44 @@ def is_zone_open_from_zonedump(self, zone, ticks) -> bool: return ticks == 0 def handle_keypad_led_state_update(self, code, data): - if len(data) == 2: - flags = KeypadLED_Flags() - flags.asByte = int(data, 16) - - _LOGGER.debug(f"Keypad LED state update: {flags}") - - if ( - self._alarmPanel._zoneBypassEnabled - and not self._bypassStateInitialized - and flags.ready - and flags.bypass - ): - # We've just started up and the LEDs indicate that there are zones bypassed - # so request a zone bypass dump. This is only necessary on startup - # to get the initial state. Zones bypassed after startup will automatically - # trigger a 616 update. - self.create_internal_task( - self.dump_zone_bypass_status(), name="dump_zone_bypass_status" - ) + if len(data) != 2: + return None + + flags = KeypadLED_Flags() + flags.asByte = int(data, 16) + + _LOGGER.debug(f"Keypad LED state update: {flags}") + + updatedPartitions = [] + new_status = { + "alarm_fire_zone": bool(flags.fire), + "alarm_in_memory": bool(flags.memory), + } + for part in self._alarmPanel.alarm_state["partition"]: + self._alarmPanel.alarm_state["partition"][part]["status"].update(new_status) + updatedPartitions.append(part) - self._bypassStateInitialized = True + if ( + self._alarmPanel._zoneBypassEnabled + and not self._bypassStateInitialized + and flags.ready + and flags.bypass + ): + # We've just started up and the LEDs indicate that there are zones bypassed + # so request a zone bypass dump. This is only necessary on startup + # to get the initial state. Zones bypassed after startup will automatically + # trigger a 616 update. + self.create_internal_task( + self.dump_zone_bypass_status(), name="dump_zone_bypass_status" + ) + + self._bypassStateInitialized = True + return {STATE_CHANGE_KEYPAD: updatedPartitions} def handle_keypad_led_flash_state_update(self, code, data): - if len(data) == 2: - flags = KeypadLED_Flags() - flags.asByte = int(data, 16) + _LOGGER.debug(f"Keypad LED FLASH state update: {flags}") + self.handle_keypad_led_state_update(code, data) - _LOGGER.debug(f"Keypad LED FLASH state update: {flags}") def set_in_alarm_alpha(self, partition_number): status = self._alarmPanel.alarm_state["partition"][partition_number]["status"] diff --git a/custom_components/envisalink_new/pyenvisalink/dsc_envisalinkdefs.py b/custom_components/envisalink_new/pyenvisalink/dsc_envisalinkdefs.py index f9d1351..4bdd975 100644 --- a/custom_components/envisalink_new/pyenvisalink/dsc_envisalinkdefs.py +++ b/custom_components/envisalink_new/pyenvisalink/dsc_envisalinkdefs.py @@ -188,6 +188,8 @@ def __str__(self) -> str: "armed_away": False, "exit_delay": False, "entry_delay": False, + "fire": False, + "panic": False, "alpha": "Ready", }, }, @@ -203,6 +205,8 @@ def __str__(self) -> str: "armed_away": False, "exit_delay": False, "entry_delay": False, + "fire": False, + "panic": False, "alpha": "Not Ready", }, }, @@ -219,6 +223,8 @@ def __str__(self) -> str: "armed_away": False, "exit_delay": False, "entry_delay": False, + "fire": False, + "panic": False, "alpha": "Ready - Force Arm", }, }, @@ -239,6 +245,8 @@ def __str__(self) -> str: "armed_away": False, "exit_delay": False, "entry_delay": False, + "fire": False, + "panic": False, "alpha": "Disarmed", }, }, @@ -246,13 +254,29 @@ def __str__(self) -> str: "name": "Exit Delay in Progress", "handler": "partition_state_change", "state_change": True, - "status": {"exit_delay": True, "alpha": "Exit Delay In Progress"}, + "status": { + "alarm": False, + "armed_stay": False, + "armed_zero_entry_delay": False, + "armed_away": False, + "exit_delay": True, + "entry_delay": False, + "alpha": "Exit Delay In Progress", + }, }, "657": { "name": "Entry Delay in Progress", "handler": "partition_state_change", "state_change": True, - "status": {"entry_delay": True, "alpha": "Entry Delay in Progress"}, + "status": { + "alarm": False, + "armed_stay": False, + "armed_zero_entry_delay": False, + "armed_away": False, + "exit_delay": False, + "entry_delay": True, + "alpha": "Entry Delay in Progress", + }, }, "663": { "name": "ChimeOn", @@ -440,13 +464,13 @@ def __str__(self) -> str: "510": { "name": "Keypad LED State", "handler": "keypad_led_state_update", - "state_change": False, + "state_change": True, "status": None, }, "511": { "name": "Keypad LED FLASH State", "handler": "keypad_led_flash_state_update", - "state_change": False, + "state_change": True, "status": None, }, }