Bluetooth Mesh Software

Last Updated on : 2024-05-21 08:13:52download

This topic describes the TuyaOS Bluetooth mesh development kit in terms of its architecture, run process, directory, and common APIs.

Software architecture

TuyaOS is designed with a modular approach, with capabilities covering basic services, security, networking middleware, and various IoT services. Built on top of TuyaOS capabilities, TuyaOS Bluetooth Development Framework is a set of SDKs used to build Bluetooth products for different specifications and scenarios.

Unified APIs and a variety of components allow you to focus on building applications with a consistent development experience, without taking care of specific implementations.

Bluetooth Mesh Software

The diagram above shows that the TuyaOS Bluetooth mesh development kit is divided into four layers. We will now review each layer, starting from the bottom.

  • The Tuya Kernel Layer (TKL) consists of Tuya-specific standard TKL APIs and chip vendor SDKs. The TKL provides unified APIs for the upper layer and adapts to different chip platforms. The adaptation development can be carried out by Tuya or chip vendors.

  • The Tuya Abstraction Layer (TAL) and Service Layer, the core parts of the development kit, consist of various components. The basic services include pairing, data communication, and system management.

  • The Application Layer covers various fields including lights, electrical products, sensors, remotes, and wireless switches. Besides the standard product routines, you can build with the standard demo projects without altering the code, or implement complex features on top of the demo.

Run process

Bluetooth Mesh Software

For more information, see Device Initialization.

Development kit directory

Bluetooth Mesh Software

Demo

Bluetooth Mesh Software

This basic demo project allows you to test almost all the Bluetooth mesh development kit features and develop complex applications accordingly.

  • app_common: Demo application initialization and basic Bluetooth mesh data reception and transmission. The demo uses a cool and warm white light to show how communication functions with standard mesh opcodes.

  • tuya_mesh_sdk_test: Used to test the Bluetooth mesh, system, and peripherals through Tuya’s production tool. You can refer to the example code for implementing the SDK’s API.

Components

Bluetooth Mesh Software Bluetooth Mesh Software
  • tal_driver: Driver API.

  • tal_gpio_test: GPIO testing with Tuya’s production tool.

  • tal_oled: OLED driver.

  • tal_system: System service API.

  • tal_utc: UTC API.

  • tal_util: Common tools.

  • tal_bluetooth: Bluetooth and Bluetooth mesh API.

  • tal_mesh_factory_test: Authorization and testing.

  • tal_mesh_gatt_ota: OTA updates.

  • tal_nv_flash: Nonvolatile storage for flash memory.

Vendor

Bluetooth Mesh Software

The vendor directory stores the development environment, including chip vendor SDKs, adaptation layers, and common header files. It is maintained by Tuya and chip vendors.

Chip vendor SDK

The chip vendor SDK is developed by Tuya based on the open routines or adapted by chip vendors.

Adaptation layers

APIs for accessing Bluetooth, peripheral drivers (such as GPIO, PWM, ADC, I2C, and SPI), system drivers (such as memory, OTA, and sleep), secure encryption and hash algorithms (AES and MD5), and common tools.

Common header files

To enable a single codebase above the TKL to run across different platforms, platform-specific code such as flash address and peripheral pins is stored in board.h as macro definitions.

Header files

Bluetooth Mesh Software
  • tuya_error_code.h: Definitions for error codes.

  • tuya_cloud_types.h: Definitions for data types, enumerations, macros, and structs.

  • tuya_iot_config: Definitions for system configuration and component enablement or configuration.

Common APIs

Initialization

  • tuya_init_first(): Initializes basic peripherals, configurations, and memory.

  • tuya_init_second(): Initializes logging, software timer, and Bluetooth.

  • tuya_init_third(): Initializes complex peripherals and peripheral components.

  • tuya_init_last(): Initializes the Bluetooth pairing protocol and the test code, and enables Bluetooth adverting. After this API is executed, the main loop will be run.

Main loop

tuya_main_loop(): A callback within the main loop, allowing you to inject custom operations into it.

Note:

  • Do not modify the return value of this API unless necessary, as it can impact the low power mode.

  • This API is intended for debugging and validation purposes. Use it with caution. Excessive time slices used by this API can compromise the stability of the entire framework.

Receive data

The Bluetooth mesh opcode varies by capability value. See Bluetooth Mesh Category and Data Transmission and DP Control for more information. The Bluetooth mesh device can receive data as expected when the correct opcode is used.

Register callbacks

OPERATE_RET tal_mesh_msg_recv_cb_init(tal_mesh_msg_recv_cb access_data_cb);

Register the Bluetooth mesh data reception callback into the tal_bluetooth component. When the device receives a control command, it will call the registered function to send the data to the application layer for processing.

typedef OPERATE_RET (*tal_mesh_msg_recv_cb)(TAL_MESH_ACCESS_MSG_T *msg_raw, TAL_MESH_NET_PARAM_T *net_param);

The callback has two parameters: msg_raw and net_param.

  • msg_raw: The data reception parameters for the access layer, including the opcode as well as the payload data in hex format. Convert the hex data into structured data based on the opcode.
  • net_param: The parameters for the network layer, including src_addr (source address), dst_addr (destination address), SEQ (sequence number of the current packet), TTL (time to live), and RSSI (signal strength upon receiving the packet).

Process data

opcode specifies the data type for the access layer, similar to a command ID. The client model sends an opcode, such as get, set, and set unacknowledged, to the server model that returns a status opcode to the client after executing the command. For more information about how to use the opcode, visit the official Bluetooth website for Mesh Model Specifications.

In most control scenarios, the mobile app, gateway, and remote use the client model to send commands, while the device uses the server model to report status.

