diff --git a/homeassistant/components/template/alarm_control_panel.py b/homeassistant/components/template/alarm_control_panel.py index 2706b2d433d..2cb830e54c2 100644 --- a/homeassistant/components/template/alarm_control_panel.py +++ b/homeassistant/components/template/alarm_control_panel.py @@ -1,4 +1,5 @@ """Support for Template alarm control panels.""" +from enum import Enum import logging import voluptuous as vol @@ -6,6 +7,7 @@ import voluptuous as vol from homeassistant.components.alarm_control_panel import ( ENTITY_ID_FORMAT, FORMAT_NUMBER, + FORMAT_TEXT, PLATFORM_SCHEMA as PARENT_PLATFORM_SCHEMA, AlarmControlPanelEntity, ) @@ -54,6 +56,16 @@ CONF_ARM_NIGHT_ACTION = "arm_night" CONF_DISARM_ACTION = "disarm" CONF_ALARM_CONTROL_PANELS = "panels" CONF_CODE_ARM_REQUIRED = "code_arm_required" +CONF_CODE_FORMAT = "code_format" + + +class CodeFormat(Enum): + """Class to represent different code formats.""" + + no_code = None + number = FORMAT_NUMBER + text = FORMAT_TEXT + ALARM_CONTROL_PANEL_SCHEMA = vol.Schema( { @@ -63,6 +75,9 @@ ALARM_CONTROL_PANEL_SCHEMA = vol.Schema( vol.Optional(CONF_ARM_HOME_ACTION): cv.SCRIPT_SCHEMA, vol.Optional(CONF_ARM_NIGHT_ACTION): cv.SCRIPT_SCHEMA, vol.Optional(CONF_CODE_ARM_REQUIRED, default=True): cv.boolean, + vol.Optional(CONF_CODE_FORMAT, default=CodeFormat.number.name): cv.enum( + CodeFormat + ), vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_UNIQUE_ID): cv.string, } @@ -89,6 +104,7 @@ async def _async_create_entities(hass, config): arm_home_action = device_config.get(CONF_ARM_HOME_ACTION) arm_night_action = device_config.get(CONF_ARM_NIGHT_ACTION) code_arm_required = device_config[CONF_CODE_ARM_REQUIRED] + code_format = device_config[CONF_CODE_FORMAT] unique_id = device_config.get(CONF_UNIQUE_ID) alarm_control_panels.append( @@ -102,6 +118,7 @@ async def _async_create_entities(hass, config): arm_home_action, arm_night_action, code_arm_required, + code_format, unique_id, ) ) @@ -128,6 +145,7 @@ class AlarmControlPanelTemplate(TemplateEntity, AlarmControlPanelEntity): arm_home_action, arm_night_action, code_arm_required, + code_format, unique_id, ): """Initialize the panel.""" @@ -139,6 +157,7 @@ class AlarmControlPanelTemplate(TemplateEntity, AlarmControlPanelEntity): self._template = state_template self._disarm_script = None self._code_arm_required = code_arm_required + self._code_format = code_format domain = __name__.split(".")[-2] if disarm_action is not None: self._disarm_script = Script(hass, disarm_action, name, domain) @@ -187,8 +206,8 @@ class AlarmControlPanelTemplate(TemplateEntity, AlarmControlPanelEntity): @property def code_format(self): - """Return one or more digits/characters.""" - return FORMAT_NUMBER + """Regex for code format or None if no code is required.""" + return self._code_format.value @property def code_arm_required(self): diff --git a/tests/components/template/test_alarm_control_panel.py b/tests/components/template/test_alarm_control_panel.py index fabf626afd3..e7a898efc49 100644 --- a/tests/components/template/test_alarm_control_panel.py +++ b/tests/components/template/test_alarm_control_panel.py @@ -204,7 +204,7 @@ async def test_no_action_scripts(hass, start_ha): "platform": "template", "panels": { "bad name here": { - "value_template": "{{ disarmed }}", + "value_template": "disarmed", "arm_away": { "service": "alarm_control_panel.alarm_arm_away", "entity_id": "alarm_control_panel.test", @@ -246,6 +246,40 @@ async def test_no_action_scripts(hass, start_ha): }, "required key not provided @ data['panels']", ), + ( + { + "alarm_control_panel": { + "platform": "template", + "panels": { + "test_template_panel": { + "value_template": "disarmed", + "arm_away": { + "service": "alarm_control_panel.alarm_arm_away", + "entity_id": "alarm_control_panel.test", + "data": {"code": "1234"}, + }, + "arm_home": { + "service": "alarm_control_panel.alarm_arm_home", + "entity_id": "alarm_control_panel.test", + "data": {"code": "1234"}, + }, + "arm_night": { + "service": "alarm_control_panel.alarm_arm_night", + "entity_id": "alarm_control_panel.test", + "data": {"code": "1234"}, + }, + "disarm": { + "service": "alarm_control_panel.alarm_disarm", + "entity_id": "alarm_control_panel.test", + "data": {"code": "1234"}, + }, + "code_format": "bad_format", + } + }, + } + }, + "value must be one of ['no_code', 'number', 'text']", + ), ], ) async def test_template_syntax_error(hass, msg, start_ha, caplog_setup_text): @@ -264,7 +298,7 @@ async def test_template_syntax_error(hass, msg, start_ha, caplog_setup_text): "panels": { "test_template_panel": { "name": "Template Alarm Panel", - "value_template": "{{ disarmed }}", + "value_template": "disarmed", "arm_away": { "service": "alarm_control_panel.alarm_arm_away", "entity_id": "alarm_control_panel.test", @@ -451,3 +485,77 @@ async def test_arm_home_action(hass, func, start_ha, calls): async def test_unique_id(hass, start_ha): """Test unique_id option only creates one alarm control panel per id.""" assert len(hass.states.async_all()) == 1 + + +@pytest.mark.parametrize("count,domain", [(1, "alarm_control_panel")]) +@pytest.mark.parametrize( + "config,code_format,code_arm_required", + [ + ( + { + "alarm_control_panel": { + "platform": "template", + "panels": { + "test_template_panel": { + "value_template": "disarmed", + } + }, + } + }, + "number", + True, + ), + ( + { + "alarm_control_panel": { + "platform": "template", + "panels": { + "test_template_panel": { + "value_template": "disarmed", + "code_format": "text", + } + }, + } + }, + "text", + True, + ), + ( + { + "alarm_control_panel": { + "platform": "template", + "panels": { + "test_template_panel": { + "value_template": "disarmed", + "code_format": "no_code", + "code_arm_required": False, + } + }, + } + }, + None, + False, + ), + ( + { + "alarm_control_panel": { + "platform": "template", + "panels": { + "test_template_panel": { + "value_template": "disarmed", + "code_format": "text", + "code_arm_required": False, + } + }, + } + }, + "text", + False, + ), + ], +) +async def test_code_config(hass, code_format, code_arm_required, start_ha): + """Test configuration options related to alarm code.""" + state = hass.states.get(TEMPLATE_NAME) + assert state.attributes.get("code_format") == code_format + assert state.attributes.get("code_arm_required") == code_arm_required