Skip to content

Ultrahuman Protocol

This describes the Bluetooth attribute protocol used between the Ultrahuman Air smart ring (firmware version 02.00.07.46) and the Ultrahuman Android application (version 2.52.2.0, package com.ultrahuman.android).

Device Identification

The BLE device name matches the Regex pattern UH_[0-9A-F]{12}. For example "UH_FE16F0F1E2D3".

Device Information service

The standard BLE device information service 0000180a-0000-1000-8000-00805f9b34fb supports reading - Read Request (0x0a) / Read Response (0x0b):

Characteristic UUID Description Data Sample
00002a24-0000-1000-8000-00805f9b34fb Model Number String R1.00.00.01
00002a25-0000-1000-8000-00805f9b34fb Serial Number String XX-XXX-XXX-XX-XXXX-XXX
00002a26-0000-1000-8000-00805f9b34fb Firmware Revision String 02.00.07.46
00002a27-0000-1000-8000-00805f9b34fb Hardware Revision String R1.01.01.01
00002a29-0000-1000-8000-00805f9b34fb Manufacturer Name String Ultrahuman Healthcare Pvt Ltd

Ultrahuman Device State service

The custom BLE service 86f61000-f706-58a0-95b2-1fb9261e4dc7 supports one characteristic 86f61001-f706-58a0-95b2-1fb9261e4dc7.

This characteristic can be read - Read Request (0x0a) / Read Response (0x0b). In addition Ultrahuman Command requests also trigger typically between 0 and 2 notifications of the characteristic - Handle Value Notification (0x1b)

payload structure

Offset Data Type Description
0 uint8 battery level (0x64 = 100%, 0x00 = 0%)
1..4 ? ?
5 uint8 device state (0x00 = discharging, 0x03 = charging)
6 uint8 device temperature in °C; temperatures below 0°C are reported as 0°C

examples:

4c4c2900000317 = battery level 79% (0x4c), device state "charging" (0x03), device temperature 23°C (0x17)

00000000000000 = unknown device state - sometimes received in response to read requests

Ultrahuman Command Response service

This custom BLE service 86f65000-f706-58a0-95b2-1fb9261e4dc7 allows writing commands 86f65001-f706-58a0-95b2-1fb9261e4dc7 and receiving their responses via value notifications 86f65002-f706-58a0-95b2-1fb9261e4dc7.

The first byte of both the Write Command (0x52) and the Handle Value Notification (0x1b) payload encodes the Ultrahuman opcode.

Opcode Description
0x02 set time
0x04 get recordings
0x05 get time
0x07 get earliest recording index
0x08 get latest recording index
0x70 activate airplane mode
0x98 reset device
0xD1 disable power saving mode
0xD2 enable power saving mode

0x02 Set Time Command

Sets the current time.

Offset Data Type Description
0 uint8 opcode
1 uint32_le time, seconds since 1970-01-01 00:00

example:

020001a5c4ac67966c = opcode 0x02, time 2025-02-12 15:56:21 (0x67acc4a5)

0x02 Set Time Response

Response echos back the effective time.

Offset Data Type Description
0 uint8 opcode
1 uint8 result: success (0x00)
2 uint8 details: OK (0x01)
3 uint32_le time, seconds since 1970-01-01 00:00
7..8 ? ? - the last 2 bytes of the message are likely a check sum

example:

020001a5c4ac67966c = opcode 0x02, success (0x00), OK (0x01), time 2025-02-12 16:56:56 (0x67acc45c)

0x04 Get Recordings Command

Requests historical sensor recordings.

Normally a new entry is recorded every ca 5 minutes. In Workout mode a new entry is recorded every ca 2 seconds.

Offset Data Type Description
0 uint8 opcode
1-2 uint16_le first recording to retrieve

examples:

040100 = opcode 0x04; request recording 1 (0x0001) and newer

042f0f = opcode 0x04; request recording 3887 (0x0f2f) and newer

0x04 Get Recordings Response

One or more responses are received for each command. The response contains 0 or more, at least up to 7, records.

Offset Data Type Description
0 uint8 opcode
1 uint8 result: success (0x00), no data (0xee), failure (0xff)
2 uint8 number of recordings in this response
3+r*32 recording a 32 byte recording, see dedicated recording chapter for details
3+r*32+30 uint16_le index of the recoding, a "Soft Reset" resets the index to 1
len-2 2 bytes ? - the last 2 bytes of the message are likely a check sum

examples:

04ee00ffff = opcode 0x04; 0 recordings

040001451da3670000000a451da3670000000000000000451da3670000000000006a00d0ae = opcode 0x04, 1 recordings, empty record 106 (0x006a)

0400028a99a5670000000a8a99a56700000000000000008a99a5670000000000007206ae9aa56700000064ae9aa5670000000000000000ae9aa5670000000000007306adad = opcode 0x04, 2 recordings, empty record 1650 (0x0672), empty record 1651 (0x0673)

040001ac23a56747520005ac23a56734340b42fec50942ac23a5670000000052003205759a = opcode 0x04, 1 recordings, record 1330 (0x0532) with sensor readings

recording structure

The recording consists of 3 sensor groups (A, B and C), each starting with its own timestamp. Depending on operation mode the timestamps are identical or different.

