Commands

Service: 6e40fff0-b5a3-f393-e0a9-e50e24dcca9e
Write Characteristic (Requests): 6e400002-b5a3-f393-e0a9-e50e24dcca9e
Notify Characteristic (Responses): 6e400003-b5a3-f393-e0a9-e50e24dcca9e

This set of commands was likely the first Characteristic added - some commands here have newer versions in Big Data. Some Commands send split arrays, and will contain a different structure depending on the array index (example).

Each command listed has the following 16-byte structure:

struct Command {
    uint8_t commandId;
    uint8_t data[14];
    uint8_t crc;
}

Notes:

  • To calculate the CRC, add up commandId and each individual byte in data to a large enough integer (16-bit or 32-bit), then & with 0xFF.
  • The commandId is actually only 7 bits - the most signifigant bit is an error flag. (commandId & 128) >> 7 will get you the error status.

Set Time

ID: 1

struct SetTimeRequest {
    uint8_t commandId = 1;
    uint8_t year; // % 2000
    uint8_t month; // January = 1
    uint8_t dayOfMonth;
    uint8_t hour;
    uint8_t minute;
    uint8_t second;
    char unused[8]
    uint8_t crc;
}
struct SetTimeResponse {
    uint8_t commandId = 1;
    uint8_t supportsTemperature;
    uint8_t supportsPlate; //?
    uint8_t supportMenstruation;
    uint8_t supportFlags1;
    uint16_t width;
    uint16_t height;
    uint8_t useNewSleepProtocol;
    uint8_t maxWatchFace;
    uint8_t supportFlags2;
    uint8_t supportFlags3;
    uint8_t maxContacts; // maxContacts == 0 means 20 contacts, maxContacts > 0 means maxContacts * 10
    uint8_t supportFlags4;
    uint8_t crc;
}
enum supportFlags1 : uint8_t {
    SUPPORT_CUSTOM_WALLPAPER    = 1 << 0,
    SUPPORT_BLOOD_OXYGEN        = 1 << 1,
    SUPPORT_BLOOD_PRESSURE      = 1 << 2,
    SUPPORT_FEATURE             = 1 << 3, //?
    SUPPORT_ONE_KEY_CHECK       = 1 << 4,
    SUPPORT_WEATHER             = 1 << 5,
    SUPPORT_WECHAT              = 1 << 6;
    SUPPORT_AVATAR              = 1 << 7;
}

enum supportFlags2 : uint8_t {
    SUPPORT_CONTACTS            = 1 << 0;
    SUPPORT_LYRICS              = 1 << 1;
    SUPPORT_ALBUM               = 1 << 2;
    SUPPORT_GPS                 = 1 << 3;
    SUPPORT_JIELIE_MUSIC        = 1 << 4;
}

enum supportFlags3 : uint8_t {
    SUPPORT_MANUAL_HEART_RATE   = 1 << 0;
    SUPPORT_ECARD               = 1 << 1;
    SUPPORT_LOCATION            = 1 << 2;
    RESERVED                    = 1 << 3;
    SUPPORT_MUSIC               = 1 << 4;
    SUPPORT_RTK_MCU             = 1 << 5; //?
    SUPPORT_EBOOK               = 1 << 6;
    SUPPORT_BLOOD_SUGAR         = 1 << 7;
}

enum supportFlags4 : uint8_t {
    RESERVED                        = 1 << 0;
    SUPPORT_BLOOD_PRESSURE_SETTINGS = 1 << 1;
    SUPPORT_4G                      = 1 << 2;
    SUPPORT_NAV_PICTURE             = 1 << 3;
    SUPPORT_PRESSURE                = 1 << 4;
    SUPPORT_HRV                     = 1 << 5;
}

Camera

ID: 2

struct CameraRequest {
    uint8_t commandId = 2;
    ActionRequest action;
    char unused[13];
    uint8_t crc;
}

enum ActionRequest : uint8_t {
    ACTION_INTO_CAMERA_UI = 4;
    ACTION_KEEP_SCREEN_ON = 5;
    ACTION_FINISH = 6;
}
struct CameraResponse {
    uint8_t commandId = 2;
    ActionResponse action;
    char unused[13];
    uint8_t crc;
}
enum ActionResponse : uint8_t {
    ACTION_INTO_CAMERA_UI = 1;
    ACTION_TAKE_PHOTO = 2;
    ACTION_FINISH = 3;
}

Battery

ID: 3

struct BatteryRequest {
    uint8_t commandId = 3;
    char unused[14];
    uint8_t crc = 3;
}
struct BatteryResponse {
    uint8_t commandId = 3;
    uint8_t chargePercent;
    uint8_t isCharging;
    char unused[12];
    uint8_t crc;
}

