Protocol
Protocol overview·
The JY ring protocol in one page: identity, GATT, chip, advertising, connection sequence — and how every claim is sourced.
In 10 seconds
One GATT service (56FF: write 33F3, notify 33F4), a 10-byte little-endian header
FE FC · cmd · total · index · len, ~50 commands, no checksum, no authentication. LoraFit calls it the
"JiangYun (JY) ring". Every claim here carries a proof tag; the chronological ledger is the full ledger.
How claims are labelled·
| tag | means | where the proof lives |
|---|---|---|
| [APK] | read from the decompiled LoraFit app (com.wq.lorafit, jadx) |
docs/raw/*.java |
| [CAPTURE] | seen on the air between the vendor app and a ring (Pixel HCI snoop) | captures/*.log, *.att.jsonl |
| [LIVE] | this driver did it against a real ring | evidence/*.jsonl (hex + decoded + timestamp) |
Anything carrying only [APK] is not yet proven on the metal and is written in italics as inferred.
Radio, chip, advertising [LIVE]·
| field | value |
|---|---|
| chip | Dialog / Renesas DA14xxx — the GATT table carries SUOTA service FEF5. Never write to it |
PnP ID 2A50 |
01 ac05 2002 1001 → vendor 0x05AC, product 0x0220, plus HID 0x1812 → macOS bonds it as a Mouse (transport) |
| MTU | 512. No Device Information strings. A second vendor service FF12 exists, unused |
| advertising | name SR116-088D / JY-Y3-011A (per unit) · UUIDs FEF5, 1812 · manufacturer 0x594A ("JY") = mac[6] · fw u16 · 3a00 · 4800 · 01 01 · 00×4 — MAC in clear |
| presence | a ring stops advertising while a central holds it; silent 8–40 s after a disconnect |
The LoraFit family — four radio stacks, one is this ring
| path | selector | devices |
|---|---|---|
JiangYun ring (hr7 / hy7) — this protocol |
a service whose UUID contains 56FF |
SR116-xxxx, JY-Y3-xxxx |
JieTuo ring (vr7) |
services 6800/6801/6802 |
other rings — different chip and protocol, not covered |
| Jieli RCSP | AE00/AE01/AE02, libjl_*.so |
earbuds, glasses |
| huahen earbud layer | DF97/DF98/DF99 |
earbuds |
Both rings we own run firmware 0x0098 (152); the advertised name is <model>-<last 4 hex of MAC> — a per-unit
sticker, not a family prefix. Filter on the manufacturer id. The APK's BleVendorDataParser XOR-0xAD layout belongs
to the earbud layer and does not apply.
GATT [APK] [LIVE]·
| role | UUID | handle (both rings) |
|---|---|---|
| service | 000056ff-0000-1000-8000-00805f9b34fb |
— |
| write (host → ring) | 000033f3-… |
0x0017 (write + write-without-response) |
| notify (ring → host) | 000033f4-… |
0x0019, CCCD 0x001a |
| battery (BAS) | 2A19 |
0x002c — lies (read 100 % while cmd 6 said 77 %); use cmd 6 |
| SUOTA (OTA) | FEF5 + Dialog chars |
0x0001–0x0013 — never touch |
sequenceDiagram
autonumber
participant H as host
participant R as ring
H->>R: subscribe 33F4
R-->>H: 37 device info · 13 B adv echo · 6 battery
H->>R: 1 set time (ts6)
R-->>H: 1 echo Y M D h m s
H->>R: 26 app id · 8 close HR · 30 auto-HR · 55 features
loop every 2 s
H->>R: 62 heartbeat
end
Connection sequence — what the ring pushes on subscribe, what the app sends back
| who | order | frames |
|---|---|---|
| ring, unprompted, on subscribe [LIVE] | 1→6 | 37 device info fw u16 · mac[6] · mfr u16 · model u16 → a headerless 13-byte echo of the advertising data 0c · fw · mac · 3a00 · 4800 (not garbage) → 68 name → 55 features remote_recording · storage → 29 steps → 6 battery percent · charging |
app (ring-cli handshake) [APK] [CAPTURE] |
1→5 | 1 set-time (echo Y u16 M D h m s) → 26 app id (12 B, not a secret) → 8 close HR → 30 auto-HR 00 00 17 3B <on> <min> → 55 features → 62 heartbeat every 2 s |
| pacing | writes ≥ 300 ms apart (150 ms during audio); a write that fails 3× is dropped |
No pairing, no challenge–response, no key exists anywhere in this path.
Next: Framing · Commands · Health data · Audio · Time · macOS transport · how it was captured: Lab → Live capture