From 6cb8a36cf1538065bb620133dfe19c9088e480a5 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Thu, 2 Mar 2017 06:38:19 +0100 Subject: [PATCH] Template sensor change flow / add restore (#6336) --- homeassistant/components/sensor/template.py | 29 ++++++++--- tests/components/sensor/test_template.py | 58 ++++++++++++++++++++- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/sensor/template.py b/homeassistant/components/sensor/template.py index 42481c95510..51a7bc82a85 100644 --- a/homeassistant/components/sensor/template.py +++ b/homeassistant/components/sensor/template.py @@ -13,11 +13,12 @@ from homeassistant.core import callback from homeassistant.components.sensor import ENTITY_ID_FORMAT, PLATFORM_SCHEMA from homeassistant.const import ( ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, CONF_VALUE_TEMPLATE, - ATTR_ENTITY_ID, CONF_SENSORS) + ATTR_ENTITY_ID, CONF_SENSORS, EVENT_HOMEASSISTANT_START) from homeassistant.exceptions import TemplateError +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity, async_generate_entity_id from homeassistant.helpers.event import async_track_state_change -import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.restore_state import async_get_last_state _LOGGER = logging.getLogger(__name__) @@ -69,7 +70,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): _LOGGER.error("No sensors added") return False - async_add_devices(sensors, True) + async_add_devices(sensors) return True @@ -88,14 +89,30 @@ class SensorTemplate(Entity): self._state = None self._icon_template = icon_template self._icon = None + self._entities = entity_ids + + @asyncio.coroutine + def async_added_to_hass(self): + """Register callbacks.""" + state = yield from async_get_last_state(self.hass, self.entity_id) + if state: + self._state = state.state @callback def template_sensor_state_listener(entity, old_state, new_state): """Called when the target device changes state.""" - hass.async_add_job(self.async_update_ha_state, True) + self.hass.async_add_job(self.async_update_ha_state(True)) - async_track_state_change( - hass, entity_ids, template_sensor_state_listener) + @callback + def template_sensor_startup(event): + """Update template on startup.""" + async_track_state_change( + self.hass, self._entities, template_sensor_state_listener) + + self.hass.async_add_job(self.async_update_ha_state(True)) + + self.hass.bus.async_listen_once( + EVENT_HOMEASSISTANT_START, template_sensor_startup) @property def name(self): diff --git a/tests/components/sensor/test_template.py b/tests/components/sensor/test_template.py index 0f5e863f328..7ba4ca136e0 100644 --- a/tests/components/sensor/test_template.py +++ b/tests/components/sensor/test_template.py @@ -1,7 +1,12 @@ """The test for the Template sensor platform.""" -from homeassistant.bootstrap import setup_component +import asyncio -from tests.common import get_test_home_assistant, assert_setup_component +from homeassistant.core import CoreState, State +from homeassistant.bootstrap import setup_component, async_setup_component +from homeassistant.helpers.restore_state import DATA_RESTORE_CACHE + +from tests.common import ( + get_test_home_assistant, assert_setup_component, mock_component) class TestTemplateSensor: @@ -33,6 +38,8 @@ class TestTemplateSensor: } }) + self.hass.start() + state = self.hass.states.get('sensor.test_template_sensor') assert state.state == 'It .' @@ -60,6 +67,8 @@ class TestTemplateSensor: } }) + self.hass.start() + state = self.hass.states.get('sensor.test_template_sensor') assert 'icon' not in state.attributes @@ -82,6 +91,8 @@ class TestTemplateSensor: } } }) + + self.hass.start() assert self.hass.states.all() == [] def test_template_attribute_missing(self): @@ -99,6 +110,8 @@ class TestTemplateSensor: } }) + self.hass.start() + state = self.hass.states.get('sensor.test_template_sensor') assert state.state == 'unknown' @@ -116,6 +129,8 @@ class TestTemplateSensor: } } }) + + self.hass.start() assert self.hass.states.all() == [] def test_invalid_sensor_does_not_create(self): @@ -129,6 +144,8 @@ class TestTemplateSensor: } } }) + + self.hass.start() assert self.hass.states.all() == [] def test_no_sensors_does_not_create(self): @@ -139,6 +156,8 @@ class TestTemplateSensor: 'platform': 'template' } }) + + self.hass.start() assert self.hass.states.all() == [] def test_missing_template_does_not_create(self): @@ -155,4 +174,39 @@ class TestTemplateSensor: } } }) + + self.hass.start() assert self.hass.states.all() == [] + + +@asyncio.coroutine +def test_restore_state(hass): + """Ensure states are restored on startup.""" + hass.data[DATA_RESTORE_CACHE] = { + 'sensor.test_template_sensor': + State('sensor.test_template_sensor', 'It Test.'), + } + + hass.state = CoreState.starting + mock_component(hass, 'recorder') + + yield from async_setup_component(hass, 'sensor', { + 'sensor': { + 'platform': 'template', + 'sensors': { + 'test_template_sensor': { + 'value_template': + "It {{ states.sensor.test_state.state }}." + } + } + } + }) + + state = hass.states.get('sensor.test_template_sensor') + assert state.state == 'It Test.' + + yield from hass.async_start() + yield from hass.async_block_till_done() + + state = hass.states.get('sensor.test_template_sensor') + assert state.state == 'It .'