aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 7502236b1b699ab323d6829e2a9e3cc00853504f (plain)
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# 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)

## Disclaimer

I request that none of this code and/or documentation, in part or in full, be hosted on GitHub, SourceForge, or any other proprietary platform. This request is made out of respect for both me, the developer, and you, the user.

## 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)

### switchFindBand (vibrate/find watch)

Find band packet structure (write/6E40FC20)
```
byte[0] = 0x51 (command)
byte[1] = 0x01 to start vibrating, else 0x00
```

Response: 0xD1 0x01 for vibrating, else 0xD1 0x00 (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

## Scripts and tests

Located in the root of this git repo are some test scripts and files to get you going with your own implementations. BLE implementations are written in Python + the bleak library from PyPI.

The following scripts are available:

- FereFit_syncTime_BLE.py --- synchronizes the time on the watch
- FereFit_switchFindBand_BLE.py --- vibrates the watch for 5 seconds

They are named after FereFit, one of the names of the app, because I am decompiling the FereFit APK (even though it's all one codebase under different names, the app detects which one it's meant to be using functions such as isFereFit() and isHomieFit(), etc and just sets the UI and API to that).  
They will probably stay that way because I can't be bothered to rename them to freefit, and therefore future ones will also be named after FereFit for consistency or something like that.

As of 2026-03-29 (NZDT), I am actively reverse engineering this device. Hopefully, as I continue to take apart the `freefit` app, I can add more test scripts and documentation to this repo.