Add the ability to reload filter platforms from yaml (#39267)

* Add the ability to reload filter platforms from yaml

* force in memory db

* fix listener leak on un-load
This commit is contained in:
J. Nick Koston 2020-08-25 20:55:45 -05:00 committed by GitHub
parent 215e3f2dab
commit eaac00acfc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 81 additions and 3 deletions

View File

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

View File

@ -25,9 +25,12 @@ from homeassistant.core import callback
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 async_setup_reload_service
from homeassistant.util.decorator import Registry from homeassistant.util.decorator import Registry
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__)
FILTER_NAME_RANGE = "range" FILTER_NAME_RANGE = "range"
@ -150,6 +153,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up the template sensors.""" """Set up the template sensors."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
entity_id = config.get(CONF_ENTITY_ID) entity_id = config.get(CONF_ENTITY_ID)
@ -279,8 +285,10 @@ class SensorFilter(Entity):
for state in history_list: for state in history_list:
self._update_filter_sensor_state(state, False) self._update_filter_sensor_state(state, False)
async_track_state_change_event( self.async_on_remove(
self.hass, [self._entity], self._update_filter_sensor_state_event async_track_state_change_event(
self.hass, [self._entity], self._update_filter_sensor_state_event
)
) )
@property @property

View File

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

View File

@ -1,8 +1,11 @@
"""The test for the data filter sensor platform.""" """The test for the data filter sensor platform."""
from datetime import timedelta from datetime import timedelta
from os import path
import unittest import unittest
from homeassistant import config as hass_config
from homeassistant.components.filter.sensor import ( from homeassistant.components.filter.sensor import (
DOMAIN,
LowPassFilter, LowPassFilter,
OutlierFilter, OutlierFilter,
RangeFilter, RangeFilter,
@ -10,8 +13,9 @@ from homeassistant.components.filter.sensor import (
TimeSMAFilter, TimeSMAFilter,
TimeThrottleFilter, TimeThrottleFilter,
) )
from homeassistant.const import SERVICE_RELOAD
import homeassistant.core as ha import homeassistant.core as ha
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
@ -307,3 +311,53 @@ class TestFilterSensor(unittest.TestCase):
for state in self.values: for state in self.values:
filtered = filt.filter_state(state) filtered = filt.filter_state(state)
assert 21.5 == filtered.state assert 21.5 == filtered.state
async def test_reload(hass):
"""Verify we can reload filter sensors."""
await hass.async_add_executor_job(
init_recorder_component, hass
) # force in memory db
hass.states.async_set("sensor.test_monitored", 12345)
await async_setup_component(
hass,
"sensor",
{
"sensor": {
"platform": "filter",
"name": "test",
"entity_id": "sensor.test_monitored",
"filters": [
{"filter": "outlier", "window_size": 10, "radius": 4.0},
{"filter": "lowpass", "time_constant": 10, "precision": 2},
{"filter": "throttle", "window_size": 1},
],
}
},
)
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", "filter/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.filtered_realistic_humidity")
def _get_fixtures_base_path():
return path.dirname(path.dirname(path.dirname(__file__)))

View File

@ -0,0 +1,11 @@
sensor:
- platform: filter
name: "filtered realistic humidity"
entity_id: sensor.realistic_humidity
filters:
- filter: outlier
window_size: 4
radius: 4.0
- filter: lowpass
time_constant: 10
precision: 2