概念介绍
涂鸦配网协议是标准 Bluetooth LE 协议的应用层规范,定义了一整套低功耗蓝牙设备和智能手机 App 之间的配网协议。通过涂鸦专属服务进行多层加密数据交互,结合涂鸦物模型实现安全可靠、点对点的物联网蓝牙数据传输协议。涂鸦配网协议是应用层协议,可兼容蓝牙 4.x/5.x 所有版本的标准蓝牙协议。
涂鸦配网协议除标准的 Primary Service 外,还引入了涂鸦专属服务(UUID:0xFD50
),该服务定义了可读可写可通知的特征值,充分利用蓝牙特性,通过规范低功耗蓝牙底层的技术参数(广播周期/间隔,连接间隔/方式,数据交互方式),最大程度地发挥蓝牙芯片的性能。
功能描述
角色
配网过程中,涉及到主机(Central)和从机(Peripheral)两个参与角色。日常交流中,主机多称为 App,从机多称为设备:
- 主机:智能生活 App(手机)、蓝牙网关。
- 从机:智能蓝牙设备,例如门锁、灯、防丢器,体脂称、手环等。
不同角色的交互流程如下所述:
- 主机通过 蓝牙广播 识别从机。
- 主机对已授权的从机发起配对请求,完成配对的主从机处于 绑定状态。
- 处于绑定状态的主从机之间存在一条符合蓝牙规范的安全通道,所有的业务类通信(包括 DP 数据)都在该安全通道中进行。
配网流程
安全通道的建立过程(配网)可以简述如下:
- 配网:
未绑定
连接
配对
绑定
安全通信
断开 - 重连:
重连
绑定
安全通信
……
解配对
未绑定
配网过程中的关键环节的解释如下:
- 连接:表示蓝牙设备链路层的状态为连接状态。
- 配对:视为一种过程,一系列的密钥交换过程。
- 绑定:视为一种状态,配对完成的状态称之为 绑定状态,处于绑定状态的两个设备可以进行安全通信。
- 重连:视为一种过程,依然是一系列的密钥交换过程,可以认为是简化的 配对。该过程的前提是,设备此前已经进入过一次绑定状态。
- 解配对:视为一种过程,秘钥删除和绑定状态等信息的清除,也称作 移除、解绑 等。
解绑流程
- 解绑
- 触发条件:App 面板上单击 解除绑定 按钮
- 触发事件:
TUYA_BLE_CB_EVT_UNBOUND
- 解绑并清除数据
- 触发条件:App 面板上单击 解绑并清除数据 按钮
- 触发事件:
TUYA_BLE_CB_EVT_DEVICE_RESET
数据结构
tuya_ble_addr_type_t
typedef enum {
TUYA_BLE_ADDRESS_TYPE_PUBLIC, // public address
TUYA_BLE_ADDRESS_TYPE_RANDOM, // random address
} tuya_ble_addr_type_t;
-
TUYA_BLE_ADDRESS_TYPE_PUBLIC
:公共地址类型。 -
TUYA_BLE_ADDRESS_TYPE_RANDOM
:随机地址类型。
tuya_ble_gap_addr_t
typedef struct {
tuya_ble_addr_type_t addr_type;
UINT8_T addr[6];
} tuya_ble_gap_addr_t;
-
addr_type
:详见tuya_ble_addr_type_t
。 -
addr
:6 字节 Mac 地址。
tuya_ble_product_id_type_t
typedef enum {
TUYA_BLE_PRODUCT_ID_TYPE_PID,
TUYA_BLE_PRODUCT_ID_TYPE_PRODUCT_KEY,
} tuya_ble_product_id_type_t;
-
TUYA_BLE_PRODUCT_ID_TYPE_PID
:product ID 类型。 -
TUYA_BLE_PRODUCT_ID_TYPE_PRODUCT_KEY
:product key 类型。
tuya_ble_device_param_t
typedef struct {
UINT8_T use_ext_license_key; //If use the license key stored by the SDK,initialized to 0, Otherwise 1.
UINT8_T device_id_len; //if ==20,Compressed into 16
UINT8_T device_id[DEVICE_ID_LEN_MAX];
UINT8_T auth_key[AUTH_KEY_LEN];
tuya_ble_gap_addr_t mac_addr;
UINT8_T mac_addr_string[MAC_STRING_LEN];
tuya_ble_product_id_type_t p_type;
UINT8_T product_id_len;
UINT8_T product_id[TUYA_BLE_PRODUCT_ID_MAX_LEN];
UINT8_T adv_local_name_len;
UINT8_T adv_local_name[TUYA_BLE_ADV_LOCAL_NAME_MAX_SPACE_LEN]; //Only supported when TUYA_BLE_PROTOCOL_VERSION_HIGN >= 4.
UINT32_T firmware_version; //0x00010102 : v1.1.2
UINT32_T hardware_version;
UINT8_T device_vid[DEVICE_VIRTUAL_ID_LEN];
UINT8_T login_key[LOGIN_KEY_LEN];
UINT8_T beacon_key[BEACON_KEY_LEN];
UINT8_T bound_flag;
UINT8_T reserve_1;
UINT8_T reserve_2;
} tuya_ble_device_param_t;
use_ext_license_key
:是否使用调试的授权信息,0
:不使用,1
:使用。device_id_len
:设备 ID 长度。device_id
:设备 ID。auth_key
:32 字节授权秘钥。mac_addr
:详见tuya_ble_gap_addr_t
。mac_addr_string
:12 字节 Mac 地址字符串。p_type
:详见tuya_ble_product_id_type_t
。product_id_len
:PID 长度。product_id
:产品 ID。adv_local_name_len
:蓝牙广播名称长度。adv_local_name
:蓝牙广播名称(通过 nRF Connect 看到的名字)。firmware_version
:固件版本,例如 1.1.0。hardware_version
:硬件版本,例如 1.0.0。device_vid
:22 字节设备虚拟 ID。login_key
:6 字节注册秘钥。beacon_key
:16 字节 Beacon 秘钥。bound_flag
:绑定标识。
实际使用方式详见 tal_ble_protocol_callback.c
中的示例程序。
tuya_ble_connect_status_t
typedef enum {
UNBONDING_UNCONN = 0,
UNBONDING_CONN,
BONDING_UNCONN,
BONDING_CONN,
BONDING_UNAUTH_CONN,
UNBONDING_UNAUTH_CONN,
UNKNOW_STATUS
} tuya_ble_connect_status_t;
-
UNBONDING_UNCONN
:未绑定未连接。 -
UNBONDING_CONN
:未绑定已连接。 -
BONDING_UNCONN
:已绑定未连接。 -
BONDING_CONN
:已绑定已连接。 -
BONDING_UNAUTH_CONN
:已绑定已连接未认证。 -
UNBONDING_UNAUTH_CONN
:未绑定未授权已连接。 -
UNKNOW_STATUS
:未知状态。
各状态之间的转换关系见下图:
接口说明
配网初始化
该接口是涂鸦蓝牙设备和 App 通信的主要接口,涵盖了配网相关的各种参数和事件处理。
VOID_T tuya_ble_protocol_init(VOID_T)
{
tuya_ble_protocol_param.firmware_version = tal_common_info.firmware_version,
tuya_ble_protocol_param.hardware_version = tal_common_info.hardware_version,
memcpy(tuya_ble_protocol_param.device_id, device_id_test, DEVICE_ID_LEN);
memcpy(tuya_ble_protocol_param.auth_key, auth_key_test, AUTH_KEY_LEN);
memcpy(tuya_ble_protocol_param.mac_addr_string, TY_DEVICE_MAC, MAC_STRING_LEN);
memcpy(tuya_ble_protocol_param.product_id, TY_DEVICE_PID, tuya_ble_protocol_param.product_id_len);
memcpy(tuya_ble_protocol_param.adv_local_name, TY_DEVICE_NAME, tuya_ble_protocol_param.adv_local_name_len);
tuya_ble_sdk_init(&tuya_ble_protocol_param);
tuya_ble_callback_queue_register(tuya_ble_protocol_callback);
……
}
tuya_ble_sdk_init()
:用于参数初始化,包括固件版本、三元组(Mac、Device id、Auth key)、PID、广播名称等参数。tuya_ble_callback_queue_register()
:用于注册回调函数,处理包括配网状态、时间戳、DP 数据、解绑等各种配网相关的逻辑。
配网回调函数
用于设备配网完成的回调接口。
STATIC VOID_T tuya_ble_protocol_callback(tuya_ble_cb_evt_param_t* event)
用于处理配网以及通信过程中发生的各种事件如下所示:
typedef enum {
TUYA_BLE_CB_EVT_CONNECTE_STATUS = TUYA_BLE_CB_EVT_BASE,
TUYA_BLE_CB_EVT_DP_WRITE, // old version
TUYA_BLE_CB_EVT_DP_QUERY,
TUYA_BLE_CB_EVT_DP_DATA_RECEIVED, // new version
TUYA_BLE_CB_EVT_OTA_DATA,
TUYA_BLE_CB_EVT_BULK_DATA,
TUYA_BLE_CB_EVT_NETWORK_INFO,
TUYA_BLE_CB_EVT_WIFI_SSID,
TUYA_BLE_CB_EVT_TIME_STAMP,
TUYA_BLE_CB_EVT_TIME_NORMAL,
TUYA_BLE_CB_EVT_APP_LOCAL_TIME_NORMAL,
TUYA_BLE_CB_EVT_TIME_STAMP_WITH_DST,
TUYA_BLE_CB_EVT_DATA_PASSTHROUGH,
TUYA_BLE_CB_EVT_DP_DATA_REPORT_RESPONSE,
TUYA_BLE_CB_EVT_DP_DATA_WTTH_TIME_REPORT_RESPONSE,
TUYA_BLE_CB_EVT_DP_DATA_WITH_FLAG_REPORT_RESPONSE,
TUYA_BLE_CB_EVT_DP_DATA_WITH_FLAG_AND_TIME_REPORT_RESPONSE,
TUYA_BLE_CB_EVT_DP_DATA_SEND_RESPONSE, // new version
TUYA_BLE_CB_EVT_DP_DATA_WITH_TIME_SEND_RESPONSE, // new version
TUYA_BLE_CB_EVT_UNBOUND,
TUYA_BLE_CB_EVT_ANOMALY_UNBOUND,
TUYA_BLE_CB_EVT_DEVICE_RESET,
TUYA_BLE_CB_EVT_UPDATE_LOGIN_KEY_VID,
TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE, // Notify the application of the result of the local reset
TUYA_BLE_CB_EVT_WEATHER_DATA_REQ_RESPONSE, // received request weather data app response
TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED, // received app sync weather data
TUYA_BLE_CB_EVT_REMOTER_PROXY_AUTH_RESP,
TUYA_BLE_CB_EVT_REMOTER_GROUP_SET,
TUYA_BLE_CB_EVT_REMOTER_GROUP_DELETE,
TUYA_BLE_CB_EVT_REMOTER_GROUP_GET,
} tuya_ble_cb_evt_t;
查询网络状态
tuya_ble_connect_status_t tuya_ble_connect_status_get(VOID_T);
tuya_ble_connect_status_t:详见 tuya_ble_connect_status_t。
使用方法
通信流程
代码开发
详见 tal_ble_protocol_callback.c
中的示例程序:
STATIC tuya_ble_device_param_t tuya_ble_protocol_param = {
#if (TUYA_SDK_DEBUG_MODE)
.use_ext_license_key = 1, //1-info in tuya_ble_protocol_callback.h, 0-auth info
.device_id_len = DEVICE_ID_LEN,
#else
.use_ext_license_key = 0,
.device_id_len = 0,
#endif
.p_type = TUYA_BLE_PRODUCT_ID_TYPE_PID,
#if (TUYA_BLE_PROD_SUPPORT_OEM_TYPE == TUYA_BLE_PROD_OEM_TYPE_NONE)
.product_id_len = 8,
#else
.product_id_len = 0,
#endif
.adv_local_name_len = 4,
};
STATIC VOID_T tuya_ble_protocol_callback(tuya_ble_cb_evt_param_t* event)
{
switch (event->evt) {
case TUYA_BLE_CB_EVT_CONNECTE_STATUS: {
if (event->connect_status == BONDING_CONN) {
TAL_PR_INFO("bonding and connecting");
tuya_ble_update_conn_param_timer_start();
}
} break;
case TUYA_BLE_CB_EVT_DP_DATA_RECEIVED: {
app_dp_parser(event->dp_received_data.p_data, event->dp_received_data.data_len);
} break;
…………
case TUYA_BLE_CB_EVT_UNBOUND: {
TAL_PR_INFO("TUYA_BLE_CB_EVT_UNBOUND");
} break;
case TUYA_BLE_CB_EVT_ANOMALY_UNBOUND: {
TAL_PR_INFO("TUYA_BLE_CB_EVT_ANOMALY_UNBOUND");
} break;
case TUYA_BLE_CB_EVT_DEVICE_RESET: {
TAL_PR_INFO("TUYA_BLE_CB_EVT_DEVICE_RESET");
} break;
case TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE: {
TAL_PR_INFO("TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE");
} break;
…………
default: {
TAL_PR_INFO("tuya_ble_protocol_callback Unprocessed event type 0x%04x", event->evt);
} break;
}
…………
}
VOID_T tuya_ble_protocol_init(VOID_T)
{
tuya_ble_protocol_param.firmware_version = tal_common_info.firmware_version,
tuya_ble_protocol_param.hardware_version = tal_common_info.hardware_version,
memcpy(tuya_ble_protocol_param.device_id, TY_DEVICE_DID, DEVICE_ID_LEN);
memcpy(tuya_ble_protocol_param.auth_key, TY_DEVICE_AUTH_KEY, AUTH_KEY_LEN);
memcpy(tuya_ble_protocol_param.mac_addr_string, TY_DEVICE_MAC, MAC_STRING_LEN);
memcpy(tuya_ble_protocol_param.product_id, TY_DEVICE_PID, tuya_ble_protocol_param.product_id_len);
memcpy(tuya_ble_protocol_param.adv_local_name, TY_DEVICE_NAME, tuya_ble_protocol_param.adv_local_name_len);
tuya_ble_sdk_init(&tuya_ble_protocol_param);
tuya_ble_callback_queue_register(tuya_ble_protocol_callback);
…………
}
功能测试
前置条件
蓝牙设备进行配网前,需要进行固件烧录和授权。
- 烧录固件跟芯片平台完全相关,请参考 TuyaOS 快速入门 中相应平台相关的资料。
- 授权一般用于设备批量生产,请参考 TuyaOS 快速入门 中 TuyaOS 开发蓝牙产品之授权产测。
若暂无生产需要,也可通过以下方式进行临时授权(仅用于调试,生产时请改回原状):
- 找到如下代码片段:
- 临时修改为如下设置:
STATIC tuya_ble_device_param_t tuya_ble_protocol_param = {
.use_ext_license_key = 1, //1-info in tuya_ble_sdk_demo.h, 0-auth info
.device_id_len = DEVICE_ID_LEN, //DEVICE_ID_LEN,
.p_type = TUYA_BLE_PRODUCT_ID_TYPE_PID,
.product_id_len = 8,
.adv_local_name_len = 4,
};
操作步骤
授权结束后,即成功激活涂鸦低功耗蓝牙设备。
此时,您可以在手机上下载 智能生活 App,登录后在 App 首页单击右上角 + > 添加设备。上位机展示的信息为更新配网状态、更新 MTU、更新时间戳、更新连接参数,整个过程如下图所示:
上位机使用的相关问题,请访问 Logic 上位机使用指南。