Files
pi-pm3/BLE_GATT_GUIDE.md
michael 4f35df1781 Initial commit - Phase 3/4
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 13:46:22 -08:00

425 lines
12 KiB
Markdown

# Dangerous Pi - BLE GATT Server Guide
**Status**: ✅ Implemented - Ready for Integration
**Architecture**: Service Layer Pattern - Zero Code Duplication
---
## 🎯 Overview
The Dangerous Pi BLE GATT server provides Bluetooth Low Energy access to all Dangerous Pi functionality by **reusing the exact same service layer** as the REST API. This ensures:
**Zero code duplication** - Business logic written once
**Identical behavior** - BLE and REST behave exactly the same
**Easy testing** - Service tests cover both interfaces
**Consistent errors** - Same error codes and handling
---
## 🏗️ Architecture
```
┌─────────────────────────────────────────┐
│ Mobile App (React Native / Flutter) │
└──────────────┬──────────────────────────┘
│ BLE GATT Protocol
┌─────────────────────────────────────────┐
│ BLE GATT Server (gatt_server.py) │
│ - Characteristic handlers │
│ - JSON encoding/decoding │
│ - Notification management │
│ - THIN ADAPTERS only │
└──────────────┬──────────────────────────┘
│ Delegates to
┌─────────────────────────────────────────┐
│ Service Layer (SHARED with REST!) │
│ - PM3Service │
│ - WiFiService │
│ - SystemService │
│ - UpdateService │
└──────────────┬──────────────────────────┘
┌─────────────────────────────────────────┐
│ Managers/Workers │
│ - PM3Worker, WiFiManager, etc. │
└─────────────────────────────────────────┘
```
**Key Point**: BLE handlers and REST endpoints are BOTH thin adapters. They share 100% of business logic through the service layer.
---
## 📡 GATT Services & Characteristics
### PM3 Service
**Service UUID**: `00000000-1234-5678-1234-56789abcdef0`
| Characteristic | UUID | Properties | Description |
|---------------|------|------------|-------------|
| Command Write | ...def1 | Write | Execute PM3 command |
| Command Result | ...def2 | Notify | Command execution result |
| Status | ...def3 | Read | Get PM3 status |
| Session Create | ...def4 | Write | Create new session |
| Session Release | ...def5 | Write | Release session |
| Session Info | ...def6 | Read | Get session information |
### WiFi Service
**Service UUID**: `00000000-1234-5678-1234-56789abcdef10`
| Characteristic | UUID | Properties | Description |
|---------------|------|------------|-------------|
| Status | ...def11 | Read | Get WiFi status |
| Scan | ...def12 | Write, Notify | Scan for networks |
| Connect | ...def13 | Write | Connect to network |
| Disconnect | ...def14 | Write | Disconnect from network |
| Mode | ...def15 | Read, Write | Get/Set WiFi mode |
| Saved Networks | ...def16 | Read | List saved networks |
| Forget Network | ...def17 | Write | Forget saved network |
### System Service
**Service UUID**: `00000000-1234-5678-1234-56789abcdef20`
| Characteristic | UUID | Properties | Description |
|---------------|------|------------|-------------|
| Info | ...def21 | Read | Get system information |
| Shutdown | ...def22 | Write | Initiate shutdown |
| Restart | ...def23 | Write | Initiate restart |
| Logs | ...def24 | Read | Get service logs |
### Update Service
**Service UUID**: `00000000-1234-5678-1234-56789abcdef30`
| Characteristic | UUID | Properties | Description |
|---------------|------|------------|-------------|
| Check | ...def31 | Write, Notify | Check for updates |
| Download | ...def32 | Write | Download update |
| Install | ...def33 | Write | Install update |
| Progress | ...def34 | Read, Notify | Update progress |
| Release Notes | ...def35 | Read | Get release notes |
---
## 📱 Client Integration Examples
### PM3 Command Execution
```javascript
// React Native / JavaScript example
// 1. Connect to Dangerous Pi
const device = await manager.connectToDevice(deviceId);
await device.discoverAllServicesAndCharacteristics();
// 2. Create session
const sessionChar = "00000000-1234-5678-1234-56789abcdef4";
const sessionRequest = JSON.stringify({ force_takeover: false });
await device.writeCharacteristicWithResponseForService(
PM3_SERVICE_UUID,
sessionChar,
base64.encode(sessionRequest)
);
// 3. Execute PM3 command
const commandChar = "00000000-1234-5678-1234-56789abcdef1";
const command = JSON.stringify({
command: "hw version",
session_id: receivedSessionId
});
await device.writeCharacteristicWithResponseForService(
PM3_SERVICE_UUID,
commandChar,
base64.encode(command)
);
// 4. Listen for result notification
const resultChar = "00000000-1234-5678-1234-56789abcdef2";
device.monitorCharacteristicForService(
PM3_SERVICE_UUID,
resultChar,
(error, characteristic) => {
if (characteristic) {
const result = JSON.parse(base64.decode(characteristic.value));
console.log("Command result:", result.output);
}
}
);
```
### WiFi Network Scan
```javascript
// 1. Trigger scan
const scanChar = "00000000-1234-5678-1234-56789abcdef12";
// Listen for scan results first
device.monitorCharacteristicForService(
WIFI_SERVICE_UUID,
scanChar,
(error, characteristic) => {
if (characteristic) {
const result = JSON.parse(base64.decode(characteristic.value));
console.log("Found networks:", result.networks);
// Display networks in UI
}
}
);
// Trigger scan (empty JSON or specify interface)
await device.writeCharacteristicWithResponseForService(
WIFI_SERVICE_UUID,
scanChar,
base64.encode(JSON.stringify({}))
);
```
### WiFi Connect
```javascript
const connectChar = "00000000-1234-5678-1234-56789abcdef13";
const connectRequest = JSON.stringify({
ssid: "MyNetwork",
password: "mypassword",
hidden: false
});
await device.writeCharacteristicWithResponseForService(
WIFI_SERVICE_UUID,
connectChar,
base64.encode(connectRequest)
);
```
### System Information
```javascript
const infoChar = "00000000-1234-5678-1234-56789abcdef21";
const infoBytes = await device.readCharacteristicForService(
SYSTEM_SERVICE_UUID,
infoChar
);
const info = JSON.parse(base64.decode(infoBytes.value));
console.log("CPU:", info.cpu.percent + "%");
console.log("Memory:", info.memory.percent + "%");
console.log("Temperature:", info.cpu.temperature + "°C");
```
---
## 🔄 Data Formats
All BLE characteristics use **JSON** for data exchange (encoded as UTF-8 bytes).
### Request Format (Write Characteristics)
```json
{
"param1": "value1",
"param2": "value2"
}
```
### Response Format (Read/Notify Characteristics)
**Success Response:**
```json
{
"success": true,
"data": {
"key": "value"
}
}
```
**Error Response:**
```json
{
"success": false,
"error": {
"code": "error_code",
"message": "Human-readable message"
}
}
```
### Error Codes
Same error codes as REST API:
- `session_locked` - Another session is active
- `pm3_not_connected` - Proxmark3 not connected
- `command_failed` - PM3 command failed
- `connection_failed` - WiFi connection failed
- `invalid_mode` - Invalid WiFi mode
- `network_not_found` - Network not in saved list
- `update_check_error` - Failed to check for updates
- etc.
---
## 🧪 Testing
### Unit Tests
The GATT server has comprehensive unit tests:
```bash
# Run BLE GATT tests
pytest tests/unit/ble/test_gatt_server.py
# Test coverage
pytest tests/unit/ble/ --cov=app/backend/ble
```
**Test Coverage:**
- ✅ Characteristic handler registration
- ✅ Delegation to services (PM3, WiFi, System, Update)
- ✅ JSON encoding/decoding
- ✅ Error handling
- ✅ Notification system
- ✅ Data format conversion
### Integration Testing with Mobile App
```python
# Python example using bleak library
import asyncio
import json
from bleak import BleakClient
async def test_pm3_command():
async with BleakClient("AA:BB:CC:DD:EE:FF") as client:
# Write command
command_char = "00000000-1234-5678-1234-56789abcdef1"
command_data = json.dumps({
"command": "hw version",
"session_id": "test"
})
await client.write_gatt_char(
command_char,
command_data.encode('utf-8')
)
# Read status
status_char = "00000000-1234-5678-1234-56789abcdef3"
status_bytes = await client.read_gatt_char(status_char)
status = json.loads(status_bytes.decode('utf-8'))
print("PM3 Status:", status)
asyncio.run(test_pm3_command())
```
---
## 🔐 Security Considerations
### Authentication
- BLE pairing should be required for sensitive operations
- Consider implementing challenge-response authentication
- Session IDs provide multi-user coordination
### Encryption
- Use BLE encryption (LE Secure Connections)
- All data is already JSON, easy to add encryption layer
- Consider end-to-end encryption for sensitive commands
### Access Control
- Session management prevents concurrent access conflicts
- Can implement per-characteristic permissions
- Rate limiting for command execution
---
## 🚀 Integration with BLEManager
The GATT server integrates with the existing BLEManager:
```python
# In app/backend/managers/ble_manager.py
from ..ble.gatt_server import DangerousPiGATTServer
class BLEManager:
def __init__(self):
# Existing notification support
self._notification_queue = asyncio.Queue()
# NEW: GATT server
self._gatt_server = None
async def initialize(self):
"""Initialize BLE with GATT server."""
# Existing notification setup
await self._setup_notifications()
# NEW: Initialize and start GATT server
self._gatt_server = DangerousPiGATTServer()
await self._gatt_server.start()
# Register notification callbacks with actual BLE implementation
# (BlueZ, etc.)
self._register_gatt_characteristics()
def _register_gatt_characteristics(self):
"""Register GATT characteristics with BLE stack."""
for uuid, handler in self._gatt_server.get_all_characteristics().items():
# Register with BlueZ or other BLE implementation
# Set up read/write callbacks
# Connect to GATT server handlers
pass
```
---
## 📊 Benefits Summary
### Code Reuse
| Component | REST API | BLE GATT | Shared |
|-----------|----------|----------|--------|
| Business Logic | ❌ | ❌ | ✅ Service Layer |
| Session Management | ❌ | ❌ | ✅ Service Layer |
| Error Handling | ❌ | ❌ | ✅ Service Layer |
| PM3 Commands | ❌ | ❌ | ✅ Service Layer |
| WiFi Operations | ❌ | ❌ | ✅ Service Layer |
| **Code Duplication** | **0%** | **0%** | **100% Shared** |
### Maintenance
- Fix bugs **once** in service layer
- Add features **once** in service layer
- Test **once** with service tests
- Both REST and BLE get the fix/feature automatically
### Consistency
- REST and BLE **guaranteed** identical behavior
- Same error codes and messages
- Same data validation
- Same session management
---
## 🎯 Next Steps
1. **Complete BlueZ Integration** - Connect GATT server to BlueZ D-Bus
2. **Mobile App Development** - Build React Native / Flutter app
3. **Security Hardening** - Implement BLE pairing and encryption
4. **Performance Testing** - Test with real Proxmark3 hardware
5. **Documentation** - Mobile app integration guide
---
## 📚 References
- [BLE GATT Specification](https://www.bluetooth.com/specifications/specs/core-specification/)
- [React Native BLE library](https://github.com/dotintent/react-native-ble-plx)
- [Flutter Blue Plus](https://pub.dev/packages/flutter_blue_plus)
- [Python Bleak](https://github.com/hbldh/bleak)
- [BlueZ D-Bus API](http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt)
---
**Summary**: The BLE GATT server is a perfect demonstration of the service layer pattern. Every handler is a thin adapter that delegates to services, achieving **zero code duplication** and **guaranteed consistency** with the REST API. 🚀