mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Add config flow to template alarm_control_panel (#125861)
* Add config flow to template alarm_control_panel * Remove commented code * Test import
This commit is contained in:
parent
cabaf37437
commit
2080b9a87c
@ -15,8 +15,10 @@ from homeassistant.components.alarm_control_panel import (
|
||||
AlarmControlPanelEntityFeature,
|
||||
CodeFormat,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_CODE,
|
||||
CONF_DEVICE_ID,
|
||||
CONF_NAME,
|
||||
CONF_UNIQUE_ID,
|
||||
CONF_VALUE_TEMPLATE,
|
||||
@ -34,12 +36,14 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import selector
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.helpers.script import Script
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import slugify
|
||||
|
||||
from .const import DOMAIN
|
||||
from .template_entity import TemplateEntity, rewrite_common_legacy_to_modern_conf
|
||||
@ -105,6 +109,25 @@ PLATFORM_SCHEMA = ALARM_CONTROL_PANEL_PLATFORM_SCHEMA.extend(
|
||||
}
|
||||
)
|
||||
|
||||
ALARM_CONTROL_PANEL_CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_NAME): cv.template,
|
||||
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
||||
vol.Optional(CONF_DISARM_ACTION): cv.SCRIPT_SCHEMA,
|
||||
vol.Optional(CONF_ARM_AWAY_ACTION): cv.SCRIPT_SCHEMA,
|
||||
vol.Optional(CONF_ARM_CUSTOM_BYPASS_ACTION): cv.SCRIPT_SCHEMA,
|
||||
vol.Optional(CONF_ARM_HOME_ACTION): cv.SCRIPT_SCHEMA,
|
||||
vol.Optional(CONF_ARM_NIGHT_ACTION): cv.SCRIPT_SCHEMA,
|
||||
vol.Optional(CONF_ARM_VACATION_ACTION): cv.SCRIPT_SCHEMA,
|
||||
vol.Optional(CONF_TRIGGER_ACTION): cv.SCRIPT_SCHEMA,
|
||||
vol.Optional(CONF_CODE_ARM_REQUIRED, default=True): cv.boolean,
|
||||
vol.Optional(CONF_CODE_FORMAT, default=TemplateCodeFormat.number.name): cv.enum(
|
||||
TemplateCodeFormat
|
||||
),
|
||||
vol.Optional(CONF_DEVICE_ID): selector.DeviceSelector(),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def _async_create_entities(
|
||||
hass: HomeAssistant, config: dict[str, Any]
|
||||
@ -128,6 +151,27 @@ async def _async_create_entities(
|
||||
return alarm_control_panels
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Initialize config entry."""
|
||||
_options = dict(config_entry.options)
|
||||
_options.pop("template_type")
|
||||
validated_config = ALARM_CONTROL_PANEL_CONFIG_SCHEMA(_options)
|
||||
async_add_entities(
|
||||
[
|
||||
AlarmControlPanelTemplate(
|
||||
hass,
|
||||
slugify(_options[CONF_NAME]),
|
||||
validated_config,
|
||||
config_entry.entry_id,
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
|
@ -39,6 +39,18 @@ from homeassistant.helpers.schema_config_entry_flow import (
|
||||
SchemaFlowMenuStep,
|
||||
)
|
||||
|
||||
from .alarm_control_panel import (
|
||||
CONF_ARM_AWAY_ACTION,
|
||||
CONF_ARM_CUSTOM_BYPASS_ACTION,
|
||||
CONF_ARM_HOME_ACTION,
|
||||
CONF_ARM_NIGHT_ACTION,
|
||||
CONF_ARM_VACATION_ACTION,
|
||||
CONF_CODE_ARM_REQUIRED,
|
||||
CONF_CODE_FORMAT,
|
||||
CONF_DISARM_ACTION,
|
||||
CONF_TRIGGER_ACTION,
|
||||
TemplateCodeFormat,
|
||||
)
|
||||
from .binary_sensor import async_create_preview_binary_sensor
|
||||
from .const import CONF_PRESS, CONF_TURN_OFF, CONF_TURN_ON, DOMAIN
|
||||
from .number import (
|
||||
@ -68,6 +80,30 @@ def generate_schema(domain: str, flow_type: str) -> vol.Schema:
|
||||
if flow_type == "config":
|
||||
schema = {vol.Required(CONF_NAME): selector.TextSelector()}
|
||||
|
||||
if domain == Platform.ALARM_CONTROL_PANEL:
|
||||
schema |= {
|
||||
vol.Optional(CONF_VALUE_TEMPLATE): selector.TemplateSelector(),
|
||||
vol.Optional(CONF_DISARM_ACTION): selector.ActionSelector(),
|
||||
vol.Optional(CONF_ARM_AWAY_ACTION): selector.ActionSelector(),
|
||||
vol.Optional(CONF_ARM_CUSTOM_BYPASS_ACTION): selector.ActionSelector(),
|
||||
vol.Optional(CONF_ARM_HOME_ACTION): selector.ActionSelector(),
|
||||
vol.Optional(CONF_ARM_NIGHT_ACTION): selector.ActionSelector(),
|
||||
vol.Optional(CONF_ARM_VACATION_ACTION): selector.ActionSelector(),
|
||||
vol.Optional(CONF_TRIGGER_ACTION): selector.ActionSelector(),
|
||||
vol.Optional(
|
||||
CONF_CODE_ARM_REQUIRED, default=True
|
||||
): selector.BooleanSelector(),
|
||||
vol.Optional(
|
||||
CONF_CODE_FORMAT, default=TemplateCodeFormat.number.name
|
||||
): selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(
|
||||
options=[e.name for e in TemplateCodeFormat],
|
||||
mode=selector.SelectSelectorMode.DROPDOWN,
|
||||
translation_key="alarm_control_panel_code_format",
|
||||
)
|
||||
),
|
||||
}
|
||||
|
||||
if domain == Platform.BINARY_SENSOR:
|
||||
schema |= _SCHEMA_STATE
|
||||
if flow_type == "config":
|
||||
@ -265,6 +301,7 @@ def validate_user_input(
|
||||
|
||||
|
||||
TEMPLATE_TYPES = [
|
||||
"alarm_control_panel",
|
||||
"binary_sensor",
|
||||
"button",
|
||||
"image",
|
||||
@ -276,6 +313,10 @@ TEMPLATE_TYPES = [
|
||||
|
||||
CONFIG_FLOW = {
|
||||
"user": SchemaFlowMenuStep(TEMPLATE_TYPES),
|
||||
Platform.ALARM_CONTROL_PANEL: SchemaFlowFormStep(
|
||||
config_schema(Platform.ALARM_CONTROL_PANEL),
|
||||
validate_user_input=validate_user_input(Platform.ALARM_CONTROL_PANEL),
|
||||
),
|
||||
Platform.BINARY_SENSOR: SchemaFlowFormStep(
|
||||
config_schema(Platform.BINARY_SENSOR),
|
||||
preview="template",
|
||||
@ -313,6 +354,10 @@ CONFIG_FLOW = {
|
||||
|
||||
OPTIONS_FLOW = {
|
||||
"init": SchemaFlowFormStep(next_step=choose_options_step),
|
||||
Platform.ALARM_CONTROL_PANEL: SchemaFlowFormStep(
|
||||
options_schema(Platform.ALARM_CONTROL_PANEL),
|
||||
validate_user_input=validate_user_input(Platform.ALARM_CONTROL_PANEL),
|
||||
),
|
||||
Platform.BINARY_SENSOR: SchemaFlowFormStep(
|
||||
options_schema(Platform.BINARY_SENSOR),
|
||||
preview="template",
|
||||
|
@ -1,6 +1,26 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"alarm_control_panel": {
|
||||
"data": {
|
||||
"device_id": "[%key:common::config_flow::data::device%]",
|
||||
"value_template": "[%key:component::template::config::step::switch::data::value_template%]",
|
||||
"name": "[%key:common::config_flow::data::name%]",
|
||||
"disarm": "Disarm action",
|
||||
"arm_away": "Arm away action",
|
||||
"arm_custom_bypass": "Arm custom bypass action",
|
||||
"arm_home": "Arm home action",
|
||||
"arm_night": "Arm night action",
|
||||
"arm_vacation": "Arm vacation action",
|
||||
"trigger": "Trigger action",
|
||||
"code_arm_required": "Code arm required",
|
||||
"code_format": "Code format"
|
||||
},
|
||||
"data_description": {
|
||||
"device_id": "[%key:component::template::config::step::sensor::data_description::device_id%]"
|
||||
},
|
||||
"title": "Template alarm control panel"
|
||||
},
|
||||
"binary_sensor": {
|
||||
"data": {
|
||||
"device_id": "[%key:common::config_flow::data::device%]",
|
||||
@ -111,6 +131,25 @@
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"alarm_control_panel": {
|
||||
"data": {
|
||||
"device_id": "[%key:common::config_flow::data::device%]",
|
||||
"value_template": "[%key:component::template::config::step::switch::data::value_template%]",
|
||||
"disarm": "[%key:component::template::config::step::alarm_control_panel::data::disarm%]",
|
||||
"arm_away": "[%key:component::template::config::step::alarm_control_panel::data::arm_away%]",
|
||||
"arm_custom_bypass": "[%key:component::template::config::step::alarm_control_panel::data::arm_custom_bypass%]",
|
||||
"arm_home": "[%key:component::template::config::step::alarm_control_panel::data::arm_home%]",
|
||||
"arm_night": "[%key:component::template::config::step::alarm_control_panel::data::arm_night%]",
|
||||
"arm_vacation": "[%key:component::template::config::step::alarm_control_panel::data::arm_vacation%]",
|
||||
"trigger": "[%key:component::template::config::step::alarm_control_panel::data::trigger%]",
|
||||
"code_arm_required": "[%key:component::template::config::step::alarm_control_panel::data::code_arm_required%]",
|
||||
"code_format": "[%key:component::template::config::step::alarm_control_panel::data::code_format%]"
|
||||
},
|
||||
"data_description": {
|
||||
"device_id": "[%key:component::template::config::step::sensor::data_description::device_id%]"
|
||||
},
|
||||
"title": "[%key:component::template::config::step::alarm_control_panel::title%]"
|
||||
},
|
||||
"binary_sensor": {
|
||||
"data": {
|
||||
"device_id": "[%key:common::config_flow::data::device%]",
|
||||
@ -200,6 +239,13 @@
|
||||
}
|
||||
},
|
||||
"selector": {
|
||||
"alarm_control_panel_code_format": {
|
||||
"options": {
|
||||
"no_code": "No code format",
|
||||
"number": "Number",
|
||||
"text": "Text"
|
||||
}
|
||||
},
|
||||
"binary_sensor_device_class": {
|
||||
"options": {
|
||||
"battery": "[%key:component::binary_sensor::entity_component::battery::name%]",
|
||||
|
@ -0,0 +1,18 @@
|
||||
# serializer version: 1
|
||||
# name: test_setup_config_entry
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'changed_by': None,
|
||||
'code_arm_required': True,
|
||||
'code_format': <CodeFormat.NUMBER: 'number'>,
|
||||
'friendly_name': 'My template',
|
||||
'supported_features': <AlarmControlPanelEntityFeature: 0>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'alarm_control_panel.my_template',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'armed_away',
|
||||
})
|
||||
# ---
|
@ -1,7 +1,9 @@
|
||||
"""The tests for the Template alarm control panel platform."""
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components import template
|
||||
from homeassistant.components.alarm_control_panel import DOMAIN as ALARM_DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_DOMAIN,
|
||||
@ -23,7 +25,7 @@ from homeassistant.const import (
|
||||
from homeassistant.core import Event, HomeAssistant, State, callback
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import assert_setup_component, mock_restore_cache
|
||||
from tests.common import MockConfigEntry, assert_setup_component, mock_restore_cache
|
||||
|
||||
TEMPLATE_NAME = "alarm_control_panel.test_template_panel"
|
||||
PANEL_NAME = "alarm_control_panel.test"
|
||||
@ -130,6 +132,41 @@ async def test_template_state_text(hass: HomeAssistant, start_ha) -> None:
|
||||
assert state.state == "unknown"
|
||||
|
||||
|
||||
async def test_setup_config_entry(
|
||||
hass: HomeAssistant, snapshot: SnapshotAssertion
|
||||
) -> None:
|
||||
"""Test the config flow."""
|
||||
value_template = "{{ states('alarm_control_panel.one') }}"
|
||||
|
||||
hass.states.async_set("alarm_control_panel.one", "armed_away", {})
|
||||
|
||||
template_config_entry = MockConfigEntry(
|
||||
data={},
|
||||
domain=template.DOMAIN,
|
||||
options={
|
||||
"name": "My template",
|
||||
"value_template": value_template,
|
||||
"template_type": "alarm_control_panel",
|
||||
"code_arm_required": True,
|
||||
"code_format": "number",
|
||||
},
|
||||
title="My template",
|
||||
)
|
||||
template_config_entry.add_to_hass(hass)
|
||||
|
||||
assert await hass.config_entries.async_setup(template_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("alarm_control_panel.my_template")
|
||||
assert state is not None
|
||||
assert state == snapshot
|
||||
|
||||
hass.states.async_set("alarm_control_panel.one", "disarmed", {})
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("alarm_control_panel.my_template")
|
||||
assert state.state == STATE_ALARM_DISARMED
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("count", "domain"), [(1, "alarm_control_panel")])
|
||||
@pytest.mark.parametrize(
|
||||
"config",
|
||||
|
@ -29,6 +29,16 @@ from tests.typing import WebSocketGenerator
|
||||
"extra_attrs",
|
||||
),
|
||||
[
|
||||
(
|
||||
"alarm_control_panel",
|
||||
{"value_template": "{{ states('alarm_control_panel.one') }}"},
|
||||
"armed_away",
|
||||
{"one": "armed_away", "two": "disarmed"},
|
||||
{},
|
||||
{},
|
||||
{"code_arm_required": True, "code_format": "number"},
|
||||
{},
|
||||
),
|
||||
(
|
||||
"binary_sensor",
|
||||
{
|
||||
@ -270,6 +280,12 @@ async def test_config_flow(
|
||||
"step": 0.1,
|
||||
},
|
||||
),
|
||||
(
|
||||
"alarm_control_panel",
|
||||
{"value_template": "{{ states('alarm_control_panel.one') }}"},
|
||||
{"code_arm_required": True, "code_format": "number"},
|
||||
{"code_arm_required": True, "code_format": "number"},
|
||||
),
|
||||
(
|
||||
"select",
|
||||
{"state": "{{ states('select.one') }}"},
|
||||
@ -476,6 +492,16 @@ def get_suggested(schema, key):
|
||||
},
|
||||
"state",
|
||||
),
|
||||
(
|
||||
"alarm_control_panel",
|
||||
{"value_template": "{{ states('alarm_control_panel.one') }}"},
|
||||
{"value_template": "{{ states('alarm_control_panel.two') }}"},
|
||||
["armed_away", "disarmed"],
|
||||
{"one": "armed_away", "two": "disarmed"},
|
||||
{"code_arm_required": True, "code_format": "number"},
|
||||
{"code_arm_required": True, "code_format": "number"},
|
||||
"value_template",
|
||||
),
|
||||
(
|
||||
"select",
|
||||
{"state": "{{ states('select.one') }}"},
|
||||
@ -1244,6 +1270,12 @@ async def test_option_flow_sensor_preview_config_entry_removed(
|
||||
"step": 0.1,
|
||||
},
|
||||
),
|
||||
(
|
||||
"alarm_control_panel",
|
||||
{"value_template": "{{ states('alarm_control_panel.one') }}"},
|
||||
{"code_arm_required": True, "code_format": "number"},
|
||||
{"code_arm_required": True, "code_format": "number"},
|
||||
),
|
||||
(
|
||||
"select",
|
||||
{"state": "{{ states('select.one') }}"},
|
||||
|
Loading…
x
Reference in New Issue
Block a user