1 """Support for device tracking of Huawei LTE routers."""
3 from __future__
import annotations
7 from typing
import Any, cast
9 from stringcase
import snakecase
12 DOMAIN
as DEVICE_TRACKER_DOMAIN,
24 CONF_TRACK_WIRED_CLIENTS,
25 DEFAULT_TRACK_WIRED_CLIENTS,
31 from .entity
import HuaweiLteBaseEntity
33 _LOGGER = logging.getLogger(__name__)
35 _DEVICE_SCAN = f
"{DEVICE_TRACKER_DOMAIN}/device_scan"
37 type _HostType = dict[str, Any]
41 router: Router, ignore_subscriptions: bool =
False
42 ) -> list[_HostType] |
None:
43 for key
in KEY_LAN_HOST_INFO, KEY_WLAN_HOST_LIST:
44 if not ignore_subscriptions
and key
not in router.subscriptions:
47 return cast(list[_HostType], router.data[key][
"Hosts"][
"Host"])
49 _LOGGER.debug(
"%s[%s][%s] not in data", key,
"Hosts",
"Host")
55 config_entry: ConfigEntry,
56 async_add_entities: AddEntitiesCallback,
58 """Set up from config entry."""
63 router = hass.data[DOMAIN].routers[config_entry.entry_id]
64 if (hosts :=
_get_hosts(router,
True))
is None:
68 tracked: set[str] = set()
69 registry = er.async_get(hass)
70 known_entities: list[Entity] = []
71 track_wired_clients = router.config_entry.options.get(
72 CONF_TRACK_WIRED_CLIENTS, DEFAULT_TRACK_WIRED_CLIENTS
74 for entity
in registry.entities.get_entries_for_config_entry_id(
77 if entity.domain == DEVICE_TRACKER_DOMAIN:
78 mac = entity.unique_id.partition(
"-")[2]
81 if not track_wired_clients:
83 if host.get(
"MacAddress") == mac:
87 tracked.add(entity.unique_id)
92 router.subscriptions[KEY_LAN_HOST_INFO].append(_DEVICE_SCAN)
93 router.subscriptions[KEY_WLAN_HOST_LIST].append(_DEVICE_SCAN)
95 async
def _async_maybe_add_new_entities(unique_id: str) ->
None:
96 """Add new entities if the update signal comes from our router."""
97 if config_entry.unique_id == unique_id:
102 hass, UPDATE_SIGNAL, _async_maybe_add_new_entities
104 config_entry.async_on_unload(disconnect_dispatcher)
113 return cast(str, host.get(
"InterfaceType",
"Wireless")) !=
"Ethernet"
119 return False if host
is None else cast(str, host.get(
"Active",
"1")) !=
"0"
123 """Try to determine if the host entry is us, the HA instance."""
125 return cast(str, host.get(
"isLocalDevice",
"0")) ==
"1"
131 async_add_entities: AddEntitiesCallback,
134 """Add new entities that are not already being tracked."""
138 track_wired_clients = router.config_entry.options.get(
139 CONF_TRACK_WIRED_CLIENTS, DEFAULT_TRACK_WIRED_CLIENTS
142 new_entities: list[Entity] = []
148 and x.get(
"MacAddress")
152 if entity.unique_id
in tracked:
154 tracked.add(entity.unique_id)
155 new_entities.append(entity)
161 if text == text.upper():
168 r"([A-Z])([A-Z]+)([A-Z](?:[^A-Z]|$))",
169 lambda match: f
"{match.group(1)}{match.group(2).lower()}{match.group(3)}",
172 return cast(str, snakecase(text))
176 """Huawei LTE router scanner entity."""
178 _ip_address: str |
None =
None
179 _is_connected: bool =
False
180 _hostname: str |
None =
None
182 def __init__(self, router: Router, mac_address: str) ->
None:
190 """Return the name of the entity."""
199 """Return the primary ip address of the device."""
204 """Return the mac address of the device."""
209 """Return hostname of the device."""
214 """Get whether the entity is connected."""
219 """Get additional attributes related to entity state."""
229 (x
for x
in hosts
if x.get(
"MacAddress") == self.
_mac_address_mac_address),
None
235 self.
_ip_address_ip_address = (host.get(
"IpAddress")
or "").split(
";", 2)[0]
or None
239 for k, v
in host.items()
None __init__(self, Router router, str mac_address)
dict[str, Any] extra_state_attributes(self)
str|None ip_address(self)
str _device_unique_id(self)
bool _is_wireless(_HostType host)
str _better_snakecase(str text)
None async_add_new_entities(Router router, AddEntitiesCallback async_add_entities, set[str] tracked)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
bool _is_connected(_HostType|None host)
list[_HostType]|None _get_hosts(Router router, bool ignore_subscriptions=False)
bool _is_us(_HostType host)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)