- 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
5.0 KiB
5.0 KiB
WebSocket Protocol
Connection
After BLE authentication, the app connects via WebSocket for all telescope control.
URL: ws://<device_ip>:9900/?client_id=<client_id>
Port: 9900 (primary), 4409/4410 (secondary)
Scheme: ws:// (unencrypted, NOT wss://)
The device IP is obtained from ResGetconfig.ip (if already on WiFi) or ResSta.ip (after STA configuration).
The client_id is stored in MMKV under key "data_default_client_id", or generated if not present.
Default device IP: 192.168.88.1
WsPacket Format
Every WebSocket message is a serialized BaseProto.WsPacket protobuf:
message WsPacket {
int32 majorVersion = 1; // Always 2
int32 minorVersion = 2; // Always 3
int32 deviceId = 3; // Target device ID (see DeviceType)
int32 moduleId = 4; // Module ID (0-18, see module table)
int32 cmd = 5; // Command ID (see WsCmd index)
int32 type = 6; // Message type: 0=request, 1=response, 2=notification, 3=reply
bytes data = 7; // Protobuf-encoded payload for the specific module
string clientId = 8; // App client identifier
}
Pseudocode: Sending a Command
import protobuf
def send_command(websocket, device_id, module_id, cmd, payload_bytes, client_id):
"""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
)
websocket.send(packet.SerializeToString())
def send_track_start(websocket, device_id, client_id, x, y, w, h, cam_id):
"""Example: Start tracking."""
track_req = TrackProto.ReqStartTrack(x=x, y=y, w=w, h=h, camId=cam_id)
send_command(websocket, device_id, module_id=7, cmd=14800,
payload_bytes=track_req.SerializeToString(), client_id=client_id)
Message Types
| type | Name | Description |
|---|---|---|
| 0 | request | App → Device command |
| 1 | response | Device → App response to a request |
| 2 | notification | Device → App spontaneous notification |
| 3 | reply | Device → App acknowledgement |
Keepalive: DwarfPing / DwarfEcho
After WebSocket connection, the app periodically sends DwarfPing and the device responds with DwarfEcho.
message DwarfPing {
int32 vocaltype = 1; // VT_PING = 1
int64 timestamp = 2; // Unix timestamp
bytes magic = 3; // Session magic bytes
repeated DwarfPing vocals = 4;
repeated NifAP mutes = 5;
}
message DwarfEcho {
int32 vocaltype = 1; // VT_ECHO = 2
int64 timestamp = 2; // Unix timestamp
bytes magic = 3; // Session magic bytes
int64 tsPing = 4; // Echo of the ping timestamp
bytes macAddress = 5; // Device MAC address
BleProto model = 6; // Device model info
string sn = 7; // Serial number
string name = 8; // Device name
string psw = 9; // Password
string fwVersion = 10; // Firmware version
string wsScheme = 11; // WebSocket scheme ("ws")
int32 session = 12; // Session ID
BleProto ap = 13; // AP info
BleProto sta = 14; // STA info
}
Note
: DwarfEcho contains complete device info (firmware, MAC, SSID, IP, etc.).
Response Routing
The client uses WsRequestHandle to dispatch responses:
- Parse
WsPacketfrom received bytes - Extract
cmd(command ID) - Look up registered handlers in a
HashMap<Integer, List>for this cmd - Execute callbacks with
WsPacket.getData()(deserialized payload)
Typical Exchange
App Device
│ │
│ WsPacket(type=0, moduleId=1, │
│ cmd=10000, data=ReqOpenCamera) │
│ ─────────────────────────────────────► │
│ │
│ WsPacket(type=1, cmd=10000, │
│ data=ComResponse{code=0}) │
│ ◄───────────────────────────────────── │
│ │
│ WsPacket(type=0, moduleId=7, │
│ cmd=14800, data=ReqStartTrack) │
│ ─────────────────────────────────────► │
│ │
│ WsPacket(type=2, cmd=15200, │
│ data=NotifyProto{...}) │
│ ◄───────────────────────────────────── │
│ (spontaneous notification) │
Protocol Version
| Field | Value | Description |
|---|---|---|
WS_MAJOR_VERSION_NUMBER |
2 | Current major version |
WS_MINOR_VERSION_NUMBER |
3 | Current minor version |