From 71a3af7910b20807d27f79ae1ffa5ffbd0271342 Mon Sep 17 00:00:00 2001 From: Laurens <43173895+GreenGrassBlueOcean@users.noreply.github.com> Date: Fri, 2 Oct 2026 12:00:26 +0200 Subject: [PATCH] test(alarm): arm with WHAT 8, not WHAT 1 Four alarm tests used *5*1*0## (activation) as "armed away". The F454 trace (#311) shows WHAT 1 on every disarm (*5*2*0## -> *5*1*0## -> *5*9*0##) and in disarmed status dumps; arming is *5*1*0## -> *5*8*0##. The H4890 (#466) and MH202 (#564) captures are disarmed status dumps with no arm transition. OWNd#66 makes is_armed_away WHAT 8 only, which turned these tests red in OWNd's downstream conformance job. The tests now arm with *5*8*0##, and the WHAT 1 case follows whatever the installed OWNd reports, so they pass on OWNd 2.0.0b9 and on OWNd#66. Co-Authored-By: Claude Opus 5.5 --- tests/test_component_alarm.py | 17 +++++++++++++---- tests/test_issue_311.py | 5 +++-- tests/test_issue_466_h4890_trace.py | 9 +++++---- tests/test_issue_564_mh202_alarm_trace.py | 5 +++-- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/tests/test_component_alarm.py b/tests/test_component_alarm.py index 1e9c7ba9a..d701d74a7 100644 --- a/tests/test_component_alarm.py +++ b/tests/test_component_alarm.py @@ -371,13 +371,22 @@ def test_handle_event(self, alarm_central): assert alarm_central.extra_state_attributes["raw_state"] == "deactivation" assert alarm_central.extra_state_attributes["state_code"] == 2 - # Armed away event (*5*1*0## - activation) - msg_away = OWNEvent.parse("*5*1*0##") - alarm_central.handle_event(msg_away) - assert alarm_central.alarm_state == STATE_ARMED_AWAY + # Activation (*5*1*0##) is "system operational", not armed: the F454 + # trace (#311) sends it on every disarm (*5*2*0## -> *5*1*0## -> *5*9*0##). + # OWNd <= 2.0.0b9 still reads it as armed_away; OWNd#66 does not. + msg_activation = OWNEvent.parse("*5*1*0##") + alarm_central.handle_event(msg_activation) + assert alarm_central.alarm_state == (STATE_ARMED_AWAY if msg_activation.is_armed_away else STATE_DISARMED) assert alarm_central.extra_state_attributes["raw_state"] == "activation" assert alarm_central.extra_state_attributes["state_code"] == 1 + # Armed away event (*5*8*0## - engage) + msg_away = OWNEvent.parse("*5*8*0##") + alarm_central.handle_event(msg_away) + assert alarm_central.alarm_state == STATE_ARMED_AWAY + assert alarm_central.extra_state_attributes["raw_state"] == "engage" + assert alarm_central.extra_state_attributes["state_code"] == 8 + # Armed home event (*5*11*0## - active zone) msg_home = OWNEvent.parse("*5*11*0##") alarm_central.handle_event(msg_home) diff --git a/tests/test_issue_311.py b/tests/test_issue_311.py index fc64f32d6..f843c9acf 100644 --- a/tests/test_issue_311.py +++ b/tests/test_issue_311.py @@ -104,8 +104,9 @@ async def test_real_world_trace_replay_issue_311(hass: HomeAssistant) -> None: # In the end of the trace, the alarm is disarmed (*5*2*0## and *5*9*0##) assert alarm_0.state == AlarmControlPanelState.DISARMED - # 2. Test arming away event explicitly on the entity - arm_msg = OWNMessage.parse("*5*1*0##") + # 2. Test arming away event explicitly on the entity. The trace arms with + # *5*1*0## -> *5*8*0##: WHAT 8 (engage) is the armed state, WHAT 1 is not. + arm_msg = OWNMessage.parse("*5*8*0##") assert isinstance(arm_msg, OWNAlarmEvent) async_dispatcher_send(hass, f"myhome_message_{mac}", arm_msg) await hass.async_block_till_done() diff --git a/tests/test_issue_466_h4890_trace.py b/tests/test_issue_466_h4890_trace.py index bb4d717de..1aeed0284 100644 --- a/tests/test_issue_466_h4890_trace.py +++ b/tests/test_issue_466_h4890_trace.py @@ -140,8 +140,9 @@ async def test_h4890_alarm_trace_replay_and_state_transitions(hass: HomeAssistan alarm_frames.append(raw) # Authentic alarm frames present in trace - assert "*5*9*0##" in alarm_frames # Disarm - assert "*5*1*0##" in alarm_frames # Arm away + # A disarmed panel's status dump: activation + disengaged, then zone states + assert "*5*9*0##" in alarm_frames # Disengaged + assert "*5*1*0##" in alarm_frames # Activation (system operational, not armed) assert "*5*11*#1##" in alarm_frames assert "*5*11*#5##" in alarm_frames assert "*5*18*#7##" in alarm_frames @@ -171,8 +172,8 @@ async def test_h4890_alarm_trace_replay_and_state_transitions(hass: HomeAssistan alarm.handle_event(OWNAlarmEvent.parse("*5*9*0##")) assert alarm.alarm_state == AlarmControlPanelState.DISARMED - # Feed arm away frame *5*1*0## - alarm.handle_event(OWNAlarmEvent.parse("*5*1*0##")) + # Feed arm away frame *5*8*0## (engage; the trace has no arm transition) + alarm.handle_event(OWNAlarmEvent.parse("*5*8*0##")) assert alarm.alarm_state == AlarmControlPanelState.ARMED_AWAY # Disarm again diff --git a/tests/test_issue_564_mh202_alarm_trace.py b/tests/test_issue_564_mh202_alarm_trace.py index 8d5ffb3f1..950e3b471 100644 --- a/tests/test_issue_564_mh202_alarm_trace.py +++ b/tests/test_issue_564_mh202_alarm_trace.py @@ -148,8 +148,9 @@ async def test_mh202_alarm_entity_state_transitions(hass: HomeAssistant) -> None alarm.hass = hass alarm.async_schedule_update_ha_state = MagicMock() - # Feed arm away frame *5*1*0## - arm_event = OWNAlarmEvent.parse("*5*1*0##") + # Feed arm away frame *5*8*0## (engage). The trace's *5*1*0## sits 3 ms + # before *5*9*0## in one status dump: activation, not armed. + arm_event = OWNAlarmEvent.parse("*5*8*0##") assert arm_event is not None assert arm_event.is_armed_away is True alarm.handle_event(arm_event)