See tal_bluetooth_mesh_def.h for the opcode definitions. For example, the macro for Generic OnOff Set is as follows.

#define TAL_MESH_OPCODE_ON_OFF_SET                      (0x8202)

After receiving the opcode data, convert the hex data into the required format. Refer to the struct definitions in tal_bluetooth_mesh_def.h. For example, change the received Generic OnOff Set data into the TAL_MESH_GENERIC_ONOFF_SET_T type.

 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;

Example of processing and responding to the data received:

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;
        }
    }

Send data

OPERATE_RET tal_mesh_data_send(USHORT_T src_addr, USHORT_T dst_addr, UINT_T opcode, UCHAR_T *data, USHORT_T data_len);

This function sends data from the access layer. Specify the payload data and opcode. The SDK will send the data based on the network layer parameters in sequence.

  • dst_addr: The destination address.
  • src_addr: The source address. It is typically the unicast address of the device, which can be obtained through tkl_mesh_primary_ele_addr_get();.
  • If src_addr is set to 0 or NULL, the SDK will populate it with the device’s main element address instead. For multi-element devices, set src_addr to the element address using the correct format primary_ele_addr + element_index.

When the device proactively reports data without knowing the unicast_addr of the mobile app or gateway, dst_addr can be set to TUYA_REPROT_PUB_ADDR as defined in tal_bluetooth_mesh_def.h. The mobile app and gateway subscribe to this address, ensuring that any data sent here will be received and processed.

Add and query group

#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);

This function subscribes to or unsubscribes from a group address for the specified model. The SDK will automatically subscribe to all models of an element.

USHORT_T* tal_group_addr_sub_list_get(USHORT_T ele_idx, USHORT_T model_id);

This function requests the subscription list of the specified model for an element. Currently, a device can subscribe to up to 32 group addresses.

Manage element and model

OPERATE_RET tal_element_register(USHORT_T element_index);
OPERATE_RET tal_model_register(USHORT_T element_index, UINT_T model_id);

For more information, see Initialization.

Reset device

typedef enum {
    MESH_NETWORK_RESET = 0x00,            /**< Kick out, mesh node will be in the unprovisioned 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 in the unprovisioned state, and it will clear the mesh provision data in RAM. The provision data is still stored in the flash */
    MESH_NETWORK_RECOVER,                 /**< Recover the network, the mesh node will be in the provisioned state, and 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);

Reset a device to the unpaired status. Two reset methods are available. MESH_NETWORK_RESET resets a device irreversibly. MESH_NETWORK_RESET_WITH_RECOVER resets a device reversibly. If a device is not paired after a reset, set the request parameter to MESH_NETWORK_RESET_WITH_RECOVER or restart the device to restore the network to its previous state before the reset.

The reversible method can prevent an accidental reset. If a device is reset irreversibly, it needs to be manually paired to reconnect to the network. If the network is restored in case of pairing timeout, this manual action is unnecessary.

Device status callback

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);

This function is a callback for the mesh device status. You need to create an instance of this function in the application layer so that the SDK can inform the service layer about the action it has performed. This callback is implemented with a weak function at the bottom layer. If a function instance is not created in the service layer, the bottom layer will link a null function to the firmware.

Enable pairing

VOID tal_mesh_node_provision_enable(MESH_PROVISION_TYPE_T enable);

This function enables or disables the device’s ability to advertise its presence for pairing. It is used when an unpaired device does not want to be paired with the mobile app or gateway, or when pairing times out.

Get pairing state

UCHAR_T tal_get_if_prov_success(VOID);

Get the provisioning status of the device. The Bluetooth mesh device pairing involves two stages: provisioning and configuration. The pairing is successful when the configuration stage is completed, which can be confirmed by the status sent from VOID tal_mesh_state_callback(TAL_MESH_NET_STATE_T state). This function is not used to verify the pairing process completion.

Get unicast address

USHORT_T tal_primary_ele_addr_get(VOID);

Get the address of the device’s main element, which is assigned by the mobile app or gateway during pairing.

VOID tal_primary_ele_addr_set(USHORT_T addr, int flash_save_en);

Set the address of the device’s main element when it is not paired. Do not call this function to change the main element address after pairing the device, as it may cause communication problems.

Common features

Logging

The demo has logging turned off by default. You can modify #define ENABLE_LOG 1 in tuya_iot_config.h to enable log output using the API in tal_log. Note that components that have been compiled into a library do not have logs. To debug them, contact Tuya’s technical support.

The chip vendor SDK is open source, allowing you to enable logging directly.

  1. For TLSR825x, enable LOG_FW_FUNC_EN in app_mesh.h to turn on logging.
  2. For PHY6222, enable PHY_LOG_EN in EM_platform.h to turn on logging.

SDK testing

In tuya_sdk_test.h, you can disable the SDK testing feature to save code size by commenting out #define TUYA_SDK_TEST 1 or modifying it to #define TUYA_SDK_TEST 0.

The SDK testing feature is enabled by default. You can test pairing, communication, and peripherals using the test code and Tuya’s host software. Make sure to disable the testing feature on production firmware.

Dynamic memory

The SDK supports dynamic memory allocation. Allocate and release heap memory with the following function.

VOID_T *tkl_system_malloc(SIZE_T size);
VOID_T tkl_system_free(VOID_T* ptr);

You can change the default size of dynamic memory with the macro HEAP_SIZE as needed.

Drivers

TuyaOS Kernel Layer (TKL) provides a set of standard driver APIs required to run a minimum viable TuyaOS product. Note that not all drivers have the TKL API.

If the driver you need in the TKL is not implemented or not available, you can directly use the API provided by the chip vendor.