11. 运动功能
控制和同步设备的运动状态
11.1. 同步运动状态
//同步状态
//使用场景:1.App连接成功 2.app接收到开始运动命令 3.app主动发送开始运动命令
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
//初始化健康功能实现
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//执行读取运动信息功能并等待结果回调
healthOp.readSportsInfo(healthOp.getConnectedDevice(), new OnOperationCallback<SportsInfo>() {
@Override
public void onSuccess(SportsInfo result) {
//成功回调
//result.getMode();//运动类型
//result.getState(); //运动状态
//result.getId(); //运动id
//RcspUtil.intToTime(result.getId()); //运动开始时间
//result.getReadRealTimeDataInterval(); //同步运动实时数据的时间间隔
//result.getHeartRateMode();//运动的心率模式
}
@Override
public void onFailed(BaseError error) {
//失败回调
//error - 错误信息
}
});
11.2. 开始运动
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
//初始化健康功能实现
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//注册RCSP事件监听器
watchManager.registerOnRcspEventListener(new OnRcspEventListener() {
@Override
public void onSportsState(BluetoothDevice device, int state) {
//此处将会回调运动状态变化
if (state == StateCode.SPORT_STATE_RUNNING) { //正在运动
//同步设备状态
healthOp.readSportsInfo(device, null);
}
}
});
int mode = SportsInfoStatusSyncCmd.SPORTS_TYPE_OUTDOOR & 0xff; //户外运动模式
//执行开始运动功能并等待结果回调
healthOp.startSports(healthOp.getConnectedDevice(), mode, new OnOperationCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
//成功回调
//结果将会OnRcspEventListener#onSportsState回调
}
@Override
public void onFailed(BaseError error) {
//失败回调
//error - 错误信息
}
});
11.3. 暂停运动
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
//初始化健康功能实现
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//注册RCSP事件监听器
watchManager.registerOnRcspEventListener(new OnRcspEventListener() {
@Override
public void onSportsState(BluetoothDevice device, int state) {
//此处将会回调运动状态变化
if (state == StateCode.SPORT_STATE_PAUSE) { //运动暂停
//更新运动状态
}
}
});
//执行暂停运动功能并等待结果回调
healthOp.pauseSports(healthOp.getConnectedDevice(), new OnOperationCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
//成功回调
//结果将会OnRcspEventListener#onSportsState回调
}
@Override
public void onFailed(BaseError error) {
//失败回调
//error - 错误信息
}
});
11.4. 继续运动
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
//初始化健康功能实现
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//注册RCSP事件监听器
watchManager.registerOnRcspEventListener(new OnRcspEventListener() {
@Override
public void onSportsState(BluetoothDevice device, int state) {
//此处将会回调运动状态变化
if (state == StateCode.SPORT_STATE_RESUME) {//继续运动
//同步设备状态
//healthOp.readSportsInfo(device, null);
}
}
});
//执行继续运动功能并等待结果回调
healthOp.resumeSports(healthOp.getConnectedDevice(), new OnOperationCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
//成功回调
//结果将会OnRcspEventListener#onSportsState回调
}
@Override
public void onFailed(BaseError error) {
//失败回调
//error - 错误信息
}
});
11.5. 停止运动
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
//初始化健康功能实现
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//注册RCSP事件监听器
watchManager.registerOnRcspEventListener(new OnRcspEventListener() {
@Override
public void onSportsState(BluetoothDevice device, int state) {
//此处将会回调运动状态变化
if (state == StateCode.SPORT_STATE_NONE) { //运动结束
//处理运动信息
//1.获取运动信息,有两种方法
//1) 等待onSportInfoChange回调
//2) 获取缓存运动信息
// SportsInfo sportsInfo = watchManager.getDeviceInfo(device).getSportsInfo();
// sportsInfo.getEndTime(); //结束时间
// sportsInfo.getRecoveryTime(); //运动恢复时间
// sportsInfo.getRecordFileId(); //运动记录文件ID
// sportsInfo.getRecordFileSize(); //运动记录文件大小
// sportsInfo.getExerciseIntensityState(); //运动强度状态
//2.获取运动记录文件
// 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);
//详细参考文件传输功能说明
}
}
@Override
public void onSportInfoChange(BluetoothDevice device, SportsInfo sportsInfo) {
//此处将会回调改变的运动信息
}
});
//执行停止运动功能并等待结果回调
healthOp.stopSports(healthOp.getConnectedDevice(), new OnOperationCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
//成功回调
//结果将会OnRcspEventListener#onSportsState回调
}
@Override
public void onFailed(BaseError error) {
//失败回调
//error - 错误信息
}
});
11.6. 同步实时运动数据
//同步运动实时数据
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
//初始化健康功能实现
HealthOpImpl healthOp = new HealthOpImpl(watchManager);
//执行读取运动实时数据功能并等待结果回调
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;
}
//成功回调
// result.getVersion(); //版本
// result.getStep(); //运动步数
// result.getDistance(); //运动距离, 单位:0.01 km
// result.getDuration(); //运动时长, 单位:秒
// result.getSpeed(); //速度,单位:km/h
// result.getPace(); //配速,单位:s/km
// result.getCalorie(); //热量,单位:kcal
// result.getStepFreq(); //步频,单位:step/min
// result.getStride(); //步幅,单位:cm
// result.getExerciseStatus(); //运动强度状态:最大心率模式={0非运动、1热身、2燃脂、3有氧耐力、4无氧耐力、5极限}<br/>储备心率模式={0非运动、1有氧基础、2有氧进阶、3乳酸阈值、4无氧基础、5无氧进阶}
// result.getHeartRate(); //实时心率
}
@Override
public void onFailed(BaseError error) {
//失败回调
//error - 错误信息
}
});
11.7. 监听设备的运动状态变化
//监听设备的运动状态变化
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
//注册RCSP事件监听器
watchManager.registerOnRcspEventListener(new OnRcspEventListener() {
@Override
public void onSportsState(BluetoothDevice device, int state) {
//此处回调运动状态
switch (state) {
case StateCode.SPORT_STATE_NONE: //运动结束
//参考结束运动功能处理
break;
case StateCode.SPORT_STATE_RUNNING: //正在运动
//参考开始运动功能处理
break;
case StateCode.SPORT_STATE_PAUSE: //运动暂停
break;
case StateCode.SPORT_STATE_RESUME: //继续运动
break;
}
}
@Override
public void onSportInfoChange(BluetoothDevice device, SportsInfo sportsInfo) {
//此处回调运动信息
}
});
11.8. 读取运动记录文件
//WatchManager是WatchOpImpl的子类,须在1.3配置好sdk
WatchManager watchManager = WatchManager.getInstance();
QueryFileTask.File file; //通过运动结束命令或者查询文件列表获取到
byte type = file.type; //文件类型
short id = file.id; //文件id
int size = file.size; //要读取的内容大小
//注意:如果运动结束返回的file.id和file.size为0,则认为运动距离过短,设备没有保存运动记录
ReadFileTask.Param param = new ReadFileTask.Param(type, id, size, 0);
ReadFileTask task = new ReadFileTask(watchManager, param);
task.setListener(new SimpleTaskListener() {
@Override
public void onBegin() {
//开始
}
@Override
public void onError(int code, String msg) {
//异常
}
@Override
public void onFinish() {
//读取完成
byte [] data = task.getReadData(); //获取文件内容
SportRecord sportRecord = SportRecord.from(data);//解析运动数据内容
}
});
task.start();
11.9. 运动记录文件结构
运功记录文件通过小文件传输方式获取, 注意:运动记录的文件数据是以小端格式存储
偏移 |
长度 |
属性名 |
备注 |
|---|---|---|---|
Byte 0 |
1 |
运动模式 |
运动模式:参考 运动模式 |
Byte 1 |
1 |
版本号 |
有效范围: 0~255 |
Byte 2 |
1 |
间隔 |
有效范围: 1~180 , 单位是秒 |
Byte 3-12 |
10 |
保留位 |
格式如下:
Byte0 : mask — 检查校验位(0xee: 检查位完整 0xe0: 数据被破坏)
Byte1-4 : 数据信息
- Bit0-14 : block — 数据块(代表有多少个数据格式)
- Bit15-31 : size — 文件大小
Byte5-9 : reserved — 保留位
|
Byte 13-n |
n |
数据区域 |
数据格式: [flag(1Byte)+len(1Byte)+data] * n
heart rate: 心率, 有效范围: 0~220
speed: 速度, 有效范围: 0~8000, 单位是0.01公里/小时
pace: 配速, 单位:秒
n : 第n公里
flag: 标志位
- 0: 开始时间包: 参考 时间结构(4Bytes)
- 1: 基础包: heart(1Byte)+step_freq(2Bytes)+speed(2Bytes)
- 2: 暂停包: 参考 时间结构(4Bytes)
- 3: 每公里配速包: pace(2Bytes)+n(1Byte)
- 0xff: 结束包: 参考 时间结构(4Bytes)
|
Byte(n+1)-(n+2) |
2 |
时长 |
有效范围: 1-28800, 单位是秒 |
Byte(n+3)-(n+6) |
4 |
保留位 |
保留位 |
Byte(n+7)-(n+8) |
2 |
距离 |
有效范围: 1-65535, 单位是0.01公里 |
Byte(n+9)-(n+10) |
2 |
热量 |
有效范围: 1-65535, 单位是千卡, Kcal |
Byte(n+11)-(n+14) |
4 |
步数 |
有效范围: 0-200000, 单位是步 |
Byte(n+15)-(n+16) |
2 |
恢复时间 |
Byte(n+15): 时, 单位是1小时, 有效范围: 0~168
Byte(n+16): 分, 单位是1分钟, 有效范围: 0~60
|
Byte(n+17) |
1 |
心率模式 |
0x00: 最大心率模式 0x01: 存储心率模式 |
Byte(n+18)-(n+38) |
20 |
运动强度状态站比时长 |
(4Bytes为一组, 从模式1开始), 单位是秒 |
11.9.1. 运动模式
模式名称 |
模式值 |
|---|---|
非运动模式 |
0x00 |
室外跑步 |
0x01 |
室内跑步 |
0x02 |
11.9.2. 时间结构(4Bytes)
意义 |
年 |
月 |
日 |
时 |
分 |
秒 |
|---|---|---|---|---|---|---|
位置 |
Bit31-26 |
Bit25-22 |
Bit21-17 |
Bit16-12 |
Bit11-6 |
Bit5-0 |
长度(bit) |
6 |
4 |
5 |
5 |
6 |
6 |
备注 |
起始时间:2010 |
1~12 |
1 ~ 31 |
0 ~ 24 |
0 ~ 59 |
0 ~ 59 |
举例:
2021-08-02 10:10:10
2E04A28A
00 1011 1000 00010 01010 001010 001010
年 月 天 时 分 秒