diff --git a/homeassistant/components/filter/__init__.py b/homeassistant/components/filter/__init__.py index ebdcec75abf2ff55ada4ebca5c4e4cd5cafa3bf0..35e374771c2fc630112d36defffec03ccfbefc84 100644 --- a/homeassistant/components/filter/__init__.py +++ b/homeassistant/components/filter/__init__.py @@ -1 +1,4 @@ """The filter component.""" + +DOMAIN = "filter" +PLATFORMS = ["sensor"] diff --git a/homeassistant/components/filter/sensor.py b/homeassistant/components/filter/sensor.py index e46af9fa13878662700f2290249b2dd16a67005a..b0cc08bc94502c79470f97396952fd02d4a2dbb7 100644 --- a/homeassistant/components/filter/sensor.py +++ b/homeassistant/components/filter/sensor.py @@ -25,9 +25,12 @@ from homeassistant.core import callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity 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 import homeassistant.util.dt as dt_util +from . import DOMAIN, PLATFORMS + _LOGGER = logging.getLogger(__name__) 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): """Set up the template sensors.""" + + await async_setup_reload_service(hass, DOMAIN, PLATFORMS) + name = config.get(CONF_NAME) entity_id = config.get(CONF_ENTITY_ID) @@ -279,8 +285,10 @@ class SensorFilter(Entity): for state in history_list: self._update_filter_sensor_state(state, False) - async_track_state_change_event( - self.hass, [self._entity], self._update_filter_sensor_state_event + self.async_on_remove( + async_track_state_change_event( + self.hass, [self._entity], self._update_filter_sensor_state_event + ) ) @property diff --git a/homeassistant/components/filter/services.yaml b/homeassistant/components/filter/services.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6f6ea1b04d6aa10b26b54307861e467479a073d6 --- /dev/null +++ b/homeassistant/components/filter/services.yaml @@ -0,0 +1,2 @@ +reload: + description: Reload all filter entities. diff --git a/tests/components/filter/test_sensor.py b/tests/components/filter/test_sensor.py index f6eae30c653d0d067e5e2c8a51405913d76da568..84db16c14642891f5e1b89c3a088f29d9a839e76 100644 --- a/tests/components/filter/test_sensor.py +++ b/tests/components/filter/test_sensor.py @@ -1,8 +1,11 @@ """The test for the data filter sensor platform.""" from datetime import timedelta +from os import path import unittest +from homeassistant import config as hass_config from homeassistant.components.filter.sensor import ( + DOMAIN, LowPassFilter, OutlierFilter, RangeFilter, @@ -10,8 +13,9 @@ from homeassistant.components.filter.sensor import ( TimeSMAFilter, TimeThrottleFilter, ) +from homeassistant.const import SERVICE_RELOAD 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 from tests.async_mock import patch @@ -307,3 +311,53 @@ class TestFilterSensor(unittest.TestCase): for state in self.values: filtered = filt.filter_state(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__))) diff --git a/tests/fixtures/filter/configuration.yaml b/tests/fixtures/filter/configuration.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c29c504b2ee79cb4ba3c24304da7307d6f6145fb --- /dev/null +++ b/tests/fixtures/filter/configuration.yaml @@ -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