1.6 标准BLE接入开发

优质
小牛编辑
115浏览
2023-12-01

本文用于指导产品开发者实现标准BLE产品接入

背景介绍

强弱绑定

强弱绑定关系是服务器端的逻辑,与固件端开发无关。

开发者可以根据自家的产品特点,开放平台创建产品后,在基础功能配置页面选择合适的绑定方式。

强绑定

​设备绑定账号后,其他人再尝试绑定时,会提示设备已经被其它用户绑定。即我不删除,谁都绑不走

弱绑定

​设备绑定账号后,其他人再尝试绑定时,能够绑定成功,原账号刷新列表,设备消失。即谁最后绑定就是谁的

配对方式

开发者同样需要在开发者平台基础功能配置页面选择蓝牙配对方式,目前有三种配对方式:APP确认即配对,RSSI符合即配对,设备确认即配对。

  • APP确认即配对:当附近有多个设备时,由APP选择与哪个设备进行配对。
  • RSSI符合即配对:要求设备靠近才能配对,选择此方式需要在开发者平台填写RSSI阈值,信号强度高于该阈值则可开始配对。
  • 设备确认即配对:要求在设备端进行确认操作(如按键)才能开始配对。

开发固件端代码时请注意:

当选择APP确认配对或RSSI符合配对时,solicited位置0。

当选择设备确认配对时:

  • 首先,正常广播的MiBeacon中solicited位为0。
  • 当用户触发(如按键),将MiBeacon中solicited位修改为1,持续2~3秒后恢复为0。
  • 当APP检测到设备的solicited位为1后,才进行连接,开始认证流程。

solicited 标志位请参考米家BLE MiBeacon协议中的说明:0表示无操作;1表示请求 APP 进行注册绑定。当用户在开发者平台选择设备确认配对时才有效,否则置0。

注意:开发者只需要调用advertising_init()接口,参数传入0/1即可修改蓝牙广播中的solicited标志位,具体可参考Demo例程中advertising_init()接口的调用方法。

注册与登录

注册表示未绑定设备通过APP进行绑定。

登录表示用户进入APP插件与已绑定设备进行交互。

接入米家

已支持的芯片方案

米家提供了基于开发板实现的标准接入 Demo Project。

Demo Project GitHub 地址如下:(请按照各分支下 README 文档,完成工程导入)

芯片厂商芯片平台Demo Project
Nordic51 Serieshttps://github.com/MiEcosystem/mijia_ble_standard/tree/nordic_legacy
Nordic52 Serieshttps://github.com/MiEcosystem/mijia_ble_standard/tree/nordic
Silicon LabsBG13https://github.com/MiEcosystem/mijia_ble_standard/tree/silabs
TelinkTLSR825xhttps://github.com/MiEcosystem/mijia_ble_standard/tree/telink
RealtekRTL8762https://github.com/MiEcosystem/mijia_ble_standard/tree/realtek
DialogDA145xxhttps://github.com/MiEcosystem/mijia_ble_standard/tree/Dialog
DialogDA146xxhttps://github.com/MiEcosystem/mijia_ble_standard/tree/da146xx

目前米家只提供了对主流芯片的支持,如果产品厂商确认要选用其它家的芯片,可以向小米产品经理提起申请,说明需要选用其它芯片的原因,如果申请通过,米家会考虑支持并适配该芯片。

注意 厂商请勿自行适配芯片,出现问题小米不保证有人力配合联调。

接入步骤

标准BLE接入方式的软件SDK,由三部分组成:芯片原厂SDK,米家标准认证库,米家标准认证示例Demo。具体步骤如下:

  • 米家标准认证库是私有工程,产品开发者首先需联系小米产品经理,申请获取米家标准认证库的权限。注意,每个新品的接入都要单独申请认证库的权限,一个产品申请一次,如果发现未经申请的新品接入,米家有权利拒绝产品上线。
  • 申请标准认证库请发送邮件至 小米IoT平台开放窗口 miot-openhome@xiaomi.com,格式请参考常用信息->开发者反馈指引。
  • 根据芯片选型,下载芯片厂商提供的SDK,各分支下有对应的下载地址链接或下载方法。
  • 下载米家标准认证示例Demo
    • 按照各分支下的README说明,进入到芯片原厂SDK的指定目录
    • 命令行执行 git clone -b xxx(对应分支) --recursive https://github.com/MiEcosystem/mijia_ble_standard.git。建议使用git clone --recursive命令,直接网站上下载会发现有些文件找不到,这是因为submodule没有下载成功
  • 联系小米产品经理申请开通“小米蓝牙开发板”白名单。
  • 按照各分支下README说明中的路径导入工程,编译固件,下载固件到硬件板卡。
  • 打开米家APP,开启蓝牙,发现附近的设备,点击“小米蓝牙开发板”,可成功连接登陆使用,表示已完成米家认证流程。
  • 后续的产品开发中,可修改Demo工程中的PRODUCT_ID宏定义(定义在custom_mi_config.h文件中)为自己实际的产品id(Demo例程中PRODUCT_ID定义为156,表示小米蓝牙开发板),进行实际产品的开发。
  • 注意事项
    • 向网关发送事件需要频繁读写flash,请在开发过程中务必测试flash的可靠性,请测试flash key-value读写达到100000次以上
    • 向网关发送事件请直接调用mibeacon_obj_enque()接口,不允许自行拼包发送

