蓝牙 Mesh 软件介绍

更新时间:2024-04-17 06:15:25下载pdf

本文介绍 TuyaOS 蓝牙 Mesh 开发包架构、运行流程、目录,以及常用 API 和常用功能。

软件架构

TuyaOS 是基于组件化的概念设计的,提供了基础服务、安全、网络服务中间件以及丰富的物联网业务功能组件,这些功能组件构成了 TuyaOS 的能力地图。TuyaOS 蓝牙开发框架就是基于 TuyaOS 的能力地图,按照蓝牙设备工作场景的能力需求,构建的不同规格的、适用于不同场景的 SDK 的集合。

这些开发框架提供了统一的接口、丰富的组件能力,您无需关心具体的实现原理,调用接口函数即可快速开发产品功能,并提供了统一的开发体验。

蓝牙 Mesh 软件介绍

根据上图可知,TuyaOS Bluetooth Mesh 开发包主要分为 4 层。

  • 第 1 层是涂鸦核心适配层(Tuya Kernel Layer,TKL 层),由涂鸦提供的 TKL 层标准接口和芯片原厂 SDK 组成。TKL 层对上提供统一的接口,对下适配不同的芯片平台,适配工作可能由涂鸦开发人员完成,也可能由芯片原厂的开发人员完成。

  • 第 2 层和第 3 层是涂鸦抽象层(Tuya Abstraction Layer,TAL 层),由各种组件组成,是开发包的主体部分。基本功能包括涂鸦配网、数据通信以及系统管理功能。

  • 第 4 层是应用层,涵盖照明、电工、传感、遥控器、无线开关等多个领域。除了提供标准的产品例程以外,涂鸦还提供了标准 Demo 工程,标准 Demo 工程无需任何改动,即可直接编译烧录,您可参考 Demo 来实现更复杂的应用。

软件运行流程

蓝牙 Mesh 软件介绍

更多信息,参考 设备初始化

开发包目录

蓝牙 Mesh 软件介绍

Demo 目录

蓝牙 Mesh 软件介绍

此处展示的 Demo 是 TuyaOS Bluetooth Mesh 开发包最基础的 Demo,您可以通过该 Demo 体验开发包支持的几乎所有功能,也可以基于该 Demo 开发更加复杂的应用功能。

  • app_common:Demo 应用初始化以及基础的 Mesh 数据收发,Demo 以两路灯为例展示了如何使用 Mesh 标准 Opcode 通信。

  • tuya_mesh_sdk_test:涂鸦串口上位机测试功能,包括蓝牙 Mesh、系统以及各种外设接口测试功能。您也可以参考代码实现来使用 SDK 提供的接口。

组件目录

蓝牙 Mesh 软件介绍 蓝牙 Mesh 软件介绍
  • 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 目录

蓝牙 Mesh 软件介绍

Vendor 是开发环境所在目录,包含芯片原厂 SDK、各类适配层以及通用头文件,由涂鸦和芯片原厂共同维护。

芯片原厂 SDK

基于芯片原厂的公开例程开发或由芯片原厂开发人员修改而来。

各类适配层

涉及蓝牙、外设驱动(GPIO、PWM、ADC、IIC、SPI……)、系统驱动(Memory、OTA、Sleep……)、安全加密与 Hash 接口(AES、MD5)和工具接口的适配。

通用头文件

为保证 TKL 层以上能够达到一套代码适用于多个芯片平台的目标,Flash 地址、外设引脚等平台相关的因素都通过统一的宏定义放置于 board.h 中。

头文件目录

蓝牙 Mesh 软件介绍
  • tuya_error_code.h:涂鸦对错误类型的定义。

  • tuya_cloud_types.h:涂鸦对数据类型、枚举、宏和结构体的定义。

  • tuya_iot_config:涂鸦对系统配置、组件使能/配置的定义。

常用 API

初始化

  • 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_rawnet_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_addr0 或者 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 个。

Element 与 Model 管理

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) 推送的状态来确定。此接口一般不用于配网过程完成的检测。

获取设备的 unicast addr

USHORT_T tal_primary_ele_addr_get(VOID);

用于获取设备当前主 Element 的地址,为配网时由 App 或者网关分配。

VOID tal_primary_ele_addr_set(USHORT_T addr, int flash_save_en);

用于设备主 Element 地址的设置,一般用于未配网时的部分特殊操作。配网后禁止调用修改,否则会出现设备无法通信的问题。

常用功能

LOG 开启

默认 Demo 中 Log 是关闭的,可以在 tuya_iot_config.h 中修改实现 #define ENABLE_LOG 1,就可以使用 tal_log 组件中接口输出日志。已经打成 lib 的组件是没有日志的,如果有问题需要调试,联系涂鸦开发人员。

另外原厂 SDK 底层由于是源码开放,Log 可以直接开启。

  1. TLSR825x 平台将 app_mesh.hLOG_FW_FUNC_EN 宏定义使能,即可开启。
  2. PHY6222 平台将 EM_platform.hPHY_LOG_EN 宏定义使能,即可开启。

SDK 测试功能关闭

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 层对应的驱动没有实现或者没有相关驱动,您可以按照实际需求,直接调用芯片原厂提供的接口。