Add mysensors state update delay (#18891)

* Add mysensors state update delay

* Schedule state update after delay to avoid updating state multiple
  times during the same short timespan.

* Code review
This commit is contained in:
Martin Hjelmare 2019-01-11 22:06:06 +01:00 committed by Paulus Schoutsen
parent 25408bd483
commit 937688f7a6
4 changed files with 34 additions and 8 deletions

View file

@ -14,7 +14,7 @@ async def async_setup_scanner(hass, config, async_see, discovery_info=None):
"""Set up the MySensors device scanner."""
new_devices = mysensors.setup_mysensors_platform(
hass, DOMAIN, discovery_info, MySensorsDeviceScanner,
device_args=(async_see, ))
device_args=(hass, async_see))
if not new_devices:
return False
@ -37,12 +37,13 @@ async def async_setup_scanner(hass, config, async_see, discovery_info=None):
class MySensorsDeviceScanner(mysensors.device.MySensorsDevice):
"""Represent a MySensors scanner."""
def __init__(self, async_see, *args):
def __init__(self, hass, async_see, *args):
"""Set up instance."""
super().__init__(*args)
self.async_see = async_see
self.hass = hass
async def async_update_callback(self):
async def _async_update_callback(self):
"""Update the device."""
await self.async_update()
node = self.gateway.sensors[self.node_id]

View file

@ -23,6 +23,7 @@ SCHEMA = 'schema'
CHILD_CALLBACK = 'mysensors_child_callback_{}_{}_{}_{}'
NODE_CALLBACK = 'mysensors_node_callback_{}_{}'
TYPE = 'type'
UPDATE_DELAY = 0.1
# MySensors const schemas
BINARY_SENSOR_SCHEMA = {PLATFORM: 'binary_sensor', TYPE: 'V_TRIPPED'}

View file

@ -1,5 +1,6 @@
"""Handle MySensors devices."""
import logging
from functools import partial
from homeassistant.const import (
ATTR_BATTERY_LEVEL, STATE_OFF, STATE_ON)
@ -7,7 +8,7 @@ from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity
from .const import CHILD_CALLBACK, NODE_CALLBACK
from .const import CHILD_CALLBACK, NODE_CALLBACK, UPDATE_DELAY
_LOGGER = logging.getLogger(__name__)
@ -39,6 +40,8 @@ class MySensorsDevice:
child = gateway.sensors[node_id].children[child_id]
self.child_type = child.type
self._values = {}
self._update_scheduled = False
self.hass = None
@property
def name(self):
@ -84,6 +87,29 @@ class MySensorsDevice:
else:
self._values[value_type] = value
async def _async_update_callback(self):
"""Update the device."""
raise NotImplementedError
@callback
def async_update_callback(self):
"""Update the device after delay."""
if self._update_scheduled:
return
async def update():
"""Perform update."""
try:
await self._async_update_callback()
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Error updating %s", self.name)
finally:
self._update_scheduled = False
self._update_scheduled = True
delayed_update = partial(self.hass.async_create_task, update())
self.hass.loop.call_later(UPDATE_DELAY, delayed_update)
class MySensorsEntity(MySensorsDevice, Entity):
"""Representation of a MySensors entity."""
@ -98,10 +124,9 @@ class MySensorsEntity(MySensorsDevice, Entity):
"""Return true if entity is available."""
return self.value_type in self._values
@callback
def async_update_callback(self):
async def _async_update_callback(self):
"""Update the entity."""
self.async_schedule_update_ha_state(True)
await self.async_update_ha_state(True)
async def async_added_to_hass(self):
"""Register update callback."""

View file

@ -99,7 +99,6 @@ def _handle_child_update(hass, hass_config, msg):
for signal in set(signals):
# Only one signal per device is needed.
# A device can have multiple platforms, ie multiple schemas.
# FOR LATER: Add timer to not signal if another update comes in.
async_dispatcher_send(hass, signal)