Write Phone Info

ID: 4

struct WritePhoneInfoRequest {
    uint8_t commandId = 7;
    uint8_t clientVersionMajor; // Current QRing version = 2
    uint8_t clientVersionMinor; // Current QRing version = 10
    char phoneName[12]; // null-terminated
    uint8_t crc;
}

Sport Request

TODO: Need response sample data

ID: 7

struct SportRequest {
    uint8_t commandId = 7;
    uint8_t dayOffset;
    char unused[13];
    uint8_t crc;
}

Reboot

ID: 8

struct RebootRequest {
    uint8_t commandId = 8;
    uint8_t constant = 1;
    char unused[13];
    uint8_t crc = 9;
}

Blood Pressure

ID: 13

struct BloodPressureResponse {
    uint8_t commandId = 13;
    uint8_t dataType;
    char data[13]; //TODO
    uint8_t crc;
}

Blood Pressure Conform

Not sure what this is used for.

ID: 14

struct BloodPressureConformRequest {
    uint8_t commandId = 14;
    uint8_t success; // 0 = false, 255 = true
    uint8_t unused[13];
    uint8_t crc;
}

ID: 15

struct BlinkTwiceRequest {
    uint8_t commandId = 15;
    uint8_t unused[14];
    uint8_t crc = 15;
}

Phone Call

ID: 17

struct PhoneCallResponse {
    uint8_t commandId = 17;
    uint8_t rejectCall; // boolean
    char unused[13];
    uint8_t crc;
}

Sports Request

TODO: Need response sample

ID: 19

struct SportsRequest {
    uint8_t commandId = 19;
    uint32_t time;
    uint8_t unused[13];
    uint8_t crc;
}

Blood Pressure

Request with Data Request

ID: 20

struct BloodPressureResponse {
    uint8_t commandId = 20;
    uint32_t time;
    uint8_t dbp;
    uint8_t sbp;
    char unused[8];
    uint8_t crc;
}

Heart Rate

Request with Data Request

Split array

ID: 21

struct HeartRateRequest {
    uint8_t commandId = 21;
    uint32_t unixTime; // UTC + Timezone offset in hours
    char unused[13];
    uint8_t crc;
}
struct HeartRateResponse {
    uint8_t commandId = 21;
    uint8_t index;
}

If index is 0:

struct HeartRateResponse {
    uint8_t commandId = 21;
    uint8_t index;
    uint8_t size;
    uint8_t range;
    char unused[11];
    uint8_t crc;
}

If index is 1:

struct HeartRateResponse {
    uint8_t commandId = 21;
    uint8_t index;
    uint32_t utcTime;
    uint8_t heartRateData[9];
    uint8_t crc;
}

If index is > 1:

struct HeartRateResponse {
    uint8_t commandId = 21;
    uint8_t index;
    uint8_t heartRateData[13];
    uint8_t crc;
}

Personalization Settings

ID: 23

struct PersonalizationSettingsRequest {
    uint8_t commandId = 23;
    uint8_t num1 = 1;
    uint8_t num2 = 2;
    uint8_t num3 = 3;
    char unused[11];
    uint8_t crc;
}
struct PersonalizationSettingsResponse {
    uint8_t commandId = 23;
    uint8_t clockSetting;
    uint8_t powerOnSetting;
    uint8_t powerOffSetting;
    char unused[11];
    uint8_t crc;
}

Weather Forecast

ID: 26

struct WeatherForecastRequest {
    uint8_t commandId = 26;
    uint8_t index;
    uint32_t timestamp;
    uint8_t weatherType;
    uint8_t minDegrees;
    uint8_t maxDegrees;
    uint8_t humidity;
    uint8_t takeUmbrella; // 1 is true, 2 is false
    char unused[4];
    uint8_t crc = 26;
}
struct WeatherForecastResponse {
    uint8_t commandId = 26;
    char unused[14];
    uint8_t crc = 26;
}

Music Switch

ID: 28

struct MusicSwitchRequest {
    uint8_t commandId = 28;
    uint8_t isPlaying;
    uint8_t progress;
    uint8_t volume;
    char songName[10];
    uint8_t crc;
}
struct MusicSwitchResponse {
    uint8_t commandId = 28;
    uint8_t action;
    uint8_t enable;
    char unused[12];
    uint8_t crc;
}

Music

ID: 29

struct MusicCommandResponse {
    uint8_t commandId = 29;
    MediaAction action;
    char unused[13];
    uint8_t crc;
}
enum MediaAction {
    Pause = 1,
    Previous = 2,
    Next = 3,
    VolumeUp = 4,
    VolumeDown = 5
}

Realtime Heart Rate

