11. Sports Function

Control and synchronize device sports status

11.1. Synchronize Sports Status

//Synchronize status
//Usage scenarios: 1.App connects successfully  2.App receives start sports command 3.App actively sends start sports command
//WatchManager is a subclass of WatchOpImpl, must be configured in sdk 1.3
WatchManager watchManager = WatchManager.getInstance();
//Initialize health function implementation
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//Execute read sports information function and wait for result callback
healthOp.readSportsInfo(healthOp.getConnectedDevice(), new OnOperationCallback<SportsInfo>() {
    @Override
    public void onSuccess(SportsInfo result) {
        //Success callback
        //result.getMode();//Sports type
        //result.getState(); //Sports status
        //result.getId(); //Sports ID
        //RcspUtil.intToTime(result.getId()); //Sports start time
        //result.getReadRealTimeDataInterval(); //Time interval for synchronizing real-time sports data
        //result.getHeartRateMode();//Sports heart rate mode
    }

    @Override
    public void onFailed(BaseError error) {
        //Failure callback
        //error - Error message
    }
});

11.2. Start Sports

//WatchManager is a subclass of WatchOpImpl, must be configured in sdk 1.3
WatchManager watchManager = WatchManager.getInstance();
//Initialize health function implementation
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//Register RCSP event listener
watchManager.registerOnRcspEventListener(new OnRcspEventListener() {
    @Override
    public void onSportsState(BluetoothDevice device, int state) {
        //This will callback sports status changes
        if (state == StateCode.SPORT_STATE_RUNNING) { //In sports
            //Synchronize device status
            healthOp.readSportsInfo(device, null);
        }
    }
});
int mode = SportsInfoStatusSyncCmd.SPORTS_TYPE_OUTDOOR & 0xff; //Outdoor sports mode
//Execute start sports function and wait for result callback
healthOp.startSports(healthOp.getConnectedDevice(), mode, new OnOperationCallback<Boolean>() {
    @Override
    public void onSuccess(Boolean result) {
        //Success callback
        //Result will be OnRcspEventListener#onSportsState callback
    }

    @Override
    public void onFailed(BaseError error) {
        //Failure callback
        //error - Error message
    }
});

11.3. Pause Sports

//WatchManager is a subclass of WatchOpImpl, must be configured in sdk 1.3
WatchManager watchManager = WatchManager.getInstance();
//Initialize health function implementation
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//Register RCSP event listener
watchManager.registerOnRcspEventListener(new OnRcspEventListener() {
    @Override
    public void onSportsState(BluetoothDevice device, int state) {
        //This will callback sports status changes
        if (state == StateCode.SPORT_STATE_PAUSE) { //Sports paused
            //Update sports status
        }
    }
});
//Execute pause sports function and wait for result callback
healthOp.pauseSports(healthOp.getConnectedDevice(), new OnOperationCallback<Boolean>() {
    @Override
    public void onSuccess(Boolean result) {
        //Success callback
        //Result will be OnRcspEventListener#onSportsState callback
    }

     @Override
    public void onFailed(BaseError error) {
        //Failure callback
        //error - Error message
    }
});

11.4. Resume Sports

//WatchManager is a subclass of WatchOpImpl, must be configured in sdk 1.3
WatchManager watchManager = WatchManager.getInstance();
//Initialize health function implementation
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//Register RCSP event listener
watchManager.registerOnRcspEventListener(new OnRcspEventListener() {
    @Override
    public void onSportsState(BluetoothDevice device, int state) {
        //This will callback sports status changes
        if (state == StateCode.SPORT_STATE_RESUME) {//Resume sports
            //Synchronize device status
            //healthOp.readSportsInfo(device, null);
        }
    }
});
//Execute resume sports function and wait for result callback
healthOp.resumeSports(healthOp.getConnectedDevice(), new OnOperationCallback<Boolean>() {
    @Override
    public void onSuccess(Boolean result) {
        //Success callback
        //Result will be OnRcspEventListener#onSportsState callback
    }

    @Override
    public void onFailed(BaseError error) {
        //Failure callback
        //error - Error message
    }
});

11.5. Stop Sports

