Add the ability to reload history_stats platforms from yaml (#39337)

* Add the ability to reload history_stats platforms from yaml

* Increase coverage and cleanup

* Fix coverage

* services.yaml
This commit is contained in:
J. Nick Koston 2020-08-28 00:22:43 -05:00 committed by GitHub
parent b5c2c9ec9b
commit f914625b8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 6 deletions

View File

@ -1 +1,4 @@
"""The history_stats component.""" """The history_stats component."""
DOMAIN = "history_stats"
PLATFORMS = ["sensor"]

View File

@ -16,16 +16,18 @@ from homeassistant.const import (
TIME_HOURS, TIME_HOURS,
UNIT_PERCENTAGE, UNIT_PERCENTAGE,
) )
from homeassistant.core import callback from homeassistant.core import CoreState, callback
from homeassistant.exceptions import TemplateError from homeassistant.exceptions import TemplateError
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.event import async_track_state_change_event
from homeassistant.helpers.reload import setup_reload_service
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from . import DOMAIN, PLATFORMS
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN = "history_stats"
CONF_START = "start" CONF_START = "start"
CONF_END = "end" CONF_END = "end"
CONF_DURATION = "duration" CONF_DURATION = "duration"
@ -75,6 +77,9 @@ PLATFORM_SCHEMA = vol.All(
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
def setup_platform(hass, config, add_entities, discovery_info=None): def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the History Stats sensor.""" """Set up the History Stats sensor."""
setup_reload_service(hass, DOMAIN, PLATFORMS)
entity_id = config.get(CONF_ENTITY_ID) entity_id = config.get(CONF_ENTITY_ID)
entity_state = config.get(CONF_STATE) entity_state = config.get(CONF_STATE)
start = config.get(CONF_START) start = config.get(CONF_START)
@ -118,6 +123,9 @@ class HistoryStatsSensor(Entity):
self.value = None self.value = None
self.count = None self.count = None
async def async_added_to_hass(self):
"""Create listeners when the entity is added."""
@callback @callback
def start_refresh(*args): def start_refresh(*args):
"""Register state tracking.""" """Register state tracking."""
@ -128,10 +136,18 @@ class HistoryStatsSensor(Entity):
self.async_schedule_update_ha_state(True) self.async_schedule_update_ha_state(True)
force_refresh() force_refresh()
async_track_state_change_event(self.hass, [self._entity_id], force_refresh) self.async_on_remove(
async_track_state_change_event(
self.hass, [self._entity_id], force_refresh
)
)
if self.hass.state == CoreState.running:
start_refresh()
return
# Delay first refresh to keep startup fast # Delay first refresh to keep startup fast
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_refresh) self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, start_refresh)
@property @property
def name(self): def name(self):

View File

@ -0,0 +1,2 @@
reload:
description: Reload all history_stats entities.

View File

@ -1,16 +1,19 @@
"""The test for the History Statistics sensor platform.""" """The test for the History Statistics sensor platform."""
# pylint: disable=protected-access # pylint: disable=protected-access
from datetime import datetime, timedelta from datetime import datetime, timedelta
from os import path
import unittest import unittest
import pytest import pytest
import pytz import pytz
from homeassistant import config as hass_config
from homeassistant.components.history_stats import DOMAIN
from homeassistant.components.history_stats.sensor import HistoryStatsSensor from homeassistant.components.history_stats.sensor import HistoryStatsSensor
from homeassistant.const import STATE_UNKNOWN from homeassistant.const import SERVICE_RELOAD, STATE_UNKNOWN
import homeassistant.core as ha import homeassistant.core as ha
from homeassistant.helpers.template import Template from homeassistant.helpers.template import Template
from homeassistant.setup import setup_component from homeassistant.setup import async_setup_component, setup_component
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from tests.async_mock import patch from tests.async_mock import patch
@ -255,3 +258,58 @@ class TestHistoryStatsSensor(unittest.TestCase):
"""Initialize the recorder.""" """Initialize the recorder."""
init_recorder_component(self.hass) init_recorder_component(self.hass)
self.hass.start() self.hass.start()
async def test_reload(hass):
"""Verify we can reload history_stats sensors."""
await hass.async_add_executor_job(
init_recorder_component, hass
) # force in memory db
hass.state = ha.CoreState.not_running
hass.states.async_set("binary_sensor.test_id", "on")
await async_setup_component(
hass,
"sensor",
{
"sensor": {
"platform": "history_stats",
"entity_id": "binary_sensor.test_id",
"name": "test",
"state": "on",
"start": "{{ as_timestamp(now()) - 3600 }}",
"duration": "01:00",
},
},
)
await hass.async_block_till_done()
await hass.async_start()
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 2
assert hass.states.get("sensor.test")
yaml_path = path.join(
_get_fixtures_base_path(),
"fixtures",
"history_stats/configuration.yaml",
)
with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path):
await hass.services.async_call(
DOMAIN,
SERVICE_RELOAD,
{},
blocking=True,
)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 2
assert hass.states.get("sensor.test") is None
assert hass.states.get("sensor.second_test")
def _get_fixtures_base_path():
return path.dirname(path.dirname(path.dirname(__file__)))

View File

@ -0,0 +1,7 @@
sensor:
- platform: history_stats
entity_id: binary_sensor.test_id
name: second_test
state: "on"
start: "{{ as_timestamp(now()) - 3600 }}"
end: "{{ now() }}"