Commit graph

311 commits

Author SHA1 Message Date
torlando-tech
564b2be07e fix(ble): Bypass MAC sorting after MAC rotation cleanup
After detecting MAC rotation and cleaning up the stale interface,
immediately add the peer to scored_peers and continue, bypassing
the MAC sorting check. This ensures reconnection always happens
after MAC rotation regardless of which device has the higher MAC.

Bug: After MAC rotation, peer interface wasn't recreated because
the code fell through to MAC sorting check which could skip the
peer if local MAC > peer MAC.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 12:22:47 -05:00
torlando-tech
f7bb63562a Merge pull request #28 from torlando-tech/fix/hw-mtu-and-mac-rotation
Fix/hw mtu and mac rotation
2025-11-26 18:04:48 -05:00
torlando-tech
0f14264b18 Revert "feat(install): Add JustWorksRepairing and GATT cache configuration"
This reverts commit 4f9df43033.
2025-11-26 18:00:22 -05:00
torlando-tech
4f9df43033 feat(install): Add JustWorksRepairing and GATT cache configuration
- Enable JustWorksRepairing = always for automatic BLE pairing
- Disable GATT caching (Cache = no) to prevent Service Changed
  subscription pairing prompts on Android 15+ devices
- Track config changes and only restart BlueZ when needed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 17:52:52 -05:00
torlando-tech
64a4e2e43b Merge pull request #27 from torlando-tech/fix/hw-mtu-and-mac-rotation
fix(ble): Prevent data loss from peripheral reassembler race condition
2025-11-26 12:22:59 -05:00
torlando-tech
12eafcdffc fix(ble): Prevent data loss from peripheral reassembler race condition
Reorder operations in handle_peripheral_data() to create
fragmenter/reassembler BEFORE spawning peer interface. This
prevents data from being dropped during the brief window when
the interface exists but the reassembler doesn't.

Also adds unit tests to verify the fix and prevent regression.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 12:21:42 -05:00
torlando-tech
b0246e320b fix(ble): Prevent data loss from peripheral reassembler race condition
Reorder operations in handle_peripheral_data() to create
fragmenter/reassembler BEFORE spawning peer interface. This
prevents data from being dropped during the brief window when
the interface exists but the reassembler doesn't.

Also adds unit tests to verify the fix and prevent regression.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 12:21:42 -05:00
torlando-tech
4ed1f1d03a Merge pull request #26 from torlando-tech/fix/hw-mtu-and-race-conditions
Fix/hw mtu and race conditions
2025-11-25 18:29:38 -05:00
torlando-tech
2663764cf4 fix: Add MAC rotation recovery for stale interface cleanup
When a peer reconnects from a new MAC address (common with Android MAC
rotation, also possible on Linux after adapter reset), the old interface
state may become stale. This change adds:

1. _cleanup_stale_interface() method:
   - Detaches old interface
   - Cleans up identity mappings
   - Removes fragmenter/reassembler for old address
   - Clears pending MTU for old address

2. MAC rotation detection in _select_peers_to_connect():
   - If interface exists for identity but old address is not in peers
     (connection dead), clean up stale state and allow reconnection
   - If old connection still active, skip as before (no change)

This is defensive code that handles edge cases like:
- Android MAC rotation (~15 min intervals)
- Linux adapter reset while peer state is tracked
- Connection timeout without proper disconnect callback

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 18:23:43 -05:00
torlando-tech
2ff9ddc4f1 fix: HW_MTU instance attribute and MTU/identity race condition
Two critical fixes ported from Android testing:

1. HW_MTU instance attribute fix:
   - Base Interface.__init__() sets self.HW_MTU = None
   - BLEInterface.HW_MTU = 500 is a CLASS attribute, not instance
   - After super().__init__(), self.HW_MTU is None (instance shadows class)
   - BLEPeerInterface copies: self.HW_MTU = parent.HW_MTU (gets None)
   - When HW_MTU is None, Transport.py truncates packet.data incorrectly
   - Result: Link establishment fails with mismatched link_id
   - Fix: Explicitly set self.HW_MTU = BLEInterface.HW_MTU after super().__init__()