//WatchManager is a subclass of WatchOpImpl, must be configured in sdk 1.3
WatchManager watchManager = WatchManager.getInstance();
//Initialize health function implementation
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//Register RCSP event listener
watchManager.registerOnRcspEventListener(new OnRcspEventListener() {
    @Override
    public void onSportsState(BluetoothDevice device, int state) {
        //This will callback sports status changes
        if (state == StateCode.SPORT_STATE_NONE) { //Sports ended
            //Process sports information
            //1. Get sports information, two methods
            //1) Wait for onSportInfoChange callback
            //2) Get cached sports information
//               SportsInfo sportsInfo = watchManager.getDeviceInfo(device).getSportsInfo();
//               sportsInfo.getEndTime(); //End time
//               sportsInfo.getRecoveryTime(); //Sports recovery time
//               sportsInfo.getRecordFileId(); //Sports record file ID
//               sportsInfo.getRecordFileSize(); //Sports record file size
//               sportsInfo.getExerciseIntensityState(); //Sports intensity status
            //2. Get sports record file
//               QueryFileTask.File file = new QueryFileTask.File(QueryFileTask.TYPE_SPORTS_RECORD, sportsInfo.getRecordFileId(), sportsInfo.getRecordFileSize());
//               ReadFileTask.Param param = new ReadFileTask.Param(QueryFileTask.TYPE_SPORTS_RECORD, (short) file.id, file.size, 0);
                //Detailed reference file transfer function description
        }
    }

    @Override
    public void onSportInfoChange(BluetoothDevice device, SportsInfo sportsInfo) {
        //This will callback changed sports information

    }
});
//Execute stop sports function and wait for result callback
healthOp.stopSports(healthOp.getConnectedDevice(), new OnOperationCallback<Boolean>() {
    @Override
    public void onSuccess(Boolean result) {
        //Success callback
        //Result will be OnRcspEventListener#onSportsState callback
    }

    @Override
    public void onFailed(BaseError error) {
        //Failure callback
         //error - Error message
    }
});

11.6. Synchronize Real-time Sports Data

//Synchronize real-time sports data
//WatchManager is a subclass of WatchOpImpl, must be configured in sdk 1.3
WatchManager watchManager = WatchManager.getInstance();
//Initialize health function implementation
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//Execute read real-time sports data function and wait for result callback
healthOp.readRealTimeSportsData(healthOp.getConnectedDevice(), new OnOperationCallback<RealTimeSportsData>() {
    @Override
    public void onSuccess(RealTimeSportsData result) {
        if(result == null){
            onFailed(new BaseError(RcspErrorCode.ERR_RESPONSE_BAD_RESULT, "Real time data is null."));
            return;
        }
        //Success callback
//        result.getVersion();        //Version
//        result.getStep();           //Sports steps
//        result.getDistance();       //Sports distance, unit: 0.01 km
//        result.getDuration();       //Sports duration, unit: seconds
//        result.getSpeed();          //Speed, unit: km/h
//        result.getPace();           //Pace, unit: s/km
//        result.getCalorie();        //Calories, unit: kcal
//        result.getStepFreq();       //Step frequency, unit: step/min
//        result.getStride();         //Stride, unit: cm
//        result.getExerciseStatus(); //Exercise intensity status: Max HR mode={0 non-exercise, 1 warm-up, 2 fat burning, 3 aerobic endurance, 4 anaerobic endurance, 5 limit}<br/>HR Reserve mode={0 non-exercise, 1 aerobic base, 2 aerobic advance, 3 lactate threshold, 4 anaerobic base, 5 anaerobic advance}
//        result.getHeartRate();      //Real-time heart rate
    }

    @Override
    public void onFailed(BaseError error) {
        //Failure callback
        //error - Error message
    }
});

11.7. Listen to Device Sports Status Changes

//Listen to device sports status changes
//WatchManager is a subclass of WatchOpImpl, must be configured in sdk 1.3
WatchManager watchManager = WatchManager.getInstance();
//Register RCSP event listener
watchManager.registerOnRcspEventListener(new OnRcspEventListener() {
    @Override
    public void onSportsState(BluetoothDevice device, int state) {
        //This callbacks sports status
        switch (state) {
            case StateCode.SPORT_STATE_NONE:     //Sports ended
                //Reference end sports function processing
                break;
            case StateCode.SPORT_STATE_RUNNING:  //In sports
                //Reference start sports function processing
                break;
            case StateCode.SPORT_STATE_PAUSE:    //Sports paused
                break;
            case StateCode.SPORT_STATE_RESUME:   //Resume sports
                break;
        }
    }

    @Override
    public void onSportInfoChange(BluetoothDevice device, SportsInfo sportsInfo) {
        //This callbacks sports information
    }
});

