mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Vacation Mode on Alarm Panels (#45980)
Co-authored-by: Nathan Tilley <nathan@tilley.xyz> Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Franck Nijhof <frenck@frenck.nl> Co-authored-by: Khole Jones <ktech6@outlook.com> Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
parent
57fbb1c3d9
commit
312531988a
@ -15,6 +15,7 @@ from homeassistant.const import (
|
||||
SERVICE_ALARM_ARM_CUSTOM_BYPASS,
|
||||
SERVICE_ALARM_ARM_HOME,
|
||||
SERVICE_ALARM_ARM_NIGHT,
|
||||
SERVICE_ALARM_ARM_VACATION,
|
||||
SERVICE_ALARM_DISARM,
|
||||
SERVICE_ALARM_TRIGGER,
|
||||
)
|
||||
@ -30,6 +31,7 @@ from .const import (
|
||||
SUPPORT_ALARM_ARM_CUSTOM_BYPASS,
|
||||
SUPPORT_ALARM_ARM_HOME,
|
||||
SUPPORT_ALARM_ARM_NIGHT,
|
||||
SUPPORT_ALARM_ARM_VACATION,
|
||||
SUPPORT_ALARM_TRIGGER,
|
||||
)
|
||||
|
||||
@ -81,6 +83,12 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"async_alarm_arm_night",
|
||||
[SUPPORT_ALARM_ARM_NIGHT],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_ALARM_ARM_VACATION,
|
||||
ALARM_SERVICE_SCHEMA,
|
||||
"async_alarm_arm_vacation",
|
||||
[SUPPORT_ALARM_ARM_VACATION],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_ALARM_ARM_CUSTOM_BYPASS,
|
||||
ALARM_SERVICE_SCHEMA,
|
||||
@ -164,6 +172,14 @@ class AlarmControlPanelEntity(Entity):
|
||||
"""Send arm night command."""
|
||||
await self.hass.async_add_executor_job(self.alarm_arm_night, code)
|
||||
|
||||
def alarm_arm_vacation(self, code: str | None = None) -> None:
|
||||
"""Send arm vacation command."""
|
||||
raise NotImplementedError()
|
||||
|
||||
async def async_alarm_arm_vacation(self, code: str | None = None) -> None:
|
||||
"""Send arm vacation command."""
|
||||
await self.hass.async_add_executor_job(self.alarm_arm_vacation, code)
|
||||
|
||||
def alarm_trigger(self, code: str | None = None) -> None:
|
||||
"""Send alarm trigger command."""
|
||||
raise NotImplementedError()
|
||||
|
@ -7,10 +7,12 @@ SUPPORT_ALARM_ARM_AWAY: Final = 2
|
||||
SUPPORT_ALARM_ARM_NIGHT: Final = 4
|
||||
SUPPORT_ALARM_TRIGGER: Final = 8
|
||||
SUPPORT_ALARM_ARM_CUSTOM_BYPASS: Final = 16
|
||||
SUPPORT_ALARM_ARM_VACATION: Final = 32
|
||||
|
||||
CONDITION_TRIGGERED: Final = "is_triggered"
|
||||
CONDITION_DISARMED: Final = "is_disarmed"
|
||||
CONDITION_ARMED_HOME: Final = "is_armed_home"
|
||||
CONDITION_ARMED_AWAY: Final = "is_armed_away"
|
||||
CONDITION_ARMED_NIGHT: Final = "is_armed_night"
|
||||
CONDITION_ARMED_VACATION: Final = "is_armed_vacation"
|
||||
CONDITION_ARMED_CUSTOM_BYPASS: Final = "is_armed_custom_bypass"
|
||||
|
@ -16,6 +16,7 @@ from homeassistant.const import (
|
||||
SERVICE_ALARM_ARM_AWAY,
|
||||
SERVICE_ALARM_ARM_HOME,
|
||||
SERVICE_ALARM_ARM_NIGHT,
|
||||
SERVICE_ALARM_ARM_VACATION,
|
||||
SERVICE_ALARM_DISARM,
|
||||
SERVICE_ALARM_TRIGGER,
|
||||
)
|
||||
@ -30,6 +31,7 @@ from .const import (
|
||||
SUPPORT_ALARM_ARM_AWAY,
|
||||
SUPPORT_ALARM_ARM_HOME,
|
||||
SUPPORT_ALARM_ARM_NIGHT,
|
||||
SUPPORT_ALARM_ARM_VACATION,
|
||||
SUPPORT_ALARM_TRIGGER,
|
||||
)
|
||||
|
||||
@ -37,6 +39,7 @@ ACTION_TYPES: Final[set[str]] = {
|
||||
"arm_away",
|
||||
"arm_home",
|
||||
"arm_night",
|
||||
"arm_vacation",
|
||||
"disarm",
|
||||
"trigger",
|
||||
}
|
||||
@ -77,6 +80,8 @@ async def async_get_actions(
|
||||
actions.append({**base_action, CONF_TYPE: "arm_home"})
|
||||
if supported_features & SUPPORT_ALARM_ARM_NIGHT:
|
||||
actions.append({**base_action, CONF_TYPE: "arm_night"})
|
||||
if supported_features & SUPPORT_ALARM_ARM_VACATION:
|
||||
actions.append({**base_action, CONF_TYPE: "arm_vacation"})
|
||||
actions.append({**base_action, CONF_TYPE: "disarm"})
|
||||
if supported_features & SUPPORT_ALARM_TRIGGER:
|
||||
actions.append({**base_action, CONF_TYPE: "trigger"})
|
||||
@ -98,6 +103,8 @@ async def async_call_action_from_config(
|
||||
service = SERVICE_ALARM_ARM_HOME
|
||||
elif config[CONF_TYPE] == "arm_night":
|
||||
service = SERVICE_ALARM_ARM_NIGHT
|
||||
elif config[CONF_TYPE] == "arm_vacation":
|
||||
service = SERVICE_ALARM_ARM_VACATION
|
||||
elif config[CONF_TYPE] == "disarm":
|
||||
service = SERVICE_ALARM_DISARM
|
||||
elif config[CONF_TYPE] == "trigger":
|
||||
|
@ -10,6 +10,7 @@ from homeassistant.components.alarm_control_panel.const import (
|
||||
SUPPORT_ALARM_ARM_CUSTOM_BYPASS,
|
||||
SUPPORT_ALARM_ARM_HOME,
|
||||
SUPPORT_ALARM_ARM_NIGHT,
|
||||
SUPPORT_ALARM_ARM_VACATION,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
@ -22,6 +23,7 @@ from homeassistant.const import (
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
)
|
||||
@ -37,6 +39,7 @@ from .const import (
|
||||
CONDITION_ARMED_CUSTOM_BYPASS,
|
||||
CONDITION_ARMED_HOME,
|
||||
CONDITION_ARMED_NIGHT,
|
||||
CONDITION_ARMED_VACATION,
|
||||
CONDITION_DISARMED,
|
||||
CONDITION_TRIGGERED,
|
||||
)
|
||||
@ -47,6 +50,7 @@ CONDITION_TYPES: Final[set[str]] = {
|
||||
CONDITION_ARMED_HOME,
|
||||
CONDITION_ARMED_AWAY,
|
||||
CONDITION_ARMED_NIGHT,
|
||||
CONDITION_ARMED_VACATION,
|
||||
CONDITION_ARMED_CUSTOM_BYPASS,
|
||||
}
|
||||
|
||||
@ -90,6 +94,8 @@ async def async_get_conditions(
|
||||
conditions.append({**base_condition, CONF_TYPE: CONDITION_ARMED_AWAY})
|
||||
if supported_features & SUPPORT_ALARM_ARM_NIGHT:
|
||||
conditions.append({**base_condition, CONF_TYPE: CONDITION_ARMED_NIGHT})
|
||||
if supported_features & SUPPORT_ALARM_ARM_VACATION:
|
||||
conditions.append({**base_condition, CONF_TYPE: CONDITION_ARMED_VACATION})
|
||||
if supported_features & SUPPORT_ALARM_ARM_CUSTOM_BYPASS:
|
||||
conditions.append(
|
||||
{**base_condition, CONF_TYPE: CONDITION_ARMED_CUSTOM_BYPASS}
|
||||
@ -114,6 +120,8 @@ def async_condition_from_config(
|
||||
state = STATE_ALARM_ARMED_AWAY
|
||||
elif config[CONF_TYPE] == CONDITION_ARMED_NIGHT:
|
||||
state = STATE_ALARM_ARMED_NIGHT
|
||||
elif config[CONF_TYPE] == CONDITION_ARMED_VACATION:
|
||||
state = STATE_ALARM_ARMED_VACATION
|
||||
elif config[CONF_TYPE] == CONDITION_ARMED_CUSTOM_BYPASS:
|
||||
state = STATE_ALARM_ARMED_CUSTOM_BYPASS
|
||||
|
||||
|
@ -9,6 +9,7 @@ from homeassistant.components.alarm_control_panel.const import (
|
||||
SUPPORT_ALARM_ARM_AWAY,
|
||||
SUPPORT_ALARM_ARM_HOME,
|
||||
SUPPORT_ALARM_ARM_NIGHT,
|
||||
SUPPORT_ALARM_ARM_VACATION,
|
||||
)
|
||||
from homeassistant.components.automation import AutomationActionType
|
||||
from homeassistant.components.device_automation import DEVICE_TRIGGER_BASE_SCHEMA
|
||||
@ -23,6 +24,7 @@ from homeassistant.const import (
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_ARMING,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
@ -39,6 +41,7 @@ TRIGGER_TYPES: Final[set[str]] = BASIC_TRIGGER_TYPES | {
|
||||
"armed_home",
|
||||
"armed_away",
|
||||
"armed_night",
|
||||
"armed_vacation",
|
||||
}
|
||||
|
||||
TRIGGER_SCHEMA: Final = DEVICE_TRIGGER_BASE_SCHEMA.extend(
|
||||
@ -100,6 +103,13 @@ async def async_get_triggers(
|
||||
CONF_TYPE: "armed_night",
|
||||
}
|
||||
)
|
||||
if supported_features & SUPPORT_ALARM_ARM_VACATION:
|
||||
triggers.append(
|
||||
{
|
||||
**base_trigger,
|
||||
CONF_TYPE: "armed_vacation",
|
||||
}
|
||||
)
|
||||
|
||||
return triggers
|
||||
|
||||
@ -134,6 +144,8 @@ async def async_attach_trigger(
|
||||
to_state = STATE_ALARM_ARMED_AWAY
|
||||
elif config[CONF_TYPE] == "armed_night":
|
||||
to_state = STATE_ALARM_ARMED_NIGHT
|
||||
elif config[CONF_TYPE] == "armed_vacation":
|
||||
to_state = STATE_ALARM_ARMED_VACATION
|
||||
|
||||
state_config = {
|
||||
state_trigger.CONF_PLATFORM: "state",
|
||||
|
@ -7,6 +7,7 @@ from homeassistant.const import (
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
STATE_OFF,
|
||||
)
|
||||
@ -24,6 +25,7 @@ def async_describe_on_off_states(
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
},
|
||||
STATE_OFF,
|
||||
|
@ -12,12 +12,14 @@ from homeassistant.const import (
|
||||
SERVICE_ALARM_ARM_CUSTOM_BYPASS,
|
||||
SERVICE_ALARM_ARM_HOME,
|
||||
SERVICE_ALARM_ARM_NIGHT,
|
||||
SERVICE_ALARM_ARM_VACATION,
|
||||
SERVICE_ALARM_DISARM,
|
||||
SERVICE_ALARM_TRIGGER,
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
)
|
||||
@ -32,6 +34,7 @@ VALID_STATES: Final[set[str]] = {
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
}
|
||||
@ -71,6 +74,8 @@ async def _async_reproduce_state(
|
||||
service = SERVICE_ALARM_ARM_HOME
|
||||
elif state.state == STATE_ALARM_ARMED_NIGHT:
|
||||
service = SERVICE_ALARM_ARM_NIGHT
|
||||
elif state.state == STATE_ALARM_ARMED_VACATION:
|
||||
service = SERVICE_ALARM_ARM_VACATION
|
||||
elif state.state == STATE_ALARM_DISARMED:
|
||||
service = SERVICE_ALARM_DISARM
|
||||
elif state.state == STATE_ALARM_TRIGGERED:
|
||||
|
@ -70,6 +70,20 @@ alarm_arm_night:
|
||||
selector:
|
||||
text:
|
||||
|
||||
alarm_arm_vacation:
|
||||
name: Arm vacation
|
||||
description: Send the alarm the command for arm vacation.
|
||||
target:
|
||||
entity:
|
||||
domain: alarm_control_panel
|
||||
fields:
|
||||
code:
|
||||
name: Code
|
||||
description: An optional code to arm vacation the alarm control panel with.
|
||||
example: "1234"
|
||||
selector:
|
||||
text:
|
||||
|
||||
alarm_trigger:
|
||||
name: Trigger
|
||||
description: Send the alarm the command for trigger.
|
||||
|
@ -5,6 +5,7 @@
|
||||
"arm_away": "Arm {entity_name} away",
|
||||
"arm_home": "Arm {entity_name} home",
|
||||
"arm_night": "Arm {entity_name} night",
|
||||
"arm_vacation": "Arm {entity_name} vacation",
|
||||
"disarm": "Disarm {entity_name}",
|
||||
"trigger": "Trigger {entity_name}"
|
||||
},
|
||||
@ -13,14 +14,16 @@
|
||||
"is_disarmed": "{entity_name} is disarmed",
|
||||
"is_armed_home": "{entity_name} is armed home",
|
||||
"is_armed_away": "{entity_name} is armed away",
|
||||
"is_armed_night": "{entity_name} is armed night"
|
||||
"is_armed_night": "{entity_name} is armed night",
|
||||
"is_armed_vacation": "{entity_name} is armed vacation"
|
||||
},
|
||||
"trigger_type": {
|
||||
"triggered": "{entity_name} triggered",
|
||||
"disarmed": "{entity_name} disarmed",
|
||||
"armed_home": "{entity_name} armed home",
|
||||
"armed_away": "{entity_name} armed away",
|
||||
"armed_night": "{entity_name} armed night"
|
||||
"armed_night": "{entity_name} armed night",
|
||||
"armed_vacation": "{entity_name} armed vacation"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
@ -30,6 +33,7 @@
|
||||
"armed_home": "Armed home",
|
||||
"armed_away": "Armed away",
|
||||
"armed_night": "Armed night",
|
||||
"armed_vacation": "Armed vacation",
|
||||
"armed_custom_bypass": "Armed custom bypass",
|
||||
"pending": "Pending",
|
||||
"arming": "Arming",
|
||||
|
@ -266,6 +266,7 @@ STATE_ALARM_DISARMED: Final = "disarmed"
|
||||
STATE_ALARM_ARMED_HOME: Final = "armed_home"
|
||||
STATE_ALARM_ARMED_AWAY: Final = "armed_away"
|
||||
STATE_ALARM_ARMED_NIGHT: Final = "armed_night"
|
||||
STATE_ALARM_ARMED_VACATION: Final = "armed_vacation"
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS: Final = "armed_custom_bypass"
|
||||
STATE_ALARM_PENDING: Final = "pending"
|
||||
STATE_ALARM_ARMING: Final = "arming"
|
||||
@ -580,6 +581,7 @@ SERVICE_ALARM_DISARM: Final = "alarm_disarm"
|
||||
SERVICE_ALARM_ARM_HOME: Final = "alarm_arm_home"
|
||||
SERVICE_ALARM_ARM_AWAY: Final = "alarm_arm_away"
|
||||
SERVICE_ALARM_ARM_NIGHT: Final = "alarm_arm_night"
|
||||
SERVICE_ALARM_ARM_VACATION: Final = "alarm_arm_vacation"
|
||||
SERVICE_ALARM_ARM_CUSTOM_BYPASS: Final = "alarm_arm_custom_bypass"
|
||||
SERVICE_ALARM_TRIGGER: Final = "alarm_trigger"
|
||||
|
||||
|
@ -8,6 +8,7 @@ from homeassistant.const import (
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
STATE_UNKNOWN,
|
||||
@ -50,6 +51,7 @@ def entity_reg(hass):
|
||||
(True, 0, const.SUPPORT_ALARM_ARM_AWAY, ["disarm", "arm_away"]),
|
||||
(True, 0, const.SUPPORT_ALARM_ARM_HOME, ["disarm", "arm_home"]),
|
||||
(True, 0, const.SUPPORT_ALARM_ARM_NIGHT, ["disarm", "arm_night"]),
|
||||
(True, 0, const.SUPPORT_ALARM_ARM_VACATION, ["disarm", "arm_vacation"]),
|
||||
(True, 0, const.SUPPORT_ALARM_TRIGGER, ["disarm", "trigger"]),
|
||||
],
|
||||
)
|
||||
@ -150,13 +152,14 @@ async def test_get_action_capabilities(
|
||||
"arm_away": {"extra_fields": []},
|
||||
"arm_home": {"extra_fields": []},
|
||||
"arm_night": {"extra_fields": []},
|
||||
"arm_vacation": {"extra_fields": []},
|
||||
"disarm": {
|
||||
"extra_fields": [{"name": "code", "optional": True, "type": "string"}]
|
||||
},
|
||||
"trigger": {"extra_fields": []},
|
||||
}
|
||||
actions = await async_get_device_automations(hass, "action", device_entry.id)
|
||||
assert len(actions) == 5
|
||||
assert len(actions) == 6
|
||||
for action in actions:
|
||||
capabilities = await async_get_device_automation_capabilities(
|
||||
hass, "action", action
|
||||
@ -196,13 +199,16 @@ async def test_get_action_capabilities_arm_code(
|
||||
"arm_night": {
|
||||
"extra_fields": [{"name": "code", "optional": True, "type": "string"}]
|
||||
},
|
||||
"arm_vacation": {
|
||||
"extra_fields": [{"name": "code", "optional": True, "type": "string"}]
|
||||
},
|
||||
"disarm": {
|
||||
"extra_fields": [{"name": "code", "optional": True, "type": "string"}]
|
||||
},
|
||||
"trigger": {"extra_fields": []},
|
||||
}
|
||||
actions = await async_get_device_automations(hass, "action", device_entry.id)
|
||||
assert len(actions) == 5
|
||||
assert len(actions) == 6
|
||||
for action in actions:
|
||||
capabilities = await async_get_device_automation_capabilities(
|
||||
hass, "action", action
|
||||
@ -256,6 +262,18 @@ async def test_action(hass, enable_custom_integrations):
|
||||
"type": "arm_night",
|
||||
},
|
||||
},
|
||||
{
|
||||
"trigger": {
|
||||
"platform": "event",
|
||||
"event_type": "test_event_arm_vacation",
|
||||
},
|
||||
"action": {
|
||||
"domain": DOMAIN,
|
||||
"device_id": "abcdefgh",
|
||||
"entity_id": "alarm_control_panel.alarm_no_arm_code",
|
||||
"type": "arm_vacation",
|
||||
},
|
||||
},
|
||||
{
|
||||
"trigger": {"platform": "event", "event_type": "test_event_disarm"},
|
||||
"action": {
|
||||
@ -302,6 +320,13 @@ async def test_action(hass, enable_custom_integrations):
|
||||
== STATE_ALARM_ARMED_HOME
|
||||
)
|
||||
|
||||
hass.bus.async_fire("test_event_arm_vacation")
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
hass.states.get("alarm_control_panel.alarm_no_arm_code").state
|
||||
== STATE_ALARM_ARMED_VACATION
|
||||
)
|
||||
|
||||
hass.bus.async_fire("test_event_arm_night")
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
|
@ -8,6 +8,7 @@ from homeassistant.const import (
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
)
|
||||
@ -50,11 +51,13 @@ def calls(hass):
|
||||
(False, const.SUPPORT_ALARM_ARM_AWAY, 0, ["is_armed_away"]),
|
||||
(False, const.SUPPORT_ALARM_ARM_HOME, 0, ["is_armed_home"]),
|
||||
(False, const.SUPPORT_ALARM_ARM_NIGHT, 0, ["is_armed_night"]),
|
||||
(False, const.SUPPORT_ALARM_ARM_VACATION, 0, ["is_armed_vacation"]),
|
||||
(False, const.SUPPORT_ALARM_ARM_CUSTOM_BYPASS, 0, ["is_armed_custom_bypass"]),
|
||||
(True, 0, 0, []),
|
||||
(True, 0, const.SUPPORT_ALARM_ARM_AWAY, ["is_armed_away"]),
|
||||
(True, 0, const.SUPPORT_ALARM_ARM_HOME, ["is_armed_home"]),
|
||||
(True, 0, const.SUPPORT_ALARM_ARM_NIGHT, ["is_armed_night"]),
|
||||
(True, 0, const.SUPPORT_ALARM_ARM_VACATION, ["is_armed_vacation"]),
|
||||
(True, 0, const.SUPPORT_ALARM_ARM_CUSTOM_BYPASS, ["is_armed_custom_bypass"]),
|
||||
],
|
||||
)
|
||||
@ -212,6 +215,24 @@ async def test_if_state(hass, calls):
|
||||
},
|
||||
{
|
||||
"trigger": {"platform": "event", "event_type": "test_event6"},
|
||||
"condition": [
|
||||
{
|
||||
"condition": "device",
|
||||
"domain": DOMAIN,
|
||||
"device_id": "",
|
||||
"entity_id": "alarm_control_panel.entity",
|
||||
"type": "is_armed_vacation",
|
||||
}
|
||||
],
|
||||
"action": {
|
||||
"service": "test.automation",
|
||||
"data_template": {
|
||||
"some": "is_armed_vacation - {{ trigger.platform }} - {{ trigger.event.event_type }}"
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"trigger": {"platform": "event", "event_type": "test_event7"},
|
||||
"condition": [
|
||||
{
|
||||
"condition": "device",
|
||||
@ -238,6 +259,7 @@ async def test_if_state(hass, calls):
|
||||
hass.bus.async_fire("test_event4")
|
||||
hass.bus.async_fire("test_event5")
|
||||
hass.bus.async_fire("test_event6")
|
||||
hass.bus.async_fire("test_event7")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 1
|
||||
assert calls[0].data["some"] == "is_triggered - event - test_event1"
|
||||
@ -249,6 +271,7 @@ async def test_if_state(hass, calls):
|
||||
hass.bus.async_fire("test_event4")
|
||||
hass.bus.async_fire("test_event5")
|
||||
hass.bus.async_fire("test_event6")
|
||||
hass.bus.async_fire("test_event7")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 2
|
||||
assert calls[1].data["some"] == "is_disarmed - event - test_event2"
|
||||
@ -260,6 +283,7 @@ async def test_if_state(hass, calls):
|
||||
hass.bus.async_fire("test_event4")
|
||||
hass.bus.async_fire("test_event5")
|
||||
hass.bus.async_fire("test_event6")
|
||||
hass.bus.async_fire("test_event7")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 3
|
||||
assert calls[2].data["some"] == "is_armed_home - event - test_event3"
|
||||
@ -271,6 +295,7 @@ async def test_if_state(hass, calls):
|
||||
hass.bus.async_fire("test_event4")
|
||||
hass.bus.async_fire("test_event5")
|
||||
hass.bus.async_fire("test_event6")
|
||||
hass.bus.async_fire("test_event7")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 4
|
||||
assert calls[3].data["some"] == "is_armed_away - event - test_event4"
|
||||
@ -282,10 +307,23 @@ async def test_if_state(hass, calls):
|
||||
hass.bus.async_fire("test_event4")
|
||||
hass.bus.async_fire("test_event5")
|
||||
hass.bus.async_fire("test_event6")
|
||||
hass.bus.async_fire("test_event7")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 5
|
||||
assert calls[4].data["some"] == "is_armed_night - event - test_event5"
|
||||
|
||||
hass.states.async_set("alarm_control_panel.entity", STATE_ALARM_ARMED_VACATION)
|
||||
hass.bus.async_fire("test_event1")
|
||||
hass.bus.async_fire("test_event2")
|
||||
hass.bus.async_fire("test_event3")
|
||||
hass.bus.async_fire("test_event4")
|
||||
hass.bus.async_fire("test_event5")
|
||||
hass.bus.async_fire("test_event6")
|
||||
hass.bus.async_fire("test_event7")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 6
|
||||
assert calls[5].data["some"] == "is_armed_vacation - event - test_event6"
|
||||
|
||||
hass.states.async_set("alarm_control_panel.entity", STATE_ALARM_ARMED_CUSTOM_BYPASS)
|
||||
hass.bus.async_fire("test_event1")
|
||||
hass.bus.async_fire("test_event2")
|
||||
@ -293,6 +331,7 @@ async def test_if_state(hass, calls):
|
||||
hass.bus.async_fire("test_event4")
|
||||
hass.bus.async_fire("test_event5")
|
||||
hass.bus.async_fire("test_event6")
|
||||
hass.bus.async_fire("test_event7")
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 6
|
||||
assert calls[5].data["some"] == "is_armed_custom_bypass - event - test_event6"
|
||||
assert len(calls) == 7
|
||||
assert calls[6].data["some"] == "is_armed_custom_bypass - event - test_event7"
|
||||
|
@ -9,6 +9,7 @@ from homeassistant.const import (
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_PENDING,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
@ -54,7 +55,7 @@ def calls(hass):
|
||||
(False, 0, 0, ["triggered", "disarmed", "arming"]),
|
||||
(
|
||||
False,
|
||||
15,
|
||||
47,
|
||||
0,
|
||||
[
|
||||
"triggered",
|
||||
@ -63,13 +64,14 @@ def calls(hass):
|
||||
"armed_home",
|
||||
"armed_away",
|
||||
"armed_night",
|
||||
"armed_vacation",
|
||||
],
|
||||
),
|
||||
(True, 0, 0, ["triggered", "disarmed", "arming"]),
|
||||
(
|
||||
True,
|
||||
0,
|
||||
15,
|
||||
47,
|
||||
[
|
||||
"triggered",
|
||||
"disarmed",
|
||||
@ -77,6 +79,7 @@ def calls(hass):
|
||||
"armed_home",
|
||||
"armed_away",
|
||||
"armed_night",
|
||||
"armed_vacation",
|
||||
],
|
||||
),
|
||||
],
|
||||
@ -256,6 +259,25 @@ async def test_if_fires_on_state_change(hass, calls):
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"trigger": {
|
||||
"platform": "device",
|
||||
"domain": DOMAIN,
|
||||
"device_id": "",
|
||||
"entity_id": "alarm_control_panel.entity",
|
||||
"type": "armed_vacation",
|
||||
},
|
||||
"action": {
|
||||
"service": "test.automation",
|
||||
"data_template": {
|
||||
"some": (
|
||||
"armed_vacation - {{ trigger.platform}} - "
|
||||
"{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
|
||||
"{{ trigger.to_state.state}} - {{ trigger.for }}"
|
||||
)
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
)
|
||||
@ -305,6 +327,15 @@ async def test_if_fires_on_state_change(hass, calls):
|
||||
== "armed_night - device - alarm_control_panel.entity - armed_away - armed_night - None"
|
||||
)
|
||||
|
||||
# Fake that the entity is armed vacation.
|
||||
hass.states.async_set("alarm_control_panel.entity", STATE_ALARM_ARMED_VACATION)
|
||||
await hass.async_block_till_done()
|
||||
assert len(calls) == 6
|
||||
assert (
|
||||
calls[5].data["some"]
|
||||
== "armed_vacation - device - alarm_control_panel.entity - armed_night - armed_vacation - None"
|
||||
)
|
||||
|
||||
|
||||
async def test_if_fires_on_state_change_with_for(hass, calls):
|
||||
"""Test for triggers firing with delay."""
|
||||
|
@ -4,12 +4,14 @@ from homeassistant.const import (
|
||||
SERVICE_ALARM_ARM_CUSTOM_BYPASS,
|
||||
SERVICE_ALARM_ARM_HOME,
|
||||
SERVICE_ALARM_ARM_NIGHT,
|
||||
SERVICE_ALARM_ARM_VACATION,
|
||||
SERVICE_ALARM_DISARM,
|
||||
SERVICE_ALARM_TRIGGER,
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
)
|
||||
@ -34,6 +36,9 @@ async def test_reproducing_states(hass, caplog):
|
||||
hass.states.async_set(
|
||||
"alarm_control_panel.entity_armed_night", STATE_ALARM_ARMED_NIGHT, {}
|
||||
)
|
||||
hass.states.async_set(
|
||||
"alarm_control_panel.entity_armed_vacation", STATE_ALARM_ARMED_VACATION, {}
|
||||
)
|
||||
hass.states.async_set(
|
||||
"alarm_control_panel.entity_disarmed", STATE_ALARM_DISARMED, {}
|
||||
)
|
||||
@ -53,6 +58,9 @@ async def test_reproducing_states(hass, caplog):
|
||||
arm_night_calls = async_mock_service(
|
||||
hass, "alarm_control_panel", SERVICE_ALARM_ARM_NIGHT
|
||||
)
|
||||
arm_vacation_calls = async_mock_service(
|
||||
hass, "alarm_control_panel", SERVICE_ALARM_ARM_VACATION
|
||||
)
|
||||
disarm_calls = async_mock_service(hass, "alarm_control_panel", SERVICE_ALARM_DISARM)
|
||||
trigger_calls = async_mock_service(
|
||||
hass, "alarm_control_panel", SERVICE_ALARM_TRIGGER
|
||||
@ -68,6 +76,9 @@ async def test_reproducing_states(hass, caplog):
|
||||
),
|
||||
State("alarm_control_panel.entity_armed_home", STATE_ALARM_ARMED_HOME),
|
||||
State("alarm_control_panel.entity_armed_night", STATE_ALARM_ARMED_NIGHT),
|
||||
State(
|
||||
"alarm_control_panel.entity_armed_vacation", STATE_ALARM_ARMED_VACATION
|
||||
),
|
||||
State("alarm_control_panel.entity_disarmed", STATE_ALARM_DISARMED),
|
||||
State("alarm_control_panel.entity_triggered", STATE_ALARM_TRIGGERED),
|
||||
]
|
||||
@ -77,6 +88,7 @@ async def test_reproducing_states(hass, caplog):
|
||||
assert len(arm_custom_bypass_calls) == 0
|
||||
assert len(arm_home_calls) == 0
|
||||
assert len(arm_night_calls) == 0
|
||||
assert len(arm_vacation_calls) == 0
|
||||
assert len(disarm_calls) == 0
|
||||
assert len(trigger_calls) == 0
|
||||
|
||||
@ -90,6 +102,7 @@ async def test_reproducing_states(hass, caplog):
|
||||
assert len(arm_custom_bypass_calls) == 0
|
||||
assert len(arm_home_calls) == 0
|
||||
assert len(arm_night_calls) == 0
|
||||
assert len(arm_vacation_calls) == 0
|
||||
assert len(disarm_calls) == 0
|
||||
assert len(trigger_calls) == 0
|
||||
|
||||
@ -104,7 +117,8 @@ async def test_reproducing_states(hass, caplog):
|
||||
"alarm_control_panel.entity_armed_home", STATE_ALARM_ARMED_CUSTOM_BYPASS
|
||||
),
|
||||
State("alarm_control_panel.entity_armed_night", STATE_ALARM_ARMED_HOME),
|
||||
State("alarm_control_panel.entity_disarmed", STATE_ALARM_ARMED_NIGHT),
|
||||
State("alarm_control_panel.entity_armed_vacation", STATE_ALARM_ARMED_NIGHT),
|
||||
State("alarm_control_panel.entity_disarmed", STATE_ALARM_ARMED_VACATION),
|
||||
State("alarm_control_panel.entity_triggered", STATE_ALARM_DISARMED),
|
||||
# Should not raise
|
||||
State("alarm_control_panel.non_existing", "on"),
|
||||
@ -132,6 +146,12 @@ async def test_reproducing_states(hass, caplog):
|
||||
assert len(arm_night_calls) == 1
|
||||
assert arm_night_calls[0].domain == "alarm_control_panel"
|
||||
assert arm_night_calls[0].data == {
|
||||
"entity_id": "alarm_control_panel.entity_armed_vacation"
|
||||
}
|
||||
|
||||
assert len(arm_vacation_calls) == 1
|
||||
assert arm_vacation_calls[0].domain == "alarm_control_panel"
|
||||
assert arm_vacation_calls[0].data == {
|
||||
"entity_id": "alarm_control_panel.entity_disarmed"
|
||||
}
|
||||
|
||||
|
@ -185,12 +185,13 @@ async def test_websocket_get_action_capabilities(
|
||||
"alarm_control_panel", "test", "5678", device_id=device_entry.id
|
||||
)
|
||||
hass.states.async_set(
|
||||
"alarm_control_panel.test_5678", "attributes", {"supported_features": 15}
|
||||
"alarm_control_panel.test_5678", "attributes", {"supported_features": 47}
|
||||
)
|
||||
expected_capabilities = {
|
||||
"arm_away": {"extra_fields": []},
|
||||
"arm_home": {"extra_fields": []},
|
||||
"arm_night": {"extra_fields": []},
|
||||
"arm_vacation": {"extra_fields": []},
|
||||
"disarm": {
|
||||
"extra_fields": [{"name": "code", "optional": True, "type": "string"}]
|
||||
},
|
||||
@ -209,7 +210,7 @@ async def test_websocket_get_action_capabilities(
|
||||
actions = msg["result"]
|
||||
|
||||
id = 2
|
||||
assert len(actions) == 5
|
||||
assert len(actions) == 6
|
||||
for action in actions:
|
||||
await client.send_json(
|
||||
{
|
||||
|
@ -8,12 +8,14 @@ from homeassistant.components.alarm_control_panel.const import (
|
||||
SUPPORT_ALARM_ARM_AWAY,
|
||||
SUPPORT_ALARM_ARM_HOME,
|
||||
SUPPORT_ALARM_ARM_NIGHT,
|
||||
SUPPORT_ALARM_ARM_VACATION,
|
||||
SUPPORT_ALARM_TRIGGER,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_TRIGGERED,
|
||||
)
|
||||
@ -79,6 +81,7 @@ class MockAlarm(MockEntity, AlarmControlPanelEntity):
|
||||
| SUPPORT_ALARM_ARM_AWAY
|
||||
| SUPPORT_ALARM_ARM_NIGHT
|
||||
| SUPPORT_ALARM_TRIGGER
|
||||
| SUPPORT_ALARM_ARM_VACATION
|
||||
)
|
||||
|
||||
def alarm_arm_away(self, code=None):
|
||||
@ -96,6 +99,11 @@ class MockAlarm(MockEntity, AlarmControlPanelEntity):
|
||||
self._state = STATE_ALARM_ARMED_NIGHT
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def alarm_arm_vacation(self, code=None):
|
||||
"""Send arm night command."""
|
||||
self._state = STATE_ALARM_ARMED_VACATION
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def alarm_disarm(self, code=None):
|
||||
"""Send disarm command."""
|
||||
if code == "1234":
|
||||
|
Loading…
x
Reference in New Issue
Block a user