1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# zwzn-freefit-re
Reverse-engineering a sketchy Chinese watch app
Documentation/protocols derived from decompiled FereFit Android app (jadx)
(com.czw.freefit, SHENZHEN ZHONGWEI INTELLIGENT TECHNOLOGY Co.,Ltd)
## What this is and why it exists
This is a git repo containing protocol documentation of the `freefit` watch app, commonly known as "FereFit", "Lyne_Wearables", "HomieFit", "zwsvibe", and "WIRCASS". It allows us to make our own app implementations for some watches that use these apps. In particular, my testing occurs with the "Watch ULTRA", which I cannot find any more brand information on, though it's a sort of no-name Apple Watch ULTRA knockoff. Although, this protocol should work fine for most other watches that use these apps.
This exists for many reasons, though here are the top few:
- I'm 13 and have too much free time
- I wanted to get into reverse-engineering
- I had an old knockoff "Watch ULTRA" from the arcade, and the original app was spyware
- The RTC on this watch drifts badly, so without an app to periodically synchronize it, it becomes almost unusable
Anyway, talk is cheap, let's get into the documentation!
## BLE characteristics
### Main characteristics (presumably Nordic UART/Nordic semiconductor chips)
- Service UUID: 6E40FC00-B5A3-F393-E0A9-E50E24DCCA9E
- Write characteristic UUID: 6E40FC20-B5A3-F393-E0A9-E50E24DCCA9E
- Notify characteristic UUID: 6E40FC21-B5A3-F393-E0A9-E50E24DCCA9E
### Jieli/JL chip characteristics (untested)
- Service UUID: 0000ae00-0000-1000-8000-00805f9b34fb
- Write characteristic UUID: 0000ae01-0000-1000-8000-00805f9b34fb
- Notify characteristic UUID: 0000ae02-0000-1000-8000-00805f9b34fb
## Protocols/functions
### Battery status/notification (read/6E40FC21)
Sent by watch if command is invalid. TODO find proper trigger for this
```
byte[0] = 0x94 (BATTERY command/response)
byte[1] = battery percentage (0-100)
```
### syncTime
Time sync packet structure (write/6E40FC20)
```
byte[0] = 0x01 (command)
byte[1-4] = Unix timestamp (big endian, seconds)
byte[5-8] = timezone offset (big endian, seconds)
byte[9] = i (unknown param, use 0x00)
byte[10] = language code
byte[11] = 0x01 if traditional Chinese, else 0x00
```
Response: 0x81 0x00 (success, notify/6E40FC21)
### enterMakeDial (watch face)
Watch face header packet (write/6E40FC20)
```
byte[0] = 0xE4 (ZK_DIAL command)
byte[1] = 0x51 (mode flag)
byte[2] = 0x01 (start)
byte[3] = 0x00
byte[4-5] = total packet count (big endian)
byte[6-9] = total image bytes (big endian)
byte[10] = 0x00
byte[11-12] = MTU size (big endian)
byte[13] = rotation flag
byte[14] = 0x01
byte[15] = time text direction
byte[16] = 0x00
byte[17-18] = transparent color (RGB565)
byte[19-20] = checksum (sum of all image bytes, big endian)
byte[21] = show date (0x01 = yes, 0x00 = no)
```
Header packet is followed by chunked RGB565 data, 1 chunk = MTU-14 bytes
|