Request with Data Request

ID: 30

struct RealtimeHeartrateRequest {
    uint8_t commandId = 30;
    uint8_t type; // Variable but only set to 3 in app
    char unused[13];
    uint8_t crc;
}
struct RealtimeHeartrateResponse {
    uint8_t commandId = 30;
    uint8_t heartRate;
    char unused[13];
    uint8_t crc;
}

Find Phone

ID: 34

struct FindPhoneResponse {
    uint8_t commandId = 34;
    FindPhoneCmd findPhoneCmd;
    char unused[13];
    uint8_t crc;
}
enum FindPhoneCmd : uint8_t {
    StartRinging = 1,
    StopRinging = 2
}

Alarm

ID: 36

struct AlarmRequest {
    uint8_t commandId = 36;
    uint8_t index;
    char unused[13];
    uint8_t crc;
}
struct AlarmResponse {
    uint8_t commandId = 36;
    uint8_t index;
    uint8_t enabled;
    uint8_t hour;
    uint8_t minute;
    uint8_t weekMask[7];
    char unused[3];
    uint8_t crc;
}

Sit Long

ID: 37 (Request) ID: 38 (Response)

struct SitLong {
    uint8_t commandId;
    uint8_t startHour;
    uint8_t startMinute;
    uint8_t endHour;
    uint8_t endMinute;
    uint8_t weekMask;
    uint8_t cycle;
    char unused[8];
    uint8_t crc;
}

Drink Alarm

TODO: Does this have a response?

ID: 39

struct SetDrinkAlarmRequest {
    uint8_t commandId = 39;
    uint8_t alarmIndex;
    uint8_t isEnabled;
    uint8_t hour;
    uint8_t minute;
    uint8_t weekMask[7]; // Array of booleans 
    char unused[3];
    uint8_t crc;
}

Alarm

ID: 40

struct AlarmRequest {
    uint8_t commandId = 40;
    uint8_t index;
    char unused[13];
    uint8_t crc;
}
struct AlarmResponse {
    uint8_t commandId = 40;
    uint8_t index;
    uint8_t enabled;
    uint8_t hour;
    uint8_t minute;
    uint8_t weekMask[7]; // Seems the flags are split so byte 1 uses bit 1, byte 2 uses bit 2. Very inefficient.
    char unused[3];
    uint8_t crc;
}

Blacklist

TODO: Response?

ID: 45

struct BlackListRequest {
    uint8_t commandId = 45;
    uint8_t data = 1;
    char unused[13];
    uint8_t crc = 46;
}

Package Length

TODO: Request?

ID: 47

struct PackageLengthResponse {
    uint8_t commandId = 47;
    uint8_t packageLenth;
    char unused[13];
    uint8_t crc;
}

Avatar

ID: 50

struct DeviceAvatarRequest {
    uint8_t commandId = 50;
    char unused[14];
    uint8_t crc = 50;
}
struct DeviceAvatarResponse {
    uint8_t commandId = 50;
    uint8_t screenType;
    uint16_t width;
    uint16_t height;
    char unused[9];
    uint8_t crc;
}

Pressure

Split array

ID: 55

struct PressureRequest {
    uint8_t commandId = 55;
    uint8_t index;
    uint8_t unused[13];
    uint8_t crc = 55;
}
struct PressureResponse {
    uint8_t commandId = 55;
    uint8_t index;
}

If index is zero, read this:

struct PressureResponse {
    uint8_t commandId = 55;
    uint8_t index;
    uint8_t totalArraySize;
    uint8_t range;
}

If index is 1, read this:

struct PressureResponse {
    uint8_t commandId = 55;
    uint8_t index;
    uint8_t startOffset;
    uint8_t pressureData[12];
    uint8_t crc;
}

If index is > 1, read this:

struct PressureResponse {
    uint8_t commandId = 55;
    uint8_t index;
    uint8_t offset;
    uint8_t pressureData[12];
    uint8_t crc;
}

HRV

Split array

ID: 57

struct HRVRequest {
    uint8_t commandId = 57;
    uint8_t index;
    char unused[13];
    uint8_t crc;
}
struct HRVResponse {
    uint8_t commandId = 57;
    uint8_t index;
}

If index is 0, read this:

struct HRVResponse {
    uint8_t commandId = 57;
    uint8_t index;
    uint8_t totalArraySize;
    uint8_t range;
    char unused[11];
    uint8_t crc;
}

If index is 1, read this:

struct HRVResponse {
    uint8_t commandId = 57;
    uint8_t index;
    uint8_t startOffset;
    uint8_t HRVData[12];
    uint8_t crc;
}

If index is > 1, read this:

