Track all connected clients, discover new devices live, and handle randomized MACs (#139) - #146
Open
shauneccles wants to merge 5 commits into
Open
Track all connected clients, discover new devices live, and handle randomized MACs (#139)#146shauneccles wants to merge 5 commits into
shauneccles wants to merge 5 commits into
Conversation
update_device_trackers() skipped any client that had neither a name nor an alias. Many IoT devices (bulbs, sensors) and some phones report blank names, so most of the network was silently untracked. Track every connected client instead; ClientDevInfo.update() already falls back to a MAC-derived name for unnamed devices. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sG#139) Two device-tracker fixes: 1. New devices appeared only after a reload. update_device_trackers() fires signal_device_new when it discovers a previously unseen client, but async_setup_entry called update_router() once at setup and never subscribed to that signal. Connect update_router() to signal_device_new (via entry.async_on_unload) so new devices get entities on the 30s poll. 2. hostname/ip_address/mac_address were cached_property values snapshotted in __init__, so a device's reported IP stayed frozen at entity-creation time. Read them (and the name) live from the underlying ClientDevInfo, which async_on_demand_update refreshes each poll. Also set should_poll=False, since updates are pushed via the dispatcher (the old value of True contradicted its own "No polling needed" docstring). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Log how many clients connected_clients returns (and their MACs), and each newly discovered tracked device. This makes "missing devices" reports (e.g. issue HarvsG#139) diagnosable from a debug log without external probing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
router.setup() registered a SCAN_INTERVAL poller via async_track_time_interval but never stored its unsub, so each config-entry reload leaked another timer that kept polling the router forever (observed as multiple concurrent pollers after a few reloads). Register the unsub with entry.async_on_unload so it is cancelled on unload/reload. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Removing the name filter means every connected client is tracked, including phones that use MAC randomization. Those present a fresh address on each (re)connection, so without handling they pile up as stale trackers. - Detect locally-administered (randomized) MACs from the address itself (is_randomized_mac in utils.py); HA core provides no helper for this. - Expose a `mac_randomized` attribute on every tracker. - Add a `track_randomized_mac` option (options flow): "enabled" tracks them with the entity enabled by default, "disabled" registers them disabled by default (the default), "ignore" skips creating the entity entirely. - entity_registry_enabled_default composes with HA's ScannerEntity heuristic: randomized MACs honour the option; every other client defers to core, which enables a tracker only when its MAC maps to a known device. - Register the previously-unwired options update listener so option changes reload the entry and take effect. Covered by unit tests for is_randomized_mac. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 21, 2026
Open
8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #139.
On the released integration most connected clients never appear as device trackers. This makes the integration track every connected client, create entities for new devices live, and adds first-class handling for MAC-randomized clients.
What's in it (per commit)
update_device_trackers()skipped any client with no name and no alias, so unnamed IoT devices (bulbs, sensors) and some phones were dropped. Track them all;ClientDevInfo.update()already falls back to a MAC-derived name.signal_device_new, so devices that join after setup get a tracker on the next 30 s poll instead of only on a reload. Also readshostname/ip/maclive (they were cached at creation and went stale) and setsshould_poll=False(state is dispatcher-pushed).connected_clientsreturns and each newly discovered device, so "missing devices" reports are diagnosable from a debug log.setup()never stored theasync_track_time_intervalunsub, so every reload leaked another poller. Registered viaentry.async_on_unload.mac_randomizedattribute, and add atrack_randomized_macoption (enabled/disabled/ignore).entity_registry_enabled_defaultcomposes with HA'sScannerEntityheuristic — defer to core for normal clients, honour the option for randomized ones.Note for Wi-Fi 7 routers
This PR deliberately leaves interface-type resolution unchanged, so on Wi-Fi 7 routers (e.g. BE9300) it still relies on the setup-crash fix in #145. I left that out to avoid overlapping with #145 — see my comment there for a complementary
iface-string idea.Testing
Validated live against a GL-iNet MT6000 (firmware 4.x): all connected clients tracked with correct interface labels; a phone joining the network produced a tracker within the poll interval without a reload; the
ignoreoption confirmed to keep a randomized MAC out of the registry entirely. Unit tests cover the randomized-MAC detection.🤖 Generated with Claude Code