11.8. Read Sports Record File

//WatchManager is a subclass of WatchOpImpl, must be configured in sdk 1.3
WatchManager watchManager = WatchManager.getInstance();
QueryFileTask.File file; //Obtained through sports end command or query file list
byte type = file.type; //File type
short id = file.id; //File ID
int size = file.size; //Content size to read
//Note: If the file.id and file.size returned by sports end are 0, it means the sports distance was too short and the device did not save the sports record
ReadFileTask.Param param = new ReadFileTask.Param(type, id, size, 0);
ReadFileTask task = new ReadFileTask(watchManager, param);
task.setListener(new SimpleTaskListener() {

    @Override
    public void onBegin() {
        //Start
    }

    @Override
    public void onError(int code, String msg) {
        //Exception
    }

    @Override
    public void onFinish() {
        //Read complete
        byte [] data =  task.getReadData(); //Get file content
        SportRecord sportRecord = SportRecord.from(data);//Parse sports data content
    }
});
task.start();

11.9. Sports Record File Structure

Sports record file obtained via small file transfer, Note: Sports record file data is stored in little-endian format

Offset

Length

Attribute Name

Remarks

Byte 0

1

Sports Mode

Sports mode: refer to Sports Modes

Byte 1

1

Version Number

Valid range: 0~255

Byte 2

1

Interval

Valid range: 1~180, unit is second

Byte 3-12

10

Reserved

Format as follows:
Byte0 : mask — Check validation bit (0xee: complete check bit 0xe0: data corrupted)
Byte1-4 : Data information
- Bit0-14 : block — Data block (represents how many data formats)
- Bit15-31 : size — File size
Byte5-9 : reserved — Reserved bits

Byte 13-n

n

Data Area

Data format: [flag(1Byte)+len(1Byte)+data] * n
heart rate: Heart rate, valid range: 0~220
speed: Speed, valid range: 0~8000, unit is 0.01 km/h
pace: Pace, unit: second
n : nth kilometer
flag: Flag bit
- 0: Start time package: refer to Time Structure (4Bytes)
- 1: Basic package: heart(1Byte)+step_freq(2Bytes)+speed(2Bytes)
- 2: Pause package: refer to Time Structure (4Bytes)
- 3: Per kilometer pace package: pace(2Bytes)+n(1Byte)
- 0xff: End package: refer to Time Structure (4Bytes)

Byte(n+1)-(n+2)

2

Duration

Valid range: 1-28800, unit is second

Byte(n+3)-(n+6)

4

Reserved

Reserved

Byte(n+7)-(n+8)

2

Distance

Valid range: 1-65535, unit is 0.01 km

Byte(n+9)-(n+10)

2

Calories

Valid range: 1-65535, unit is kcal, Kcal

Byte(n+11)-(n+14)

4

Steps

Valid range: 0-200000, unit is steps

Byte(n+15)-(n+16)

2

Recovery Time

Byte(n+15): Hour, unit is 1 hour, valid range: 0~168
Byte(n+16): Minute, unit is 1 minute, valid range: 0~60

Byte(n+17)

1

Heart Rate Mode

0x00: Max HR mode 0x01: HR Reserve mode

Byte(n+18)-(n+38)

20

Exercise Intensity Status Ratio Duration

(4Bytes per group, starting from mode 1), unit is second

11.9.1. Sports Modes

Mode Name

Mode Value

Non-sports Mode

0x00

Outdoor Running

0x01

Indoor Running

0x02

11.9.2. Time Structure (4Bytes)

Meaning

Year

Mont

Day

Hour

Minute

Second

Position

Bit31-26

Bit25-22

Bit21-17

Bit16-12

Bit11-6

Bit5-0

Length(bit)

6

4

5

5

6

6

Remarks

Start year:2010

1~12

1 ~ 31

0 ~ 24

0 ~ 59

0 ~ 59

Example:
2021-08-02 10:10:10
2E04A28A
00 1011   1000  00010     01010    001010    001010
   Year   Month   Day     Hour     Minute    Second