小度蓝牙Mesh软件规范
应用场景
- 基础协议:小度蓝牙Mesh软件规范的基础是蓝牙技术联盟(Bluetooth SIG)在2017年发布的蓝牙Mesh协议。
- 应用场景:小度蓝牙Mesh软件规范主要应用在家居场景,一般为不超过200平米的3居室,音箱与被控设备的直线距离一般不超过15米,中间可以相隔一道15cm的实心墙壁。以下是小度系列音箱的蓝牙信号接收灵敏度数据,供智能硬件厂商参考进行做出合理的蓝牙芯片选型。
产品型号 | BLE发射信号强度(距离设备1米内) | BLE接收灵敏度 |
---|---|---|
小度音箱标准版 | -22dBm | -90dBm |
小度音箱1S | -22dBm | -90dBm |
小度音箱cube | -20dBm | -93dBm |
小度音箱Metal | -19dBm | -92dBm |
小度在家1S | -23dBm | -91.5dBm |
小度在家1C | -19dBm | -91.5dBm |
小度在家1L | -19dBm | -91dBm |
小度在家X8 | -25dBm | -89dBm |
- 主控音箱:目前在售的小度在家智能屏和小度音箱,都已经支持蓝牙Mesh协议(现已停售的2018年4月发布的小度在家1代,目前没有支持计划)。如果没有特别说明,下文中『小度音箱』指代所有支持蓝牙Mesh的小度在家智能屏和小度音箱,小度音箱在蓝牙Mesh网络中作为provisioner。下文中『外设』指代通过小度音箱入网的蓝牙Mesh智能设备(如照明设备、窗帘)。
- 外设品类:对于照明品类和只具备简单开关操作的设备品类,可以通过蓝牙Mesh标准Mesh Model支持。对于其他在蓝牙Mesh标准中未定义的品类,或蓝牙Mesh标准中未定义的操作,例如窗帘、墙壁开关、红外遥控器、低功耗按钮等,采用百度自定义Vendor Mesh Model支持。百度自定义Vendor Mesh Model已经支持了窗帘、红外遥控器和低功耗品类品类,在后续的标准升级过程中会确保向后兼容性(即新版本的小度音箱持续支持较早版本的外设),并尽量保证向前兼容性(即较早版本的音箱也支持新版本的外设)。
- 外设功能:通过电源供电的蓝牙Mesh外设必须具备Relay和Proxy功能,Friend功能可选。蓝牙Mesh设备至少支持2个NetKey(2个NetKey是支持KeyRefresh的必要条件)。支持Relay的外设建议TTL设置该值为4。
基础规范
设备识别和鉴权约定
- 蓝牙Mesh在行业中经过一段时间的推广,目前市面上已经快速发展出大量蓝牙Mesh设备,覆盖了多个智能设备品类,支持这些智能设备的芯片厂商和模组厂商数量也非常大。为了方便智能硬件生产厂商能够最高效地接入到小度蓝牙Mesh平台,快速实现规模化量产上市,我们采取了与现存大多数蓝牙Mesh设备兼容的设备识别方式。
- 设备识别:外设的识别信息编码在UUID字段中,该UUID信息包含在蓝牙Mesh设备启动时的未配网广播包中(Unprovisioned Device beacon)。
- Unprovisioned Device beacon格式:
- Device UUID的格式(UUID中各字段采用小端模式进行存储):
Field | Size(Byte) | Notes |
---|---|---|
CID | 2 | 公司ID,设置为0x011C:BIDU |
PID | 1 | bit0-3::蓝牙广播包版本号,目前是0x01;bit4设置为1,表示一机一密;bit5设置为1,表示支持OTA;bit6~7:蓝牙版本,枚举值 {00:BLE4.0 ,01:BLE4.2,10:BLE5.0,11:BLE5.0以上} |
ProductID | 4 | 百度颁发,一型一号 |
MAC地址 | 6 | 百度颁发,一机一号 |
FeatureFlag | 1 | bit0: 广播消息类型,枚举值{0:处于未配网广播;1:处于静默广播状态} |
RFU | 2 | Reserved for future use,0x0001 ~ 0xffff |
- 鉴权约定:小度音箱和外设之间的认证通过Static OOB,也就是在蓝牙Mesh外设中提前烧录由百度发放的三元组信息。
- Static OOB: BLE Mesh支持Input OOB、Output OOB、Static OOB和No OOB四种认证数据交互方式。但包括照明设备在内,大多数设备既不支持有效地显示数字、编号等信息,也不支持输入信息。为了确保小度音箱和外设之间有双向认证,小度音箱统一采用Static OOB。
- 有关三元组的详细信息参见:安全认证
设备发现和配网过程
设备配网分为provisioning和configuration两个阶段,小度要求两个阶段都成功,设备配网才算成功。如果出现provisioning阶段成功,configuration阶段失败,希望外设能够自行回退到未配网状态,即广播unprovision device beacon和0x1827 service uuid。
- 在设备发现和配网过程中,小度音箱蓝牙Mesh运行在provision模式,scan interval/scan window为60ms/30ms,配网过程结束后,蓝牙Mesh切换到Standby模式
- 设备发现:根据蓝牙Mesh协议,外设在进入配网状态后,开始持续广播Unprovisioned Device beacon。当小度音箱扫描到外设的广播包且用户确认给该设备配网后,就会发起连接。
- 广播时长:电源供电的蓝牙Mesh设备,例如照明设备,直流窗帘电机等,建议广播至少5分钟。用户可能希望对多个设备加电复位后,一次性地对这多个设备完成配网,由于目前小度音箱只能串行对每个蓝牙Mesh设备进行配网,因此建议外设广播至少5分钟。电池类的低功耗设备,建议广播至少1分钟,以便用户在复位外设进入配网状态后,还有充足的时间触发小度音箱并开始发现设备。
- 打包频率:建议adv interval为10ms,即每10ms向37、38、39信道发送一个Unprovisioned Device beacon广播报文。
- provisioning:音箱与外设通过Static OOB完成双向认证,这一过程严格遵守蓝牙Mesh规范。认证完成后,小度音箱会按照协议将NetKey、Unicast Address等信息发送给外设。
- Provision和Config阶段小度音箱的scan interval/scan window为60ms/30ms; 在Provision和Config阶段,建议外设发送广播时adv interval为10ms,adv period至少60ms
- 地址维护:目前小度音箱的NetKey由云端维护,一般情况下,同一账号的小度音箱NetKey一致。UnicastAddress,也统一通过云端分配和维护,大致策略如下:
地址 | 范围 | 分配策略 | 说明 |
---|---|---|---|
UnicastAddress | [0x0001 ~ 0x7fff],其中[0x0001, 0x7000]地址分配给设备,最多分配28671个;[0x7001, 0x7fff]地址分配给小度音箱,最多分给4095个 | 假设当前账号下已分配的地址是MaxUnicastAdress,第N+1次给设备分配时,从MaxUnicastAdress + 1开始连续分配sizeofelement)个 | 参考《Mesh Profile v1.0.1》3.4.2.2 |
GroupAddress | [0xc001, 0xcfff] | IoT支持的分组个已确定,不同类型逐一递增分配个组地址,映射到不同的分组 | 参考《Mesh Profile v1.0.1》3.4.2.4 |
- config:Provisioning完成后,音箱会对外设进行设置,例如设置外设订阅房间位置的分组地址和品类的分组地址,以便实现按位置和按品类的控制
- Config 阶段音箱端发送message后,如果在1s内没有收到外设反馈的status,会重试4次发送config message
- Heartbeat Publication Set和Model Subscription Add根据设备ProductID进行配置;其中Model Subscription Add,音箱端会对默认Bind的Model设置一次,其余使用的Model(如果存在的话)由外设自行完成订阅的操作,旨在优化Config过程的交互时间和成功率
- Config Model AppKey Bind操作绑定的Model由外设品类决定。为了优化Config过程的交互时间和成功率,小度音箱只会发起对一个Model进行Bind,如果外设支持多个Model,其他Model的Bind操作由设备端自动完成,Bind规则见下表
- 其中Data Trans Server Model是百度自定义的Vendor Mesh Model,用于控制目前标准蓝牙Mesh未定义的操作。Data Trans Model分为Client Model(Data Trans Client, model Id是0x0001011C)和 Model(Data Trans Server, model Id是0x0002011C)
品类 | 小度音箱配网时设置Bind的Model | 外设需要默认自行Bind的Model | 音箱是否设置Heartbeat |
---|---|---|---|
照明 | Generic OnOff Server (0x1000) | Generic OnOff Server (0x1000) Light Lightness Server (0x1300) Light CTL Server (0x1303) Data Trans Server(0x0002011C)[如果支持彩灯才会bind此Model] |
是 |
按钮 | Data Trans Server(0x0002011C) | Data Trans Server(0x0002011C) | 否 |
红外 | Data Trans Server(0x0002011C) | Data Trans Server(0x0002011C) | 是 |
插座 | Generic OnOff Server (0x1000) | Generic OnOff Server (0x1000) | 是 |
窗帘 | Generic OnOff Server (0x1000) | Generic OnOff Server (0x1000) Data Trans (0x0002011C) |
是 |
- Config Model Subscription Add是为了给外设设置订阅的分组地址,这里一般包括两类分组地址,品类分组地址和品类所在位置的地址; 例如照明品类,我们在小度音箱上约定其分组地址是0xc001;对于照明品类在卧室区域的,我们在小度音箱上约定其分组地址是0xc005; 下面是枚举的各个品类的分组地址,以及各个品类在常见的家庭位置中的分组地址:
品类 | 位置 | 组地址 |
---|---|---|
灯泡 | 品类分组地址 | c001 |
插座 | 品类分组地址 | c024 |
窗帘 | 品类分组地址 | c047 |
开关 | 品类分组地址 | c06d |
灯泡 | 主卧 | c002 |
插座 | 主卧 | c025 |
窗帘 | 主卧 | c048 |
开关 | 主卧 | c06e |
灯泡 | 次卧 | c003 |
插座 | 次卧 | c026 |
窗帘 | 次卧 | c049 |
开关 | 次卧 | c06f |
灯泡 | 客厅 | c004 |
插座 | 客厅 | c027 |
窗帘 | 客厅 | c04a |
开关 | 客厅 | c070 |
灯泡 | 卧室 | c005 |
插座 | 卧室 | c028 |
窗帘 | 卧室 | c04b |
开关 | 卧室 | c071 |
灯泡 | 餐厅 | c006 |
插座 | 餐厅 | c029 |
窗帘 | 餐厅 | c04c |
开关 | 餐厅 | c072 |
灯泡 | 书房 | c007 |
插座 | 书房 | c02a |
窗帘 | 书房 | c04d |
开关 | 书房 | c073 |
灯泡 | 厨房 | c008 |
插座 | 厨房 | c02b |
窗帘 | 厨房 | c04e |
开关 | 厨房 | c074 |
灯泡 | 洗手间 | c009 |
插座 | 洗手间 | c02c |
窗帘 | 洗手间 | c04f |
开关 | 洗手间 | c075 |
... | ... | ... |
灯泡 | 其他位置 | c06a |
插座 | 其他位置 | c06b |
窗帘 | 其他位置 | c06c |
开关 | 其他位置 | c090 |
- 小度音箱对照明品类的外设配网全过程时序图
控制过程
-
控制对外设的要求
- 外设收到需要回复ack的控制命令,在回复ack时候,外设需要保证ack消息的dst等于控制命令的src;
- 外设收到控制命令,若参数10秒内与上一次控制命令完全一致,当作重复指令处理,需要回复ack的命令,只回复ack不执行即可;
- 外设收到控制命令,需要回复二次确认或者本地事件上报,外设回复消息的dst等于前一次控制命令的src;建议这个机制维护30s,超时之后仍然走组播上报;
- 控制过程中,小度音箱处于控制模式,scan interval/scan window为90ms/20ms,在控制操作完成后,小度音箱蓝牙Mesh从控制模式返回到Standby模式;在响应小度音箱的控制请求时,建议外设发送数据包的adv interval为10ms,adv period不少于90ms。
- 指令串行化:音箱会对云端下发的控制指令做串行化处理,以照明设备为例,如果有对设备的两次操作,这两次操作会在音箱本地串行化,依次顺序执行;如果音箱发送消息后,音箱没有在超时时间内收到外设的消息,那么音箱将会触发重试策略,重试最多两次; 通常情况下,控制消息不做分包处理时,超时时间为1s;如果需要分包发送,超时时间是3s。
- 典型控制过程(单条命令收到回复):
- 设备没有收到灯泡返回的status进行重传的过程:
- 云端同时下发两条命令,小度音箱端串行化处理的过程:
外设心跳、上电通知、状态同步
- 小度音箱在Standby模式下接收外设发送的心跳、上电通知和状态同步消息,scan interval/scan window为180ms/20ms。
- 上电通知:外设初始化完毕后,随机选择0 - 10秒的延迟,发送心跳消息给小度音箱,以通知外设上线。为了让音箱尽可能可靠地收到外设的上电通知,建议适当延长外设第一次的心跳通知广播时间,即建议广播参数adv interval为10ms,adv period为300ms。在发送完心跳消息后,外设还需要发送状态同步消息,把设备的必要状态同步给音箱。
- 心跳:对于非低功耗设备,小度音箱会给外设发送Config Heartbeat Publication Set消息,心跳周期设置为32s,小度音箱通过外设的心跳消息来给云端上报online/offline事件,连续6个周期收不到心跳时则判定外设offline。外设上电后的第一个心跳通知广播时间,建议广播参数adv interval为10ms,adv period为300ms。除外设上电后的第一个心跳包外,后续心跳消息建议广播参数adv interval为10ms,adv period为300ms。
- 状态同步:外设在设备上电初始化完毕或状态发生变化后需要向小度音箱发送状态同步消息,每个品类的状态同步消息根据品类属性确定;状态同步消息建议广播参数adv interval为10ms,adv period为300ms。假设设备在上电初始化后有三个状态A、B、C需要同步,每个状态同步的间隔建议为250ms,三个状态发送完成后需要扫描800ms接收小度音箱发送的状态确认消息,外设状态上报重试逻辑时序图如下所示。
- 小度音箱已经订阅了0xF000这个地址,状态同步或者心跳广播可以走组播方式;
- 状态同步支持组播0xF000上报,上报TTL默认10;
- 心跳同步支持组播0xF000上报,上报TTL默认4,需要注意的是,无论proxy连接是否存在,心跳都需要通过adv方式上报,即通过小度音箱链路上报心跳;
- 外设上报0xF8消息后,会收到小度侧回复的0xFA消息,外设需要判断tid和attribute type完全一致,外设才能认为本次F8上报成功;
Mesh Proxy软件规范
- Proxy入网方式对于低功耗设备来说,可以选择性支持,而对于非低功耗设备来说,必须支持;
- 设备处于未配网状态时,需要向外广播可连接的Mesh Provisioning Service[uuid=0x1827],广播的时间必须30分钟以上;
- 使用Proxy方式配网成功以后,需要向外广播可连接的Mesh Proxy Service[uuid=0x1828];
- 使用Proxy方式配网以后,如果音箱与外设断开GATT连接,外设依旧需要向外广播Mesh Proxy Service,不得自行关闭或停止这个广播;
- Proxy配网的方式和Mesh配网方式没有区别,都遵循蓝牙mesh标准的配网流程,其中在设备认证上都是Static OOB,需要提前申请三元组并将其按照一机一密的方式烧录在设备上;
小度音箱和外设在各个阶段的BLE扫描参数和广播参数建议
scan interval/scan window/adv interval/adv period 解释参考
- 为了介绍scan interva/window以及adv interval/period的概念,使用以下图示进行说明,scan interval为50ms; scan window为25ms; adv interval为20ms; adv period为140ms, 其中参数仅供举例,与音箱/外设实际使用参数无关。
小度音箱与电源供电的外设
小度音箱状态 | 小度音箱扫描参数 | 小度音箱广播参数(adv interval/adv period) | 外设扫描参数 | 外设广播参数(adv interval/adv period) |
---|---|---|---|---|
Provision/Config | 60ms/30ms | N/A | 全时段扫描 | 10ms/60ms |
Control | 90ms/20ms | 20ms/1000ms | 全时段扫描 | 10ms/90ms |
Standby | 180ms/20ms | N/A | 全时段扫描 | 10ms/300ms |