# 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. 🚀