应用层开发

应用开发需要关注custom_mi_config.h文件,用户可自定义文件中的配置,Demo工程中已经将 CUSTOMIZED_MI_CONFIG_FILE=<custom_mi_config.h> 添加到了工程的 Preprocesser symbols中。

custom_mi_config.h文件中的宏定义如下表所示

宏名作用
CUSTOMIZED_MI_CONFIG_FILE自定义的 config 头文件
DEVELOPER_VERSION开发者固件版本号
PRODUCT_ID必须与在小米IoT开发者平台创建的产品 ID 相同
MI_BLE_ENABLED采用 BLE 协议接入
HAVE_MSC使用标准认证,无须外接认证芯片,定义为 0 即可
HAVE_RESET_BUTTON具有重置按键
OOB_USE_NUMPAD_INPUT绑定时,通过数字键盘确认,增强安全性
OOB_USE_QR_CODE_OUT绑定时,通过二维码确认,增强安全性
OOB_USE_DISPLAT_OUT绑定时,通过显示屏提示,增强安全性
OBJ_QUEUE_SIZEmibeacon object 发送队列大小
OBJ_ADV_INTERVAL_MS每条 mibeacon object 发送间隔
OBJ_ADV_TIMEOUT_MS每条 mibeacon object 发送时长

<注> 如果缺省宏定义,会采用 mi_config.h 中默认值。例如,不定义 PRODUCT_ID,则默认为 156 小米蓝牙开发板,此产品为白名单用户可见。(如需使用此 PID 进行功能验证,请申请白名单权限)

如需查看 log 信息,则需要将下列宏定义添加到工程 Preprocesser symbols 中。

宏名作用
MI_LOG_ENABLED打开调试log,仅在调试阶段使用,量产时应去除
MI_ASSERTMI_LOG_ENABLED 打开时才有效,进行 assert 检查

烧写固件到产品中,产品侧已支持米家标准认证功能,可以使用米家 APP 进行功能验证。具体操作如下:

  • 开启蓝牙,打开米家 APP,点击右上角 ➕ 发现附近的设备;(如果没有出现待测产品,请检查 MiBeacon 广播格式以及产品 PID 是否正确。)
  • 点击待测产品,开始注册绑定。(产品侧 log 会提示连接状态等信息)
  • 注册绑定成功后,即进入产品插件页(如果 APP 插件暂未上传,可以跳过此步骤。)
  • 退出插件,再次进入,米家 APP 将进行登录操作。
  • 重置方法,目前需要两步
    • 米家 APP 里删除设备
    • 设备上长按重置按钮

APP发现页面无法发现设备存在以下几种情况:

  • 设备端已重置,但APP端未删除设备,APP的发现页面不会显示还在本机设备列表中的设备,请先在APP端也删除设备再重试。
  • APP端已删除设备,设备端未重置,对于目前最新的V5版本MiBeacon协议,APP会判断设备发出MiBeacon中的“已注册”标志位,扫到“已注册”的设备,APP的发现页面不会显示,这种情况下请重置设备再重试。对于无法重置的设备(如蓝牙温湿度计),请修改工程中的宏定义HAVE_RESET_BUTTON为0,这样设备端发出的MiBeacon的“已注册”标志位就一直为0。
  • APP端已删除设备,设备端也已经重置,请确认设备是否已上线或者用户的小米ID是否在设备的白名单中。调试Demo工程请联系小米产品经理申请开通“小米蓝牙开发板”白名单。

认证完成后,产品便具备安全通信的能力。产品可以通过发送广播或建立连接进行加密数据传输。

广播上报

BLE 是一种近场通信方式,如果要实现消息的远程上报,则需要搭配一个能够连接互联网的桥接设备,这个设备称为蓝牙网关。

产品如果需要通过蓝牙网关向服务器上报事件或属性,开发者请先联系对接的产品经理,确认子设备要上报哪些事件和属性,然后在米家服务器端进行配置。目前申请Object ID流程已规划线上化,敬请期待。