2. MTU/identity race condition fix:
   - MTU negotiation can complete before identity is received
   - Previously: Warning logged, fragmenter not created
   - Now: Store pending MTU, create fragmenter when identity arrives
   - Adds pending_mtu dict to track deferred MTU values
   - _device_connected_callback checks for pending MTU after storing identity

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 18:18:22 -05:00
torlando-tech
857c0b8145 chore: prepare v0.2.2 release
Update CHANGELOG.md with release notes for v0.2.2

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 22:45:47 -05:00
torlando-tech
05ac05d1c0 Merge pull request #14 from torlando-tech/fix/issue-13-justworksrepairing
Fix issue #13: Enable JustWorksRepairing in install.sh
2025-11-15 22:41:13 -05:00
torlando-tech
0874f8f153 Merge pull request #24 from torlando-tech/torlando-tech-patch-1
Rename 'ko-fi' to 'ko_fi' in FUNDING.yml
2025-11-15 21:25:32 -05:00
torlando-tech
9916c09251 Rename 'ko-fi' to 'ko_fi' in FUNDING.yml 2025-11-15 21:25:19 -05:00
torlando-tech
c197b483d0 Merge pull request #23 from torlando-tech/torlando-tech-patch-1
Add funding information for Ko-fi
2025-11-15 21:24:25 -05:00
torlando-tech
f7551225da Add funding information for Ko-fi 2025-11-15 21:24:09 -05:00
torlando-tech
d819008f05 Merge pull request #22 from torlando-tech/fix/remove-duplicate-deploy-workflow
fix: remove duplicate deploy workflow file
2025-11-15 21:16:34 -05:00
torlando-tech
58ef0a4bf8 fix: remove duplicate deploy workflow file
Removed .github/workflows/deploy.yaml which was a byte-for-byte duplicate
of deploy.yml. Both workflows were executing independently, causing:
- Duplicate deployments to Raspberry Pi devices
- Potential race conditions from concurrent SSH sessions
- Unnecessary resource usage

Kept deploy.yml as it uses the more standard extension in the GitHub
Actions ecosystem.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 21:14:59 -05:00
torlando-tech
c93fabb944 fix: remove duplicate deploy workflow file
Removed .github/workflows/deploy.yaml which was a byte-for-byte duplicate
of deploy.yml. Both workflows were executing independently, causing:
- Duplicate deployments to Raspberry Pi devices
- Potential race conditions from concurrent SSH sessions
- Unnecessary resource usage

Kept deploy.yml as it uses the more standard extension in the GitHub
Actions ecosystem.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 21:14:59 -05:00
torlando-tech
9514a6570a fix: enable JustWorksRepairing in install.sh to prevent pairing failures
Adds Step 5C to install.sh that automatically configures BlueZ's
JustWorksRepairing setting to "always" in /etc/bluetooth/main.conf.
This enables automatic pairing for peer-initiated BLE connections,
which is required for zero-touch mesh networking.

Changes:
- install.sh: Add Step 5C to configure JustWorksRepairing
  - Checks current setting and only modifies if needed
  - Handles both root and non-root execution
  - Restarts bluetooth service to apply changes
  - Container-friendly with non-fatal restart operations
- README.md: Document JustWorksRepairing in manual installation steps
- README.md: Add troubleshooting section for JustWorksRepairing warning

Fixes #13

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 21:06:57 -05:00
torlando-tech
3e3de053cb Merge pull request #12 from torlando-tech/fix/issue-11-pipx-dbus
docs: add pipx installation instructions and troubleshooting
2025-11-15 21:05:41 -05:00
torlando-tech
79a4c3179f Merge pull request #12 from torlando-tech/fix/issue-11-pipx-dbus
docs: add pipx installation instructions and troubleshooting
2025-11-15 21:05:41 -05:00
torlando-tech
0ead1fecb5 feat: add automated pipx support to install.sh
Enhances the installation script to automatically detect and handle
pipx installations of RNS, eliminating the need for manual dependency
injection in most cases.