Offset Data Type Description
0 uint32_le timestamp A, seconds since 1970-01-01 00:00
4 uint8 heartrate (HR) in BPM, 0 if not measured
5 uint8 heartrate variability (HRV), 0 if not measured
6 uint8 blood oxygen level (SpO2) in %, 0 if not measured
7 uint8 type of measurement: 1 = normal, 5 = exercise, 6 = breathing, 100 = not on finger
8 uint32_le timestamp for group B, seconds since 1970-01-01 00:00
12 float32_le max skin temperatur in °C
16 float32_le min skin temperatur in °C
20 uint32_le timestamp for group C, seconds since 1970-01-01 00:00
24 uint16_le activity level (1 - 150), 0 = no data
26 uint16_le steps since last record
28 uint16_le stress (1 - 255), 0 = no data

example:

E945AD67443362018546AD67785B0E4230D20C428546AD67960025003300 = time A 2025-02-13 01:07:53 (0x67AD45E9), heart reate 68 BPM (0x44), heart rate variability 51 (0x33), SpO2 98% (0x62), time B 2025-02-13 01:10:29 (0x67AD8546), max skin temperatur 35.58°C (0x420E5B78), min skin temperature 35.21°C (0x420CD230), time C 2025-02-13 01:10:29 (0x67AD4685), activity level 150 (0x0096), steps 37 (0x0025), stress 51 (0x0033)

0x05 Get Time Command

Retrieve the current device time.

Offset Data Type Description
0 uint8 opcode

example:

05 = opcode 0x05

0x05 Get Time Response

The current UTC time of the device.

Offset Data Type Description
0 uint8 opcode
1 uint8 result: success (0x00)
2 uint8 details: OK (0x01)
3 uint32_le time, seconds since 1970-01-01 00:00
7..8 ? ? - the last 2 bytes of the message are likely a check sum

example:

050001d8d2ac67a6e6 = opcode 0x05, success (0x00), OK (0x01), time 2025-02-12 16:56:56 (0x67acd2d8)

0x07 Get Earliest Recording Index Command

Request the index of the oldest recording retrivable via 0x04 Get Recordings.

Offset Data Type Description
0 uint8 opcode

example:

07 = opcode 0x07

0x07 Get Earliest Recording Index Response

Offset Data Type Description
0 uint8 opcode
1 uint8 result: success (0x00), no data (0xee), failure (0xff)
2 uint8 details: OK (0x01)
3 uint16_le index of oldest recording
5..6 ? ? - the last 2 bytes of the message are likely a check sum

example:

070001c401bed7 = opcode 0x07, success (0x00), OK (0x01), first recording 452 (0x001c4)

0x08 Get Latest Recording Index Command

Request the index of the newest record retriveable via 0x04 Get Recordings.

Offset Data Type Description
0 uint8 opcode

example:

08 = opcode 0x08

0x08 Get Latest Recording Index Response

Offset Data Type Description
0 uint8 opcode
1 uint8 result: success (0x00), no data (0xee), failure (0xff)
2 uint8 details: OK (0x01)
3 uint16_le index of latest recording
5..6 ? ? - the last 2 bytes of the message are likely a check sum

example:

0800017306c320 = opcode 0x08, success (0x00), OK (0x01), latest recording 1651 (0x0673)

0x70 Activate Airplane Mode Command

Airplane Mode disables the BLE radio on the ring. The radio can be re-enabled by charging the ring.

Offset Data Type Description
0 uint8 opcode

example:

70 = opcode 0x70

0x70 Activate Airplane Mode Response

The ring will switch of it's radio immediately after sending a success response.

Offset Data Type Description
0 uint8 opcode
1 uint8 result: success (0x00), no data (0xee), failure (0xff)
2 uint8 details: OK (0x01), ring is charging (0x02), ring is fully charged (0x03)
3 ? ?
4..5 ? ? - the last 2 bytes of the message are likely a check sum

example:

70000161779d = opcode 0x70, success (0x00), OK (0x01)

70ff02ff00ff = opcode 0x70, failure (0xFF), ring is charging (0x02)

0x98 Reset Device Command

Purges recorded data from the device and reboots immediately without generating a response.

Offset Data Type Description
0 uint8 opcode

example:

98 = opcode 0x98

0xD1 Disable Power Saving Mode Command

Enables the SpO2 sensing.

Offset Data Type Description
0 uint8 opcode

example:

D1 = opcode 0xD1

0xD1 Disable Power Saving Mode Response

If successful, the next recordings are going to try to sense SpO2.

Offset Data Type Description
0 uint8 opcode
1 uint8 result: success (0x00), no data (0xee), failure (0xff)
2 uint8 details: OK (0x01)
3 ? ?
4..5 ? ? - the last 2 bytes of the message are likely a check sum

example:

d10001d1ac3a = opcode 0xD1, success (0x00), OK (0x01)

0xD2 Enable Power Saving Mode Command

Disable SpO2 sensing.

Offset Data Type Description
0 uint8 opcode

example:

D2 = opcode 0xD2

0xD2 Enable Power Saving Mode Response

If successful, the next recordings are NOT going to try to sense SPO2.

Offset Data Type Description
0 uint8 opcode
1 uint8 result: success (0x00), no data (0xee), failure (0xff)
2 uint8 details: OK (0x01)
3 ? ?
4..5 ? ? - the last 2 bytes of the message are likely a check sum

example:

d2000100f0e1 = opcode 0xD2, success (0x00), OK (0x01)