Add time_throttle filter to sensor.filter (#20334)

* Added time_throttle filter

* Added time_throttle filter test

* Updated comments for time_throttle filter
This commit is contained in:
Andrey Kupreychik 2019-01-25 17:07:45 +07:00 committed by Diogo Gomes
parent c94834d8f6
commit d4c7515681
2 changed files with 48 additions and 2 deletions

View File

@ -32,6 +32,7 @@ FILTER_NAME_RANGE = 'range'
FILTER_NAME_LOWPASS = 'lowpass'
FILTER_NAME_OUTLIER = 'outlier'
FILTER_NAME_THROTTLE = 'throttle'
FILTER_NAME_TIME_THROTTLE = 'time_throttle'
FILTER_NAME_TIME_SMA = 'time_simple_moving_average'
FILTERS = Registry()
@ -101,6 +102,12 @@ FILTER_THROTTLE_SCHEMA = FILTER_SCHEMA.extend({
default=DEFAULT_WINDOW_SIZE): vol.Coerce(int),
})
FILTER_TIME_THROTTLE_SCHEMA = FILTER_SCHEMA.extend({
vol.Required(CONF_FILTER_NAME): FILTER_NAME_TIME_THROTTLE,
vol.Required(CONF_FILTER_WINDOW_SIZE): vol.All(cv.time_period,
cv.positive_timedelta)
})
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Optional(CONF_NAME): cv.string,
@ -109,6 +116,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
FILTER_LOWPASS_SCHEMA,
FILTER_TIME_SMA_SCHEMA,
FILTER_THROTTLE_SCHEMA,
FILTER_TIME_THROTTLE_SCHEMA,
FILTER_RANGE_SCHEMA)])
})
@ -444,7 +452,7 @@ class TimeSMAFilter(Filter):
The window_size is determined by time, and SMA is time weighted.
Args:
variant (enum): type of argorithm used to connect discrete values
type (enum): type of algorithm used to connect discrete values
"""
def __init__(self, window_size, precision, entity,
@ -502,3 +510,29 @@ class ThrottleFilter(Filter):
self._skip_processing = True
return new_state
@FILTERS.register(FILTER_NAME_TIME_THROTTLE)
class TimeThrottleFilter(Filter):
"""Time Throttle Filter.
One sample per time period.
"""
def __init__(self, window_size, precision, entity):
"""Initialize Filter."""
super().__init__(FILTER_NAME_TIME_THROTTLE,
window_size, precision, entity)
self._time_window = window_size
self._last_emitted_at = None
def _filter_state(self, new_state):
"""Implement the filter."""
window_start = new_state.timestamp - self._time_window
if not self._last_emitted_at or self._last_emitted_at <= window_start:
self._last_emitted_at = new_state.timestamp
self._skip_processing = False
else:
self._skip_processing = True
return new_state

View File

@ -5,7 +5,7 @@ from unittest.mock import patch
from homeassistant.components.sensor.filter import (
LowPassFilter, OutlierFilter, ThrottleFilter, TimeSMAFilter,
RangeFilter)
RangeFilter, TimeThrottleFilter)
import homeassistant.util.dt as dt_util
from homeassistant.setup import setup_component
import homeassistant.core as ha
@ -178,6 +178,18 @@ class TestFilterSensor(unittest.TestCase):
filtered.append(new_state)
assert [20, 21] == [f.state for f in filtered]
def test_time_throttle(self):
"""Test if lowpass filter works."""
filt = TimeThrottleFilter(window_size=timedelta(minutes=2),
precision=2,
entity=None)
filtered = []
for state in self.values:
new_state = filt.filter_state(state)
if not filt.skip_processing:
filtered.append(new_state)
assert [20, 18, 22] == [f.state for f in filtered]
def test_time_sma(self):
"""Test if time_sma filter works."""
filt = TimeSMAFilter(window_size=timedelta(minutes=2),