"""Support for ASUSWRT routers.""" from typing import Dict from homeassistant.components.device_tracker import SOURCE_TYPE_ROUTER from homeassistant.components.device_tracker.config_entry import ScannerEntity from homeassistant.config_entries import ConfigEntry from homeassistant.core import callback from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.typing import HomeAssistantType from .const import DATA_ASUSWRT, DOMAIN from .router import AsusWrtRouter DEFAULT_DEVICE_NAME = "Unknown device" async def async_setup_entry( hass: HomeAssistantType, entry: ConfigEntry, async_add_entities ) -> None: """Set up device tracker for AsusWrt component.""" router = hass.data[DOMAIN][entry.entry_id][DATA_ASUSWRT] tracked = set() @callback def update_router(): """Update the values of the router.""" add_entities(router, async_add_entities, tracked) router.async_on_close( async_dispatcher_connect(hass, router.signal_device_new, update_router) ) update_router() @callback def add_entities(router, async_add_entities, tracked): """Add new tracker entities from the router.""" new_tracked = [] for mac, device in router.devices.items(): if mac in tracked: continue new_tracked.append(AsusWrtDevice(router, device)) tracked.add(mac) if new_tracked: async_add_entities(new_tracked) class AsusWrtDevice(ScannerEntity): """Representation of a AsusWrt device.""" def __init__(self, router: AsusWrtRouter, device) -> None: """Initialize a AsusWrt device.""" self._router = router self._mac = device.mac self._name = device.name or DEFAULT_DEVICE_NAME self._active = False self._icon = None self._attrs = {} @callback def async_update_state(self) -> None: """Update the AsusWrt device.""" device = self._router.devices[self._mac] self._active = device.is_connected self._attrs = { "mac": device.mac, "ip_address": device.ip_address, } if device.last_activity: self._attrs["last_time_reachable"] = device.last_activity.isoformat( timespec="seconds" ) @property def unique_id(self) -> str: """Return a unique ID.""" return self._mac @property def name(self) -> str: """Return the name.""" return self._name @property def is_connected(self): """Return true if the device is connected to the network.""" return self._active @property def source_type(self) -> str: """Return the source type.""" return SOURCE_TYPE_ROUTER @property def icon(self) -> str: """Return the icon.""" return self._icon @property def device_state_attributes(self) -> Dict[str, any]: """Return the attributes.""" return self._attrs @property def device_info(self) -> Dict[str, any]: """Return the device information.""" return { "connections": {(CONNECTION_NETWORK_MAC, self._mac)}, "identifiers": {(DOMAIN, self.unique_id)}, "name": self.name, "manufacturer": "AsusWRT Tracked device", } @property def should_poll(self) -> bool: """No polling needed.""" return False @callback def async_on_demand_update(self): """Update state.""" self.async_update_state() self.async_write_ha_state() async def async_added_to_hass(self): """Register state update callback.""" self.async_update_state() self.async_on_remove( async_dispatcher_connect( self.hass, self._router.signal_device_update, self.async_on_demand_update, ) )