Commit graph

1 commit

Author SHA1 Message Date
torlando-tech
e97e550b4e fix(ble): Add peripheral disconnect cleanup to prevent peer limit blocking
Fixes a critical bug where Android devices (acting as BLE centrals) disconnecting
from Pi GATT servers (acting as peripherals) never triggered cleanup, causing stale
peer entries to accumulate until the 7-peer limit was reached and blocked all new
connections.

## Root Cause
- When centrals disconnected from peripheral mode, no cleanup occurred
- `BLEGATTServer._handle_central_disconnected()` method didn't exist
- `on_central_disconnected` callback was never wired to driver
- No D-Bus signal monitoring for device disconnections
- Stale entries remained in `_peers` dict until daemon restart

## Implementation (TDD Approach)

**New Methods:**
- `LinuxBluetoothDriver._handle_peripheral_disconnected()` (line 852)
  - Removes peer from `_peers` dictionary
  - Notifies on_device_disconnected callback
  - Triggers full cleanup chain in BLEInterface

- `BluezeroGATTServer._handle_central_disconnected()` (line 1945)
  - Removes from `connected_centrals` dictionary
  - Logs connection duration
  - Invokes driver callback

- `BluezeroGATTServer._monitor_device_disconnections()` (line 1645)
  - Monitors D-Bus PropertiesChanged signals
  - Detects when Connected property becomes False
  - Runs in separate daemon thread
  - Automatically triggers cleanup on disconnect

**Callback Wiring:** (line 1558)
`on_central_disconnected = driver._handle_peripheral_disconnected`

## Testing
- Created comprehensive test suite (9 tests, all passing)
- `tests/test_peripheral_disconnect_cleanup.py`:
  - Callback wiring verification
  - Peer dictionary cleanup
  - D-Bus signal handling simulation
  - Edge cases (multiple disconnects, race conditions, shutdown)
  - Reproduces real-world bug from production logs
- No regressions in existing tests (test_bluez_state_cleanup.py passes)

## Current Status
 Core cleanup logic implemented and tested
 Deployed to 4 production devices (10.0.0.80, .242, .39, .246)
⚠️  D-Bus monitoring thread needs debugging (not logging yet)

**Known Issue:** D-Bus signal subscription may need alternative approach.
See PERIPHERAL_DISCONNECT_FIX_SUMMARY.md for troubleshooting steps.

**Fallback Option:** Timeout-based polling can be implemented if D-Bus proves difficult.

Reference: Production logs showed device 4A:87:8C:C7:E3:F3 repeatedly blocked
by "max peers (7) reached" due to uncleaned peripheral disconnections.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-12 19:37:12 -05:00