From 3630aabd4e9c8c8fbabef6d5550f979bd641663a Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Wed, 18 Mar 2020 21:28:40 +0100 Subject: [PATCH 01/23] Manual Alarm Control Panel: use proper "Arming" state --- .../components/manual/alarm_control_panel.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index b41da2d51bdb2..f2ffb56597aca 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -26,6 +26,7 @@ STATE_ALARM_ARMED_CUSTOM_BYPASS, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT, + STATE_ALARM_ARMING, STATE_ALARM_DISARMED, STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, @@ -237,7 +238,7 @@ def state(self): if self._state in SUPPORTED_PENDING_STATES and self._within_pending_time( self._state ): - return STATE_ALARM_PENDING + return STATE_ALARM_ARMING return self._state @@ -255,7 +256,7 @@ def supported_features(self) -> int: @property def _active_state(self): """Get the current state.""" - if self.state == STATE_ALARM_PENDING: + if self.state == STATE_ALARM_PENDING or self.state == STATE_ALARM_ARMING: return self._previous_state return self._state @@ -385,7 +386,7 @@ def device_state_attributes(self): """Return the state attributes.""" state_attr = {} - if self.state == STATE_ALARM_PENDING: + if self.state == STATE_ALARM_PENDING or self.state == STATE_ALARM_ARMING: state_attr[ATTR_PRE_PENDING_STATE] = self._previous_state state_attr[ATTR_POST_PENDING_STATE] = self._state @@ -397,7 +398,10 @@ async def async_added_to_hass(self): state = await self.async_get_last_state() if state: if ( - state.state == STATE_ALARM_PENDING + ( + state.state == STATE_ALARM_PENDING + or state.state == STATE_ALARM_ARMING + ) and hasattr(state, "attributes") and state.attributes["pre_pending_state"] ): From 3567396c1dba52f3fd6ca4b7497e1c55378ae6bc Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 20 Mar 2020 12:18:40 +0100 Subject: [PATCH 02/23] Update previous and next attributes --- .../components/manual/alarm_control_panel.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index f2ffb56597aca..c9a5c4c259167 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -64,8 +64,8 @@ state for state in SUPPORTED_STATES if state != STATE_ALARM_DISARMED ] -ATTR_PRE_PENDING_STATE = "pre_pending_state" -ATTR_POST_PENDING_STATE = "post_pending_state" +ATTR_PREVIOUS_STATE = "previous_state" +ATTR_NEXT_STATE = "next_state" def _state_validator(config): @@ -387,8 +387,8 @@ def device_state_attributes(self): state_attr = {} if self.state == STATE_ALARM_PENDING or self.state == STATE_ALARM_ARMING: - state_attr[ATTR_PRE_PENDING_STATE] = self._previous_state - state_attr[ATTR_POST_PENDING_STATE] = self._state + state_attr[ATTR_PREVIOUS_STATE] = self._previous_state + state_attr[ATTR_NEXT_STATE] = self._state return state_attr @@ -403,10 +403,10 @@ async def async_added_to_hass(self): or state.state == STATE_ALARM_ARMING ) and hasattr(state, "attributes") - and state.attributes["pre_pending_state"] + and state.attributes[ATTR_PREVIOUS_STATE] ): - # If in pending state, we return to the pre_pending_state - self._state = state.attributes["pre_pending_state"] + # If in pending state, we return to the ATTR_PREVIOUS_STATE + self._state = state.attributes[ATTR_PREVIOUS_STATE] self._state_ts = dt_util.utcnow() else: self._state = state.state From cec490788eda5ef6708a6491c8f1c8fdc57513db Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sun, 22 Mar 2020 18:37:52 +0100 Subject: [PATCH 03/23] add CONF_ARMING_TIME --- homeassistant/const.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/const.py b/homeassistant/const.py index 74095a2583b6b..73e89ba87e680 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -34,6 +34,7 @@ CONF_ALIAS = "alias" CONF_API_KEY = "api_key" CONF_API_VERSION = "api_version" +CONF_ARMING_TIME = "arming_time" CONF_AT = "at" CONF_AUTH_MFA_MODULES = "auth_mfa_modules" CONF_AUTH_PROVIDERS = "auth_providers" From daa4984a7477567a3ab7a87c251afa77b05c6e49 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sun, 22 Mar 2020 19:06:50 +0100 Subject: [PATCH 04/23] Split up arming and pending time, pending_time --> arming_time --- .../components/manual/alarm_control_panel.py | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index c9a5c4c259167..40ee63dbe3518 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -19,7 +19,7 @@ CONF_DELAY_TIME, CONF_DISARM_AFTER_TRIGGER, CONF_NAME, - CONF_PENDING_TIME, + CONF_ARMING_TIME, CONF_PLATFORM, CONF_TRIGGER_TIME, STATE_ALARM_ARMED_AWAY, @@ -43,7 +43,7 @@ DEFAULT_ALARM_NAME = "HA Alarm" DEFAULT_DELAY_TIME = datetime.timedelta(seconds=0) -DEFAULT_PENDING_TIME = datetime.timedelta(seconds=60) +DEFAULT_ARMING_TIME = datetime.timedelta(seconds=60) DEFAULT_TRIGGER_TIME = datetime.timedelta(seconds=120) DEFAULT_DISARM_AFTER_TRIGGER = False @@ -60,7 +60,7 @@ state for state in SUPPORTED_STATES if state != STATE_ALARM_TRIGGERED ] -SUPPORTED_PENDING_STATES = [ +SUPPORTED_ARMING_STATES = [ state for state in SUPPORTED_STATES if state != STATE_ALARM_DISARMED ] @@ -76,9 +76,9 @@ def _state_validator(config): config[state][CONF_DELAY_TIME] = config[CONF_DELAY_TIME] if CONF_TRIGGER_TIME not in config[state]: config[state][CONF_TRIGGER_TIME] = config[CONF_TRIGGER_TIME] - for state in SUPPORTED_PENDING_STATES: - if CONF_PENDING_TIME not in config[state]: - config[state][CONF_PENDING_TIME] = config[CONF_PENDING_TIME] + for state in SUPPORTED_ARMING_STATES: + if CONF_ARMING_TIME not in config[state]: + config[state][CONF_ARMING_TIME] = config[CONF_ARMING_TIME] return config @@ -93,8 +93,8 @@ def _state_schema(state): schema[vol.Optional(CONF_TRIGGER_TIME)] = vol.All( cv.time_period, cv.positive_timedelta ) - if state in SUPPORTED_PENDING_STATES: - schema[vol.Optional(CONF_PENDING_TIME)] = vol.All( + if state in SUPPORTED_ARMING_STATES: + schema[vol.Optional(CONF_ARMING_TIME)] = vol.All( cv.time_period, cv.positive_timedelta ) return vol.Schema(schema) @@ -111,7 +111,7 @@ def _state_schema(state): vol.Optional(CONF_DELAY_TIME, default=DEFAULT_DELAY_TIME): vol.All( cv.time_period, cv.positive_timedelta ), - vol.Optional(CONF_PENDING_TIME, default=DEFAULT_PENDING_TIME): vol.All( + vol.Optional(CONF_ARMING_TIME, default=DEFAULT_ARMING_TIME): vol.All( cv.time_period, cv.positive_timedelta ), vol.Optional(CONF_TRIGGER_TIME, default=DEFAULT_TRIGGER_TIME): vol.All( @@ -165,9 +165,9 @@ class ManualAlarm(alarm.AlarmControlPanel, RestoreEntity): """ Representation of an alarm status. - When armed, will be pending for 'pending_time', after that armed. + When armed, will be arming for 'arming_time', after that armed. When triggered, will be pending for the triggering state's 'delay_time' - plus the triggered state's 'pending_time'. + plus the triggered state's 'arming_time'. After that will be triggered for 'trigger_time', after that we return to the previous state or disarm if `disarm_after_trigger` is true. A trigger_time of zero disables the alarm_trigger service. @@ -205,9 +205,8 @@ def __init__( state: config[state][CONF_TRIGGER_TIME] for state in SUPPORTED_PRETRIGGER_STATES } - self._pending_time_by_state = { - state: config[state][CONF_PENDING_TIME] - for state in SUPPORTED_PENDING_STATES + self._arming_time_by_state = { + state: config[state][CONF_ARMING_TIME] for state in SUPPORTED_ARMING_STATES } @property @@ -235,7 +234,7 @@ def state(self): self._state = self._previous_state return self._state - if self._state in SUPPORTED_PENDING_STATES and self._within_pending_time( + if self._state in SUPPORTED_ARMING_STATES and self._within_arming_time( self._state ): return STATE_ALARM_ARMING @@ -260,12 +259,20 @@ def _active_state(self): return self._previous_state return self._state + def _arming_time(self, state): + """Get the arming time.""" + return self._arming_time_by_state[state] + def _pending_time(self, state): """Get the pending time.""" - pending_time = self._pending_time_by_state[state] - if state == STATE_ALARM_TRIGGERED: - pending_time += self._delay_time_by_state[self._previous_state] - return pending_time + return ( + self._arming_time_by_state[state] + + self._delay_time_by_state[self._previous_state] + ) + + def _within_arming_time(self, state): + """Get if the action is in the arming time window.""" + return self._state_ts + self._arming_time(state) > dt_util.utcnow() def _within_pending_time(self, state): """Get if the action is in the pending time window.""" @@ -352,6 +359,7 @@ def _update_state(self, state): self.schedule_update_ha_state() pending_time = self._pending_time(state) + arming_time = self._arming_time(state) if state == STATE_ALARM_TRIGGERED: track_point_in_time( self._hass, self.async_update_ha_state, self._state_ts + pending_time @@ -363,9 +371,9 @@ def _update_state(self, state): self.async_update_ha_state, self._state_ts + pending_time + trigger_time, ) - elif state in SUPPORTED_PENDING_STATES and pending_time: + elif state in SUPPORTED_ARMING_STATES and arming_time: track_point_in_time( - self._hass, self.async_update_ha_state, self._state_ts + pending_time + self._hass, self.async_update_ha_state, self._state_ts + arming_time ) def _validate_code(self, code, state): @@ -405,7 +413,7 @@ async def async_added_to_hass(self): and hasattr(state, "attributes") and state.attributes[ATTR_PREVIOUS_STATE] ): - # If in pending state, we return to the ATTR_PREVIOUS_STATE + # If in arming or pending state, we return to the ATTR_PREVIOUS_STATE self._state = state.attributes[ATTR_PREVIOUS_STATE] self._state_ts = dt_util.utcnow() else: From ff283528af52bc5522035cdd52f3daef4d636ae6 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sun, 22 Mar 2020 19:25:42 +0100 Subject: [PATCH 05/23] update tests --- .../manual/test_alarm_control_panel.py | 153 +++++++++--------- 1 file changed, 77 insertions(+), 76 deletions(-) diff --git a/tests/components/manual/test_alarm_control_panel.py b/tests/components/manual/test_alarm_control_panel.py index f1596277e3c39..fe5fbb5138a87 100644 --- a/tests/components/manual/test_alarm_control_panel.py +++ b/tests/components/manual/test_alarm_control_panel.py @@ -10,6 +10,7 @@ STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED, + STATE_ALARM_ARMING, STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, ) @@ -41,7 +42,7 @@ async def test_arm_home_no_pending(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -67,7 +68,7 @@ async def test_arm_home_no_pending_when_code_not_req(hass): "name": "test", "code": CODE, "code_arm_required": False, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -92,7 +93,7 @@ async def test_arm_home_with_pending(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 1, + "arming_time": 1, "disarm_after_trigger": False, } }, @@ -104,10 +105,10 @@ async def test_arm_home_with_pending(hass): await common.async_alarm_arm_home(hass, CODE, entity_id) - assert STATE_ALARM_PENDING == hass.states.get(entity_id).state + assert STATE_ALARM_ARMING == hass.states.get(entity_id).state state = hass.states.get(entity_id) - assert state.attributes["post_pending_state"] == STATE_ALARM_ARMED_HOME + assert state.attributes["next_state"] == STATE_ALARM_ARMED_HOME future = dt_util.utcnow() + timedelta(seconds=1) with patch( @@ -131,7 +132,7 @@ async def test_arm_home_with_invalid_code(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 1, + "arming_time": 1, "disarm_after_trigger": False, } }, @@ -156,7 +157,7 @@ async def test_arm_away_no_pending(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -182,7 +183,7 @@ async def test_arm_away_no_pending_when_code_not_req(hass): "name": "test", "code": CODE, "code_arm_required": False, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -207,7 +208,7 @@ async def test_arm_home_with_template_code(hass): "platform": "manual", "name": "test", "code_template": '{{ "abc" }}', - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -233,7 +234,7 @@ async def test_arm_away_with_pending(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 1, + "arming_time": 1, "disarm_after_trigger": False, } }, @@ -245,10 +246,10 @@ async def test_arm_away_with_pending(hass): await common.async_alarm_arm_away(hass, CODE) - assert STATE_ALARM_PENDING == hass.states.get(entity_id).state + assert STATE_ALARM_ARMING == hass.states.get(entity_id).state state = hass.states.get(entity_id) - assert state.attributes["post_pending_state"] == STATE_ALARM_ARMED_AWAY + assert state.attributes["next_state"] == STATE_ALARM_ARMED_AWAY future = dt_util.utcnow() + timedelta(seconds=1) with patch( @@ -272,7 +273,7 @@ async def test_arm_away_with_invalid_code(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 1, + "arming_time": 1, "disarm_after_trigger": False, } }, @@ -297,7 +298,7 @@ async def test_arm_night_no_pending(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -323,7 +324,7 @@ async def test_arm_night_no_pending_when_code_not_req(hass): "name": "test", "code": CODE, "code_arm_required": False, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -348,7 +349,7 @@ async def test_arm_night_with_pending(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 1, + "arming_time": 1, "disarm_after_trigger": False, } }, @@ -360,10 +361,10 @@ async def test_arm_night_with_pending(hass): await common.async_alarm_arm_night(hass, CODE, entity_id) - assert STATE_ALARM_PENDING == hass.states.get(entity_id).state + assert STATE_ALARM_ARMING == hass.states.get(entity_id).state state = hass.states.get(entity_id) - assert state.attributes["post_pending_state"] == STATE_ALARM_ARMED_NIGHT + assert state.attributes["next_state"] == STATE_ALARM_ARMED_NIGHT future = dt_util.utcnow() + timedelta(seconds=1) with patch( @@ -392,7 +393,7 @@ async def test_arm_night_with_invalid_code(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 1, + "arming_time": 1, "disarm_after_trigger": False, } }, @@ -452,7 +453,7 @@ async def test_trigger_with_delay(hass): "name": "test", "code": CODE, "delay_time": 1, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -470,7 +471,7 @@ async def test_trigger_with_delay(hass): state = hass.states.get(entity_id) assert STATE_ALARM_PENDING == state.state - assert STATE_ALARM_TRIGGERED == state.attributes["post_pending_state"] + assert STATE_ALARM_TRIGGERED == state.attributes["next_state"] future = dt_util.utcnow() + timedelta(seconds=1) with patch( @@ -493,7 +494,7 @@ async def test_trigger_zero_trigger_time(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 0, + "arming_time": 0, "trigger_time": 0, "disarm_after_trigger": False, } @@ -518,7 +519,7 @@ async def test_trigger_zero_trigger_time_with_pending(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 2, + "arming_time": 2, "trigger_time": 0, "disarm_after_trigger": False, } @@ -543,7 +544,7 @@ async def test_trigger_with_pending(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 2, + "arming_time": 2, "trigger_time": 3, "disarm_after_trigger": False, } @@ -559,7 +560,7 @@ async def test_trigger_with_pending(hass): assert STATE_ALARM_PENDING == hass.states.get(entity_id).state state = hass.states.get(entity_id) - assert state.attributes["post_pending_state"] == STATE_ALARM_TRIGGERED + assert state.attributes["next_state"] == STATE_ALARM_TRIGGERED future = dt_util.utcnow() + timedelta(seconds=2) with patch( @@ -595,7 +596,7 @@ async def test_trigger_with_unused_specific_delay(hass): "name": "test", "code": CODE, "delay_time": 5, - "pending_time": 0, + "arming_time": 0, "armed_home": {"delay_time": 10}, "disarm_after_trigger": False, } @@ -614,7 +615,7 @@ async def test_trigger_with_unused_specific_delay(hass): state = hass.states.get(entity_id) assert STATE_ALARM_PENDING == state.state - assert STATE_ALARM_TRIGGERED == state.attributes["post_pending_state"] + assert STATE_ALARM_TRIGGERED == state.attributes["next_state"] future = dt_util.utcnow() + timedelta(seconds=5) with patch( @@ -639,7 +640,7 @@ async def test_trigger_with_specific_delay(hass): "name": "test", "code": CODE, "delay_time": 10, - "pending_time": 0, + "arming_time": 0, "armed_away": {"delay_time": 1}, "disarm_after_trigger": False, } @@ -658,7 +659,7 @@ async def test_trigger_with_specific_delay(hass): state = hass.states.get(entity_id) assert STATE_ALARM_PENDING == state.state - assert STATE_ALARM_TRIGGERED == state.attributes["post_pending_state"] + assert STATE_ALARM_TRIGGERED == state.attributes["next_state"] future = dt_util.utcnow() + timedelta(seconds=1) with patch( @@ -683,8 +684,8 @@ async def test_trigger_with_pending_and_delay(hass): "name": "test", "code": CODE, "delay_time": 1, - "pending_time": 0, - "triggered": {"pending_time": 1}, + "arming_time": 0, + "triggered": {"arming_time": 1}, "disarm_after_trigger": False, } }, @@ -702,7 +703,7 @@ async def test_trigger_with_pending_and_delay(hass): state = hass.states.get(entity_id) assert state.state == STATE_ALARM_PENDING - assert state.attributes["post_pending_state"] == STATE_ALARM_TRIGGERED + assert state.attributes["next_state"] == STATE_ALARM_TRIGGERED future = dt_util.utcnow() + timedelta(seconds=1) with patch( @@ -714,7 +715,7 @@ async def test_trigger_with_pending_and_delay(hass): state = hass.states.get(entity_id) assert state.state == STATE_ALARM_PENDING - assert state.attributes["post_pending_state"] == STATE_ALARM_TRIGGERED + assert state.attributes["next_state"] == STATE_ALARM_TRIGGERED future += timedelta(seconds=1) with patch( @@ -739,9 +740,9 @@ async def test_trigger_with_pending_and_specific_delay(hass): "name": "test", "code": CODE, "delay_time": 10, - "pending_time": 0, + "arming_time": 0, "armed_away": {"delay_time": 1}, - "triggered": {"pending_time": 1}, + "triggered": {"arming_time": 1}, "disarm_after_trigger": False, } }, @@ -759,7 +760,7 @@ async def test_trigger_with_pending_and_specific_delay(hass): state = hass.states.get(entity_id) assert state.state == STATE_ALARM_PENDING - assert state.attributes["post_pending_state"] == STATE_ALARM_TRIGGERED + assert state.attributes["next_state"] == STATE_ALARM_TRIGGERED future = dt_util.utcnow() + timedelta(seconds=1) with patch( @@ -771,7 +772,7 @@ async def test_trigger_with_pending_and_specific_delay(hass): state = hass.states.get(entity_id) assert state.state == STATE_ALARM_PENDING - assert state.attributes["post_pending_state"] == STATE_ALARM_TRIGGERED + assert state.attributes["next_state"] == STATE_ALARM_TRIGGERED future += timedelta(seconds=1) with patch( @@ -794,8 +795,8 @@ async def test_armed_home_with_specific_pending(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 10, - "armed_home": {"pending_time": 2}, + "arming_time": 10, + "armed_home": {"arming_time": 2}, } }, ) @@ -804,7 +805,7 @@ async def test_armed_home_with_specific_pending(hass): await common.async_alarm_arm_home(hass) - assert STATE_ALARM_PENDING == hass.states.get(entity_id).state + assert STATE_ALARM_ARMING == hass.states.get(entity_id).state future = dt_util.utcnow() + timedelta(seconds=2) with patch( @@ -826,8 +827,8 @@ async def test_armed_away_with_specific_pending(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 10, - "armed_away": {"pending_time": 2}, + "arming_time": 10, + "armed_away": {"arming_time": 2}, } }, ) @@ -836,7 +837,7 @@ async def test_armed_away_with_specific_pending(hass): await common.async_alarm_arm_away(hass) - assert STATE_ALARM_PENDING == hass.states.get(entity_id).state + assert STATE_ALARM_ARMING == hass.states.get(entity_id).state future = dt_util.utcnow() + timedelta(seconds=2) with patch( @@ -858,8 +859,8 @@ async def test_armed_night_with_specific_pending(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 10, - "armed_night": {"pending_time": 2}, + "arming_time": 10, + "armed_night": {"arming_time": 2}, } }, ) @@ -868,7 +869,7 @@ async def test_armed_night_with_specific_pending(hass): await common.async_alarm_arm_night(hass) - assert STATE_ALARM_PENDING == hass.states.get(entity_id).state + assert STATE_ALARM_ARMING == hass.states.get(entity_id).state future = dt_util.utcnow() + timedelta(seconds=2) with patch( @@ -890,8 +891,8 @@ async def test_trigger_with_specific_pending(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 10, - "triggered": {"pending_time": 2}, + "arming_time": 10, + "triggered": {"arming_time": 2}, "trigger_time": 3, "disarm_after_trigger": False, } @@ -935,7 +936,7 @@ async def test_trigger_with_disarm_after_trigger(hass): "platform": "manual", "name": "test", "trigger_time": 5, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": True, } }, @@ -971,7 +972,7 @@ async def test_trigger_with_zero_specific_trigger_time(hass): "name": "test", "trigger_time": 5, "disarmed": {"trigger_time": 0}, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": True, } }, @@ -997,7 +998,7 @@ async def test_trigger_with_unused_zero_specific_trigger_time(hass): "name": "test", "trigger_time": 5, "armed_home": {"trigger_time": 0}, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": True, } }, @@ -1032,7 +1033,7 @@ async def test_trigger_with_specific_trigger_time(hass): "platform": "manual", "name": "test", "disarmed": {"trigger_time": 5}, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": True, } }, @@ -1067,7 +1068,7 @@ async def test_trigger_with_no_disarm_after_trigger(hass): "platform": "manual", "name": "test", "trigger_time": 5, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -1106,7 +1107,7 @@ async def test_back_to_back_trigger_with_no_disarm_after_trigger(hass): "platform": "manual", "name": "test", "trigger_time": 5, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -1196,7 +1197,7 @@ async def test_disarm_during_trigger_with_invalid_code(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 5, + "arming_time": 5, "code": CODE + "2", "disarm_after_trigger": False, } @@ -1236,7 +1237,7 @@ async def test_disarm_with_template_code(hass): "platform": "manual", "name": "test", "code_template": '{{ "" if from_state == "disarmed" else "abc" }}', - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -1272,7 +1273,7 @@ async def test_arm_custom_bypass_no_pending(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -1298,7 +1299,7 @@ async def test_arm_custom_bypass_no_pending_when_code_not_req(hass): "name": "test", "code": CODE, "code_arm_required": False, - "pending_time": 0, + "arming_time": 0, "disarm_after_trigger": False, } }, @@ -1323,7 +1324,7 @@ async def test_arm_custom_bypass_with_pending(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 1, + "arming_time": 1, "disarm_after_trigger": False, } }, @@ -1335,10 +1336,10 @@ async def test_arm_custom_bypass_with_pending(hass): await common.async_alarm_arm_custom_bypass(hass, CODE, entity_id) - assert STATE_ALARM_PENDING == hass.states.get(entity_id).state + assert STATE_ALARM_ARMING == hass.states.get(entity_id).state state = hass.states.get(entity_id) - assert state.attributes["post_pending_state"] == STATE_ALARM_ARMED_CUSTOM_BYPASS + assert state.attributes["next_state"] == STATE_ALARM_ARMED_CUSTOM_BYPASS future = dt_util.utcnow() + timedelta(seconds=1) with patch( @@ -1362,7 +1363,7 @@ async def test_arm_custom_bypass_with_invalid_code(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 1, + "arming_time": 1, "disarm_after_trigger": False, } }, @@ -1386,8 +1387,8 @@ async def test_armed_custom_bypass_with_specific_pending(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 10, - "armed_custom_bypass": {"pending_time": 2}, + "arming_time": 10, + "armed_custom_bypass": {"arming_time": 2}, } }, ) @@ -1396,7 +1397,7 @@ async def test_armed_custom_bypass_with_specific_pending(hass): await common.async_alarm_arm_custom_bypass(hass) - assert STATE_ALARM_PENDING == hass.states.get(entity_id).state + assert STATE_ALARM_ARMING == hass.states.get(entity_id).state future = dt_util.utcnow() + timedelta(seconds=2) with patch( @@ -1419,9 +1420,9 @@ async def test_arm_away_after_disabled_disarmed(hass): "platform": "manual", "name": "test", "code": CODE, - "pending_time": 0, + "arming_time": 0, "delay_time": 1, - "armed_away": {"pending_time": 1}, + "armed_away": {"arming_time": 1}, "disarmed": {"trigger_time": 0}, "disarm_after_trigger": False, } @@ -1435,16 +1436,16 @@ async def test_arm_away_after_disabled_disarmed(hass): await common.async_alarm_arm_away(hass, CODE) state = hass.states.get(entity_id) - assert STATE_ALARM_PENDING == state.state - assert STATE_ALARM_DISARMED == state.attributes["pre_pending_state"] - assert STATE_ALARM_ARMED_AWAY == state.attributes["post_pending_state"] + assert STATE_ALARM_ARMING == state.state + assert STATE_ALARM_DISARMED == state.attributes["previous_state"] + assert STATE_ALARM_ARMED_AWAY == state.attributes["next_state"] await common.async_alarm_trigger(hass, entity_id=entity_id) state = hass.states.get(entity_id) assert STATE_ALARM_PENDING == state.state - assert STATE_ALARM_DISARMED == state.attributes["pre_pending_state"] - assert STATE_ALARM_ARMED_AWAY == state.attributes["post_pending_state"] + assert STATE_ALARM_DISARMED == state.attributes["previous_state"] + assert STATE_ALARM_ARMED_AWAY == state.attributes["next_state"] future = dt_util.utcnow() + timedelta(seconds=1) with patch( @@ -1461,8 +1462,8 @@ async def test_arm_away_after_disabled_disarmed(hass): state = hass.states.get(entity_id) assert STATE_ALARM_PENDING == state.state - assert STATE_ALARM_ARMED_AWAY == state.attributes["pre_pending_state"] - assert STATE_ALARM_TRIGGERED == state.attributes["post_pending_state"] + assert STATE_ALARM_ARMED_AWAY == state.attributes["previous_state"] + assert STATE_ALARM_TRIGGERED == state.attributes["next_state"] future += timedelta(seconds=1) with patch( @@ -1492,7 +1493,7 @@ async def test_restore_armed_state(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 0, + "arming_time": 0, "trigger_time": 0, "disarm_after_trigger": False, } @@ -1518,7 +1519,7 @@ async def test_restore_disarmed_state(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "pending_time": 0, + "arming_time": 0, "trigger_time": 0, "disarm_after_trigger": False, } From e19d965fdb98142eed30c1a9d4e53934989e3980 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sun, 22 Mar 2020 19:28:06 +0100 Subject: [PATCH 06/23] fix issort --- homeassistant/components/manual/alarm_control_panel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index 40ee63dbe3518..88d1312d528be 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -15,11 +15,11 @@ SUPPORT_ALARM_TRIGGER, ) from homeassistant.const import ( + CONF_ARMING_TIME, CONF_CODE, CONF_DELAY_TIME, CONF_DISARM_AFTER_TRIGGER, CONF_NAME, - CONF_ARMING_TIME, CONF_PLATFORM, CONF_TRIGGER_TIME, STATE_ALARM_ARMED_AWAY, From 6f807168cb78b05da34639e3c1b1827ce5f06da6 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sun, 22 Mar 2020 19:35:39 +0100 Subject: [PATCH 07/23] fix issort --- tests/components/manual/test_alarm_control_panel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/components/manual/test_alarm_control_panel.py b/tests/components/manual/test_alarm_control_panel.py index fe5fbb5138a87..0aed641a317e8 100644 --- a/tests/components/manual/test_alarm_control_panel.py +++ b/tests/components/manual/test_alarm_control_panel.py @@ -9,8 +9,8 @@ STATE_ALARM_ARMED_CUSTOM_BYPASS, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT, - STATE_ALARM_DISARMED, STATE_ALARM_ARMING, + STATE_ALARM_DISARMED, STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, ) From 48d30f6cbcd81def29f8cad4d1774b60a6767fbf Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sun, 22 Mar 2020 20:30:15 +0100 Subject: [PATCH 08/23] fix demo platform --- homeassistant/components/demo/alarm_control_panel.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/demo/alarm_control_panel.py b/homeassistant/components/demo/alarm_control_panel.py index 0323b68b1b04a..d5bb71da67b01 100644 --- a/homeassistant/components/demo/alarm_control_panel.py +++ b/homeassistant/components/demo/alarm_control_panel.py @@ -3,8 +3,8 @@ from homeassistant.components.manual.alarm_control_panel import ManualAlarm from homeassistant.const import ( + CONF_ARMING_TIME, CONF_DELAY_TIME, - CONF_PENDING_TIME, CONF_TRIGGER_TIME, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_CUSTOM_BYPASS, @@ -28,18 +28,18 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= False, { STATE_ALARM_ARMED_AWAY: { + CONF_ARMING_TIME: datetime.timedelta(seconds=5), CONF_DELAY_TIME: datetime.timedelta(seconds=0), - CONF_PENDING_TIME: datetime.timedelta(seconds=5), CONF_TRIGGER_TIME: datetime.timedelta(seconds=10), }, STATE_ALARM_ARMED_HOME: { + CONF_ARMING_TIME: datetime.timedelta(seconds=5), CONF_DELAY_TIME: datetime.timedelta(seconds=0), - CONF_PENDING_TIME: datetime.timedelta(seconds=5), CONF_TRIGGER_TIME: datetime.timedelta(seconds=10), }, STATE_ALARM_ARMED_NIGHT: { + CONF_ARMING_TIME: datetime.timedelta(seconds=5), CONF_DELAY_TIME: datetime.timedelta(seconds=0), - CONF_PENDING_TIME: datetime.timedelta(seconds=5), CONF_TRIGGER_TIME: datetime.timedelta(seconds=10), }, STATE_ALARM_DISARMED: { @@ -47,12 +47,12 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= CONF_TRIGGER_TIME: datetime.timedelta(seconds=10), }, STATE_ALARM_ARMED_CUSTOM_BYPASS: { + CONF_ARMING_TIME: datetime.timedelta(seconds=5), CONF_DELAY_TIME: datetime.timedelta(seconds=0), - CONF_PENDING_TIME: datetime.timedelta(seconds=5), CONF_TRIGGER_TIME: datetime.timedelta(seconds=10), }, STATE_ALARM_TRIGGERED: { - CONF_PENDING_TIME: datetime.timedelta(seconds=5) + CONF_ARMING_TIME: datetime.timedelta(seconds=5) }, }, ) From af825533f3ba21381d1f3204483e9c636b1c8ae7 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sun, 22 Mar 2020 20:35:04 +0100 Subject: [PATCH 09/23] fix alarm test --- tests/components/manual/test_alarm_control_panel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/components/manual/test_alarm_control_panel.py b/tests/components/manual/test_alarm_control_panel.py index 0aed641a317e8..8669f9b6c5dc0 100644 --- a/tests/components/manual/test_alarm_control_panel.py +++ b/tests/components/manual/test_alarm_control_panel.py @@ -1443,7 +1443,7 @@ async def test_arm_away_after_disabled_disarmed(hass): await common.async_alarm_trigger(hass, entity_id=entity_id) state = hass.states.get(entity_id) - assert STATE_ALARM_PENDING == state.state + assert STATE_ALARM_ARMING == state.state assert STATE_ALARM_DISARMED == state.attributes["previous_state"] assert STATE_ALARM_ARMED_AWAY == state.attributes["next_state"] From ed2c8ad0c0838639a2501d4ca7ecab2f504dd88b Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sat, 28 Mar 2020 13:22:45 +0100 Subject: [PATCH 10/23] remove arming_time from the triggered state --- homeassistant/components/manual/alarm_control_panel.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index 88d1312d528be..c3cc9c8039e72 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -166,8 +166,7 @@ class ManualAlarm(alarm.AlarmControlPanel, RestoreEntity): Representation of an alarm status. When armed, will be arming for 'arming_time', after that armed. - When triggered, will be pending for the triggering state's 'delay_time' - plus the triggered state's 'arming_time'. + When triggered, will be pending for the triggering state's 'delay_time'. After that will be triggered for 'trigger_time', after that we return to the previous state or disarm if `disarm_after_trigger` is true. A trigger_time of zero disables the alarm_trigger service. @@ -265,10 +264,7 @@ def _arming_time(self, state): def _pending_time(self, state): """Get the pending time.""" - return ( - self._arming_time_by_state[state] - + self._delay_time_by_state[self._previous_state] - ) + return self._delay_time_by_state[self._previous_state] def _within_arming_time(self, state): """Get if the action is in the arming time window.""" From 0e093944306e601456efba6c16feab7154c69776 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sat, 28 Mar 2020 14:32:33 +0100 Subject: [PATCH 11/23] Match previous default "delay_time" --- homeassistant/components/manual/alarm_control_panel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index c3cc9c8039e72..027f3b0df615b 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -42,7 +42,7 @@ CONF_CODE_ARM_REQUIRED = "code_arm_required" DEFAULT_ALARM_NAME = "HA Alarm" -DEFAULT_DELAY_TIME = datetime.timedelta(seconds=0) +DEFAULT_DELAY_TIME = datetime.timedelta(seconds=60) DEFAULT_ARMING_TIME = datetime.timedelta(seconds=60) DEFAULT_TRIGGER_TIME = datetime.timedelta(seconds=120) DEFAULT_DISARM_AFTER_TRIGGER = False From b02ab1ef0fd0c685cd00649abd20c27c9eadddec Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sat, 28 Mar 2020 16:37:44 +0100 Subject: [PATCH 12/23] fix tests --- .../manual/test_alarm_control_panel.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/components/manual/test_alarm_control_panel.py b/tests/components/manual/test_alarm_control_panel.py index 8669f9b6c5dc0..22dceec312b75 100644 --- a/tests/components/manual/test_alarm_control_panel.py +++ b/tests/components/manual/test_alarm_control_panel.py @@ -544,7 +544,7 @@ async def test_trigger_with_pending(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "arming_time": 2, + "delay_time": 2, "trigger_time": 3, "disarm_after_trigger": False, } @@ -683,9 +683,8 @@ async def test_trigger_with_pending_and_delay(hass): "platform": "manual", "name": "test", "code": CODE, - "delay_time": 1, + "delay_time": 2, "arming_time": 0, - "triggered": {"arming_time": 1}, "disarm_after_trigger": False, } }, @@ -741,8 +740,7 @@ async def test_trigger_with_pending_and_specific_delay(hass): "code": CODE, "delay_time": 10, "arming_time": 0, - "armed_away": {"delay_time": 1}, - "triggered": {"arming_time": 1}, + "armed_away": {"delay_time": 2}, "disarm_after_trigger": False, } }, @@ -891,8 +889,8 @@ async def test_trigger_with_specific_pending(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "arming_time": 10, - "triggered": {"arming_time": 2}, + "delay_time": 10, + "disarmed": {"delay_time": 2}, "trigger_time": 3, "disarm_after_trigger": False, } @@ -936,7 +934,7 @@ async def test_trigger_with_disarm_after_trigger(hass): "platform": "manual", "name": "test", "trigger_time": 5, - "arming_time": 0, + "delay_time": 0, "disarm_after_trigger": True, } }, @@ -998,7 +996,7 @@ async def test_trigger_with_unused_zero_specific_trigger_time(hass): "name": "test", "trigger_time": 5, "armed_home": {"trigger_time": 0}, - "arming_time": 0, + "delay_time": 0, "disarm_after_trigger": True, } }, @@ -1033,7 +1031,7 @@ async def test_trigger_with_specific_trigger_time(hass): "platform": "manual", "name": "test", "disarmed": {"trigger_time": 5}, - "arming_time": 0, + "delay_time": 0, "disarm_after_trigger": True, } }, @@ -1069,6 +1067,7 @@ async def test_trigger_with_no_disarm_after_trigger(hass): "name": "test", "trigger_time": 5, "arming_time": 0, + "delay_time": 0, "disarm_after_trigger": False, } }, @@ -1108,6 +1107,7 @@ async def test_back_to_back_trigger_with_no_disarm_after_trigger(hass): "name": "test", "trigger_time": 5, "arming_time": 0, + "delay_time": 0, "disarm_after_trigger": False, } }, @@ -1197,7 +1197,7 @@ async def test_disarm_during_trigger_with_invalid_code(hass): "alarm_control_panel": { "platform": "manual", "name": "test", - "arming_time": 5, + "delay_time": 5, "code": CODE + "2", "disarm_after_trigger": False, } From df94b2eb4953665d437ee5db44e183bad13317a7 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sat, 28 Mar 2020 17:52:44 +0100 Subject: [PATCH 13/23] fix arming state when triggering --- homeassistant/components/manual/alarm_control_panel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index 027f3b0df615b..761f8271ad798 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -61,7 +61,9 @@ ] SUPPORTED_ARMING_STATES = [ - state for state in SUPPORTED_STATES if state != STATE_ALARM_DISARMED + state + for state in SUPPORTED_STATES + if (state != STATE_ALARM_DISARMED and state != STATE_ALARM_TRIGGERED) ] ATTR_PREVIOUS_STATE = "previous_state" From 483d7767b7ebbf83ebbe6556cecf3503b535bb86 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sat, 28 Mar 2020 20:08:15 +0100 Subject: [PATCH 14/23] fix arming _arming_time_by_state for Triggering state --- .../components/manual/alarm_control_panel.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index 761f8271ad798..991a4ed4e723b 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -356,9 +356,8 @@ def _update_state(self, state): self._state_ts = dt_util.utcnow() self.schedule_update_ha_state() - pending_time = self._pending_time(state) - arming_time = self._arming_time(state) if state == STATE_ALARM_TRIGGERED: + pending_time = self._pending_time(state) track_point_in_time( self._hass, self.async_update_ha_state, self._state_ts + pending_time ) @@ -369,10 +368,12 @@ def _update_state(self, state): self.async_update_ha_state, self._state_ts + pending_time + trigger_time, ) - elif state in SUPPORTED_ARMING_STATES and arming_time: - track_point_in_time( - self._hass, self.async_update_ha_state, self._state_ts + arming_time - ) + elif state in SUPPORTED_ARMING_STATES: + arming_time = self._arming_time(state) + if arming_time: + track_point_in_time( + self._hass, self.async_update_ha_state, self._state_ts + arming_time + ) def _validate_code(self, code, state): """Validate given code.""" From 22ee780cbd79be6700389aca543e2c427bafa845 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sat, 28 Mar 2020 21:25:14 +0100 Subject: [PATCH 15/23] change to not in list --- homeassistant/components/manual/alarm_control_panel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index 991a4ed4e723b..1eb8da1e53113 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -63,7 +63,7 @@ SUPPORTED_ARMING_STATES = [ state for state in SUPPORTED_STATES - if (state != STATE_ALARM_DISARMED and state != STATE_ALARM_TRIGGERED) + if state not in (STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED) ] ATTR_PREVIOUS_STATE = "previous_state" From 17f5d344c4501ffaa73507095e45b5b30417ceed Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 17 Apr 2020 19:23:07 +0200 Subject: [PATCH 16/23] Update homeassistant/components/manual/alarm_control_panel.py Co-Authored-By: Martin Hjelmare --- homeassistant/components/manual/alarm_control_panel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index 1eb8da1e53113..e32a48169dcb4 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -256,7 +256,7 @@ def supported_features(self) -> int: @property def _active_state(self): """Get the current state.""" - if self.state == STATE_ALARM_PENDING or self.state == STATE_ALARM_ARMING: + if self.state in (STATE_ALARM_PENDING, STATE_ALARM_ARMING): return self._previous_state return self._state From 536fc9b1f2838e35ffeb73f204aeb10638bd1585 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 17 Apr 2020 20:09:08 +0200 Subject: [PATCH 17/23] async_update_ha_state -> async_write_ha_state --- homeassistant/components/manual/alarm_control_panel.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index e32a48169dcb4..3d9799b9320e2 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -359,20 +359,20 @@ def _update_state(self, state): if state == STATE_ALARM_TRIGGERED: pending_time = self._pending_time(state) track_point_in_time( - self._hass, self.async_update_ha_state, self._state_ts + pending_time + self._hass, self.async_scheduled_update, self._state_ts + pending_time ) trigger_time = self._trigger_time_by_state[self._previous_state] track_point_in_time( self._hass, - self.async_update_ha_state, + self.async_scheduled_update, self._state_ts + pending_time + trigger_time, ) elif state in SUPPORTED_ARMING_STATES: arming_time = self._arming_time(state) if arming_time: track_point_in_time( - self._hass, self.async_update_ha_state, self._state_ts + arming_time + self._hass, self.async_scheduled_update, self._state_ts + arming_time ) def _validate_code(self, code, state): @@ -399,6 +399,10 @@ def device_state_attributes(self): return state_attr + async def async_scheduled_update(self, now): + """Update state at a scheduled point in time.""" + self.async_write_ha_state() + async def async_added_to_hass(self): """Run when entity about to be added to hass.""" await super().async_added_to_hass() From 8f41e76d4975919c3dfbee1b1146f4d7c985c431 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 17 Apr 2020 20:15:56 +0200 Subject: [PATCH 18/23] black formatting --- homeassistant/components/manual/alarm_control_panel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index 3d9799b9320e2..bf251f719e9df 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -372,7 +372,9 @@ def _update_state(self, state): arming_time = self._arming_time(state) if arming_time: track_point_in_time( - self._hass, self.async_scheduled_update, self._state_ts + arming_time + self._hass, + self.async_scheduled_update, + self._state_ts + arming_time, ) def _validate_code(self, code, state): From 471ea5435d76533f7fe2ff9c9819bf36d5508761 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sat, 18 Apr 2020 10:48:26 +0200 Subject: [PATCH 19/23] add Callback Co-Authored-By: Martin Hjelmare --- homeassistant/components/manual/alarm_control_panel.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index bf251f719e9df..2f5869d276abf 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -401,7 +401,8 @@ def device_state_attributes(self): return state_attr - async def async_scheduled_update(self, now): + @callback + def async_scheduled_update(self, now): """Update state at a scheduled point in time.""" self.async_write_ha_state() From 3aafcf86d0f2669bc4451c69a3615da25866cafb Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sat, 18 Apr 2020 10:52:22 +0200 Subject: [PATCH 20/23] import callback --- homeassistant/components/manual/alarm_control_panel.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/manual/alarm_control_panel.py b/homeassistant/components/manual/alarm_control_panel.py index 2f5869d276abf..89f5e34213b9d 100644 --- a/homeassistant/components/manual/alarm_control_panel.py +++ b/homeassistant/components/manual/alarm_control_panel.py @@ -31,6 +31,7 @@ STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, ) +from homeassistant.core import callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.event import track_point_in_time from homeassistant.helpers.restore_state import RestoreEntity From 3675069aafa629e0c51f8056bd4b0010d679d9fc Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Tue, 21 Apr 2020 13:04:47 +0200 Subject: [PATCH 21/23] update device triggers alarm_control_panel --- .../alarm_control_panel/device_trigger.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/device_trigger.py b/homeassistant/components/alarm_control_panel/device_trigger.py index 95ae17aaaf562..43cf17ec2196d 100644 --- a/homeassistant/components/alarm_control_panel/device_trigger.py +++ b/homeassistant/components/alarm_control_panel/device_trigger.py @@ -19,6 +19,7 @@ STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT, + STATE_ALARM_ARMING, STATE_ALARM_DISARMED, STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, @@ -32,6 +33,7 @@ TRIGGER_TYPES = { "triggered", "disarmed", + "arming", "armed_home", "armed_away", "armed_night", @@ -79,6 +81,13 @@ async def async_get_triggers(hass: HomeAssistant, device_id: str) -> List[dict]: CONF_ENTITY_ID: entry.entity_id, CONF_TYPE: "triggered", }, + { + CONF_PLATFORM: "device", + CONF_DEVICE_ID: device_id, + CONF_DOMAIN: DOMAIN, + CONF_ENTITY_ID: entry.entity_id, + CONF_TYPE: "arming", + }, ] if supported_features & SUPPORT_ALARM_ARM_HOME: triggers.append( @@ -129,14 +138,17 @@ async def async_attach_trigger( elif config[CONF_TYPE] == "disarmed": from_state = STATE_ALARM_TRIGGERED to_state = STATE_ALARM_DISARMED + elif config[CONF_TYPE] == "arming": + from_state = STATE_ALARM_DISARMED + to_state = STATE_ALARM_ARMING elif config[CONF_TYPE] == "armed_home": - from_state = STATE_ALARM_PENDING + from_state = STATE_ALARM_ARMING to_state = STATE_ALARM_ARMED_HOME elif config[CONF_TYPE] == "armed_away": - from_state = STATE_ALARM_PENDING + from_state = STATE_ALARM_ARMING to_state = STATE_ALARM_ARMED_AWAY elif config[CONF_TYPE] == "armed_night": - from_state = STATE_ALARM_PENDING + from_state = STATE_ALARM_ARMING to_state = STATE_ALARM_ARMED_NIGHT state_config = { From ffe5616d93faca013c83a628a585dcaf16e2446b Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Tue, 21 Apr 2020 14:35:17 +0200 Subject: [PATCH 22/23] Update test_device_trigger.py --- .../components/alarm_control_panel/test_device_trigger.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/components/alarm_control_panel/test_device_trigger.py b/tests/components/alarm_control_panel/test_device_trigger.py index 9b890aa4d2514..9d414d179ab02 100644 --- a/tests/components/alarm_control_panel/test_device_trigger.py +++ b/tests/components/alarm_control_panel/test_device_trigger.py @@ -69,6 +69,13 @@ async def test_get_triggers(hass, device_reg, entity_reg): "device_id": device_entry.id, "entity_id": f"{DOMAIN}.test_5678", }, + { + "platform": "device", + "domain": DOMAIN, + "type": "arming", + "device_id": device_entry.id, + "entity_id": f"{DOMAIN}.test_5678", + }, { "platform": "device", "domain": DOMAIN, From 85a12ada83d6c47b4f8983b5067839062be97b61 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Wed, 22 Apr 2020 22:44:39 +0200 Subject: [PATCH 23/23] Update device_trigger.py --- .../components/alarm_control_panel/device_trigger.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/device_trigger.py b/homeassistant/components/alarm_control_panel/device_trigger.py index 43cf17ec2196d..849da062665c3 100644 --- a/homeassistant/components/alarm_control_panel/device_trigger.py +++ b/homeassistant/components/alarm_control_panel/device_trigger.py @@ -131,32 +131,32 @@ async def async_attach_trigger( ) -> CALLBACK_TYPE: """Attach a trigger.""" config = TRIGGER_SCHEMA(config) + from_state = None if config[CONF_TYPE] == "triggered": - from_state = STATE_ALARM_PENDING to_state = STATE_ALARM_TRIGGERED elif config[CONF_TYPE] == "disarmed": - from_state = STATE_ALARM_TRIGGERED to_state = STATE_ALARM_DISARMED elif config[CONF_TYPE] == "arming": from_state = STATE_ALARM_DISARMED to_state = STATE_ALARM_ARMING elif config[CONF_TYPE] == "armed_home": - from_state = STATE_ALARM_ARMING + from_state = STATE_ALARM_PENDING or STATE_ALARM_ARMING to_state = STATE_ALARM_ARMED_HOME elif config[CONF_TYPE] == "armed_away": - from_state = STATE_ALARM_ARMING + from_state = STATE_ALARM_PENDING or STATE_ALARM_ARMING to_state = STATE_ALARM_ARMED_AWAY elif config[CONF_TYPE] == "armed_night": - from_state = STATE_ALARM_ARMING + from_state = STATE_ALARM_PENDING or STATE_ALARM_ARMING to_state = STATE_ALARM_ARMED_NIGHT state_config = { state.CONF_PLATFORM: "state", CONF_ENTITY_ID: config[CONF_ENTITY_ID], - state.CONF_FROM: from_state, state.CONF_TO: to_state, } + if from_state: + state_config[state.CONF_FROM] = from_state state_config = state.TRIGGER_SCHEMA(state_config) return await state.async_attach_trigger( hass, state_config, action, automation_info, platform_type="device"