133 lines
4.0 KiB
Python
133 lines
4.0 KiB
Python
"""Support for Ruckus Unleashed devices."""
|
|
from __future__ import annotations
|
|
|
|
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 HomeAssistant, callback
|
|
from homeassistant.helpers import entity_registry
|
|
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
|
|
from homeassistant.helpers.entity import DeviceInfo
|
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|
|
|
from .const import (
|
|
API_ACCESS_POINT,
|
|
API_CLIENTS,
|
|
API_NAME,
|
|
COORDINATOR,
|
|
DOMAIN,
|
|
MANUFACTURER,
|
|
UNDO_UPDATE_LISTENERS,
|
|
)
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities
|
|
) -> None:
|
|
"""Set up device tracker for Ruckus Unleashed component."""
|
|
coordinator = hass.data[DOMAIN][entry.entry_id][COORDINATOR]
|
|
|
|
tracked = set()
|
|
|
|
@callback
|
|
def router_update():
|
|
"""Update the values of the router."""
|
|
add_new_entities(coordinator, async_add_entities, tracked)
|
|
|
|
router_update()
|
|
|
|
hass.data[DOMAIN][entry.entry_id][UNDO_UPDATE_LISTENERS].append(
|
|
coordinator.async_add_listener(router_update)
|
|
)
|
|
|
|
registry = await entity_registry.async_get_registry(hass)
|
|
restore_entities(registry, coordinator, entry, async_add_entities, tracked)
|
|
|
|
|
|
@callback
|
|
def add_new_entities(coordinator, async_add_entities, tracked):
|
|
"""Add new tracker entities from the router."""
|
|
new_tracked = []
|
|
|
|
for mac in coordinator.data[API_CLIENTS]:
|
|
if mac in tracked:
|
|
continue
|
|
|
|
device = coordinator.data[API_CLIENTS][mac]
|
|
new_tracked.append(RuckusUnleashedDevice(coordinator, mac, device[API_NAME]))
|
|
tracked.add(mac)
|
|
|
|
if new_tracked:
|
|
async_add_entities(new_tracked)
|
|
|
|
|
|
@callback
|
|
def restore_entities(registry, coordinator, entry, async_add_entities, tracked):
|
|
"""Restore clients that are not a part of active clients list."""
|
|
missing = []
|
|
|
|
for entity in registry.entities.values():
|
|
if (
|
|
entity.config_entry_id == entry.entry_id
|
|
and entity.platform == DOMAIN
|
|
and entity.unique_id not in coordinator.data[API_CLIENTS]
|
|
):
|
|
missing.append(
|
|
RuckusUnleashedDevice(
|
|
coordinator, entity.unique_id, entity.original_name
|
|
)
|
|
)
|
|
tracked.add(entity.unique_id)
|
|
|
|
if missing:
|
|
async_add_entities(missing)
|
|
|
|
|
|
class RuckusUnleashedDevice(CoordinatorEntity, ScannerEntity):
|
|
"""Representation of a Ruckus Unleashed client."""
|
|
|
|
def __init__(self, coordinator, mac, name) -> None:
|
|
"""Initialize a Ruckus Unleashed client."""
|
|
super().__init__(coordinator)
|
|
self._mac = mac
|
|
self._name = name
|
|
|
|
@property
|
|
def unique_id(self) -> str:
|
|
"""Return a unique ID."""
|
|
return self._mac
|
|
|
|
@property
|
|
def name(self) -> str:
|
|
"""Return the name."""
|
|
if self.is_connected:
|
|
return (
|
|
self.coordinator.data[API_CLIENTS][self._mac][API_NAME]
|
|
or f"{MANUFACTURER} {self._mac}"
|
|
)
|
|
return self._name
|
|
|
|
@property
|
|
def is_connected(self) -> bool:
|
|
"""Return true if the device is connected to the network."""
|
|
return self._mac in self.coordinator.data[API_CLIENTS]
|
|
|
|
@property
|
|
def source_type(self) -> str:
|
|
"""Return the source type."""
|
|
return SOURCE_TYPE_ROUTER
|
|
|
|
@property
|
|
def device_info(self) -> DeviceInfo | None:
|
|
"""Return the device information."""
|
|
if self.is_connected:
|
|
return {
|
|
"name": self.name,
|
|
"connections": {(CONNECTION_NETWORK_MAC, self._mac)},
|
|
"via_device": (
|
|
CONNECTION_NETWORK_MAC,
|
|
self.coordinator.data[API_CLIENTS][self._mac][API_ACCESS_POINT],
|
|
),
|
|
}
|
|
return None
|