Skip to content

Protocol

Command reference·

Every JY ring command id with its request payload, reply shape and proof status.

  • hackers and protocol readers
  • 2 min read
  • 293 words

In 10 seconds

52 command ids: 28 ✅ proven live, 6 📡 seen on the air, 16 📖 APK-only, 2 ⛔ never sent. cmd is the u16 at offset 2 of the frame; ts6 = 6-byte local seconds (Time). Ids are decimal here, (0x..) alongside where the audio pages use hex — sleep is 34, the memo stream is 0x34 = 52. The twelve below are the ones a gateway actually uses; the full ledger is collapsed by group underneath.

The twelve that matter·

cmd does request → reply
1 set time ts6 + 00 → echo Y u16 M D h m s
6 battery 00 00percent u8, charging u8 (also pushed on the cradle)
37 device info — → fw u16, mac[6], mfr u16, model u16 (pushed on connect)
55 features 00 00remote_recording, storage
7 / 8 / 11 / 17 live HR open / close / tick ts6, hr u8 every ~5 s / session ended
30 auto-HR schedule start_h, start_m, end_h, end_m, enable, interval_min → echo
29 steps snapshot — → ts6, steps u32, kcal u16, distance u16
33 → 42 step history day → 16 B items … terminator with day 00:00
34 → 43 sleep day → 8 B items ts6, quality, motion (300 s buckets) … terminator
36 → 45 health records day → 14 B items ts6, hr, spo2, temp_tenths i16, u32 … terminator
61 · 64 · 52 · 54 (0x3D · 0x40 · 0x34 · 0x36) voice memo count → stop-transfer → Opus stream → echo remaining deletes (Audio)
4 find (vibrate) mode u8 → echo 01

Never sent by this driver or by tiny: 39 deviceOperation (reboot / factory reset), 67 unbind, anything on SUOTA FEF5.

Status in the ledger: ✅ [LIVE] · 📡 [CAPTURE] · 📖 [APK] only · ⛔ never send.

Ledger · link, identity, time — 11 rows
cmd name (APK) request payload reply status
1 setTime ts6 + 00 echo: year u16, month, day, hour, min, sec
3 getMTU 00 00 — (MTU is negotiated at ATT level; 512) 📖
26 (0x1A) setAppInfo 00 + app_id[12] echo
28 (0x1C) setAppRunningInfo u32 ack 📖
37 (0x25) getDeviceInfo — (also pushed on connect) firmware u16, mac[6], manufacturer u16, model u16
55 (0x37) queryDeviceFeature 00 00 remote_recording, storage u8 each (APK also lists classic_bt, alarm_supported; both rings answer 2 bytes)
62 (0x3E) sendAppHeartbeat — · every 2 s while connected
66 (0x42) (connect request) android/ios_connect_request, classic_bt_address 📖
68 (0x44) (push) device name len u8, ASCII — not in the APK parser
67 (0x43) requestDeviceUnbind unbind_result
39 (0x27) deviceOperation u8: 0 reboot · 2 factory reset
Ledger · battery, find, settings — 9 rows
cmd name request reply status
6 getBattery 00 00 (also pushed) percent u8, charging u8
4 vibrateLED mode u8 echo 01 ✅ (buzz felt)
2 setUserInfo u8×5 (sex, age, height, weight, ?) + u64 ack 📖
12 (0x0C) setSportTarget steps u32 ack 📖
13 (0x0D) setAuxFunction 13 flag bytes ack 📖
14 (0x0E) setTimeFormat u8 (0 = 24 h) ack 📖
30 (0x1E) setAutoHeartRateSetting start_h, start_m, end_h, end_m, enable, interval_min echo
65 (0x41) setAlarmList 5 × enabled, hour, minute, repeat&0x7F = 20 B alarm_set_result 📖
69 (0x45) queryAlarmList alarms[] 4 B each (both rings: empty)
Ledger · vitals, live — 10 rows
cmd name request reply status
7 openHeartRate ack; ticks follow as cmd 11
8 closeHeartRate echo
11 (0x0B) (stream) live HR ts6, hr u8 every ~5 s
17 (0x11) (push) HR session ended empty
23 (0x17) openCloseSpo2 u8 toggles; then 24 📡
24 (0x18) (stream) SpO₂ ts6, spo2 u8 📡
25 (0x19) (push) SpO₂ ended without value empty (setBloodStatus(false)) 📡
20 (0x14) openCloseTemperature u8 then 21 📖
21 (0x15) (stream) temperature ts6, raw i16 (/100 °C) 📖
15 / 19 BP · HRV · BP calibration no parser branch → not supported on this ring 📖
Ledger · activity, sleep, history — 12 rows
cmd name request reply status
29 (0x1D) getStepInfo — (also pushed) ts6, steps u32, kcal u16, distance u16
33 (0x21) getStepCountInfo day u8 (0 = today) items 16 B: ts6, duration u16, steps u32, kcal u16, distance u16; FF-filled = end
34 (0x22) getSleepData day u8 items 8 B: ts6, quality u8, motion u8 — 300 s buckets
36 (0x24) getHealthRecord day u8 items 14 B: ts6, hr u8, spo2 u8, temp_tenths i16, u32 unused
42 (0x2A) (terminator) steps done ts6 = day 00:00
43 (0x2B) (terminator) sleep done ts6
45 (0x2D) (terminator) records done ts6
38 (0x26) controlMultiSport u8 38 📡
10 (0x0A) pauseOrResumeSport u8, 00 sport_id u8, paused u8 📡
27 (0x1B) (stream) sport realtime 26 B: start ts6, type, now ts6, duration u16, steps u32, kcal u16, dist u16, hr u8, temp i16, spo2 u8 📡
9 getSportStatus 00 00 ? 📖
40 (0x28) (event) button u8: 1 press · 2 → 0 release
Ledger · audio — 11 rows
cmd name request reply status
47 (0x2F) queryAudioState 00 00 state u8, ext u80x00 idle · 0x10 recording · 0x40 recording to flash
48 (0x30) controlAudioMode mode u8, 00 — 0 stop · 1 online record · 2 AI dialog action, final_state
49 (0x31) pauseOrResumeAudio u8, 00 📖
50 / 51 (0x32/0x33) (stream) live audio packets u32 seq, u16 0, 12 × 40 B Opus 📖
52 (0x34) getOfflineAudioData / (stream) memo packets same layout, total/index = packets
54 (0x36) clearOfflineAudioData remaining u16 (echo what the ring pushed) ring pushes 0x36 <remaining> after the last packet
61 (0x3D) queryOfflineAudioFileCount count u16
63 (0x3F) stopOfflineRecord 📖
64 (0x40) stopOfflineRecordTransfer — · sent 1 s before 0x34
41 (0x29) sendPaste 01 HID paste trigger for the translation flow 📖