From 6c32337c8e37b9902b66241275047b406b2cf6f5 Mon Sep 17 00:00:00 2001
From: Martin Hjelmare <marhje52@gmail.com>
Date: Tue, 27 Dec 2022 20:29:25 +0100
Subject: [PATCH] Clean mysensors update callbacks (#84629)

---
 .../components/mysensors/__init__.py          |  2 +-
 homeassistant/components/mysensors/climate.py |  7 +++--
 homeassistant/components/mysensors/device.py  | 27 ++++++++++-------
 .../components/mysensors/device_tracker.py    | 21 ++++++++------
 homeassistant/components/mysensors/gateway.py |  2 +-
 homeassistant/components/mysensors/handler.py | 29 ++++++++++---------
 homeassistant/components/mysensors/light.py   | 10 ++++---
 homeassistant/components/mysensors/notify.py  |  7 ++++-
 homeassistant/components/mysensors/switch.py  |  7 +++--
 9 files changed, 65 insertions(+), 47 deletions(-)

diff --git a/homeassistant/components/mysensors/__init__.py b/homeassistant/components/mysensors/__init__.py
index cc0d918ec05..8316572379c 100644
--- a/homeassistant/components/mysensors/__init__.py
+++ b/homeassistant/components/mysensors/__init__.py
@@ -181,5 +181,5 @@ def setup_mysensors_platform(
     if new_devices:
         _LOGGER.info("Adding new devices: %s", new_devices)
         if async_add_entities is not None:
-            async_add_entities(new_devices, True)
+            async_add_entities(new_devices)
     return new_devices
diff --git a/homeassistant/components/mysensors/climate.py b/homeassistant/components/mysensors/climate.py
index 6d101c4f7a5..d207d7ff550 100644
--- a/homeassistant/components/mysensors/climate.py
+++ b/homeassistant/components/mysensors/climate.py
@@ -12,7 +12,7 @@ from homeassistant.components.climate import (
 )
 from homeassistant.config_entries import ConfigEntry
 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.entity_platform import AddEntitiesCallback
 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.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."""
-        await super().async_update()
+        super()._async_update()
         self._values[self.value_type] = DICT_MYS_TO_HA[self._values[self.value_type]]
diff --git a/homeassistant/components/mysensors/device.py b/homeassistant/components/mysensors/device.py
index d9f95fa391f..a7e0cd9b68b 100644
--- a/homeassistant/components/mysensors/device.py
+++ b/homeassistant/components/mysensors/device.py
@@ -1,7 +1,7 @@
 """Handle MySensors devices."""
 from __future__ import annotations
 
-from functools import partial
+from abc import ABC, abstractmethod
 import logging
 from typing import Any
 
@@ -34,7 +34,7 @@ ATTR_HEARTBEAT = "heartbeat"
 MYSENSORS_PLATFORM_DEVICES = "mysensors_devices_{}"
 
 
-class MySensorsDevice:
+class MySensorsDevice(ABC):
     """Representation of a MySensors device."""
 
     hass: HomeAssistant
@@ -151,7 +151,8 @@ class MySensorsDevice:
 
         return attr
 
-    async def async_update(self) -> None:
+    @callback
+    def _async_update(self) -> None:
         """Update the controller with the latest value from a sensor."""
         node = self.gateway.sensors[self.node_id]
         child = node.children[self.child_id]
@@ -178,9 +179,10 @@ class MySensorsDevice:
             else:
                 self._values[value_type] = value
 
-    async def _async_update_callback(self) -> None:
+    @callback
+    @abstractmethod
+    def _async_update_callback(self) -> None:
         """Update the device."""
-        raise NotImplementedError
 
     @callback
     def async_update_callback(self) -> None:
@@ -188,18 +190,18 @@ class MySensorsDevice:
         if self._update_scheduled:
             return
 
-        async def update() -> None:
+        @callback
+        def async_update() -> None:
             """Perform update."""
             try:
-                await self._async_update_callback()
+                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)
+        self.hass.loop.call_later(UPDATE_DELAY, async_update)
 
 
 def get_mysensors_devices(
@@ -235,9 +237,11 @@ class MySensorsEntity(MySensorsDevice, Entity):
 
         return attr
 
-    async def _async_update_callback(self) -> None:
+    @callback
+    def _async_update_callback(self) -> None:
         """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:
         """Register update callback."""
@@ -255,3 +259,4 @@ class MySensorsEntity(MySensorsDevice, Entity):
                 self.async_update_callback,
             )
         )