米家定义了两类广播消息:事件和状态。事件上报不存在频率限制,具有高实时性,可以用来触发自动化场景,比如开门事件触发开灯;状态上报存在频率限制,具有高延迟,适用于周期或缓慢变化的数据,比如环境温度。

请直接使用 mibeacon_obj_enque() 接口,将待发送消息放入发送队列,设备将按照设置的间隔进行多次广播。每条消息的发送间隔和总时长可以通过宏定义修改,具体参数参考custom_mi_config.h文件中的宏定义。 示例代码

不允许开发者调用系统广播函数广播MiBeacon。必须采用此接口,小米在其中定义了重发次数和重发间隔,确保事件可以被网关收到。

米家透传服务

建立连接后,双方可以通过 GATT 服务进行数据传输。米家透传服务作为一个示例,演示如何在一个自定义服务上实现加密传输。

1.参考 stdio_service_init() 创建数据传输示例服务,注册回调函数,以接收 APP 数据。(示例服务创建时使用了 mijia ble api, 开发者可直接使用原厂 SDK API) 示例代码

2.建立连接并完成米家登陆后,双方会生成会话密钥。在发送数据前,先使用 mi_session_encrypt() 加密数据,再发送。参考 stdio_tx() 实现: 示例代码

3.接收加密数据后,调用 get_mi_authorization() 判断设备当前登录状态,若已登录使用 mi_session_decrypt() 解密数据,再上报应用层处理。参考 stdio 服务 on_write_permit() 实现: 示例代码

OTA实现

mijia统一OTA目前已经支持Nordic、Silabs、realtek、telink芯片平台,请check最新Demo工程,并保证在固件工程中将USE_MIBLE_OTA宏定义打开即可使用。

开发者也可以自行实现OTA的蓝牙通路,同样也可完成APP端从开放平台下载固件,再通过蓝牙连接将固件包传输到设备端。

对于带有外部MCU设备(例如门锁设备)的OTA方案,OTA只是实现将整个的固件包下载到设备端,设备端可以再自行拆分,蓝牙和MCU分别进行升级。

开发者需要关注的API

函数名功能说明
mi_session_encrypt加密函数登陆成功后,设备和手机之间建立了加密通道,负责对传输数据加密
mi_session_decrypt解密函数负责对传输数据解密
mibeacon_obj_enque事件/属性信息上报发送带有object的MiBeacon

<注> mibeacon_obj_enque的使用方法:搭配蓝牙网关使用,开发者调用mibeacon_obj_enque将要发送的object放入发送队列,之后libs自动发送带有object的MiBeacon。不允许开发者调用系统广播函数广播MiBeacon。必须采用此接口,小米在其中定义了重发次数和重发间隔,确保事件可以被网关收到。

空白工程集成米家标准认证库

如果开发者在 Demo Project 基础上进行开发,可以略过本章

软件环境

  • IDE/toolchains (根据芯片 SDK 要求进行安装,如遇问题可咨询芯片原厂 FAE)
  • JLink
  • Git

硬件环境

硬件平台可以选用芯片原厂的开发板,或使用在研产品 PCBA。推荐使用原厂开发板环境进行功能验证。完成功能验证后再移植到在研产品 PCBA。

代码集成

Demo Project 代码结构:

高安全级 BLE 产品软件框架

如上图所示,标准 BLE 产品接入需要用到以下代码:

其中,SoC stack & SDK 由芯片原厂提供,米家会推荐已验证的 SDK 版本; mijia ble api & libs 由米家提供,以源码形式托管在 GitHub 上。推荐使用 git submodule 方式将米家代码集成到自己仓库中,以便后续通过 submodule update 方式进行更新。mijia ble api 为开源仓库,无需申请权限即可访问。mijia ble libs 为私有仓库,需申请访问权限。(请联系产品接口人)

以 nordic 为例

1.下载芯片原厂 SDK。(SDK 版本根据 mijia ble api 要求进行选择)

