2.5. 详细时序图¶
2.5.1. 获取手环状态¶
网关发送 CougarRequest.status() 可以获取手环的 时间戳,软件版本和硬件版本。
2.5.2. 设置手环¶
设置里包含多个设置项。这些设置项可以独立设置,也可以组合在一起一次设置。但是`擦除`需要单独一条命令。如果设置里包含`擦除`,那么其他设置会被忽略。
如果有多条设置项一起下发,手环是按下列顺序处理。一个设置项出错就会返回错误,剩余设置项会被跳过。
擦除(erase)
新的时间戳(newTimestamp)
广播设置(advSettings)
Beacon 扫描设置(beaconScanSettings)
休眠设置(sleepSettings)
下面对每个设置项依次介绍:
2.5.2.1. 新的时间戳(newTimestamp)¶
手环只关心以秒为单位的时间戳而非日期。初次上电或重启之后时间戳是0,且不会自增。获取到新的时间戳后,手环的时间戳才开始按秒自增,并采集记录传感器数据。
重要
因为更小的数字在传输时可以节约字节数,所以可以用最近的某个时间点(比如2025/01/01 00:00:00)作为初始时间。
一个手环的初始时间确定之后,不可以往回大幅(超过2分钟)修改。
手环每天的时间漂移不到10秒。网关可以每天使用此命令更新一下手环的时间。手环会在2分钟之内慢慢更新到新时间,以防止记录的传感器数据的时间戳回退或大幅跳跃。
手环返回的 errorCode 含义如下:
SettingErrorCode.SE_SUCCESS: 成功
SettingErrorCode.SE_INVALID_PARAMETER: 手环时间戳 - 新时间戳 > 2 分钟
2.5.2.2. 广播设置(advSettings)¶
为了节省电量,手环BLE广播有以下两个规则:
广播是按照广播1秒,停止1s这个循环工作的。目前此行为不可修改,未来可能会做调整。
在每天的工作时段,如果网关从手环取走了所有的数据,广播会停止一段时间,然后再次开启。
此设置可以控制广播停止时长:最小报告时间间隔(miniReportThresholdInMinute),单位是分钟,从网关断开BLE连接开始计算。
手环返回的 errorCode 含义如下:
SettingErrorCode.SE_SUCCESS: 成功
SettingErrorCode.SE_INVALID_PARAMETER: 参数范围不合法。miniReportThresholdInMinute 合法范围是:[1, 60]。
2.5.2.3. Beacon 扫描设置(beaconScanSettings)¶
Beacon 扫描设置控制的是手环扫描Beacon的行为。总共包含五个参数,其中前三个是底层BLE的参数需要和Beacon的广播匹配,以便能尽快扫描到Beacon以节省电量。
bleInterval:手环会以这个周期开始持续扫描。数值合法范围是[4,16384],单位是625us
bleWindow: 一个 bleInterval 周期内 BLE 持续扫描的时间。数值合法范围是[4,16384],单位是625us,必须小于等于bleInterval。
bleDuration:一次BLE扫描的持续时间。单位10ms。必须大于0。
intervalInSecond:多久触发一次扫描Beacon。每次扫描都会按前3个参数设计的行为扫描Beacon,直到超时。
beaconMACs:需要扫描的Beacon的MAC地址。这是一个数组,里面可以包含最多20个MAC地址,每个MAC是6字节。MAC地址之间没有分隔符。
几个扫描行为的参数的关系¶
手环返回的 errorCode 含义如下:
SettingErrorCode.SE_SUCCESS: 成功
SettingErrorCode.SE_INVALID_PARAMETER: 参数范围不合法。
注意
这个接口没有最终确定。
2.5.2.4. 休眠设置(sleepSettings)¶
休眠是为了让手环完全进入低功耗模式。休眠时间到时,手环会停止采集数据,停止BLE广播(如果手环有数据未上传,不会关闭BLE广播),停止扫描Beacon。
休眠设置有两个参数:
append : 此设置里的休眠命令是追加还是替换之前的休眠命令。为 True,则追加。为 False,则替换。
sleepCommands: 这是一个数组。表明一系列时间戳和对应的时间。比如:在1000秒休眠,在1500秒唤醒,在2000秒休眠,在2500秒唤醒。
SleepCommand 结构包含如下两个成员: #. timeStampInSecond: 事件的时间戳 #. sleep: True 为休眠,False 为唤醒。
手环返回的 errorCode 含义如下:
SettingErrorCode.SE_SUCCESS: 成功
SettingErrorCode.SE_INVALID_PARAMETER: 休眠设置里最后一个命令必须是唤醒。
2.5.2.5. 擦除(erase)¶
可以选择擦除
用户数据(EraseOptions.EO_PERSONAL)
设置(EraseOptions.EO_SETTINGS)
全部(EraseOptions.EO_ALL)
擦除 设置 或者 全部 之后,手环不会回复response直接重启。状态回到初次上电。
手环返回的 errorCode 含义如下:
SettingErrorCode.SE_SUCCESS: 成功
2.5.3. 获取传感器记录的数据¶
Step 1 中网关必须填写 startTimestamp 和 endTimestamp 来指定获取哪个时间段的数据。
手环收到request后会准备数据。因为要发送的数据可能会超过MTU,所以数据会被拆分成N个包发送。网关收到的 CougarResponse.report 规则如下:
index 从 0 开始,每发送一个包,index会增加1。
data是被拆分的数据。如果网关收到了一个 data 的长度为0,则表明数据全部发送完毕,
不同传感器的 data 格式各不相同,里面包含若干个传感器数据单元。(例如,心跳的数据单元是:时间戳+心跳值)
一个传感器数据单元不会被拆分到两个 CougarResponse.report.data 里。
传感器数据单元里的格式是经过简单压缩编码的。首先,需要了解如下编码格式:Varints。
2.5.3.1. 数据的基本编码格式(Varints)¶
Varints 会把一个int编码成一个变长数组。数组里每一个字节都是一个基本单元。
一个基本单元由一个标识位(F)和7个数据位组成。如果MSB是1,代表后续还有基本单元。MSB是0,则这个最后一个单元。
Varints的基本单元结构¶
下面是两个例子,分别展示如何解码 0000 0001 和 10010110 00000001
Varints解码示例¶
2.5.3.2. 负数问题(ZigZag)¶
如果一个int是负数,按照Varints规则会编出一个最长数据。所以对于一个可能是负数的待编码数据,使用 ZigZag 编码把负数转成正数,再用 Varints 编码。
ZigZag 编码规则是:正数n编码成 2*n,负数n编码成 2 * -n - 1。 如0编成0, 1 编成 2,-1 编成 1, -2 编成 3。
ZigZag编码¶
解码一个ZigZag数据使用如下代码:
1n = (n >> 1) ^ -(n & 1)
备注
负数经过 ZigZag 编码之后,再经过 Varints 编码就可以把编码之后的长度缩小很多。换来的代价是正数的编码比直接 Varints 编码可能会略长。
2.5.3.3. 心率数据的格式¶
每一个有效的 CougarResponse.report.data 里面都是一个 时间戳差值(dt)+心跳(h) 结构 的数组。示例如下:
心率数据格式¶
dt均经过Varints编码,心率值是一个字节(uint8_t)的原始数据。
dt0代表的时间差是指此心跳数据和 startTimestamp 之间的差值。dt1代表的时间差是指此心跳数据和前一个时间戳的差值。后面以此类推。
2.5.3.4. 加速度数据的格式¶
和心跳数据格式类似,加速度data里的格式是一个 时间戳差值(dt)+x+y+z 结构 的数组。示例如下:
加速度数据格式¶
dt的编码和含义同心率。x,y,z存储的是对应轴上的加速度值。因为可能有正负,所以x,y,z都是经过ZigZag编码再Varints编码。
注意
这个数据格式没有最终确定。
2.5.3.5. Beacon扫描数据的格式¶
因为Beacon的数据量不会很大,所以数据不进行压缩。数据格式是一个存储了下列格式的数组。
单个Beacon数据格式¶
2.5.3.6. 体温数据的格式¶
体温的数据量也不会很大,所以数据也不进行压缩。数据格式是一个存储了下列格式的数组。
单个体温数据格式¶
备注
体温是一个字节的有符号数