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
Adding expire_after to mqtt sensor to expire outdated values #6708
Changes from 2 commits
7c62b42
45ee8b9
3413a9b
74afdb8
ae5e0e3
0dc47d7
4a25e4e
596fc2f
5d53175
b48f8fa
520a0b8
c34a562
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 |
---|---|---|
|
@@ -6,6 +6,8 @@ | |
""" | ||
import asyncio | ||
import logging | ||
import time | ||
from datetime import timedelta | ||
|
||
import voluptuous as vol | ||
|
||
|
@@ -17,9 +19,11 @@ | |
import homeassistant.components.mqtt as mqtt | ||
import homeassistant.helpers.config_validation as cv | ||
|
||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
CONF_FORCE_UPDATE = 'force_update' | ||
CONF_EXPIRE_AFTER = 'expire_after' | ||
|
||
DEFAULT_NAME = 'MQTT Sensor' | ||
DEFAULT_FORCE_UPDATE = False | ||
|
@@ -31,6 +35,7 @@ | |
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean, | ||
}) | ||
|
||
SCAN_INTERVAL = timedelta(seconds=1) | ||
|
||
@asyncio.coroutine | ||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): | ||
|
@@ -48,6 +53,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): | |
config.get(CONF_QOS), | ||
config.get(CONF_UNIT_OF_MEASUREMENT), | ||
config.get(CONF_FORCE_UPDATE), | ||
config.get(CONF_EXPIRE_AFTER), | ||
value_template, | ||
)]) | ||
|
||
|
@@ -56,7 +62,7 @@ class MqttSensor(Entity): | |
"""Representation of a sensor that can be updated using MQTT.""" | ||
|
||
def __init__(self, name, state_topic, qos, unit_of_measurement, | ||
force_update, value_template): | ||
force_update, expire_after, value_template): | ||
"""Initialize the sensor.""" | ||
self._state = STATE_UNKNOWN | ||
self._name = name | ||
|
@@ -65,6 +71,8 @@ def __init__(self, name, state_topic, qos, unit_of_measurement, | |
self._unit_of_measurement = unit_of_measurement | ||
self._force_update = force_update | ||
self._template = value_template | ||
self._expire_after = int(expire_after or 0) | ||
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. Please use the config schema to convert it to an integer and set default value |
||
self._value_expiration_at = 0 | ||
|
||
def async_added_to_hass(self): | ||
"""Subscribe mqtt events. | ||
|
@@ -73,6 +81,9 @@ def async_added_to_hass(self): | |
""" | ||
@callback | ||
def message_received(topic, payload, qos): | ||
"""Reset expiration time.""" | ||
self._value_expiration_at = time.time() + self._expire_after | ||
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. Please use the event helper |
||
|
||
"""A new MQTT message has been received.""" | ||
if self._template is not None: | ||
payload = self._template.async_render_with_possible_json_value( | ||
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. why did you change this? 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. Line was 80 chars long (not my edit but wanted to have it fixed). |
||
|
@@ -85,8 +96,13 @@ def message_received(topic, payload, qos): | |
|
||
@property | ||
def should_poll(self): | ||
"""No polling needed.""" | ||
return False | ||
"""Polling needed only for auto-expire.""" | ||
return self._expire_after > 0 | ||
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. This should not be implemented with polling |
||
|
||
def update(self): | ||
"""Check if value is expired.""" | ||
if self._expire_after > 0 and time.time() > self._value_expiration_at: | ||
self._state = STATE_UNKNOWN | ||
|
||
@property | ||
def name(self): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
"""The tests for the MQTT sensor platform.""" | ||
import unittest | ||
|
||
import time | ||
import homeassistant.core as ha | ||
from homeassistant.setup import setup_component | ||
import homeassistant.components.sensor as sensor | ||
|
@@ -37,11 +38,49 @@ def test_setting_sensor_value_via_mqtt_message(self): | |
fire_mqtt_message(self.hass, 'test-topic', '100') | ||
self.hass.block_till_done() | ||
state = self.hass.states.get('sensor.test') | ||
|
||
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. blank line contains whitespace |
||
self.assertEqual('100', state.state) | ||
self.assertEqual('fav unit', | ||
state.attributes.get('unit_of_measurement')) | ||
|
||
def test_setting_sensor_value_expires(self): | ||
"""Test the expiration of the value.""" | ||
mock_component(self.hass, 'mqtt') | ||
assert setup_component(self.hass, sensor.DOMAIN, { | ||
sensor.DOMAIN: { | ||
'platform': 'mqtt', | ||
'name': 'test', | ||
'state_topic': 'test-topic', | ||
'unit_of_measurement': 'fav unit', | ||
'expire_after': '2', | ||
'force_update': True | ||
} | ||
}) | ||
|
||
state = self.hass.states.get('sensor.test') | ||
self.assertEqual('unknown', state.state) | ||
|
||
fire_mqtt_message(self.hass, 'test-topic', '100') | ||
self.hass.block_till_done() | ||
|
||
state = self.hass.states.get('sensor.test') | ||
self.assertEqual('100', state.state) | ||
|
||
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. blank line contains whitespace |
||
time.sleep(1) | ||
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. You are never allowed to call time.sleep in tests. Please use the |
||
# FIXME: how to call update() on the sensor? | ||
|
||
""" Not yet expired """ | ||
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. Comments in Python start with a 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. Please prefix comments with |
||
state = self.hass.states.get('sensor.test') | ||
self.assertEqual('100', state.state) | ||
|
||
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. blank line contains whitespace |
||
time.sleep(2) | ||
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. |
||
# FIXME: how to call update() on the sensor? | ||
|
||
""" Expired """ | ||
state = self.hass.states.get('sensor.test') | ||
# FIXME: this will fail unless the fixmes above are fixed | ||
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. Soo, fixed now? 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. Oops, forgot that one ;) Yes, the test is fixed now. |
||
# self.assertEqual('unknown', state.state) | ||
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. stale comment. |
||
|
||
def test_setting_sensor_value_via_mqtt_json_message(self): | ||
"""Test the setting of the value via MQTT with JSON playload.""" | ||
mock_component(self.hass, 'mqtt') | ||
|
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.
Remove this.