- Architecture overview, BLE and WebSocket protocols - All 19 modules with command IDs validated against smali source - BLE packet format with CRC-16/MODBUS pseudocode - Complete WsCmd index (~300 commands) - Connection flow with pseudocode examples - Methodology section explaining APK decompilation process
145 lines
5.6 KiB
Markdown
145 lines
5.6 KiB
Markdown
# BLE Protocol
|
|
|
|
## GATT Architecture
|
|
|
|
The device exposes a single BLE service with multiple characteristics:
|
|
|
|
| UUID | Type | Role |
|
|
|------|------|------|
|
|
| `0000180A-0000-1000-8000-00805F9B34FB` | Service | Device Information (standard) |
|
|
| `0000DAF2-0000-1000-8000-00805f9b34fb` | Service | **DWARF Primary Service** |
|
|
| `0000DAF3-0000-1000-8000-00805f9b34fb` | Characteristic | **Write** — Send protobuf requests |
|
|
| `0000DAF4-0000-1000-8000-00805F9B34FB` | Characteristic | **Notify** — Receive protobuf responses |
|
|
| `0000DAF5-0000-1000-8000-00805F9B34FB` | Characteristic | **Write** — STA mode configuration |
|
|
| `0000DAF6-0000-1000-8000-00805F9B34FB` | Characteristic | **Notify** — STA mode responses |
|
|
| `0000DAF7-0000-1000-8000-00805F9B34FB` | Characteristic | **Write** — AP mode configuration |
|
|
| `00009999-0000-1000-8000-00805F9B34FB` | Characteristic | **Notify** — AP mode responses |
|
|
|
|
> **Note**: UUIDs DAF2/DAF3 use lowercase `00805f9b34fb` while DAF4-DAF7/9999 use uppercase `00805F9B34FB`. This is as-is in the source code (`cg1.smali`).
|
|
|
|
## BLE Packet Format (BluetoothPacket)
|
|
|
|
All BLE data is framed in a custom packet format before being sent over GATT characteristics.
|
|
|
|
### Binary Layout
|
|
|
|
```
|
|
Offset Size Field Description
|
|
------ ---- ----------------- -------------------------------------------
|
|
0 1 magic 0xAA (constant)
|
|
1 1 protocolVersion Protocol version (typically 1)
|
|
2 1 cmdInstruction Command type (0-7, see below)
|
|
3 1 packageSequence Current packet sequence number (0-based)
|
|
4 1 totalPackages Total number of packets for this message
|
|
5 2 extendedProtocol Extended protocol field (big-endian, usually 0)
|
|
7 2 validDataLength Length of protobuf payload (big-endian)
|
|
9 N dataPayload Protobuf-encoded BleProto message
|
|
9+N 2 crc CRC-16/MODBUS (poly=0x8005, init=0xFFFF, reflected, XOR=0x0000)
|
|
11+N 1 endMarker 0x0D (constant)
|
|
|
|
Total packet size = validDataLength + 12
|
|
```
|
|
|
|
### Pseudocode: Building a BLE Packet
|
|
|
|
```python
|
|
import struct
|
|
|
|
def build_ble_packet(cmd: int, protobuf_data: bytes, seq: int = 0, total: int = 1) -> bytes:
|
|
"""Build a BLE packet from protobuf data."""
|
|
header = struct.pack('>BBBH', # big-endian: B=cmd, B=seq, B=total, H=extended
|
|
0xAA, # magic byte
|
|
1, # protocolVersion
|
|
cmd, # cmdInstruction
|
|
seq, # packageSequence
|
|
total, # totalPackages
|
|
0 # extendedProtocol (reserved)
|
|
)
|
|
# validDataLength
|
|
length_bytes = struct.pack('>H', len(protobuf_data))
|
|
# CRC over header + length + data
|
|
crc_input = header + length_bytes + protobuf_data
|
|
crc = crc16_modbus(crc_input)
|
|
crc_bytes = struct.pack('>H', crc)
|
|
# Assemble: header(7B) + length(2B) + data(NB) + crc(2B) + end(1B)
|
|
return header + length_bytes + protobuf_data + crc_bytes + b'\x0D'
|
|
```
|
|
|
|
### Pseudocode: CRC-16/MODBUS
|
|
|
|
```python
|
|
def crc16_modbus(data: bytes) -> int:
|
|
"""CRC-16/MODBUS: poly=0x8005, init=0xFFFF, reflected=True, XOR_out=0x0000"""
|
|
crc = 0xFFFF
|
|
for byte in data:
|
|
crc ^= byte
|
|
for _ in range(8):
|
|
if crc & 0x0001:
|
|
crc = (crc >> 1) ^ 0xA001 # reflected poly
|
|
else:
|
|
crc >>= 1
|
|
return crc & 0xFFFF
|
|
```
|
|
|
|
### Fragmentation
|
|
|
|
When a protobuf message exceeds the BLE MTU, it is split across multiple packets:
|
|
|
|
- `packageSequence` starts at 0, increments per packet
|
|
- `totalPackages` indicates total number of packets for the message
|
|
- Each packet contains a fragment of the protobuf payload
|
|
- `isLastPacket` = (`packageSequence` == `totalPackages` - 1)
|
|
|
|
## BLE Commands
|
|
|
|
| cmdInstruction | Name | Description |
|
|
|----------------|------|-------------|
|
|
| 0 | Unknown | Reserved |
|
|
| 1 | GetWiFiConfig | Authenticate and get device config |
|
|
| 2 | SetApMode | Configure device as WiFi hotspot (AP) |
|
|
| 3 | SetSTAMode | Configure device to connect to WiFi (STA) |
|
|
| 4 | SetNamePwd | Set BLE/WiFi name and password |
|
|
| 5 | Reset | Factory reset |
|
|
| 6 | GetWiFiList | Scan available WiFi networks |
|
|
| 7 | GetDeviceInfo | Get system info (protocol version, MAC, firmware) |
|
|
|
|
## Authentication Flow
|
|
|
|
```
|
|
App Device
|
|
│ │
|
|
│ BLE SCAN: discover "DWARF*" │
|
|
│ GATT CONNECT to service DAF2 │
|
|
│ │
|
|
│ ReqGetconfig {blePsd, clientId} │
|
|
│ ──── DAF3 (write) ────────────────► │
|
|
│ │
|
|
│ ResGetconfig {code, ip, ssid, ...} │
|
|
│ ◄──── DAF4 (notify) ────────────── │
|
|
│ │
|
|
│ [Optional] ReqSta/ReqAp │
|
|
│ ──── DAF5/DAF7 ───────────────────► │
|
|
│ │
|
|
│ Connect to ws://<ip>:9900 │
|
|
│ │
|
|
```
|
|
|
|
## Connection States
|
|
|
|
| State | Description |
|
|
|-------|-------------|
|
|
| Loading | Connecting |
|
|
| Success | Connected |
|
|
| PwdError | Authentication failed |
|
|
| DeviceError | Device error |
|
|
| Disconnecting | Disconnecting |
|
|
| Disconnected | Disconnected |
|
|
|
|
## BLE Error Types
|
|
|
|
| Error | Description |
|
|
|-------|-------------|
|
|
| BluetoothConnection | BLE connection failure |
|
|
| MTU | MTU negotiation failure |
|
|
| Communication | Communication error |
|
|
| ConfigFailed | Configuration failed | |