struct HRVResponse {
    uint8_t commandId = 57;
    uint8_t index;
    uint8_t HRVData[13];
    uint8_t crc;
}

Sports Data

ID: 67

struct SportsDataRequest {
    uint8_t commandId = 67;
    uint8_t dayIndex;
    uint8_t unk1; // Statically set to 15
    uint8_t unk2; // Only ever set to 0
    uint8_t unk3; // Only ever set to 95
    char unused[10];
    uint8_t crc;
}
struct SportsDataResponse {
    uint8_t commandId = 67;
    uint8_t year; // % 2000
    uint8_t month; // January = 1
    uint8_t day;
    uint8_t time;
    uint16_t calories;
    uint16_t steps;
    uint16_t distance;
    char unused[4];
    uint8_t crc;
}

Sleep Data

Newer request in Big Data

ID: 68

struct SleepDataRequest {
    uint8_t commandId = 68;
    uint8_t dayOffset;
    uint8_t unk1; // Statically set to 15
    uint8_t unk2; // Only ever set to 0
    uint8_t unk3; // Only ever set to 95
    char unused[3]
    uint8_t crc;
}
struct SleepDataResponse {
    uint8_t commandId = 68;
    uint8_t year; // value of 15 = 2015
    uint8_t month;
    uint8_t day; // starts at 1
    uint8_t time;
    uint8_t sleepQualities; //TODO
    char unused[3]
    uint8_t crc;
}

Today's Sports

TODO: Request?

ID: 72

struct TodaySportsResponse {
    uint8_t commandId = 72;
    uint32_t totalSteps : 24;
    uint32_t runningSteps : 24;
    uint32_t calories : 24;
    uint32_t walkingDistance : 24;
    uint16_t activityDuration;
    uint8_t crc;
}

Find Device

On rings, enables the green light for 10 seconds.

ID: 80

struct FindDeviceRequest {
    uint8_t commandId = 80;
    uint8_t data1 = 85;
    uint8_t data2 = 170;
    uint8_t unused[12];
    uint8_t crc;
}

ANCS Request

TODO: What does ANCS stand for?

ID: 96

struct ANCSRequest {
    uint8_t commandId = 96;
    uint8_t unk1 = 255;
    uint8_t unk2 = 159
    char unused[12];
    uint8_t crc;
}

Message Push

ID: 97

struct MessagePushResponse{
    uint8_t commandId = 97;
    char unused[2];
    uint16_t deviceSupport1;
    uint16_t deviceSupport2;
    uint16_t deviceSupport3;
    char unused[6];
    uint8_t crc;
}

Data Request

ID: 105

struct DataRequest {
    uint8_t commandId = 105;
    DataType dataType;
    DataAction dataAction;
    char unused[12];
    uint8_t crc;
}
enum DataType : uint8_t {
    HeartRate = 1,
    BloodPressure = 2,
    BloodOxygen = 3,
    Fatigue = 4,
    HealthCheck = 5,
    RealtimeHeartRate = 6,
    ECG = 7,
    Pressure = 8,
    BloodSugar = 9,
    HRV = 10
}
enum DataAction : uint8_t {
    Start = 1,
    Pause = 2,
    Continue = 3,
    Stop = 4
}

Stop Data Request

This shares an enumeration with 105, which supersets the features of this command. The 2 unknown fields are always set to 0 in the code, so I'm unsure of this command's purpose.

ID: 106

struct DataRequest {
    uint8_t commandId = 106;
    DataType dataType;
    uint8_t unk1;
    uint8_t unk2
    char unused[11];
    uint8_t crc;
}

3rd Party Push Message

Split array

ID: 114

struct PushMessageRequest {
    uint8_t commandId = 114;
    PushMessageSource source;
    uint8_t curDataLen;
    uint8_t curDataIndex;
    uint8_t data[11];
    uint8_t crc;
}
enum PushMessageSource : uint8_t {
    SMS = 1,
    QQ = 2,
    WeChat = 3,
    PhoneAction = 4,
    Facebook = 5,
    WhatsApp = 6,
    Twitter = 7,
    Skype = 8,
    Line = 9
}

App Activity

ID: 119

struct AppActivityResponse {
    uint8_t commandId = 119;
    uint8_t gpsStatus; // Unkown enumeration
    uint32_t timestamp; // Only exists when status gpsStatus = 6
}

Device Notify

ID: 115

struct DeviceNotifyResponse {
    uint8_t commandId = 115;
    NotifyType dataType;
    // TODO: Seems to be variable data
}

enum NotifyType : uint8_t {
    HeartRate = 1,
    BloodPressure = 2,
    BloodOxygen = 3,
    Steps = 4,
    Temperature = 5,
    Activity = 7
    //TODO there's more here
}