Changes to install.sh:
- Add pipx detection logic that checks for RNS in pipx paths
- Verify pipx command availability and RNS listing
- Install build dependencies (build-essential, python3-dev, libdbus-dev)
  for Debian/Ubuntu and (base-devel, gobject-introspection) for Arch
- Implement automated pipx inject for all BLE dependencies
  (bleak, bluezero, dbus-python)
- Add progress messages for long-running dbus-python compilation
- Verify all dependencies after injection
- Use correct Python executable for setcap based on install mode

Changes to README.md:
- Update Option A description to mention pipx detection
- Add note to Option C that install.sh now handles pipx automatically
- Keep manual instructions for troubleshooting/fallback

Benefits:
- Consistent "one-command installation" experience for all users
- Reduces user errors from manual pipx injection
- Provides clear error messages with recovery instructions
- Maintains manual documentation as fallback

Related to #11

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:51:02 -05:00
torlando-tech
17445e97f3 feat: add automated pipx support to install.sh
Enhances the installation script to automatically detect and handle
pipx installations of RNS, eliminating the need for manual dependency
injection in most cases.

Changes to install.sh:
- Add pipx detection logic that checks for RNS in pipx paths
- Verify pipx command availability and RNS listing
- Install build dependencies (build-essential, python3-dev, libdbus-dev)
  for Debian/Ubuntu and (base-devel, gobject-introspection) for Arch
- Implement automated pipx inject for all BLE dependencies
  (bleak, bluezero, dbus-python)
- Add progress messages for long-running dbus-python compilation
- Verify all dependencies after injection
- Use correct Python executable for setcap based on install mode

Changes to README.md:
- Update Option A description to mention pipx detection
- Add note to Option C that install.sh now handles pipx automatically
- Keep manual instructions for troubleshooting/fallback

Benefits:
- Consistent "one-command installation" experience for all users
- Reduces user errors from manual pipx injection
- Provides clear error messages with recovery instructions
- Maintains manual documentation as fallback

Related to #11

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:51:02 -05:00
torlando-tech
15618df04b docs: add pipx installation instructions and troubleshooting
Fixes #11

When RNS is installed via pipx, the BLE interface cannot access
system-installed packages like python-dbus due to pipx's isolated
virtual environments. This commit adds comprehensive documentation
for pipx users.

Changes:
- Add new "Option C: pipx Installation" section with step-by-step
  instructions for installing BLE dependencies via pipx inject
- Include system dependency installation for both Arch and Debian/Ubuntu
- Document how to find and grant capabilities to pipx Python executable
- Add BlueZ experimental mode configuration steps
- Explain why pipx requires special handling
- Add troubleshooting entry for ModuleNotFoundError issues with pipx

The documented solution uses `pipx inject rns bleak==1.1.1 bluezero dbus-python`
to install BLE dependencies into the isolated RNS environment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:50:33 -05:00
torlando-tech
6b980a6a14 docs: add pipx installation instructions and troubleshooting
Fixes #11

When RNS is installed via pipx, the BLE interface cannot access
system-installed packages like python-dbus due to pipx's isolated
virtual environments. This commit adds comprehensive documentation
for pipx users.

Changes:
- Add new "Option C: pipx Installation" section with step-by-step
  instructions for installing BLE dependencies via pipx inject
- Include system dependency installation for both Arch and Debian/Ubuntu
- Document how to find and grant capabilities to pipx Python executable
- Add BlueZ experimental mode configuration steps
- Explain why pipx requires special handling
- Add troubleshooting entry for ModuleNotFoundError issues with pipx