示例:从 nordic 官网下载 [SDK 15.2.0](https://www.nordicsemi.com/Software-and-Tools/Software/nRF5-SDK/Download#infotabs)

2.按照芯片原厂 SDK 说明文档,新建 BLE 空工程。(如果已创建工程,可以跳过此步)

示例:nordic BLE 空工程在 `SDK\examples\ble_peripheral\ble_app_template` 目录下,复制一份 ble_app_template 并重命名,比如叫 stand_demo

3.在新建的 BLE 工程目录下创建 Git 本地仓库。(如果已有本地仓库,可以跳过此步)

示例:
$ git init

4.添加 mijia ble api 和 mijia ble libs 到本地仓库。添加 mijia ble api 时需选择对应芯片平台的分支。

示例:
$ git submodule add -b nordic https://github.com/MiEcosystem/mijia_ble_api.git
$ git submodule add -b master https://github.com/MiEcosystem/mijia_ble_libs.git
$ git commit -am "add submodules mijia ble api & libs"

5.添加 mijia ble api 和 mijia ble libs 路径下源码到 BLE 工程中,并将路径加入到工程的 include path。mijia ble api 会使用到 SoC SDK 中的 BLE,TIMER,FLASH 等功能,需要开发者将这些功能模块添加到工程中。 (详细资源占用情况及配置方法,请参考芯片对应分支下的 README)。添加下列路径下代码和库。(根据编译器和芯片 CPU 型号选择对应库文件)

mijia_ble_libs
├── common
│   ├── mible_beacon.c
│   ├── mible_crypto.c
│   ├── mible_rxfer.c
│   └── queue.c
├── cryptography
│   ├── mi_crypto.c
│   ├── mi_crypto_backend_mbedtls.c
│   └── mi_crypto_backend_uECC.c
├── mijia_profiles
│   ├── mi_service_server.c
│   └── stdio_service_server.c
├── standard_auth
│   ├── stand-auth-cortex-?.a (搭配 gcc 使用)
│   └── stand-auth-cortex-?.lib (搭配 armcc/keil 使用)
└── third_party
    ├── SEGGER_RTT
    │   ├── SEGGER_RTT.c
    │   └── SEGGER_RTT_printf.c
    ├── mbedtls
    │   ├── asn1parse.c
    │   ├── ccm.c
    │   └── sha256_hkdf.c
    ├── micro-ecc
    │   ├── micro_ecc_?.a
    │   ├── micro_ecc_?.lib
    │   └── uECC.c(如果缺少对应平台库文件,可使用源码代替)
    └── pt
        └── pt_misc.c

<注> libs 引用的 ./third_party/ 路径下的第三方开源代码(例如, mbedtls,RTT),可能在 SoC SDK 中已经包含。当工程编译出现重复定义冲突时,开发者需要去掉 libs 中重复的文件。(比如,原厂工程中已经包含 SEGGER RTT 文件,就无需再添加 ./third_party/SEGGER_RTT 路径下源码)

米家认证

进行以下步骤前请先阅读 mijia ble libs 使用手册

标准 BLE 接入设备需支持 米家标准认证协议 standard auth,该功能已在 mijia ble libs 中集成,使用方法如下:

1.芯片运行环境初始化(包括芯片电源,时钟,GPIO,TIMER,BLE stack 等功能模块)。

2.实现认证事件处理函数 mi_schd_event_handler(),进行 mi_scheduler_init() 初始化。(mi_schd_event_handler() 在收到 SCHD_EVT_OOB_REQUEST 事件的 30 秒内,产品端根据自身 IO 能力获取 OOB 数据,再调用 mi_schd_oob_rsp()mi_schduler 提供所需 OOB 数据。) 示例代码

3.初始化后,调用 mi_scheduler_start(SYS_KEY_RESTORE) 尝试读取绑定信息,执行结果会通过 mi_schd_event_handler() 传参返回。如果已重置,将收到 SCHD_EVT_KEY_NOT_FOUND 事件。 示例代码

4.调用 mi_service_init() 创建米家服务。米家服务提供认证数据传输通道,服务缺失将导致认证失败。

5.使用 mibeacon_adv_data_set() 设置广播数据:第一个参数 is_solicited 用于请求手机进行绑定,比如,当特定按键按下后 5 秒内设置为 1,请求手机进行绑定。第二个参数 采用 BLE 接入无须填写。如果用户要发送自定义数据,需先按照标准蓝牙广播格式编码,再通过 user data 参数传入。 注意 请勿使用 SDK 中 ADV API 直接修改广播数据。以免 MiBeacon 广播数据被覆盖,造成产品无法被米家 APP 发现。 示例代码

6.将 mi_schd_process() 添加到 main loop 中。

7.米家认证相关的事件,会通过 mi_schd_event_handler() 通知应用层:

事件名称含义
SCHD_EVT_REG_SUCCESS绑定注册成功
SCHD_EVT_REG_FAILED绑定注册失败
SCHD_EVT_ADMIN_LOGIN_SUCCESS登录成功
SCHD_EVT_ADMIN_LOGIN_FAILED登录失败
SCHD_EVT_TIMEOUT操作超时
SCHD_EVT_KEY_NOT_FOUND未绑定
SCHD_EVT_KEY_FOUND已绑定
SCHD_EVT_KEY_DEL_SUCC重置成功
SCHD_EVT_OOB_REQUEST请求输入 OOB

此外,开发者还可以使用 mi_scheduler_start() 发送以下命令,进行本地系统管理:

命令名称含义
SYS_KEY_RESTORE读取绑定信息
SYS_KEY_DELETE删除绑定信息