Add complete DWARFLAB protocol documentation

- 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
This commit is contained in:
Jacquin Antoine
2026-06-13 00:21:19 +02:00
parent fe534ce77b
commit be87e8a4ca
14 changed files with 2373 additions and 0 deletions

209
13_connection_flow.md Normal file
View File

@ -0,0 +1,209 @@
# Connection Flow
## Complete Connection Sequence
```
Step 1: BLE Discovery Step 4: WebSocket Step 6: Commands
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ SCAN for │ │ Connect to │ │ Send WsPacket│
│ "DWARF*" │ │ ws://IP:9900 │ │ (moduleId+cmd)│
│ devices │ │ ?client_id= │ │ │
│ via BleManager│ │ <clientId> │ │ Receive │
└──────┬───────┘ └──────┬───────┘ │ WsPacket │
│ │ │ (response/ │
Step 2: GATT Connect Step 5: Keepalive │ notification)│
┌──────────────┐ ┌──────────────┐ └──────────────┘
│ Connect to │ │ DwarfPing → │
│ Service DAF2 │ │ ← DwarfEcho │
│ (UUID DAF2) │ │ (periodic) │
└──────┬───────┘ └──────────────┘
Step 3: Auth
┌──────────────┐
│ Write │
│ ReqGetconfig │
│ on DAF3 │
│ → Receive │
│ ResGetconfig │
│ on DAF4 │
└──────────────┘
```
## Step 1-3: BLE Phase
### Pseudocode: BLE Authentication
```python
# 1. Scan for DWARF devices
devices = ble_scan(filter_name="DWARF*")
# 2. Connect to GATT service
gatt = ble_connect(device, service_uuid="0000DAF2-0000-1000-8000-00805f9b34fb")
# 3. Authenticate
auth_request = BleProto.ReqGetconfig(
cmd=1, # GetWiFiConfig
blePsd="DWARF_12345678", # default password
clientId="my-app-client-id"
)
ble_packet = build_ble_packet(cmd=1, data=auth_request.SerializeToString())
ble_write(characteristic=DAF3, data=ble_packet)
# 4. Receive response
response_data = ble_notify(characteristic=DAF4)
response_packet = parse_ble_packet(response_data)
config = BleProto.ResGetconfig()
config.ParseFromString(response_packet.dataPayload)
device_ip = config.ip # e.g., "192.168.88.1"
```
### Pseudocode: WiFi Configuration (STA mode)
```python
# Configure device to connect to local WiFi
sta_request = BleProto.ReqSta(
cmd=3, # SetSTAMode
autoStart=1,
blePsd="DWARF_12345678",
ssid="MyHomeWiFi",
psd="home_password",
clientId="my-app-client-id"
)
ble_packet = build_ble_packet(cmd=3, data=sta_request.SerializeToString())
ble_write(characteristic=DAF5, data=ble_packet)
# Receive STA response
sta_data = ble_notify(characteristic=DAF6)
sta_packet = parse_ble_packet(sta_data)
sta_response = BleProto.ResSta()
sta_response.ParseFromString(sta_packet.dataPayload)
device_ip = sta_response.ip # IP for WebSocket
```
## Step 4: WebSocket Phase
### Pseudocode: WebSocket Connection
```python
import websocket
import protobuf
# Connect to device WebSocket
ws = websocket.connect(f"ws://{device_ip}:9900/?client_id={client_id}")
# Start keepalive thread
def keepalive():
while connected:
ping = BleProto.DwarfPing(
vocaltype=1, # VT_PING
timestamp=current_time_ms(),
magic=session_magic_bytes
)
packet = WsPacket(
majorVersion=2,
minorVersion=3,
deviceId=device_id,
moduleId=0, # NONE
cmd=0,
type=0, # request
data=ping.SerializeToString(),
clientId=client_id
)
ws.send(packet.SerializeToString())
sleep(5) # 5-second interval
```
### Pseudocode: Send Command
```python
def send_command(ws, device_id, module_id, cmd, payload_bytes):
"""Send a command via WebSocket."""
packet = WsPacket(
majorVersion=2,
minorVersion=3,
deviceId=device_id,
moduleId=module_id,
cmd=cmd,
type=0, # request
data=payload_bytes,
clientId=client_id
)
ws.send(packet.SerializeToString())
# Example: Start tracking
track_req = TrackProto.ReqStartTrack(x=500, y=300, w=100, h=100, camId=0)
send_command(ws, device_id=4, module_id=7, cmd=14800,
payload_bytes=track_req.SerializeToString())
# Example: Open tele camera
camera_req = CameraProto.ReqOpenCamera(binning=False, rtspEncodeType=0)
send_command(ws, device_id=4, module_id=1, cmd=10000,
payload_bytes=camera_req.SerializeToString())
```
## BLE Packet Binary Format
```
Byte Field Size Description
---- ----------------- ---- -----------
0 magic 1 0xAA (constant)
1 protocolVersion 1 Protocol version (typically 1)
2 cmdInstruction 1 BLE command (0-7)
3 packageSequence 1 Current packet number (0-based)
4 totalPackages 1 Total packets for this message
5-6 extendedProtocol 2 Extended protocol (big-endian, usually 0)
7-8 validDataLength 2 Length of protobuf payload (big-endian)
9..N dataPayload N Protobuf-encoded BleProto message
N+1..N+2 crc 2 CRC-16/MODBUS (poly=0x8005, init=0xFFFF, reflected)
N+3 endMarker 1 0x0D (constant)
Total = validDataLength + 12 bytes
```
### CRC-16/MODBUS Parameters
- Polynomial: 0x8005 (reflected: 0xA001)
- Initial value: 0xFFFF
- Reflect input: Yes
- Reflect output: Yes
- XOR out: 0x0000
- Computed over: header (9 bytes) + payload (N bytes), **excluding** CRC and end marker
## WsPacket Binary Format
```
Field Proto# Type Description
-------------- ------ ---- -----------
majorVersion 1 int32 Always 2
minorVersion 2 int32 Always 3
deviceId 3 int32 Target device (0-6, see DeviceType)
moduleId 4 int32 Module (0-18, see module table)
cmd 5 int32 Command ID (see WsCmd index)
type 6 int32 0=request, 1=response, 2=notification, 3=reply
data 7 bytes Protobuf-encoded module-specific payload
clientId 8 string App client identifier
```
Serialized using standard protobuf proto3 encoding.
## Device Models
| Model | deviceId | Codename | Max Name | Special |
|-------|----------|----------|----------|---------|
| Unknown | 0 | — | — | — |
| DWARF 2 | 1 | — | 21 | — |
| DWARF 3 | 2 | — | 19 | — |
| *(gap)* | 3 | — | — | *unused* |
| DWARF mini | 4 | Bilbo | 15 | No Panorama Create, `indexBilbo.html` |
| DWARF 4 | 5 | — | 19 | — |
| DWARF DRAGON | 6 | — | — | — |
## Ports & Endpoints
| Service | URL/Port | Note |
|---------|----------|------|
| WebSocket | `ws://<ip>:9900/?client_id=<id>` | Primary control channel |
| WebSocket (alt) | Ports 4409 (0x1139), 4410 (0x113A) | Secondary ports |
| Firebase | `dwarflab-a7062.appspot.com` | Cloud backend |
| S3 | `dwarf-bucket-02-1251529954` | OTA storage |