The documented solution uses `pipx inject rns bleak==1.1.1 bluezero dbus-python`
to install BLE dependencies into the isolated RNS environment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:50:33 -05:00
torlando-tech
a8b47e465d Merge pull request #16 from torlando-tech/refactor/abstraction-layer
Refactor/abstraction layer
2025-11-15 20:40:16 -05:00
torlando-tech
09b69393a7 Merge pull request #16 from torlando-tech/refactor/abstraction-layer
Refactor/abstraction layer
2025-11-15 20:40:16 -05:00
torlando-tech
c32d23c1d4 fix(tests): Move mock_driver fixture to module level for shared access
Fixes integration test failures where TestRealWorldScenario tests
couldn't access the mock_driver fixture.

The mock_driver fixture was defined inside TestPeripheralDisconnectCleanup
class, making it unavailable to TestRealWorldScenario class. This caused
pytest fixture lookup errors:

- test_both_monitoring_mechanisms_detect_disconnect_idempotent
- test_polling_catches_missed_dbus_signal

Solution: Move mock_driver to module level (outside class) so all test
classes can access it as a shared fixture.

All integration tests now pass locally.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:26:04 -05:00
torlando-tech
adb5544bff fix(tests): Move mock_driver fixture to module level for shared access
Fixes integration test failures where TestRealWorldScenario tests
couldn't access the mock_driver fixture.

The mock_driver fixture was defined inside TestPeripheralDisconnectCleanup
class, making it unavailable to TestRealWorldScenario class. This caused
pytest fixture lookup errors:

- test_both_monitoring_mechanisms_detect_disconnect_idempotent
- test_polling_catches_missed_dbus_signal

Solution: Move mock_driver to module level (outside class) so all test
classes can access it as a shared fixture.

All integration tests now pass locally.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:26:04 -05:00
torlando-tech
71b68aba36 fix(ci): Skip BlueZ LE-only mode configuration in containers
Fixes installer failures in container environments due to missing sudo command.

The BlueZ LE-only mode configuration section was attempting to modify
/etc/bluetooth/main.conf using sudo, even in container environments where:
1. Bluetooth hardware is not available
2. sudo is often not installed (containers run as root)
3. BlueZ configuration is not applicable

Now detects container environments using is_container() and skips the
LE-only mode configuration entirely, consistent with the Bluetooth
adapter power state checks.

This prevents "sudo: command not found" errors in Debian/Ubuntu CI containers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:17:37 -05:00
torlando-tech
b336b73396 fix(ci): Skip BlueZ LE-only mode configuration in containers
Fixes installer failures in container environments due to missing sudo command.

The BlueZ LE-only mode configuration section was attempting to modify
/etc/bluetooth/main.conf using sudo, even in container environments where:
1. Bluetooth hardware is not available
2. sudo is often not installed (containers run as root)
3. BlueZ configuration is not applicable

Now detects container environments using is_container() and skips the
LE-only mode configuration entirely, consistent with the Bluetooth
adapter power state checks.

This prevents "sudo: command not found" errors in Debian/Ubuntu CI containers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:17:37 -05:00
torlando-tech
e9f20c27a8 fix(ci): Fix integration test failures and installer container detection
Fixes three CI failures identified in workflow run #19395416465:

1. **Missing threading import** (test_peripheral_disconnect_cleanup.py)
   - Added missing `import threading` to fix NameError during test setup
   - Tests use threading.RLock() but import was missing

2. **Timing race condition** (test_stale_connection_polling.py)
   - Increased sleep from 0.15s to 1.5s in test_polling_interval_30_seconds
   - Test expects 2 polling cycles at 0.6s each, was timing out in CI

3. **Container-aware Bluetooth checks** (install.sh)
   - Added is_container() helper to detect Docker/container environments
   - Skip Bluetooth adapter power checks in containers (no hardware access)
   - Prevents false failures from bluetoothctl crashes in CI environments

All changes are test/installer infrastructure only - no production code changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:05:17 -05:00
torlando-tech
c75747f535 fix(ci): Fix integration test failures and installer container detection
Fixes three CI failures identified in workflow run #19395416465:

