feat: Add connection handshake to trigger peripheral callbacks

Sends empty WRITE to RX characteristic immediately after connection
to guarantee remote side's on_central_connected callback fires.

Problem: Peripheral callback triggered by WRITE events, not connections.
When central connects and only READs (Identity characteristic), the
peripheral's on_central_connected never fires, preventing peer interface
spawning on the peripheral side.

Solution: After reading Identity, write empty bytes to RX characteristic.
This triggers the WRITE callback which calls _handle_central_connected(),
ensuring bidirectional peer interface spawning.

Benefits:
- Works for Pi-to-Pi (ensures both sides spawn interfaces)
- Works for Android-to-Pi (Pi spawns interface when Android connects)
- Minimal overhead (single empty GATT write)
- Backwards compatible (empty write is harmless)

Implementation:
- Added after Identity read in _connect_to_peer()
- Uses write_gatt_char() with response=True for reliability
- Non-critical failure (logged as warning, doesn't block connection)
- TODO comment for future handshake protocol enhancements

This solves the asymmetric peer spawning issue seen in testing where
only the central side had a peer interface.

Tested: Enables bidirectional data flow for single-direction discoveries.
This commit is contained in:
torlando-tech 2025-10-31 17:43:10 -04:00
commit e473a00e91

View file

@ -1445,6 +1445,16 @@ class BLEInterface(Interface):
RNS.log(f"{self} failed to read identity from {peer.name}: {type(e).__name__}: {e}", RNS.LOG_DEBUG)
# Continue without identity
# Send connection handshake to trigger peripheral callback
# Write empty bytes to RX characteristic to ensure remote's on_central_connected fires
# This guarantees bidirectional peer interface spawning even when only one side discovers
# TODO: Consider sending handshake packet with protocol version/capabilities/flags
try:
await client.write_gatt_char(self.CHARACTERISTIC_RX_UUID, b'', response=True)
RNS.log(f"{self} sent connection handshake to {peer.name}", RNS.LOG_DEBUG)
except Exception as e:
RNS.log(f"{self} handshake write failed (non-critical): {e}", RNS.LOG_WARNING)
# Get negotiated MTU
try:
# For BlueZ backend, acquire MTU first to avoid warning