"""Support for tracking MySensors devices.""" from __future__ import annotations from typing import Any, cast from homeassistant.components import mysensors from homeassistant.components.device_tracker import AsyncSeeCallback from homeassistant.const import Platform from homeassistant.core import HomeAssistant from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.util import slugify from .const import ATTR_GATEWAY_ID, DevId, DiscoveryInfo, GatewayId from .helpers import on_unload async def async_setup_scanner( hass: HomeAssistant, config: ConfigType, async_see: AsyncSeeCallback, discovery_info: DiscoveryInfoType | None = None, ) -> bool: """Set up the MySensors device scanner.""" if not discovery_info: return False new_devices = mysensors.setup_mysensors_platform( hass, Platform.DEVICE_TRACKER, cast(DiscoveryInfo, discovery_info), MySensorsDeviceScanner, device_args=(hass, async_see), ) if not new_devices: return False for device in new_devices: gateway_id: GatewayId = discovery_info[ATTR_GATEWAY_ID] dev_id: DevId = (gateway_id, device.node_id, device.child_id, device.value_type) on_unload( hass, gateway_id, async_dispatcher_connect( hass, mysensors.const.CHILD_CALLBACK.format(*dev_id), device.async_update_callback, ), ) on_unload( hass, gateway_id, async_dispatcher_connect( hass, mysensors.const.NODE_CALLBACK.format(gateway_id, device.node_id), device.async_update_callback, ), ) return True class MySensorsDeviceScanner(mysensors.device.MySensorsDevice): """Represent a MySensors scanner.""" def __init__( self, hass: HomeAssistant, async_see: AsyncSeeCallback, *args: Any, ) -> None: """Set up instance.""" super().__init__(*args) self.async_see = async_see self.hass = hass async def _async_update_callback(self) -> None: """Update the device.""" await 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, )