1. **Missing threading import** (test_peripheral_disconnect_cleanup.py)
   - Added missing `import threading` to fix NameError during test setup
   - Tests use threading.RLock() but import was missing

2. **Timing race condition** (test_stale_connection_polling.py)
   - Increased sleep from 0.15s to 1.5s in test_polling_interval_30_seconds
   - Test expects 2 polling cycles at 0.6s each, was timing out in CI

3. **Container-aware Bluetooth checks** (install.sh)
   - Added is_container() helper to detect Docker/container environments
   - Skip Bluetooth adapter power checks in containers (no hardware access)
   - Prevents false failures from bluetoothctl crashes in CI environments

All changes are test/installer infrastructure only - no production code changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:05:17 -05:00
torlando-tech
3e41e66d46 Merge pull request #21 from torlando-tech/torlando-tech-patch-1
Update deploy.yaml workflow file
2025-11-15 19:55:13 -05:00
torlando-tech
44aad31c3b Merge pull request #21 from torlando-tech/torlando-tech-patch-1
Update deploy.yaml workflow file
2025-11-15 19:55:13 -05:00
torlando-tech
97d5430ec7 Update deploy.yaml workflow file 2025-11-15 19:54:55 -05:00
torlando-tech
804449ab1c Update deploy.yaml workflow file 2025-11-15 19:54:55 -05:00
torlando-tech
692bd7628e Merge pull request #20 from torlando-tech/feature/deploy
Add deployment workflow for Raspberry Pi
2025-11-15 19:50:56 -05:00
torlando-tech
e8a46486d5 Merge pull request #20 from torlando-tech/feature/deploy
Add deployment workflow for Raspberry Pi
2025-11-15 19:50:56 -05:00
torlando-tech
9797299e4c Add deployment workflow for Raspberry Pi
This workflow automates the deployment of code to multiple Raspberry Pi devices and validates the BLE interface after deployment. It includes setup, deployment, validation, and summary steps.
2025-11-15 19:50:35 -05:00
torlando-tech
29313c4104 Add deployment workflow for Raspberry Pi
This workflow automates the deployment of code to multiple Raspberry Pi devices and validates the BLE interface after deployment. It includes setup, deployment, validation, and summary steps.
2025-11-15 19:50:35 -05:00
torlando-tech
8f2b0a02b7 fix: initialize log_prefix 2025-11-15 15:52:01 -05:00
torlando-tech
b8342efe9a fix: initialize log_prefix 2025-11-15 15:52:01 -05:00
torlando-tech
3657346fb8 feat: Add service UUID filter to BLE scanner for more efficient scanning
Filter BLE scanner to only detect devices advertising the Reticulum service
UUID, reducing noise from non-Reticulum BLE devices and improving scan efficiency.

Changes:
- Pass service_uuids parameter to BleakScanner initialization
- Only detects devices with our service UUID (37145b00-442d-4a94-917f-8f42c5da28e3)
- Reduces callback invocations for irrelevant BLE devices

Benefits:
- More efficient scanning (fewer devices to process)
- Less CPU usage processing non-Reticulum devices
- Faster peer discovery

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 17:38:21 -05:00
torlando-tech
37d6a9fbec feat: Add service UUID filter to BLE scanner for more efficient scanning
Filter BLE scanner to only detect devices advertising the Reticulum service
UUID, reducing noise from non-Reticulum BLE devices and improving scan efficiency.

Changes:
- Pass service_uuids parameter to BleakScanner initialization
- Only detects devices with our service UUID (37145b00-442d-4a94-917f-8f42c5da28e3)
- Reduces callback invocations for irrelevant BLE devices

