BLE peer interfaces weren't being cleaned up when connections dropped
if the identity-to-address mapping wasn't available at disconnect time.
This caused orphaned interfaces to persist (peer interfaces shown with
zero active connections).
Changes:
- Add address_to_interface mapping for direct address-based cleanup
- Update _device_disconnected_callback with dual-index approach:
try identity lookup first, fall back to address_to_interface
- Update handle_central_disconnected with same dual-index approach
- Add _validate_spawned_interfaces() periodic validation (every 30s)
that cross-checks interfaces against driver.connected_peers
- Update _cleanup_stale_interface and _address_changed_callback to
maintain the new mapping
- Clear address_to_interface on detach()
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>