Restore state of template binary sensor with on or off delay (#67546)

This commit is contained in:
Erik Montnemery 2022-03-04 00:27:39 +01:00 committed by GitHub
parent 69f08ec524
commit 2007379701
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 4 deletions

View File

@ -30,6 +30,9 @@ from homeassistant.const import (
CONF_UNIQUE_ID,
CONF_UNIT_OF_MEASUREMENT,
CONF_VALUE_TEMPLATE,
STATE_ON,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
)
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.exceptions import TemplateError
@ -38,6 +41,7 @@ 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.event import async_call_later
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import TriggerUpdateCoordinator
@ -186,7 +190,7 @@ async def async_setup_platform(
)
class BinarySensorTemplate(TemplateEntity, BinarySensorEntity):
class BinarySensorTemplate(TemplateEntity, BinarySensorEntity, RestoreEntity):
"""A virtual binary sensor that triggers from another sensor."""
def __init__(
@ -212,7 +216,14 @@ class BinarySensorTemplate(TemplateEntity, BinarySensorEntity):
self._delay_off_raw = config.get(CONF_DELAY_OFF)
async def async_added_to_hass(self):
"""Register callbacks."""
"""Restore state and register callbacks."""
if (
(self._delay_on_raw is not None or self._delay_off_raw is not None)
and (last_state := await self.async_get_last_state()) is not None
and last_state.state not in (STATE_UNKNOWN, STATE_UNAVAILABLE)
):
self._state = last_state.state == STATE_ON
self.add_template_attribute("_state", self._template, None, self._update_state)
if self._delay_on_raw is not None:

View File

@ -15,11 +15,16 @@ from homeassistant.const import (
STATE_UNAVAILABLE,
STATE_UNKNOWN,
)
from homeassistant.core import Context, CoreState
from homeassistant.core import Context, CoreState, State
from homeassistant.helpers import entity_registry
from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util
from tests.common import async_fire_time_changed
from tests.common import (
assert_setup_component,
async_fire_time_changed,
mock_restore_cache,
)
ON = "on"
OFF = "off"
@ -914,6 +919,70 @@ async def test_availability_icon_picture(hass, start_ha, entity_id):
}
@pytest.mark.parametrize("count,domain", [(1, "template")])
@pytest.mark.parametrize(
"config",
[
{
"template": {
"binary_sensor": {
"name": "test",
"state": "{{ states.sensor.test_state.state == 'on' }}",
},
},
},
],
)
@pytest.mark.parametrize(
"extra_config, restored_state, initial_state",
[
({}, ON, OFF),
({}, OFF, OFF),
({}, STATE_UNAVAILABLE, OFF),
({}, STATE_UNKNOWN, OFF),
({"delay_off": 5}, ON, ON),
({"delay_off": 5}, OFF, OFF),
({"delay_off": 5}, STATE_UNAVAILABLE, STATE_UNKNOWN),
({"delay_off": 5}, STATE_UNKNOWN, STATE_UNKNOWN),
({"delay_on": 5}, ON, ON),
({"delay_on": 5}, OFF, OFF),
({"delay_on": 5}, STATE_UNAVAILABLE, STATE_UNKNOWN),
({"delay_on": 5}, STATE_UNKNOWN, STATE_UNKNOWN),
],
)
async def test_restore_state(
hass, count, domain, config, extra_config, restored_state, initial_state
):
"""Test restoring template binary sensor."""
fake_state = State(
"binary_sensor.test",
restored_state,
{},
)
mock_restore_cache(hass, (fake_state,))
config = dict(config)
config["template"]["binary_sensor"].update(**extra_config)
with assert_setup_component(count, domain):
assert await async_setup_component(
hass,
domain,
config,
)
await hass.async_block_till_done()
context = Context()
hass.bus.async_fire("test_event", {"beer": 2}, context=context)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.test")
assert state.state == initial_state
@pytest.mark.parametrize("count,domain", [(2, "template")])
@pytest.mark.parametrize(
"config",