Clean mysensors update callbacks (#84629)

This commit is contained in:
Martin Hjelmare 2022-12-27 20:29:25 +01:00 committed by GitHub
parent eae8154753
commit 6c32337c8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 65 additions and 47 deletions

View File

@ -181,5 +181,5 @@ def setup_mysensors_platform(
if new_devices: if new_devices:
_LOGGER.info("Adding new devices: %s", new_devices) _LOGGER.info("Adding new devices: %s", new_devices)
if async_add_entities is not None: if async_add_entities is not None:
async_add_entities(new_devices, True) async_add_entities(new_devices)
return new_devices return new_devices

View File

@ -12,7 +12,7 @@ from homeassistant.components.climate import (
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_TEMPERATURE, Platform, UnitOfTemperature from homeassistant.const import ATTR_TEMPERATURE, Platform, UnitOfTemperature
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util.unit_system import METRIC_SYSTEM from homeassistant.util.unit_system import METRIC_SYSTEM
@ -213,7 +213,8 @@ class MySensorsHVAC(mysensors.device.MySensorsEntity, ClimateEntity):
self._values[self.value_type] = hvac_mode self._values[self.value_type] = hvac_mode
self.async_write_ha_state() self.async_write_ha_state()
async def async_update(self) -> None: @callback
def _async_update(self) -> None:
"""Update the controller with the latest value from a sensor.""" """Update the controller with the latest value from a sensor."""
await super().async_update() super()._async_update()
self._values[self.value_type] = DICT_MYS_TO_HA[self._values[self.value_type]] self._values[self.value_type] = DICT_MYS_TO_HA[self._values[self.value_type]]

View File

@ -1,7 +1,7 @@
"""Handle MySensors devices.""" """Handle MySensors devices."""
from __future__ import annotations from __future__ import annotations
from functools import partial from abc import ABC, abstractmethod
import logging import logging
from typing import Any from typing import Any
@ -34,7 +34,7 @@ ATTR_HEARTBEAT = "heartbeat"
MYSENSORS_PLATFORM_DEVICES = "mysensors_devices_{}" MYSENSORS_PLATFORM_DEVICES = "mysensors_devices_{}"
class MySensorsDevice: class MySensorsDevice(ABC):
"""Representation of a MySensors device.""" """Representation of a MySensors device."""
hass: HomeAssistant hass: HomeAssistant
@ -151,7 +151,8 @@ class MySensorsDevice:
return attr return attr
async def async_update(self) -> None: @callback
def _async_update(self) -> None:
"""Update the controller with the latest value from a sensor.""" """Update the controller with the latest value from a sensor."""
node = self.gateway.sensors[self.node_id] node = self.gateway.sensors[self.node_id]
child = node.children[self.child_id] child = node.children[self.child_id]
@ -178,9 +179,10 @@ class MySensorsDevice:
else: else:
self._values[value_type] = value self._values[value_type] = value
async def _async_update_callback(self) -> None: @callback
@abstractmethod
def _async_update_callback(self) -> None:
"""Update the device.""" """Update the device."""
raise NotImplementedError
@callback @callback
def async_update_callback(self) -> None: def async_update_callback(self) -> None:
@ -188,18 +190,18 @@ class MySensorsDevice:
if self._update_scheduled: if self._update_scheduled:
return return
async def update() -> None: @callback
def async_update() -> None:
"""Perform update.""" """Perform update."""
try: try:
await self._async_update_callback() self._async_update_callback()
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
_LOGGER.exception("Error updating %s", self.name) _LOGGER.exception("Error updating %s", self.name)
finally: finally:
self._update_scheduled = False self._update_scheduled = False
self._update_scheduled = True self._update_scheduled = True
delayed_update = partial(self.hass.async_create_task, update()) self.hass.loop.call_later(UPDATE_DELAY, async_update)
self.hass.loop.call_later(UPDATE_DELAY, delayed_update)
def get_mysensors_devices( def get_mysensors_devices(
@ -235,9 +237,11 @@ class MySensorsEntity(MySensorsDevice, Entity):
return attr return attr
async def _async_update_callback(self) -> None: @callback
def _async_update_callback(self) -> None:
"""Update the entity.""" """Update the entity."""
await self.async_update_ha_state(True) self._async_update()
self.async_write_ha_state()
async def async_added_to_hass(self) -> None: async def async_added_to_hass(self) -> None:
"""Register update callback.""" """Register update callback."""
@ -255,3 +259,4 @@ class MySensorsEntity(MySensorsDevice, Entity):
self.async_update_callback, self.async_update_callback,
) )
) )
self._async_update()

View File

@ -5,7 +5,7 @@ from typing import Any, cast
from homeassistant.components.device_tracker import AsyncSeeCallback from homeassistant.components.device_tracker import AsyncSeeCallback
from homeassistant.const import Platform from homeassistant.const import Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import slugify from homeassistant.util import slugify
@ -74,18 +74,21 @@ class MySensorsDeviceScanner(mysensors.device.MySensorsDevice):
self.async_see = async_see self.async_see = async_see
self.hass = hass self.hass = hass
async def _async_update_callback(self) -> None: @callback
def _async_update_callback(self) -> None:
"""Update the device.""" """Update the device."""
await self.async_update() self._async_update()
node = self.gateway.sensors[self.node_id] node = self.gateway.sensors[self.node_id]
child = node.children[self.child_id] child = node.children[self.child_id]
position = child.values[self.value_type] position = child.values[self.value_type]
latitude, longitude, _ = position.split(",") latitude, longitude, _ = position.split(",")
await self.async_see( self.hass.async_create_task(
dev_id=slugify(self.name), self.async_see(
host_name=self.name, dev_id=slugify(self.name),
gps=(latitude, longitude), host_name=self.name,
battery=node.battery_level, gps=(latitude, longitude),
attributes=self._extra_attributes, battery=node.battery_level,
attributes=self._extra_attributes,
)
) )

View File

@ -329,6 +329,6 @@ def _gw_callback_factory(
if msg_handler is None: if msg_handler is None:
return return
hass.async_create_task(msg_handler(hass, gateway_id, msg)) msg_handler(hass, gateway_id, msg)
return mysensors_callback return mysensors_callback

View File

@ -1,8 +1,7 @@
"""Handle MySensors messages.""" """Handle MySensors messages."""
from __future__ import annotations from __future__ import annotations
from collections.abc import Callable, Coroutine from collections.abc import Callable
from typing import Any
from mysensors import Message from mysensors import Message
@ -16,30 +15,31 @@ from .device import get_mysensors_devices
from .helpers import discover_mysensors_platform, validate_set_msg from .helpers import discover_mysensors_platform, validate_set_msg
HANDLERS: decorator.Registry[ HANDLERS: decorator.Registry[
str, Callable[[HomeAssistant, GatewayId, Message], Coroutine[Any, Any, None]] str, Callable[[HomeAssistant, GatewayId, Message], None]
] = decorator.Registry() ] = decorator.Registry()
@HANDLERS.register("set") @HANDLERS.register("set")
async def handle_set(hass: HomeAssistant, gateway_id: GatewayId, msg: Message) -> None: @callback
def handle_set(hass: HomeAssistant, gateway_id: GatewayId, msg: Message) -> None:
"""Handle a mysensors set message.""" """Handle a mysensors set message."""
validated = validate_set_msg(gateway_id, msg) validated = validate_set_msg(gateway_id, msg)
_handle_child_update(hass, gateway_id, validated) _handle_child_update(hass, gateway_id, validated)
@HANDLERS.register("internal") @HANDLERS.register("internal")
async def handle_internal( @callback
hass: HomeAssistant, gateway_id: GatewayId, msg: Message def handle_internal(hass: HomeAssistant, gateway_id: GatewayId, msg: Message) -> None:
) -> None:
"""Handle a mysensors internal message.""" """Handle a mysensors internal message."""
internal = msg.gateway.const.Internal(msg.sub_type) internal = msg.gateway.const.Internal(msg.sub_type)
if (handler := HANDLERS.get(internal.name)) is None: if (handler := HANDLERS.get(internal.name)) is None:
return return
await handler(hass, gateway_id, msg) handler(hass, gateway_id, msg)
@HANDLERS.register("I_BATTERY_LEVEL") @HANDLERS.register("I_BATTERY_LEVEL")
async def handle_battery_level( @callback
def handle_battery_level(
hass: HomeAssistant, gateway_id: GatewayId, msg: Message hass: HomeAssistant, gateway_id: GatewayId, msg: Message
) -> None: ) -> None:
"""Handle an internal battery level message.""" """Handle an internal battery level message."""
@ -47,15 +47,15 @@ async def handle_battery_level(
@HANDLERS.register("I_HEARTBEAT_RESPONSE") @HANDLERS.register("I_HEARTBEAT_RESPONSE")
async def handle_heartbeat( @callback
hass: HomeAssistant, gateway_id: GatewayId, msg: Message def handle_heartbeat(hass: HomeAssistant, gateway_id: GatewayId, msg: Message) -> None:
) -> None:
"""Handle an heartbeat.""" """Handle an heartbeat."""
_handle_node_update(hass, gateway_id, msg) _handle_node_update(hass, gateway_id, msg)
@HANDLERS.register("I_SKETCH_NAME") @HANDLERS.register("I_SKETCH_NAME")
async def handle_sketch_name( @callback
def handle_sketch_name(
hass: HomeAssistant, gateway_id: GatewayId, msg: Message hass: HomeAssistant, gateway_id: GatewayId, msg: Message
) -> None: ) -> None:
"""Handle an internal sketch name message.""" """Handle an internal sketch name message."""
@ -63,7 +63,8 @@ async def handle_sketch_name(
@HANDLERS.register("I_SKETCH_VERSION") @HANDLERS.register("I_SKETCH_VERSION")
async def handle_sketch_version( @callback
def handle_sketch_version(
hass: HomeAssistant, gateway_id: GatewayId, msg: Message hass: HomeAssistant, gateway_id: GatewayId, msg: Message
) -> None: ) -> None:
"""Handle an internal sketch version message.""" """Handle an internal sketch version message."""

View File

@ -144,9 +144,10 @@ class MySensorsLightDimmer(MySensorsLight):
if self.assumed_state: if self.assumed_state:
self.async_write_ha_state() self.async_write_ha_state()
async def async_update(self) -> None: @callback
def _async_update(self) -> None:
"""Update the controller with the latest value from a sensor.""" """Update the controller with the latest value from a sensor."""
await super().async_update() super()._async_update()
self._async_update_light() self._async_update_light()
self._async_update_dimmer() self._async_update_dimmer()
@ -181,9 +182,10 @@ class MySensorsLightRGB(MySensorsLight):
self._attr_rgb_color = new_rgb self._attr_rgb_color = new_rgb
self._values[self.value_type] = hex_color self._values[self.value_type] = hex_color
async def async_update(self) -> None: @callback
def _async_update(self) -> None:
"""Update the controller with the latest value from a sensor.""" """Update the controller with the latest value from a sensor."""
await super().async_update() super()._async_update()
self._async_update_light() self._async_update_light()
self._async_update_dimmer() self._async_update_dimmer()
self._async_update_rgb_or_w() self._async_update_rgb_or_w()

View File

@ -5,7 +5,7 @@ from typing import Any, cast
from homeassistant.components.notify import ATTR_TARGET, BaseNotificationService from homeassistant.components.notify import ATTR_TARGET, BaseNotificationService
from homeassistant.const import Platform from homeassistant.const import Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from .. import mysensors from .. import mysensors
@ -35,6 +35,11 @@ async def async_get_service(
class MySensorsNotificationDevice(mysensors.device.MySensorsDevice): class MySensorsNotificationDevice(mysensors.device.MySensorsDevice):
"""Represent a MySensors Notification device.""" """Represent a MySensors Notification device."""
@callback
def _async_update_callback(self) -> None:
"""Update the device."""
self._async_update()
def send_msg(self, msg: str) -> None: def send_msg(self, msg: str) -> None:
"""Send a message.""" """Send a message."""
for sub_msg in [msg[i : i + 25] for i in range(0, len(msg), 25)]: for sub_msg in [msg[i : i + 25] for i in range(0, len(msg), 25)]:

View File

@ -8,7 +8,7 @@ import voluptuous as vol
from homeassistant.components.switch import SwitchEntity from homeassistant.components.switch import SwitchEntity
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, Platform from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, Platform
from homeassistant.core import HomeAssistant, ServiceCall from homeassistant.core import HomeAssistant, ServiceCall, callback
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -178,7 +178,8 @@ class MySensorsIRSwitch(MySensorsSwitch):
self._values[set_req.V_LIGHT] = STATE_OFF self._values[set_req.V_LIGHT] = STATE_OFF
self.async_write_ha_state() self.async_write_ha_state()
async def async_update(self) -> None: @callback
def _async_update(self) -> None:
"""Update the controller with the latest value from a sensor.""" """Update the controller with the latest value from a sensor."""
await super().async_update() super()._async_update()
self._ir_code = self._values.get(self.value_type) self._ir_code = self._values.get(self.value_type)