🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
425 lines
12 KiB
Markdown
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. 🚀
|