Skip to content

Protocol

Protocol overview·

The JY ring protocol in one page: identity, GATT, chip, advertising, connection sequence — and how every claim is sourced.

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

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 0x002clies (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 · storage29 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