Use "arming" state during transition in manual alarm panel (#32950)
* Manual Alarm Control Panel: use proper "Arming" state * Update previous and next attributes * add CONF_ARMING_TIME * Split up arming and pending time, pending_time --> arming_time * update tests * fix issort * fix issort * fix demo platform * fix alarm test * remove arming_time from the triggered state * Match previous default "delay_time" * fix tests * fix arming state when triggering * fix arming _arming_time_by_state for Triggering state * change to not in list * Update homeassistant/components/manual/alarm_control_panel.py Co-Authored-By: Martin Hjelmare <marhje52@gmail.com> * async_update_ha_state -> async_write_ha_state * black formatting * add Callback Co-Authored-By: Martin Hjelmare <marhje52@gmail.com> * import callback * update device triggers alarm_control_panel * Update test_device_trigger.py * Update device_trigger.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com>pull/34624/head
parent
e9c5f3e74a
commit
7bfc1d2840
|
@ -19,6 +19,7 @@ from homeassistant.const import (
|
|||
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 @@ from . import DOMAIN
|
|||
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(
|
||||
|
@ -122,29 +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_PENDING
|
||||
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_PENDING
|
||||
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_PENDING
|
||||
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"
|
||||
|
|
|
@ -3,8 +3,8 @@ import datetime
|
|||
|
||||
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)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
|
@ -15,21 +15,23 @@ from homeassistant.components.alarm_control_panel.const import (
|
|||
SUPPORT_ALARM_TRIGGER,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_ARMING_TIME,
|
||||
CONF_CODE,
|
||||
CONF_DELAY_TIME,
|
||||
CONF_DISARM_AFTER_TRIGGER,
|
||||
CONF_NAME,
|
||||
CONF_PENDING_TIME,
|
||||
CONF_PLATFORM,
|
||||
CONF_TRIGGER_TIME,
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
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,
|
||||
)
|
||||
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
|
||||
|
@ -41,8 +43,8 @@ CONF_CODE_TEMPLATE = "code_template"
|
|||
CONF_CODE_ARM_REQUIRED = "code_arm_required"
|
||||
|
||||
DEFAULT_ALARM_NAME = "HA Alarm"
|
||||
DEFAULT_DELAY_TIME = datetime.timedelta(seconds=0)
|
||||
DEFAULT_PENDING_TIME = datetime.timedelta(seconds=60)
|
||||
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
|
||||
|
||||
|
@ -59,12 +61,14 @@ SUPPORTED_PRETRIGGER_STATES = [
|
|||
state for state in SUPPORTED_STATES if state != STATE_ALARM_TRIGGERED
|
||||
]
|
||||
|
||||
SUPPORTED_PENDING_STATES = [
|
||||
state for state in SUPPORTED_STATES if state != STATE_ALARM_DISARMED
|
||||
SUPPORTED_ARMING_STATES = [
|
||||
state
|
||||
for state in SUPPORTED_STATES
|
||||
if state not in (STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED)
|
||||
]
|
||||
|
||||
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):
|
||||
|
@ -75,9 +79,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
|
||||
|
||||
|
@ -92,8 +96,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)
|
||||
|
@ -110,7 +114,7 @@ PLATFORM_SCHEMA = vol.Schema(
|
|||
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(
|
||||
|
@ -164,9 +168,8 @@ class ManualAlarm(alarm.AlarmControlPanel, RestoreEntity):
|
|||
"""
|
||||
Representation of an alarm status.
|
||||
|
||||
When armed, will be pending for 'pending_time', after that armed.
|
||||
When triggered, will be pending for the triggering state's 'delay_time'
|
||||
plus the triggered state's 'pending_time'.
|
||||
When armed, will be arming for 'arming_time', after that armed.
|
||||
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.
|
||||
|
@ -204,9 +207,8 @@ class ManualAlarm(alarm.AlarmControlPanel, RestoreEntity):
|
|||
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
|
||||
|
@ -234,10 +236,10 @@ class ManualAlarm(alarm.AlarmControlPanel, RestoreEntity):
|
|||
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_PENDING
|
||||
return STATE_ALARM_ARMING
|
||||
|
||||
return self._state
|
||||
|
||||
|
@ -255,16 +257,21 @@ class ManualAlarm(alarm.AlarmControlPanel, RestoreEntity):
|
|||
@property
|
||||
def _active_state(self):
|
||||
"""Get the current state."""
|
||||
if self.state == STATE_ALARM_PENDING:
|
||||
if self.state in (STATE_ALARM_PENDING, STATE_ALARM_ARMING):
|
||||
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._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."""
|
||||
|
@ -350,22 +357,26 @@ class ManualAlarm(alarm.AlarmControlPanel, RestoreEntity):
|
|||
self._state_ts = dt_util.utcnow()
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
pending_time = self._pending_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
|
||||
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_PENDING_STATES and pending_time:
|
||||
track_point_in_time(
|
||||
self._hass, self.async_update_ha_state, self._state_ts + pending_time
|
||||
)
|
||||
elif state in SUPPORTED_ARMING_STATES:
|
||||
arming_time = self._arming_time(state)
|
||||
if arming_time:
|
||||
track_point_in_time(
|
||||
self._hass,
|
||||
self.async_scheduled_update,
|
||||
self._state_ts + arming_time,
|
||||
)
|
||||
|
||||
def _validate_code(self, code, state):
|
||||
"""Validate given code."""
|
||||
|
@ -385,24 +396,32 @@ class ManualAlarm(alarm.AlarmControlPanel, RestoreEntity):
|
|||
"""Return the state attributes."""
|
||||
state_attr = {}
|
||||
|
||||
if self.state == STATE_ALARM_PENDING:
|
||||
state_attr[ATTR_PRE_PENDING_STATE] = self._previous_state
|
||||
state_attr[ATTR_POST_PENDING_STATE] = self._state
|
||||
if self.state == STATE_ALARM_PENDING or self.state == STATE_ALARM_ARMING:
|
||||
state_attr[ATTR_PREVIOUS_STATE] = self._previous_state
|
||||
state_attr[ATTR_NEXT_STATE] = self._state
|
||||
|
||||
return state_attr
|
||||
|
||||
@callback
|
||||
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()
|
||||
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"]
|
||||
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 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:
|
||||
self._state = state.state
|
||||
|
|
|
@ -34,6 +34,7 @@ CONF_AFTER = "after"
|
|||
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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -9,6 +9,7 @@ from homeassistant.const import (
|
|||
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,
|
||||
|
@ -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,
|
||||
"delay_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(
|
||||
|
@ -682,9 +683,8 @@ async def test_trigger_with_pending_and_delay(hass):
|
|||
"platform": "manual",
|
||||
"name": "test",
|
||||
"code": CODE,
|
||||
"delay_time": 1,
|
||||
"pending_time": 0,
|
||||
"triggered": {"pending_time": 1},
|
||||
"delay_time": 2,
|
||||
"arming_time": 0,
|
||||
"disarm_after_trigger": False,
|
||||
}
|
||||
},
|
||||
|
@ -702,7 +702,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 +714,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 +739,8 @@ async def test_trigger_with_pending_and_specific_delay(hass):
|
|||
"name": "test",
|
||||
"code": CODE,
|
||||
"delay_time": 10,
|
||||
"pending_time": 0,
|
||||
"armed_away": {"delay_time": 1},
|
||||
"triggered": {"pending_time": 1},
|
||||
"arming_time": 0,
|
||||
"armed_away": {"delay_time": 2},
|
||||
"disarm_after_trigger": False,
|
||||
}
|
||||
},
|
||||
|
@ -759,7 +758,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 +770,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 +793,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 +803,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 +825,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 +835,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 +857,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 +867,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 +889,8 @@ async def test_trigger_with_specific_pending(hass):
|
|||
"alarm_control_panel": {
|
||||
"platform": "manual",
|
||||
"name": "test",
|
||||
"pending_time": 10,
|
||||
"triggered": {"pending_time": 2},
|
||||
"delay_time": 10,
|
||||
"disarmed": {"delay_time": 2},
|
||||
"trigger_time": 3,
|
||||
"disarm_after_trigger": False,
|
||||
}
|
||||
|
@ -935,7 +934,7 @@ async def test_trigger_with_disarm_after_trigger(hass):
|
|||
"platform": "manual",
|
||||
"name": "test",
|
||||
"trigger_time": 5,
|
||||
"pending_time": 0,
|
||||
"delay_time": 0,
|
||||
"disarm_after_trigger": True,
|
||||
}
|
||||
},
|
||||
|
@ -971,7 +970,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 +996,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,
|
||||
"delay_time": 0,
|
||||
"disarm_after_trigger": True,
|
||||
}
|
||||
},
|
||||
|
@ -1032,7 +1031,7 @@ async def test_trigger_with_specific_trigger_time(hass):
|
|||
"platform": "manual",
|
||||
"name": "test",
|
||||
"disarmed": {"trigger_time": 5},
|
||||
"pending_time": 0,
|
||||
"delay_time": 0,
|
||||
"disarm_after_trigger": True,
|
||||
}
|
||||
},
|
||||
|
@ -1067,7 +1066,8 @@ async def test_trigger_with_no_disarm_after_trigger(hass):
|
|||
"platform": "manual",
|
||||
"name": "test",
|
||||
"trigger_time": 5,
|
||||
"pending_time": 0,
|
||||
"arming_time": 0,
|
||||
"delay_time": 0,
|
||||
"disarm_after_trigger": False,
|
||||
}
|
||||
},
|
||||
|
@ -1106,7 +1106,8 @@ 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,
|
||||
"delay_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,
|
||||
"delay_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_ARMING == state.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,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue