更新时间:2024-07-30 03:10:21下载pdf
本文介绍 TuyaOS 蓝牙 Mesh 开发包架构、运行流程、目录,以及常用 API 和常用功能。
TuyaOS 是基于组件化的概念设计的,提供了基础服务、安全、网络服务中间件以及丰富的物联网业务功能组件,这些功能组件构成了 TuyaOS 的能力地图。TuyaOS 蓝牙开发框架就是基于 TuyaOS 的能力地图,按照蓝牙设备工作场景的能力需求,构建的不同规格的、适用于不同场景的 SDK 的集合。
这些开发框架提供了统一的接口、丰富的组件能力,您无需关心具体的实现原理,调用接口函数即可快速开发产品功能,并提供了统一的开发体验。
根据上图可知,TuyaOS Bluetooth Mesh 开发包主要分为 4 层。
第 1 层是涂鸦核心适配层(Tuya Kernel Layer,TKL 层),由涂鸦提供的 TKL 层标准接口和芯片原厂 SDK 组成。TKL 层对上提供统一的接口,对下适配不同的芯片平台,适配工作可能由涂鸦开发人员完成,也可能由芯片原厂的开发人员完成。
第 2 层和第 3 层是涂鸦抽象层(Tuya Abstraction Layer,TAL 层),由各种组件组成,是开发包的主体部分。基本功能包括涂鸦配网、数据通信以及系统管理功能。
第 4 层是应用层,涵盖照明、电工、传感、遥控器、无线开关等多个领域。除了提供标准的产品例程以外,涂鸦还提供了标准 Demo 工程,标准 Demo 工程无需任何改动,即可直接编译烧录,您可参考 Demo 来实现更复杂的应用。
更多信息,参考 设备初始化。
此处展示的 Demo 是 TuyaOS Bluetooth Mesh 开发包最基础的 Demo,您可以通过该 Demo 体验开发包支持的几乎所有功能,也可以基于该 Demo 开发更加复杂的应用功能。
app_common
:Demo 应用初始化以及基础的 Mesh 数据收发,Demo 以两路灯为例展示了如何使用 Mesh 标准 Opcode 通信。
tuya_mesh_sdk_test
:涂鸦串口上位机测试功能,包括蓝牙 Mesh、系统以及各种外设接口测试功能。您也可以参考代码实现来使用 SDK 提供的接口。
tal_driver
:实现驱动相关接口封装。
tal_gpio_test
:实现涂鸦产测工具 GPIO 测试功能。
tal_oled
:实现 OLED 屏幕驱动功能。
tal_system
:实现系统相关接口封装。
tal_utc
:实现 UTC 相关接口。
tal_util
:实现通用工具接口。
tal_bluetooth
:实现蓝牙、蓝牙 Mesh 相关接口封装。
tal_mesh_factory_test
:实现授权(产测)功能。
tal_mesh_gatt_ota
:实现 OTA 功能。
tal_nv_flash
:实现 Flash NV 存储功能。
Vendor 是开发环境所在目录,包含芯片原厂 SDK、各类适配层以及通用头文件,由涂鸦和芯片原厂共同维护。
芯片原厂 SDK
基于芯片原厂的公开例程开发或由芯片原厂开发人员修改而来。
各类适配层
涉及蓝牙、外设驱动(GPIO、PWM、ADC、IIC、SPI……)、系统驱动(Memory、OTA、Sleep……)、安全加密与 Hash 接口(AES、MD5)和工具接口的适配。
通用头文件
为保证 TKL 层以上能够达到一套代码适用于多个芯片平台的目标,Flash 地址、外设引脚等平台相关的因素都通过统一的宏定义放置于 board.h
中。
tuya_error_code.h
:涂鸦对错误类型的定义。
tuya_cloud_types.h
:涂鸦对数据类型、枚举、宏和结构体的定义。
tuya_iot_config
:涂鸦对系统配置、组件使能/配置的定义。
tuya_init_first()
:一般用于基础外设、配置信息和内存处理相关的初始化。
tuya_init_second()
:一般用于 Log、软定时和蓝牙基础协议相关的初始化。
tuya_init_third()
:一般用于复杂外设和外设组件相关的初始化。
tuya_init_last()
:一般用于初始化的收尾工作,包含蓝牙配网协议的初始化、测试代码的初始化、开启广播等动作。在执行完该 API 之后,一般会进入主循环。
tuya_main_loop()
:TuyaOS 蓝牙 Mesh 开发包基于前后台软件框架,提供了主循环内的回调接口 tuya_main_loop()
,您可依据需求,自定义相关操作注入此接口。
注意:
此接口的返回值会影响低功耗功能,请勿随意修改。
此接口主要用于您添加调试、验证性的操作,需 谨慎使用。此接口占用过多时间片会影响整个系统框架的稳定性。
参考 蓝牙 Mesh Category 与 数据收发与 DP 控制,在不同的能力值时设备所使用的 Mesh opcode
是不同的。因此,在 Mesh 数据接收时,使用与设备能力值相对应的 opcode
才能正确接收数据。
回调注册
OPERATE_RET tal_mesh_msg_recv_cb_init(tal_mesh_msg_recv_cb access_data_cb);
此函数用于注册 Mesh 数据接收回调到 tal_bluetooth
组件中。当设备接收到控制命令时,会调用注册函数,将数据给到应用层处理。
typedef OPERATE_RET (*tal_mesh_msg_recv_cb)(TAL_MESH_ACCESS_MSG_T *msg_raw, TAL_MESH_NET_PARAM_T *net_param);
对于回调函数,包括两个入参,即 msg_raw
与 net_param
。
msg_raw
:即 Access 层数据接收参数,包括数据的 opcode
与实际 data
数据的 Hex 格式等。根据不同的 opcode
,可将 Hex data
转换为对应的结构化数据。net_param
:即数据 Network 层相关的参数,数据的 src_addr
(源地址)、dst_addr
(目的地址)、SEQ(当前数据的序列号)、TTL(当前数据包中的 TLL 值)和 RSSI(当前数据包接收到时的信号强度)等。数据处理
opcode
为 Access 层类似 CMD ID 的属性,代表当前数据的类型。一般 Client Model 发送 get/set/set unack 等 opcode
给 Server Model,Server Model 接收处理后回复 Status opcode
给 client。上述为大部分 opcode
的使用方式,更多信息,根据蓝牙官方 Model Specification 中的定义进行使用。
在大部分控制场景中,App、网关以及遥控器一般都是使用 Client Model,设备一般使用 Server Model,以此来实现设备间控制数据与状态回复数据的通信。
opcode
宏定义参考 tal_bluetooth_mesh_def.h
中的定义,例如 Genric onoff set 所对应的宏定义为:
#define TAL_MESH_OPCODE_ON_OFF_SET (0x8202)
同时收到 opcode
的数据,将 Hex Data 转换为对应的数据格式。也可以参考 tal_bluetooth_mesh_def.h
中的结构体定义,例如在收到 Genric onoff set 的数据时,可以将 data
转换为 TAL_MESH_GENERIC_ONOFF_SET_T
类型。
typedef struct{
UCHAR_T onoff; /**< The target value of the Generic OnOff state. */
UCHAR_T tid; /**< Transaction Identifier */
UCHAR_T transit_t; /**< Generic Default Transition Time(optional). */
UCHAR_T delay; /**< If the transit_t field is present, the Delay field shall also be present; otherwise these fields shall not be present. */
}TAL_MESH_GENERIC_ONOFF_SET_T;
数据接收处理与回复示例:
OPERATE_RET app_mesh_data_recv(TAL_MESH_ACCESS_MSG_T *msg_raw, TAL_MESH_NET_PARAM_T *net_param){
switch(msg_raw->opcode){
case TAL_MESH_OPCODE_ON_OFF_SET:
case TAL_MESH_OPCODE_ON_OFF_SET_UNACK:
TAL_MESH_GENERIC_ONOFF_SET_T *onoff_set = (TAL_MESH_GENERIC_ONOFF_SET_T)msg_raw->data;
BOOL_T onoff = onoff_set->onoff;
light_onoff_set(onoff);
TAL_MESH_GENERIC_ONOFF_STATUS_T onoff_status;
onoff_status.present = onoff;
onoff_status.target = onoff;
onoff_status.remain_t = 0;
if(TAL_MESH_OPCODE_ON_OFF_SET == msg_raw->opcode){
tal_mesh_data_send(net_param->dst_addr, net_param->src_addr, TAL_MESH_OPCODE_ON_OFF_STAT, &onoff_status, sizeof(onoff_status));
}
break;
}
}
OPERATE_RET tal_mesh_data_send(USHORT_T src_addr, USHORT_T dst_addr, UINT_T opcode, UCHAR_T *data, USHORT_T data_len);
此接口为 Access 层接口发送,可以直接填写发送的数据与 opcode
,SDK 底层将数据按照当前的 Network 层参数按照顺序发送出去。
dst_addr
为接收设备的目的地址。src_addr
则为发送数据的源地址,一般为设备自己的 unicast addr,可以通过 tkl_mesh_primary_ele_addr_get();
获取。src_addr
填 0
或者 NULL,则 SDK 会自动转换为设备的主 element addr。对于多 element 类设备在填充 src_addr
时,则要填写正确的 element addr(primary_ele_addr
+ element_index
)。当设备需要主动上报数据但是未知对端手机 App 或者网关的 unicast_addr
时,可以在上报数据时将 dst_addr
填充为 TUYA_REPROT_PUB_ADDR
(tal_bluetooth_mesh_def.h
中的宏定义)。手机 App 与网关会订阅此地址,向此地址发送的数据将会正常收到并处理。
#define TAL_MESH_OPCODE_CFG_MODEL_SUB_ADD (0x801B)
#define TAL_MESH_OPCODE_CFG_MODEL_SUB_DELETE (0x801C)
OPERATE_RET tal_group_addr_sub_set(UINT_T opcode, USHORT_T ele_index, USHORT_T group_addr);
此接口用于给指定的 Model 增加或者删除订阅群组地址,SDK 底层会自动对当前 Element 的所有 Model 进行订阅。
USHORT_T* tal_group_addr_sub_list_get(USHORT_T ele_idx, USHORT_T model_id);
此接口用于获取 Element 指定 Model 的订阅列表,目前设备支持的群组地址最大订阅数量为 32 个。
OPERATE_RET tal_element_register(USHORT_T element_index);
OPERATE_RET tal_model_register(USHORT_T element_index, UINT_T model_id);
更多信息,参考 初始化。
typedef enum {
MESH_NETWORK_RESET = 0x00, /**< Kick out, mesh node will be unprovision state, and it will clear the mesh provision data in ram and flash */
MESH_NETWORK_RESET_WITH_RECOVER, /**< Node reset in tam, mesh node will be unprovision state, and it will clear the mesh provision data in ram. The provision data still store in flash */
MESH_NETWORK_RECOVER, /**< Recover the network, mesh node will be provision state, it will restore the provision data from flash into ram */
} MESH_NETWORK_STATE_SET_T;
OPERATE_RET tal_mesh_network_state_set(MESH_NETWORK_STATE_SET_T net_state);
通过此接口,将设备重置为未配网状态。有两种重置方式,MESH_NETWORK_RESET
为设备彻底重置。MESH_NETWORK_RESET_WITH_RECOVER
则为可恢复的重置方式,重置之后如果没有新配网,set 为 MESH_NETWORK_RESET_WITH_RECOVER
或者将设备重启,设备都可以恢复到重置之前的网络。
带恢复的方式一般用于误重置恢复功能,有些设备的重置可能是人为或者非人为的误操作。如果设备直接重置,则需要手动重新配回网络。如果超时恢复,则省略该操作。
typedef enum{
TAL_MESH_POWER_ON_UNPROVISION = 0,
TAL_MESH_POWER_ON_PROVISIONED,
TAL_MESH_PROVISION_SUCCESS,
TAL_MESH_RESET,
TAL_MESH_RESET_IN_RAM,
TAL_MESH_REVERT_IN_MESH,
TAL_MESH_GROUP_SUB_ADD,
TAL_MESH_GROUP_SUB_DEL,
TAL_GATT_OTA_START,
TAL_GATT_OTA_SUCCESS,
TAL_GATT_OTA_FAIL,
TAL_STATE_UNKONWN
}TAL_MESH_NET_STATE_T;
VOID tal_mesh_state_callback(TAL_MESH_NET_STATE_T state);
此函数为 Mesh 设备状态的回调,您需要在应用层实现此函数的实例,则 SDK 在相关操作后会通过此函数给到业务层提示。底层实现方式为 Weak 函数方式,如果业务层不实现,则底层会使用一个空函数链接到固件中。
VOID tal_mesh_node_provision_enable(MESH_PROVISION_TYPE_T enable);
此接口可以开启或者关闭设备发送未配网广播,用于设备虽然处于未配网状态,但此时不想被 App 或者网关配网或者用来实现配网时间窗口,超时后不允许配网等功能。
UCHAR_T tal_get_if_prov_success(VOID);
用于获取当前设备的配网状态(具体为 provision 状态)。但是对于 Mesh 的标准配网分为两个阶段,为 provision 与 config 阶段。只有在 config 阶段完成后才是完整的配网成功,可以依据 VOID tal_mesh_state_callback(TAL_MESH_NET_STATE_T state)
推送的状态来确定。此接口一般不用于配网过程完成的检测。
USHORT_T tal_primary_ele_addr_get(VOID);
用于获取设备当前主 Element 的地址,为配网时由 App 或者网关分配。
VOID tal_primary_ele_addr_set(USHORT_T addr, int flash_save_en);
用于设备主 Element 地址的设置,一般用于未配网时的部分特殊操作。配网后禁止调用修改,否则会出现设备无法通信的问题。
默认 Demo 中 Log 是关闭的,可以在 tuya_iot_config.h
中修改实现 #define ENABLE_LOG 1
,就可以使用 tal_log
组件中接口输出日志。已经打成 lib
的组件是没有日志的,如果有问题需要调试,联系涂鸦开发人员。
另外原厂 SDK 底层由于是源码开放,Log 可以直接开启。
app_mesh.h
中 LOG_FW_FUNC_EN
宏定义使能,即可开启。EM_platform.h
中 PHY_LOG_EN
宏定义使能,即可开启。tuya_sdk_test.h
中将 #define TUYA_SDK_TEST 1
注释或者修改为 #define TUYA_SDK_TEST 0
后,即可关闭原有的串口上位机 SDK 测试功能,将会节省大量的 code size。
功能默认开启,测试代码结合测试上位机(Logic)可实现大部分配网、通信和外设等功能的测试,可帮助您更好地开发产品,但是生产固件请务必关闭测试功能。
Tuya Bluetooth Mesh SDK 中支持动态内存,通过如下接口可以实现堆的申请与释放。
VOID_T *tkl_system_malloc(SIZE_T size);
VOID_T tkl_system_free(VOID_T* ptr);
动态内存默认配置大小可搜索宏定义 HEAP_SIZE
,目前不同平台配置不同,可以根据自身需求改动。
涂鸦通过 TKL 层提供了最小功能集所需的驱动接口,TKL 只是涂鸦标准化的接口,并非所有驱动都有 TKL。
为了保证开发效率,如果 TKL 层对应的驱动没有实现或者没有相关驱动,您可以按照实际需求,直接调用芯片原厂提供的接口。
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