+        self._async_update()
diff --git a/homeassistant/components/mysensors/device_tracker.py b/homeassistant/components/mysensors/device_tracker.py
index a3fd86d1b44..f2ea3736d15 100644
--- a/homeassistant/components/mysensors/device_tracker.py
+++ b/homeassistant/components/mysensors/device_tracker.py
@@ -5,7 +5,7 @@ from typing import Any, cast
 
 from homeassistant.components.device_tracker import AsyncSeeCallback
 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.typing import ConfigType, DiscoveryInfoType
 from homeassistant.util import slugify
@@ -74,18 +74,21 @@ class MySensorsDeviceScanner(mysensors.device.MySensorsDevice):
         self.async_see = async_see
         self.hass = hass
 
-    async def _async_update_callback(self) -> None:
+    @callback
+    def _async_update_callback(self) -> None:
         """Update the device."""
-        await self.async_update()
+        self._async_update()
         node = self.gateway.sensors[self.node_id]
         child = node.children[self.child_id]
         position = child.values[self.value_type]
         latitude, longitude, _ = position.split(",")
 
-        await self.async_see(
-            dev_id=slugify(self.name),
-            host_name=self.name,
-            gps=(latitude, longitude),
-            battery=node.battery_level,
-            attributes=self._extra_attributes,
+        self.hass.async_create_task(
+            self.async_see(
+                dev_id=slugify(self.name),
+                host_name=self.name,
+                gps=(latitude, longitude),
+                battery=node.battery_level,
+                attributes=self._extra_attributes,
+            )
         )
diff --git a/homeassistant/components/mysensors/gateway.py b/homeassistant/components/mysensors/gateway.py
index a920faf49fa..635df264f75 100644
--- a/homeassistant/components/mysensors/gateway.py
+++ b/homeassistant/components/mysensors/gateway.py
@@ -329,6 +329,6 @@ def _gw_callback_factory(
         if msg_handler is None:
             return
 
-        hass.async_create_task(msg_handler(hass, gateway_id, msg))
+        msg_handler(hass, gateway_id, msg)
 
     return mysensors_callback
diff --git a/homeassistant/components/mysensors/handler.py b/homeassistant/components/mysensors/handler.py
index 57ff12fc6f0..8a77d167f8b 100644
--- a/homeassistant/components/mysensors/handler.py
+++ b/homeassistant/components/mysensors/handler.py
@@ -1,8 +1,7 @@
 """Handle MySensors messages."""
 from __future__ import annotations
 
-from collections.abc import Callable, Coroutine
-from typing import Any
+from collections.abc import Callable
 
 from mysensors import Message
 
@@ -16,30 +15,31 @@ from .device import get_mysensors_devices
 from .helpers import discover_mysensors_platform, validate_set_msg
 
 HANDLERS: decorator.Registry[
-    str, Callable[[HomeAssistant, GatewayId, Message], Coroutine[Any, Any, None]]
+    str, Callable[[HomeAssistant, GatewayId, Message], None]
 ] = decorator.Registry()
 
 
 @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."""
     validated = validate_set_msg(gateway_id, msg)
     _handle_child_update(hass, gateway_id, validated)
 
 
 @HANDLERS.register("internal")
-async def handle_internal(
-    hass: HomeAssistant, gateway_id: GatewayId, msg: Message
-) -> None:
+@callback
+def handle_internal(hass: HomeAssistant, gateway_id: GatewayId, msg: Message) -> None:
     """Handle a mysensors internal message."""
     internal = msg.gateway.const.Internal(msg.sub_type)
     if (handler := HANDLERS.get(internal.name)) is None:
         return
-    await handler(hass, gateway_id, msg)
+    handler(hass, gateway_id, msg)
 
 
 @HANDLERS.register("I_BATTERY_LEVEL")
-async def handle_battery_level(
+@callback
+def handle_battery_level(
     hass: HomeAssistant, gateway_id: GatewayId, msg: Message
 ) -> None:
     """Handle an internal battery level message."""
@@ -47,15 +47,15 @@ async def handle_battery_level(
 
 
 @HANDLERS.register("I_HEARTBEAT_RESPONSE")
-async def handle_heartbeat(
-    hass: HomeAssistant, gateway_id: GatewayId, msg: Message
-) -> None:
+@callback
+def handle_heartbeat(hass: HomeAssistant, gateway_id: GatewayId, msg: Message) -> None:
     """Handle an heartbeat."""
     _handle_node_update(hass, gateway_id, msg)
 
 
 @HANDLERS.register("I_SKETCH_NAME")
-async def handle_sketch_name(
+@callback
+def handle_sketch_name(
     hass: HomeAssistant, gateway_id: GatewayId, msg: Message
 ) -> None:
     """Handle an internal sketch name message."""
@@ -63,7 +63,8 @@ async def handle_sketch_name(
 
 
 @HANDLERS.register("I_SKETCH_VERSION")
-async def handle_sketch_version(
+@callback
+def handle_sketch_version(
     hass: HomeAssistant, gateway_id: GatewayId, msg: Message
 ) -> None:
     """Handle an internal sketch version message."""
diff --git a/homeassistant/components/mysensors/light.py b/homeassistant/components/mysensors/light.py
index e7ccdf8c569..e83002ed870 100644
--- a/homeassistant/components/mysensors/light.py
+++ b/homeassistant/components/mysensors/light.py
@@ -144,9 +144,10 @@ class MySensorsLightDimmer(MySensorsLight):
         if self.assumed_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."""
-        await super().async_update()
+        super()._async_update()
         self._async_update_light()
         self._async_update_dimmer()
 
@@ -181,9 +182,10 @@ class MySensorsLightRGB(MySensorsLight):
             self._attr_rgb_color = new_rgb
             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."""
-        await super().async_update()
+        super()._async_update()
         self._async_update_light()
         self._async_update_dimmer()
         self._async_update_rgb_or_w()
diff --git a/homeassistant/components/mysensors/notify.py b/homeassistant/components/mysensors/notify.py
index 9083b325e8d..b19ce7b85ca 100644
--- a/homeassistant/components/mysensors/notify.py
+++ b/homeassistant/components/mysensors/notify.py
@@ -5,7 +5,7 @@ from typing import Any, cast
 
 from homeassistant.components.notify import ATTR_TARGET, BaseNotificationService
 from homeassistant.const import Platform
-from homeassistant.core import HomeAssistant
+from homeassistant.core import HomeAssistant, callback
 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
 
 from .. import mysensors
@@ -35,6 +35,11 @@ async def async_get_service(
 class MySensorsNotificationDevice(mysensors.device.MySensorsDevice):
     """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:
         """Send a message."""
         for sub_msg in [msg[i : i + 25] for i in range(0, len(msg), 25)]:
diff --git a/homeassistant/components/mysensors/switch.py b/homeassistant/components/mysensors/switch.py
index dd79c6819ec..df0e6fe8532 100644
--- a/homeassistant/components/mysensors/switch.py
+++ b/homeassistant/components/mysensors/switch.py
@@ -8,7 +8,7 @@ import voluptuous as vol
 from homeassistant.components.switch import SwitchEntity
 from homeassistant.config_entries import ConfigEntry
 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
 from homeassistant.helpers.dispatcher import async_dispatcher_connect
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
@@ -178,7 +178,8 @@ class MySensorsIRSwitch(MySensorsSwitch):
             self._values[set_req.V_LIGHT] = STATE_OFF
             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."""
-        await super().async_update()
+        super()._async_update()
         self._ir_code = self._values.get(self.value_type)