本文介绍如何获取授权码、将其写入设备,以及如何在固件中集成产测接口。
授权码 是涂鸦统一为设备颁发的安全加密证书,是智能设备运行涂鸦 IoT 操作系统的合法凭证,每台设备都具有唯一的授权码。一个授权码代表一个设备接入许可,仅用于一台设备连接和访问云端。
授权码包含以下核心字段:
| 字段 | 说明 |
|---|---|
uuid |
设备唯一标识,全局唯一,不可重复烧录 |
auth_key |
鉴权密钥,与 uuid 一一对应 |
pin |
Wi-Fi 设备扫码配网的短码,可选择 高级能力 后生效 |
关于如何获取授权码,参考:
授权码订单有 2 种交付方式:授权码清单 和 生产凭证。
以 Excel 表格 形式交付,内容为 uuid + auth_key 明文密钥清单。在提取订单时生成授权码,为您输出明文密钥,密钥对由您自己管理。
烧录方式:通过您自己的工具,将授权信息逐个写入设备。
以一串字母(涂鸦内部称为 Token)形式交付。提货时需选择以下两种交付形式之一:
| 交付形式 | 包含内容 |
|---|---|
| 生产凭证 | 固件 + 授权信息 |
| 生产凭证 - 仅授权 | 仅授权信息,不含固件 |
烧录方式:通过涂鸦的产测工具进行密钥解析,写入到设备。
使用生产凭证烧录时,需要校验固件等信息。若固件不正确,将会导致无法烧录。所以下单需要提供正确的 PID、固件 Key 和版本号。
取决于您的生产方式:
| 生产方式 | 推荐交付形式 |
|---|---|
| 采用 涂鸦产测工具 生产 | 必须使用 生产凭证 |
| 采用 自己的工具 生产 | 可使用生产凭证,也可使用授权码清单 |
uuid + auth_key)写入设备。ty_rvc_mf_init 调用。在涂鸦开发者平台下载对应产品品类的 生产解决方案,其中包含配套的产测工具。
设备串口 (TX/RX/GND)
│
TTL 转 USB 模块
│
PC USB 口
在 功能测试 下选择 扫地机器人。
选择 授权模式 并填入 生产凭证,然后单击 启动测试。
在 测试项列表 > 配置 栏下单击配置按钮,然后在 串口连接设置 窗口中选择 串口号 和 波特率。
ty_rvc_mf_init 是涂鸦扫地机 RVC SDK 提供的 产测授权的初始化入口,在设备上电启动时调用,用于判断是否需要进入产测流程,并完成产测授权信息的写入。
OPERATE_RET ty_rvc_mf_init(IN CHAR_T *user_sw_ver, TY_RVC_MF_DATA_EVENT_CB mf_info_cb);
| 参数 | 类型 | 方向 | 说明 |
|---|---|---|---|
user_sw_ver |
CHAR_T * |
in | 固件版本号字符串,例如 "1.0.0" |
mf_info_cb |
TY_RVC_MF_DATA_EVENT_CB |
in | 授权信息回调函数,产测工具下发授权码后触发,用于写入 Flash |
| 返回值 | 含义 |
|---|---|
OPRT_OK |
产测入口已关闭(正常量产设备),或 500 ms 窗口超时未收到指令,函数正常退出 |
| 其他错误码 | 内部初始化失败(内存分配、定时器创建、线程创建等异常) |
因 产测入口已关闭 和 超时未收到指令 退出,返回值均为 OPRT_OK,调用方无需区分这两种情况。
typedef INT_T (*TY_RVC_MF_DATA_EVENT_CB)(IN void *param);
回调参数 param 实际类型为 GW_BASE_IF_S *,产测工具下发授权码后触发,您需在回调中将授权信息写入 Flash。
关键时序参数:
| 参数 | 值 | 说明 |
|---|---|---|
MF_DETECT_MSTIME |
500 ms | 产测检测窗口,超时后退出 |
UART_BAUD_RATE |
9600 bps | 产测串口波特率 |
| 激活后自动关闭产测 | 15 分钟 | 设备成功激活 15 分钟后,写入关闭标志,后续不再进入产测 |
/**
* @brief Validate manufacturing authorization base info
* @param[in] base_if GW base interface data
* @return OPRT_OK on success, error code on invalid data
*/
STATIC OPERATE_RET __ty_mf_info_validate(CONST GW_BASE_IF_S *base_if)
{
if (base_if == NULL) {
PR_ERR("mf info param null");
return OPRT_INVALID_PARM;
}
if (base_if->uuid[0] == '\0' || strlen(base_if->uuid) > GW_UUID_LEN) {
PR_ERR("mf info uuid invalid");
return OPRT_INVALID_PARM;
}
if (base_if->auth_key[0] == '\0' || strlen(base_if->auth_key) > AUTH_KEY_LEN) {
PR_ERR("mf info auth_key invalid");
return OPRT_INVALID_PARM;
}
if (base_if->pin[0] == '\0' || strlen(base_if->pin) >= SIZEOF(base_if->pin)) {
PR_ERR("mf info pin invalid");
return OPRT_INVALID_PARM;
}
return OPRT_OK;
}
/**
* @brief Manufacturing authorization info callback
* @param[in] param GW_BASE_IF_S pointer
* @return OPRT_OK on success, error code on failure
*/
STATIC INT_T ty_mf_info_cb(void *param)
{
GW_BASE_IF_S *base_if = (GW_BASE_IF_S *)param;
GW_BASE_IF_S local_info = {{0}};
OPERATE_RET rt = OPRT_OK;
if (base_if == NULL) {
return OPRT_INVALID_PARM;
}
memcpy(&local_info, base_if, SIZEOF(GW_BASE_IF_S));
rt = __ty_mf_info_validate(&local_info);
if (OPRT_OK != rt) {
return rt;
}
PR_NOTICE("mf info ok, uuid=%s", local_info.uuid);
/* 开发者需要在此将 uuid/auth_key/pin 写入 Flash */
return OPRT_OK;
}
static OPERATE_RET ty_iot_sdk_init(CHAR_T *p_token)
{
/* ... 其他初始化 ... */
/* 产测初始化:必须在 tuya_iot_wf_dev_init 之前调用 */
ty_rvc_mf_init(TY_APP_VERSION, ty_mf_info_cb);
/* 正常业务初始化继续 */
TUYA_CALL_ERR_RETURN(tuya_iot_wf_dev_init(...));
/* ... */
}
ty_rvc_mf_init 必须在 tuya_iot_wf_dev_init、tuya_iot_soc_init 之前 调用。如果在 500 ms 内收到产测指令,函数会 阻塞 在产测流程中,后续的正常初始化不会执行。
ty_rvc_mf_init 的产测通信和硬件操作依赖 TKL(Tuya Kernel Layer)接口。移植到新平台时,需要在 vendor/<platform>/tuyaos/tuyaos_adapter/ 目录下实现以下接口。
产测串口通信通过 tkl_uart.h 中定义的接口完成。SDK 的 TAL 层封装了 UART 操作,但底层依赖平台提供以下 5 个 TKL 接口的具体实现:
| 接口 | 函数签名 | 说明 |
|---|---|---|
tkl_uart_init |
OPERATE_RET tkl_uart_init(TUYA_UART_NUM_E port_id, TUYA_UART_BASE_CFG_T *cfg) |
初始化串口,产测固定使用 TUYA_UART_NUM_0,波特率 9600/8N1 |
tkl_uart_deinit |
OPERATE_RET tkl_uart_deinit(TUYA_UART_NUM_E port_id) |
产测结束后释放串口资源 |
tkl_uart_write |
INT_T tkl_uart_write(TUYA_UART_NUM_E port_id, VOID_T *buff, UINT16_T len) |
向上位机发送产测协议应答帧 |
tkl_uart_read |
INT_T tkl_uart_read(TUYA_UART_NUM_E port_id, VOID_T *buff, UINT16_T len) |
从接收缓冲区读取上位机数据(非阻塞) |
tkl_uart_rx_irq_cb_reg |
VOID_T tkl_uart_rx_irq_cb_reg(TUYA_UART_NUM_E port_id, TUYA_UART_IRQ_CB rx_cb) |
注册 RX 中断回调,TAL 层用此回调将数据写入内部 ring buffer |
产测期间串口的固定配置如下:
TUYA_UART_BASE_CFG_T base_cfg = {
.baudrate = 9600,
.databits = TUYA_UART_DATA_BIT_8,
.parity = TUYA_UART_PARITY_NONE,
.stopbits = TUYA_UART_STOP_BIT_1,
.flowctrl = TUYA_UART_FLOWCTRL_NONE,
};
TAL UART 驱动采用中断 + ring buffer 模型,tkl_uart_read 只从 ring buffer 中读取数据。tkl_uart_rx_irq_cb_reg 必须正确实现并注册 RX 中断,否则接收数据会丢失,产测无法正常工作。
当产测工具需要读取 Wi-Fi 模组 MAC 地址时,SDK 会调用 tkl_wifi.h 中的以下接口:
| 接口 | 函数签名 | 说明 |
|---|---|---|
tkl_wifi_get_mac |
OPERATE_RET tkl_wifi_get_mac(CONST WF_IF_E wf, NW_MAC_S *mac) |
读取 Wi-Fi 模组 MAC 地址,上报给上位机用于记录 |
NW_MAC_S 结构定义:
typedef struct {
BYTE_T mac[6]; /* MAC 地址,6 字节,网络字节序 */
} NW_MAC_S;
若平台不需要产测工具管理 MAC(例如 MAC 已出厂固化),可将 tkl_wifi_get_mac 实现为直接读取固化 MAC,tkl_wifi_set_mac 实现为空操作(返回 OPRT_OK)。
| 事项 | 说明 |
|---|---|
| 调用时机 | 必须在 tuya_iot_wf_dev_init 之前调用 |
| 阻塞特性 | 进入产测后函数会持续阻塞,后续代码不会执行,直到产测完成 |
| 产测关闭标志 | 设备激活成功后 15 分钟,SDK 自动将产测关闭标志写入 DB 文件,之后不再进入产测窗口 |
| 回调内存安全 | mf_info_cb 中收到的 GW_BASE_IF_S 指针仅在回调期间有效,需立即复制后使用 |
| 授权码唯一性 | uuid 与设备绑定,具有全局唯一性,同一 uuid 不得烧录到多台设备 |
| 串口资源 | 产测期间串口由 SDK 独占,应用层不应同时操作同一串口 |
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