Skip to content

Commit

Permalink
Add RestoreEntity to template alarm_control_panel (home-assistant#125844
Browse files Browse the repository at this point in the history
)
  • Loading branch information
gjohansson-ST authored Sep 13, 2024
1 parent a2a049c commit d855f70
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 8 deletions.
33 changes: 26 additions & 7 deletions homeassistant/components/template/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from enum import Enum
import logging
from typing import Any

import voluptuous as vol

Expand All @@ -29,12 +30,14 @@
STATE_ALARM_PENDING,
STATE_ALARM_TRIGGERED,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import TemplateError
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

Expand Down Expand Up @@ -103,7 +106,9 @@ class TemplateCodeFormat(Enum):
)


async def _async_create_entities(hass, config):
async def _async_create_entities(
hass: HomeAssistant, config: dict[str, Any]
) -> list[AlarmControlPanelTemplate]:
"""Create Template Alarm Control Panels."""
alarm_control_panels = []

Expand Down Expand Up @@ -133,18 +138,18 @@ async def async_setup_platform(
async_add_entities(await _async_create_entities(hass, config))


class AlarmControlPanelTemplate(TemplateEntity, AlarmControlPanelEntity):
class AlarmControlPanelTemplate(TemplateEntity, AlarmControlPanelEntity, RestoreEntity):
"""Representation of a templated Alarm Control Panel."""

_attr_should_poll = False

def __init__(
self,
hass,
object_id,
config,
unique_id,
):
hass: HomeAssistant,
object_id: str,
config: dict,
unique_id: str | None,
) -> None:
"""Initialize the panel."""
super().__init__(
hass, config=config, fallback_name=object_id, unique_id=unique_id
Expand All @@ -153,6 +158,7 @@ def __init__(
ENTITY_ID_FORMAT, object_id, hass=hass
)
name = self._attr_name
assert name is not None
self._template = config.get(CONF_VALUE_TEMPLATE)
self._disarm_script = None
self._attr_code_arm_required: bool = config[CONF_CODE_ARM_REQUIRED]
Expand Down Expand Up @@ -216,6 +222,19 @@ def __init__(
)
self._attr_supported_features = supported_features

async def async_added_to_hass(self) -> None:
"""Restore last state."""
await super().async_added_to_hass()
if (
(last_state := await self.async_get_last_state()) is not None
and last_state.state not in (STATE_UNKNOWN, STATE_UNAVAILABLE)
and last_state.state in _VALID_STATES
# The trigger might have fired already while we waited for stored data,
# then we should not restore state
and self._state is None
):
self._state = last_state.state

@property
def state(self) -> str | None:
"""Return the state of the device."""
Expand Down
68 changes: 67 additions & 1 deletion tests/components/template/test_alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@
STATE_ALARM_DISARMED,
STATE_ALARM_PENDING,
STATE_ALARM_TRIGGERED,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
)
from homeassistant.core import Event, HomeAssistant, callback
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

TEMPLATE_NAME = "alarm_control_panel.test_template_panel"
PANEL_NAME = "alarm_control_panel.test"
Expand Down Expand Up @@ -400,3 +405,64 @@ async def test_code_config(
state = hass.states.get(TEMPLATE_NAME)
assert state.attributes.get("code_format") == code_format
assert state.attributes.get("code_arm_required") == code_arm_required


@pytest.mark.parametrize(("count", "domain"), [(1, "alarm_control_panel")])
@pytest.mark.parametrize(
"config",
[
{
"alarm_control_panel": {
"platform": "template",
"panels": {"test_template_panel": TEMPLATE_ALARM_CONFIG},
}
},
],
)
@pytest.mark.parametrize(
("restored_state", "initial_state"),
[
(STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_AWAY),
(STATE_ALARM_ARMED_CUSTOM_BYPASS, STATE_ALARM_ARMED_CUSTOM_BYPASS),
(STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_HOME),
(STATE_ALARM_ARMED_NIGHT, STATE_ALARM_ARMED_NIGHT),
(STATE_ALARM_ARMED_VACATION, STATE_ALARM_ARMED_VACATION),
(STATE_ALARM_ARMING, STATE_ALARM_ARMING),
(STATE_ALARM_DISARMED, STATE_ALARM_DISARMED),
(STATE_ALARM_PENDING, STATE_ALARM_PENDING),
(STATE_ALARM_TRIGGERED, STATE_ALARM_TRIGGERED),
(STATE_UNAVAILABLE, STATE_UNKNOWN),
(STATE_UNKNOWN, STATE_UNKNOWN),
("faulty_state", STATE_UNKNOWN),
],
)
async def test_restore_state(
hass: HomeAssistant,
count,
domain,
config,
restored_state,
initial_state,
) -> None:
"""Test restoring template alarm control panel."""

fake_state = State(
"alarm_control_panel.test_template_panel",
restored_state,
{},
)
mock_restore_cache(hass, (fake_state,))
with assert_setup_component(count, domain):
assert await async_setup_component(
hass,
domain,
config,
)

await hass.async_block_till_done()

await hass.async_start()
await hass.async_block_till_done()

state = hass.states.get("alarm_control_panel.test_template_panel")
assert state.state == initial_state

0 comments on commit d855f70

Please sign in to comment.