Files
meshcore-gui/docs/INTEGRATION_GUIDE.md
2026-03-09 17:53:29 +01:00

109 lines
4.9 KiB
Markdown

# v5.5 Integration Guide — Subprocess BLE Connection
## Overzicht
Deze wijziging lost het BlueZ 5.82 probleem op door `meshcore-ble-connect`
als **persistent subprocess** te draaien dat de D-Bus/BLE connectie openhoudt,
terwijl `BleakClient` er alleen GATT service discovery overheen doet.
---
## Gewijzigde bestanden
### meshcore-ble-connect (5 bestanden)
| Bestand | Wijziging |
|---|---|
| `constants.py` | Versie → 1.1.0. Nieuwe constanten: `SERVICES_RESOLVED_TIMEOUT`, `DISCONNECT_POLL_INTERVAL`. Nieuwe exit codes: `CONNECT_FAILED` (5), `DISCONNECTED` (6). |
| `exceptions.py` | Nieuwe exception: `ConnectHoldError`. |
| `__main__.py` | Nieuw `--connect` flag. Mutual exclusion met `--check-only`. Doorgifte `connect_hold=` aan `BleConnectApp`. |
| `app.py` | Nieuw `connect_hold` parameter. Na bond OK → `_enter_connect_hold()``device.connect_and_hold()`. Werkt bij zowel bestaande bond als verse pairing. |
| `device.py` | Nieuwe methoden: `connect_and_hold()`, `is_connected()`, `is_services_resolved()`, `_wait_for_services_resolved()`, `_monitor_connection()`. Signal handling (SIGTERM/SIGINT) voor clean shutdown. |
### meshcore-gui (1 bestand)
| Bestand | Wijziging |
|---|---|
| `worker.py` | Nieuwe methoden: `_connect_via_subprocess()`, `_kill_connect_subprocess()`. Gewijzigd: `_connect()` gebruikt subprocess als primary path wanneer `_use_ble_connect=True`. Subprocess health check in main loop. Cleanup in finally block. |
---
## Architectuur
```
┌─────────────────────────────────────────────┐
│ meshcore-gui (worker.py) │
│ │
│ 1. ensure_bond() → bond OK │
│ 2. start subprocess: │
│ meshcore-ble-connect MAC --pin X │
│ --connect │
│ 3. wait for "READY" op stdout │
│ 4. BleakScanner.find_device_by_address() │
│ → populeert bleak's interne cache │
│ 5. BleakClient(addr).connect() │
│ → bleak ziet Connected=True in BlueZ │
│ → slaat Device1.Connect() over │
│ → doet alleen GATT service discovery │
│ 6. MeshCore.create_ble(client=client) │
│ 7. Main loop draait │
│ 8. subprocess health check elke 100ms │
└──────────────┬──────────────────────────────┘
│ subprocess (stdout PIPE)
┌──────────────▼──────────────────────────────┐
│ meshcore-ble-connect --connect │
│ │
│ 1. Bond flow (ensure/pair/trust) │
│ 2. Device1.Connect() via D-Bus │
│ 3. Poll ServicesResolved tot True │
│ 4. print("READY") → stdout │
│ 5. Monitor Connected property │
│ → print("DISCONNECTED") bij verlies │
│ 6. Wacht op SIGTERM of disconnect │
│ 7. Device1.Disconnect() bij shutdown │
└─────────────────────────────────────────────┘
```
## Installatie
```bash
# 1. Update meshcore-ble-connect
cd ~/meshcore-ble-connect
# Vervang de 5 gewijzigde bestanden in meshcore_ble_connect/
pip install -e . --break-system-packages
# 2. Test --connect mode standalone
meshcore-ble-connect FF:05:D6:71:83:8D --pin 123456 --connect --verbose
# Verwacht: READY op stdout, proces blijft draaien
# Ctrl+C om te stoppen
# 3. Update worker.py
cp worker.py ~/meshcore-gui/meshcore_gui/ble/worker.py
# 4. Start meshcore-gui
cd ~/meshcore-gui && python -m meshcore_gui
```
## Fallback gedrag
Als het subprocess faalt (bijv. op BlueZ < 5.78 waar het niet nodig is),
valt `_connect()` automatisch terug op de directe `MeshCore.create_ble(address)`
aanroep. Dit garandeert backwards compatibility.
## Risico-mitigatie
Het document noemde het risico dat bleak mogelijk opnieuw `Device1.Connect()`
aanroept. Dit is opgelost door:
1. **`BleakScanner.find_device_by_address()`** vóór `BleakClient.connect()`
dit triggert bleak's `BlueZManager` singleton om bestaande BlueZ device
objecten te ontdekken via `GetManagedObjects()`.
2. De manager ziet `Connected=True` op het device (gezet door het subprocess)
`BleakClient.connect()` slaat `Device1.Connect()` over.
3. Bleak doet alleen GATT service resolution over de bestaande connectie.
Als de scanner het device niet vindt (het adverteert mogelijk niet terwijl
het connected is), probeert bleak alsnog. De `GetManagedObjects` call bij
manager initialisatie vangt dit op in de meeste gevallen.