This is a macOS CoreBluetooth peripheral simulator that emulates the J-Style 2301 ring GATT service.
- Service UUID: FFF0
- Write characteristic: FFF6 (phone -> ring)
- Notify characteristic: FFF7 (ring -> phone)
- 16 byte packets with CRC (sum of first 15 bytes & 0xFF)
Supported commands (realistic replies):
- 0x01 Set time
- 0x41 Get time
- 0x02 Set personal info
- 0x42 Get personal info
- 0x05 Set device ID (ack)
- 0x07 Get step goal
- 0x08 Set step goal (ack)
- 0x09 Realtime step (streamed, variable length)
- 0x12 Factory reset (ack)
- 0x13 Get battery
- 0x16 VO2MAX control (ack)
- 0x21 Read chip ID
- 0x22 Get MAC
- 0x27 Get version
- 0x28 Measurement control + periodic results
- 0x2A Set auto monitoring (ack)
- 0x2B Get auto monitoring
- 0x2E MCU reset (ack)
- 0x3D Set device name (ack + update advertising)
- 0x3E Get device name
- 0x51 Total activity data (variable length, realistic)
- 0x52 Detail activity data (variable length, realistic)
- 0x53 Sleep data (variable length, realistic)
- 0x54 Continuous HR data (variable length, realistic)
- 0x55 Single HR data (variable length, realistic)
- 0x56 HRV data (variable length, realistic)
- 0x62 Temperature data (variable length, realistic)
- 0x66 SpO2 data (variable length, realistic)
- 0x67 Realtime PPG data (streamed while PPG is active)
- 0x78 PPG control (start/stop/progress/quit)
Unknown commands are acknowledged with a zero payload.
cd ring-sim-macos
swift run
If macOS asks for Bluetooth access, allow it. If you do not see a prompt, check: System Settings -> Privacy & Security -> Bluetooth, and allow Terminal.
help Show help
status Show current simulator state
name <device-name> Set BLE advertised name
advertise on|off Toggle advertising
battery <0-100> Set battery percentage
hr <bpm> Set current heart rate
spo2 <0-100> Set current SpO2 percentage
temp <celsius> Set temperature in Celsius
steps <count> Set step count and send one realtime packet
realtime on|off Enable or disable periodic realtime steps
send <hex-bytes> Send a raw 15 or 16 byte packet (CRC auto for 15)
Example raw send (15 bytes, CRC auto):
send 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- Use a real iPhone or Android device (emulators do not support BLE).
- Scan for the advertised name (default: JCRingSim), connect, then enable notifications on FFF7.
- Your existing app should be able to connect as if it were a ring.
- The real device may send longer notifications if MTU is increased. This simulator sticks to 16 byte frames.
- If you have a specific command that is not working, use
sendto inject raw packets and we can expand support. - Variable length responses are sent as single notifications up to 180 bytes; if your central needs smaller chunks, tell me and we can tune it.
- PPG data is streamed on command 0x67 while the app enables PPG via command 0x78. If your SDK expects a different PPG data command, tell me and we can adjust.