-
-
Notifications
You must be signed in to change notification settings - Fork 32.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update TimeSMAFilter based on time #53053
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,6 +55,7 @@ | |
CONF_FILTER_PRECISION = "precision" | ||
CONF_FILTER_RADIUS = "radius" | ||
CONF_FILTER_TIME_CONSTANT = "time_constant" | ||
CONF_FILTER_UPDATE_BY_TIME = "update_by_time" | ||
CONF_FILTER_LOWER_BOUND = "lower_bound" | ||
CONF_FILTER_UPPER_BOUND = "upper_bound" | ||
CONF_TIME_SMA_TYPE = "type" | ||
|
@@ -72,6 +73,8 @@ | |
NAME_TEMPLATE = "{} filter" | ||
ICON = "mdi:chart-line-variant" | ||
|
||
SCAN_INTERVAL = timedelta(minutes=3) | ||
|
||
FILTER_SCHEMA = vol.Schema( | ||
{vol.Optional(CONF_FILTER_PRECISION, default=DEFAULT_PRECISION): vol.Coerce(int)} | ||
) | ||
|
@@ -117,6 +120,7 @@ | |
vol.Required(CONF_FILTER_WINDOW_SIZE): vol.All( | ||
cv.time_period, cv.positive_timedelta | ||
), | ||
vol.Optional(CONF_FILTER_UPDATE_BY_TIME, default=False): cv.boolean, | ||
} | ||
) | ||
|
||
|
@@ -192,12 +196,23 @@ def __init__(self, name, entity_id, filters): | |
self._icon = None | ||
self._device_class = None | ||
|
||
self._attr_should_poll = False | ||
for filt in filters: | ||
if getattr(filt, "update_by_time", False): | ||
self._attr_should_poll = True | ||
break | ||
|
||
@callback | ||
def _update_filter_sensor_state_event(self, event): | ||
"""Handle device state changes.""" | ||
_LOGGER.debug("Update filter on event: %s", event) | ||
self._update_filter_sensor_state(event.data.get("new_state")) | ||
|
||
def update(self): | ||
"""Update TimeSMAFilter value.""" | ||
_LOGGER.debug("Update filter: %s", self._state) | ||
self._update_filter_sensor_state(self.hass.states.get(self._entity)) | ||
|
||
@callback | ||
def _update_filter_sensor_state(self, new_state, update_ha=True): | ||
"""Process device state changes.""" | ||
|
@@ -346,11 +361,6 @@ def unit_of_measurement(self): | |
"""Return the unit_of_measurement of the device.""" | ||
return self._unit_of_measurement | ||
|
||
@property | ||
def should_poll(self): | ||
"""No polling needed.""" | ||
return False | ||
|
||
@property | ||
def extra_state_attributes(self): | ||
"""Return the state attributes of the sensor.""" | ||
|
@@ -454,7 +464,7 @@ def filter_state(self, new_state): | |
|
||
|
||
@FILTERS.register(FILTER_NAME_RANGE) | ||
class RangeFilter(Filter, SensorEntity): | ||
class RangeFilter(Filter): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might have misunderstood something, but I see no reason for the filters to inherit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not that I can recall :/ since tests didn't break and coverage is high, I'm ok with this |
||
"""Range filter. | ||
|
||
Determines if new state is in the range of upper_bound and lower_bound. | ||
|
@@ -509,7 +519,7 @@ def _filter_state(self, new_state): | |
|
||
|
||
@FILTERS.register(FILTER_NAME_OUTLIER) | ||
class OutlierFilter(Filter, SensorEntity): | ||
class OutlierFilter(Filter): | ||
"""BASIC outlier filter. | ||
|
||
Determines if new state is in a band around the median. | ||
|
@@ -547,7 +557,7 @@ def _filter_state(self, new_state): | |
|
||
|
||
@FILTERS.register(FILTER_NAME_LOWPASS) | ||
class LowPassFilter(Filter, SensorEntity): | ||
class LowPassFilter(Filter): | ||
"""BASIC Low Pass Filter.""" | ||
|
||
def __init__(self, window_size, precision, entity, time_constant: int): | ||
|
@@ -571,21 +581,27 @@ def _filter_state(self, new_state): | |
|
||
|
||
@FILTERS.register(FILTER_NAME_TIME_SMA) | ||
class TimeSMAFilter(Filter, SensorEntity): | ||
class TimeSMAFilter(Filter): | ||
"""Simple Moving Average (SMA) Filter. | ||
|
||
The window_size is determined by time, and SMA is time weighted. | ||
""" | ||
|
||
def __init__( | ||
self, window_size, precision, entity, type | ||
self, | ||
window_size, | ||
precision, | ||
entity, | ||
type, | ||
update_by_time, | ||
): # pylint: disable=redefined-builtin | ||
"""Initialize Filter. | ||
|
||
:param type: type of algorithm used to connect discrete values | ||
""" | ||
super().__init__(FILTER_NAME_TIME_SMA, window_size, precision, entity) | ||
self._time_window = window_size | ||
self.update_by_time = update_by_time | ||
self.last_leak = None | ||
self.queue = deque() | ||
|
||
|
@@ -617,7 +633,7 @@ def _filter_state(self, new_state): | |
|
||
|
||
@FILTERS.register(FILTER_NAME_THROTTLE) | ||
class ThrottleFilter(Filter, SensorEntity): | ||
class ThrottleFilter(Filter): | ||
"""Throttle Filter. | ||
|
||
One sample per window. | ||
|
@@ -640,7 +656,7 @@ def _filter_state(self, new_state): | |
|
||
|
||
@FILTERS.register(FILTER_NAME_TIME_THROTTLE) | ||
class TimeThrottleFilter(Filter, SensorEntity): | ||
class TimeThrottleFilter(Filter): | ||
"""Time Throttle Filter. | ||
|
||
One sample per time period. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reasoning for choosing 3min ?