Benefits:
- More efficient scanning (fewer devices to process)
- Less CPU usage processing non-Reticulum devices
- Faster peer discovery

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 17:38:21 -05:00
torlando-tech
f759af46e7 fix: Filter out 1-byte keepalive packets from Columba Android peers
Add filtering for Android Columba's 15-second keepalive packets to prevent
unnecessary processing. Keepalive packets are 1 byte (0x00) and should be
ignored by the BLE interface.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 17:27:48 -05:00
torlando-tech
16d4cb8be9 fix: Filter out 1-byte keepalive packets from Columba Android peers
Add filtering for Android Columba's 15-second keepalive packets to prevent
unnecessary processing. Keepalive packets are 1 byte (0x00) and should be
ignored by the BLE interface.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 17:27:48 -05:00
torlando-tech
8cd54443c8 fix: Clean up identity mappings on disconnect to prevent stale connections
Fix stale connection issue where identity mappings persist after disconnect,
preventing automatic reconnection when peer returns with different MAC address.

ROOT CAUSE:
- _device_disconnected_callback() cleaned up spawned_interfaces but NOT:
  - address_to_identity mapping
  - identity_to_address mapping
- handle_central_disconnected() had same issue
- Result: Laptop thinks it's still connected after Android restarts
- Manual rnsd restart required to clear stale state

THE FIX (TDD Approach):
1. RED: Wrote 5 tests demonstrating the bug (all FAILED initially)
2. GREEN: Added identity mapping cleanup to both disconnect methods
3. GREEN: All 5 tests now PASS

Changes:
- BLEInterface.py _device_disconnected_callback():
  - Added del address_to_identity[address]
  - Added del identity_to_address[identity_hash]

- BLEInterface.py handle_central_disconnected():
  - Added del address_to_identity[address]
  - Added del identity_to_address[identity_hash]

- linux_bluetooth_driver.py:
  - Added RNS warning handler for better logging

- tests/test_identity_mapping_cleanup.py (NEW):
  - 5 tests verifying identity mapping cleanup
  - Tests both central and peripheral disconnect modes
  - Reproduces real-world stale connection scenario
  - Verifies automatic reconnection after fix

Test Results:
 All 5 tests PASS after fix
 Mappings properly cleaned up on disconnect
 Automatic reconnection enabled

Impact:
- No more manual rnsd restart needed
- Android MAC rotation handled correctly
- Stale connections automatically cleaned up
- Reconnection works without intervention

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 15:37:54 -05:00
torlando-tech
5a8c26c6ba fix: Clean up identity mappings on disconnect to prevent stale connections
Fix stale connection issue where identity mappings persist after disconnect,
preventing automatic reconnection when peer returns with different MAC address.

ROOT CAUSE:
- _device_disconnected_callback() cleaned up spawned_interfaces but NOT:
  - address_to_identity mapping
  - identity_to_address mapping
- handle_central_disconnected() had same issue
- Result: Laptop thinks it's still connected after Android restarts
- Manual rnsd restart required to clear stale state

THE FIX (TDD Approach):
1. RED: Wrote 5 tests demonstrating the bug (all FAILED initially)
2. GREEN: Added identity mapping cleanup to both disconnect methods
3. GREEN: All 5 tests now PASS

Changes:
- BLEInterface.py _device_disconnected_callback():
  - Added del address_to_identity[address]
  - Added del identity_to_address[identity_hash]

- BLEInterface.py handle_central_disconnected():
  - Added del address_to_identity[address]
  - Added del identity_to_address[identity_hash]

- linux_bluetooth_driver.py:
  - Added RNS warning handler for better logging

- tests/test_identity_mapping_cleanup.py (NEW):
  - 5 tests verifying identity mapping cleanup
  - Tests both central and peripheral disconnect modes
  - Reproduces real-world stale connection scenario
  - Verifies automatic reconnection after fix

Test Results:
 All 5 tests PASS after fix
 Mappings properly cleaned up on disconnect
 Automatic reconnection enabled

Impact:
- No more manual rnsd restart needed
- Android MAC rotation handled correctly
- Stale connections automatically cleaned up
- Reconnection works without intervention

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 15:37:54 -05:00