Last Updated on : 2024-11-20 02:13:27download
The HomeKit MCU SDK contains all you need to get started with MCU development, such as functions and sample code. It is automatically generated based on the product features defined on the Tuya Developer Platform. This topic describes how to port the HomeKit MCU SDK to your project.
The HomeKit MCU SDK is automatically generated based on the product features defined on the Tuya Developer Platform. With the built-in support for communication and protocol parsing, the HomeKit MCU SDK can facilitate interfacing with Tuya’s Wi-Fi module. You can add this SDK to existing projects and complete the required configuration to implement the MCU program development.
SDK requirements for the MCU are as follows. If your MCU does not have sufficient resources, you can refer to the functions in the SDK for interfacing with Tuya’s protocol.
Files | Description |
---|---|
mcu_api.c |
Contains functions that can be called. |
mcu_api.h |
Contains declarations for functions in mcu_api.c . |
protocol.c |
Contains functions for processing protocol data. You can add code to related functions as needed and get data sent by the Wi-Fi module to the MCU. |
protocol.h |
protocol.h contains the following information:
|
system.c |
Contains the implementation of parsing the serial protocol. |
system.h |
system.h contains the following information:
|
wifi.h |
Contains macro definitions for Wi-Fi communication. |
homekit.c |
Contains HomeKit configurations and data handles. |
homekit.h |
homekit.h contains the following information:
|
tuya_type.h |
Definition of the data type, which defaults to 32 bits. If this definition does not apply to your MCU, you can change the data type in this header file. |
protocol.h
.protocol.c
file and call functions.homekit.c
.In your original project, initialize the MCU peripherals, including serial port, external interrupt (button), timer (indicator flickering), and more.
Copy the .c
and .h
files in the MCU SDK folder to your project directory where your other .c
and .h
files are located.
protocol.h
Define the product ID (PID). PRODUCT_KEY
is the macro defined for the PID. PID is the unique identifier of each product and can be found on the Smart Products page on the Tuya Developer Platform.
#define PRODUCT_KEY "ax23rawjo4np****"
If the PRODUCT_KEY
and the PID are inconsistent, you can go to Hardware Development > Download Documents section and download the latest SDK.
Define the version number. MCU_VER
defines the software version, which defaults to 1.0.0
. If you enable OTA updates for the MCU firmware, you need to add the new MCU version number after updates.
#define MCU_VER "1.0.0"
Select HomeKit accessory category. The category name must follow the accessory categories defined by HomeKit Accessory Protocol (HAP). For example, if you create an air purifier on the HomeKit platform, you must choose air purifier as the product type.
/* Select HomeKit accessory category. Configure services and characteristics in `homekit.c` */
//#define HOMEKIT_PRODUCT_TYPE 3 // Fan
//#define HOMEKIT_PRODUCT_TYPE 4 // Garage Door Opener
//#define HOMEKIT_PRODUCT_TYPE 5 // Lighting
//#define HOMEKIT_PRODUCT_TYPE 9 // Thermostat
//#define HOMEKIT_PRODUCT_TYPE 12 // Door
//#define HOMEKIT_PRODUCT_TYPE 13 // Window
//#define HOMEKIT_PRODUCT_TYPE 14 // Window Covering
#define HOMEKIT_PRODUCT_TYPE 19 // Air Purifier
//#define HOMEKIT_PRODUCT_TYPE 20 // Heater
//#define HOMEKIT_PRODUCT_TYPE 22 // Humidifier
//#define HOMEKIT_PRODUCT_TYPE 23 // Dehumidifier
//#define HOMEKIT_PRODUCT_TYPE 28 // Sprinkler
//#define HOMEKIT_PRODUCT_TYPE 29 // Faucet
//#define HOMEKIT_PRODUCT_TYPE 30 // Shower System
Specify whether to configure the valid values of characteristics.
/* Specify whether to configure the valid values of characteristics. */
//#define HOMEKIT_CHARACTER_VALID_CFG_ENABLE
Configure the valid values of characteristics in char_valid_value_cfg
.
/**
* @brief Configure the valid values of characteristics.
* @param Null
* @return Null
* @note
*/
static void char_valid_value_cfg(void)
{
//#error "Complete the code and delete this row."
static u8 cfg_count = 0;
u16 send_len = 0;
char strbuff[80] = {0};
u8 strlen = 0;
switch(cfg_count++) {
case 0:
// Configure valid values.
// For example, strlen = sprintf(strbuff, "{\"service_serial\":7,\"char_str\":\"A9\",\"val_type\":0,\"valid_val\":[0,2]}");
break;
// If you have multiple characteristics to be configured, add case.
// case 1:
// // Configure valid values.
// break;
default:
// Configuration is completed.
send_len = set_wifi_uart_byte(send_len, HK_SUB_CMD_CFG_QUERY);
wifi_uart_write_frame(HOMEKIT_FUN_CMD, MCU_TX_VER, send_len);
cfg_count = 0;
return;
break;
}
send_len = set_wifi_uart_byte(send_len, HK_SUB_CMD_CHARACTER_VALID_CFG);
send_len = set_wifi_uart_buffer(send_len, strbuff, strlen);
wifi_uart_write_frame(HOMEKIT_FUN_CMD, MCU_TX_VER, send_len);
}
Enable OTA updates. To support OTA firmware updates, define SUPPORT_MCU_FIRM_UPDATE
. OTA updates are disabled by default.
#define SUPPORT_MCU_FIRM_UPDATE
Define the size of a single package.
#ifdef SUPPORT_MCU_FIRM_UPDATE
#define PACKAGE_SIZE 0 // One update package is 256 bytes.
//#define PACKAGE_SIZE 1 // One update package is 512 bytes.
//#define PACKAGE_SIZE 2 // One update package is 1024 bytes.
#endif
For more information about the OTA updates, see Update Firmware.
Configure MCU firmware partition
/* Types of firmware partition */
#define MCU_FIRMWARE_BACKUP_AREA_TYPE 0 // The MCU has two firmware partitions. 0 is the default value.
//#define MCU_FIRMWARE_BACKUP_AREA_TYPE 1 // The MCU has one firmware partition.
The OTA update process differs depending on the types of firmware partition. For more information, see OTA Updates.
Serial receive buffer: The buffer size depends on how often the serial data handler is called. If the MCU can quickly process serial data, the buffer size can be reduced.
Serial transmit buffer: The buffer size must be greater than the maximum length of DP data.
Buffer for serial data processing: The buffer size must be greater than the maximum length of DP data. If OTA updates and specific weather services are enabled, the buffer size must be greater than the maximum amount of data.
/******************************************************************************
3: Define the transmit and receive buffer:
If your MCU has insufficient RAM, you can change the buffer size to 24 bytes.
******************************************************************************/
#ifndef SUPPORT_MCU_FIRM_UPDATE
#define WIFI_UART_RECV_BUF_LMT 16 // The serial receive buffer size, which can be reduced if your MCU has insufficient RAM.
#define WIFI_DATA_PROCESS_LMT 24 // The buffer size for serial data processing. It depends on the amount of DP data. A size greater than 24 bytes is recommended.
#else
#define WIFI_UART_RECV_BUF_LMT 128 // The serial receive buffer size, which can be reduced if your MCU has insufficient RAM.
// Set the proper buffer size. Consider the defined update package and specific weather services, if applicable.
#define WIFI_DATA_PROCESS_LMT 300 // The buffer size for serial data processing. When OTA updates are enabled, if you set the size of a single update package to 256 bytes, the buffer size must be greater than 260 bytes. If weather services are also enabled, more buffer is required.
//#define WIFI_DATA_PROCESS_LMT 600 // The buffer size for serial data processing. When OTA updates are enabled, if you set the size of a single update package to 512 bytes, the buffer size must be greater than 520 bytes. If weather services are also enabled, more buffer is required.
//#define WIFI_DATA_PROCESS_LMT 1200 // The buffer size for serial data processing. When OTA updates are enabled, if you set the size of a single update package to 1024 bytes, the buffer size must be greater than 1030 bytes. If weather services are also enabled, more buffer is required.
#endif
#define WIFIR_UART_SEND_BUF_LMT 60 // It depends on the amount of DP data but must be greater than 51 bytes.
If the reset button and LED indicator for network status are connected to the MCU, the module works with the MCU to process network events, which is most commonly used. You need to comment out the macro WIFI_CONTROL_SELF_MODE
.
//#define WIFI_CONTROL_SELF_MODE // If you use the module self-processing mode, enable this macro and specify I/Os for Tuya-defined Wi-Fi status indicator, HomeKit-defined Wi-Fi status indicator, and the reset button. If your MCU works with the module to process network events, you need to disable this macro.
If the reset button and LED indicator for network status are connected to the Wi-Fi module, the module processes network events itself. You need to enable the macro WIFI_CONTROL_SELF_MODE
. Specify the GPIO pins connected to the indicator and the button in the following two macros.
#ifdef WIFI_CONTROL_SELF_MODE // The module processes network events itself.
#define TY_STATE_LED 0 // Tuya-defined Wi-Fi status indicator. Set it according to your circuit.
#define HK_STATE_LED 4 // HomeKit-defined Wi-Fi status indicator. Set it according to your circuit.
#define WF_RESERT_KEY 5 // Wi-Fi module reset button. Set it according to your circuit.
#endif
The production test feature for the Wi-Fi module is enabled by default. To help you smoothly and efficiently carry out mass production, it is recommended to enable the production test feature.
#define WIFI_TEST_ENABLE // Enable the production test feature.
For more information, see Production Test Guide.
You can complete corresponding functions to implement specific features.
protocol.c
file and call functionsCopy the wifi.h
file to the folder where Wi-Fi files are stored, such as the main.c
folder.
Call wifi_protocol_init()
function in the mcu_api.c
file after the MCU serial port and other peripherals are initialized.
Specify the function of single-byte data transmission in uart_transmit_output
in the protocol.c
file, and delete #error
.
/**
* @brief Send serial data
* @param[in] {value} The 1-byte data to be transmitted.
* @return Null
*/
void uart_transmit_output(u8 value)
{
//#error "Specify the UART transmission function and delete this line."
UART3_SendByte(value);
}
In the interrupt handler function for serial data reception, call uart_receive_input
in the mcu_api.c
file. Use the returned value as the parameter.
void UART3_SendByte(unsigned char data)
{
while((USART3->SR&UART_FLAG_TXE)!=UART_FLAG_TXE);
USART3->DR = data;
}
After the MCU executes the while(1)
loop, it calls the wifi_uart_service()
function in the mcu_api.c
file. The sample code in main.c
is as follows:
#include "wifi.h"
...
void main(void)
{
wifi_protocol_init();
...
while(1) {
wifi_uart_service();
...
}
...
}
The MCU must directly call wifi_uart_service(
) function in the mcu_api.c
file during while(1)
loop. After the program is initialized, if an interrupt service routine (ISR) is necessary, you must keep it as short as possible and not call the data reporting function to avoid loss of data.
The DP supports six data types.
To sync DP data with the Home app, you can call homekit_character_upload
.
After the module is restarted or paired again, it will initiate a status query. The MCU must return the status of all DPs.
Open protocol.c
and find the function all_data_update(void)
.
Specify the initial values in corresponding functions for all DPs to be reported. These values will be displayed on the control panel in the app.
Do not call all_data_update()
because this function will be called at the specified time.
/**
* @brief Upload the status of all DPs to sync with the app.
* @param Null
* @return Null
* @note The MCU implements the data reporting in this function, which must support two data transfer types, namely send only as well as send and report.
*/
void all_data_update(void)
{
//#error "Complete the example of two data transfer types and delete this line."
// This code is automatically generated. You need to edit it based on the actual DPs.
mcu_dp_bool_update(DPID_SWITCH,current on/off status); // Report Boolean data
mcu_dp_enum_update(DPID_MODE,current mode); // Report enum data
mcu_dp_fault_update(DPID_FAULT,current fault alert); // Report fault data
mcu_dp_value_update(DPID_PM25,current PM2.5); // Report value data
mcu_dp_value_update(DPID_PM10,current PM10); // Report value data
mcu_dp_enum_update(DPID_TIMER,current scheduled tasks); // Report enum data
mcu_dp_value_update(DPID_FILTER_PERCENT,current filter life level); // Report value data
mcu_dp_value_update(DPID_FILTER_USEH,current filter usage time); // Report value data
mcu_dp_bool_update(DPID_PHYSICAL_LOCKED,current child lock status); // Report Boolean data
#ifdef HOMEKIT_PRODUCT_TYPE
homekit_character_upload_all();
#endif
}
When the status of a single DP changes, the MCU must actively report the current DP status to sync with the app. The data format is mcu_dp_xxxx_updata(DPID_X,n)
, where DPID_X
is the DP whose status changes. You can call each function in all_data_update()
individually.
mcu_dp_bool_update(DPID_SWITCH,1); // Report Boolean data
mcu_dp_value_update(DPID_PM25,15); // Report value data
mcu_dp_enum_update(DPID_MODE,2); // Report enum data
mcu_dp_fault_update(DPID_FAULT,0x01); // Report fault data
mcu_dp_string_update(DPID_DAY,"1234",4); // Report string data
In protocol.c
, each DP that can send control commands has an individual command handler. The format is dp_download_xxx_handle()
, where xxx
is the DP that can send commands. After the function parses the DP, the MCU will execute commands accordingly.
Take the received switch DP data as an example:
/*****************************************************************************
Function name: dp_download_switch_handle
Feature description: the handler of `DPID_SWITCH`.
Input parameters: value indicates the data source
: length: the length of the data
Return parameters: Return SUCCESS on success and ERROR on failure
Note: For the type of send and report, the module must return the result to the cloud to sync with the app.
*****************************************************************************/
static u8 dp_download_switch_handle(const u8 value[], u16 length)
{
// For example, a DP of Boolean type
u8 ret;
// 0: off. 1: on.
u8 switch_1;
switch_1 = mcu_get_dp_download_bool(value,length);
if(switch_1 == 0) {
// The switch is off.
}else {
// The switch is on.
}
// Return the result of the operation.
ret = mcu_dp_bool_update(DPID_SWITCH,switch_1);
if(ret == SUCCESS)
return SUCCESS;
else
return ERROR;
}
If the change of device status is not triggered by control commands, the MCU will call mcu_dp_bool_update(DPID_SWITCH_1,switch_1);
to upload the current status of the DP for feedback. You can also choose the reporting time as needed.
The function of pairing and LED indicator is required only when the module works with the MCU to process network events.
To implement device pairing, add the pairing command and LED indicator function. If the module works with the MCU to process network events, you can customize the ways to pair devices and indicate pairing status. Generally, you can set the keypress trigger and LED indication.
mcu_reset_wifi()
is called in the button handler after the reset button is pressed.
mcu_reset_wifi()
will reset the Wi-Fi module. All the pairing information will be cleared.
To get Wi-Fi module’s network status, call get_wifi_tuya_state()
and get_wifi_homekit_state()
during while(1)
loop. Write the flickering mode of the LED indicator according to the network status.
Tuya-defined network status
Network status | Description | Status value |
---|---|---|
Status 1 | Waiting for connection | The LED flickers at an interval of 250 milliseconds. |
Status 2 | The Wi-Fi network has been set up but not connected to the router. | The LED indicator is steady off. |
Status 3 | The Wi-Fi module has been connected to the router but not to the cloud. | The LED indicator is steady off. |
Status 4 | The Wi-Fi module has been connected to the cloud. | The LED indicator is steady on. |
HomeKit-defined network status
Network status | Description | Status value |
---|---|---|
Status 1 | To be bound or being bound | The LED flickers at an interval of 250 milliseconds. |
Status 2 | Not connected | The LED indicator is steady off. |
Status 3 | Connected | The LED indicator is steady on. |
Call get_wifi_tuya_state()
and get_wifi_homekit_state()
to get Wi-Fi connection status.
void main(void){
...
while(1)
{
...
switch(get_wifi_tuya_state()) {
case CONFIG_STATE: //0x00
if(Timer3_Value % 2 == 0) // LED flickers quickly.
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
}
break;
case WIFI_NOT_CONNECTED: //0x02
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET); // LED is off.
break;
case WIFI_CONNECTED: //0x03
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);// LED is steady on.
break;
case WIFI_CONN_CLOUD: //0x04
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET); // LED is steady on.
break;
default:
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
break;
}
switch(get_wifi_homekit_state()) {
case CONFIG_STATE: //0x00
if(Timer3_Value % 2 == 0) // LED flickers quickly.
{
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
}
break;
case WIFI_NOT_CONNECTED: //0x02
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET); // LED is off.
break;
case WIFI_CONNECTED: //0x03
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);// LED is steady on.
break;
default:
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
break;
}
}
}
Scan the specified router For more information, see Production Test.
homekit.c
and configure HomeKit services and characteristicsConfigure HomeKit services
Enable the macro for your required HomeKit services. Take the fan as an example.
/******************************************************************************
1. Select the HomeKit service
Enable the required service according to your product features.
******************************************************************************/
#ifdef HOMEKIT_PRODUCT_TYPE
#define HOMEKIT_SERV_FAN_V2 // Fan
//#define HOMEKIT_SERV_GARAGE_DOOR_OPENER // Garage Door Opener
//#define HOMEKIT_SERV_LIGHTBULB // Light Bulb
//#define HOMEKIT_SERV_THERMOSTAT // Thermostat
//#define HOMEKIT_SERV_DOOR // Door
//#define HOMEKIT_SERV_WINDOW // Window
//#define HOMEKIT_SERV_WINDOW_COVERING // Window Covering
//#define HOMEKIT_SERV_AIR_PURIFIER // Air Purifier
//#define HOMEKIT_SERV_FILTER_MAINTENANCE // Filter Maintenance
//#define HOMEKIT_SERV_AIR_QUALITY_SENSOR // Air Quality Sensor
//#define HOMEKIT_SERV_SLAT // Slat
//#define HOMEKIT_SERV_HEATER_COOLER // Heater Cooler
//#define HOMEKIT_SERV_HUMIDIFIER_DEHUMIDIFIER // Humidifier Dehumidifier
//#define HOMEKIT_SERV_IRRIGATION_SYSTEM // Irrigation System
//#define HOMEKIT_SERV_VALVE // Valve
//#define HOMEKIT_SERV_FAUCET // Faucet
#endif
Configure optional characteristics
Select optional characteristics for your HomeKit services. Take the fan as an example. The optional characteristics can be current fan state, target fan state, rotation direction, and rotation speed.
/* FAN_V2 Optional characteristics of the fan service */
#ifdef HOMEKIT_SERV_FAN_V2//
#define FAN_V2_CHAR_NAME // Name
#define FAN_V2_CHAR_CURRENT_FAN_STATE // Current fan state
#define FAN_V2_CHAR_TARGET_FAN_STATE // Target fan state
#define FAN_V2_CHAR_ROTATION_DIRECTION // Rotation direction
#define FAN_V2_CHAR_ROTATION_SPEED // Rotation speed
//#define FAN_V2_CHAR_SWING_MODE // Swing mode
//#define FAN_V2_CHAR_LOCK_PHYSICAL_CONTROLS // Lock physical controls
#endif
Configure the initial values of characteristics
Set the initial value for each optional characteristic. The minimum value is used as the initial value by default. You can change it as needed.
HOMEKIT_CHARACTER_S fan_v2_character[] = {
{fan_v2_char_uuid_active_str, TRUE, TRUE, HAP_DATA_TYPE_UINT, .hap_val.u = 0 /* Assign the initial value */ },
#ifdef FAN_V2_CHAR_NAME
{fan_v2_char_uuid_name_str, FALSE, FALSE, HAP_DATA_TYPE_STRING, .hap_val.s = /* Assign the initial value */ },
#endif
#ifdef FAN_V2_CHAR_CURRENT_FAN_STATE
{fan_v2_char_uuid_current_fan_state_str, FALSE, FALSE, HAP_DATA_TYPE_UINT, .hap_val.u = 0 /* Assign the initial value */ },
#endif
#ifdef FAN_V2_CHAR_TARGET_FAN_STATE
{fan_v2_char_uuid_target_fan_state_str, FALSE, FALSE, HAP_DATA_TYPE_UINT, .hap_val.u = 0 /* Assign the initial value */ },
#endif
#ifdef FAN_V2_CHAR_ROTATION_DIRECTION
{fan_v2_char_uuid_rotation_direction_str, FALSE, FALSE, HAP_DATA_TYPE_INT, .hap_val.i = 0 /* Assign the initial value */ },
#endif
#ifdef FAN_V2_CHAR_ROTATION_SPEED
{fan_v2_char_uuid_rotation_speed_str, FALSE, FALSE, HAP_DATA_TYPE_FLOAT, .hap_val.f = 0 /* Assign the initial value */ },
#endif
#ifdef FAN_V2_CHAR_SWING_MODE
{fan_v2_char_uuid_swing_mode_str, FALSE, FALSE, HAP_DATA_TYPE_UINT, .hap_val.u = 0 /* Assign the initial value */ },
#endif
#ifdef FAN_V2_CHAR_LOCK_PHYSICAL_CONTROLS
{fan_v2_char_uuid_lock_physical_controls_str, FALSE, FALSE, HAP_DATA_TYPE_UINT, .hap_val.u = 0 /* Assign the initial value */ },
#endif
};
Configure service serial number
A configured service is identified by its serial number. This way, you can distinguish between services if you configure multiple identical services for a single product such as an irrigation system. To configure multiple identical services, add them following the code format below.
#ifdef HOMEKIT_SERV_FAN_V2
{
0, // Change the service serial number, which must be unique.
hap_serv_uuid_fan_v2_str,
FALSE,
CNTSOF(fan_v2_character),
fan_v2_character,
},
#endif
Process HomeKit characteristic commands
When the MCU receives commands from the module, it should execute the operation accordingly and return the result to the module. Implement the code in homekit_character_ctrl
. To sync HomeKit characteristic data with the Tuya Smart app, call functions such as mcu_dp_bool_update
, mcu_dp_value_update
, and mcu_dp_enum_update
based on data types.
/**
* @brief Receive and process HomeKit characteristic commands
* @param[in] {serv_serial} Service serial number
* @param[in] {p_char_str} Characteristic string identifier
* @param[in] {char_data_type} Data type of characteristic
* @param[in] {char_val_len} Data length of characteristic
* @param[in] {p_char_val} Data of characteristic
* @return SUCCESS/ERROR
* @note
*/
u8 homekit_character_ctrl(u8 serv_serial, i8 p_char_str[], u8 char_data_type, u16 char_val_len, HAP_VALUE_T *p_char_val)
{
//#error "Complete code for processing HomeKit commands and delete this line."
u8 serv_i = 0, char_j = 0;
for(serv_i = 0; serv_i < CNTSOF(homekit_service); serv_i++) {
if(serv_serial == homekit_service[serv_i].serial) {
for(char_j = 0; char_j < homekit_service[serv_i].character_amount; char_j++) {
if(0 == my_strcmp(p_char_str, homekit_service[serv_i].p_character_arr[char_j].p_character_str)) {
if(char_data_type == homekit_service[serv_i].p_character_arr[char_j].hap_val_type) {
// Implement code for processing HomeKit characteristic commands.
//homekit_service[serv_i].p_service_str: services
//homekit_service[serv_i].p_character_arr[char_j].p_character_str: characteristics
//char_data_type: data type
//char_val_len: data length
//p_char_val: data
if(0 == my_strcmp(homekit_service[serv_i].p_service_str, HAP_SERV_UUID_AIR_PURIFIER) && 0 == my_strcmp(homekit_service[serv_i].p_character_arr[char_j].p_character_str, HAP_CHAR_UUID_ACTIVE))
{
homekit_character_upload(serv_serial, HAP_CHAR_UUID_CURRENT_AIR_PURIFIER_STATE, char_data_type, char_val_len, p_char_val);
}
// Implement code for returning results to the cloud. For example,
homekit_character_upload(serv_serial, homekit_service[serv_i].p_character_arr[char_j].p_character_str, char_data_type, char_val_len, p_char_val);
return SUCCESS;
}
}
}
return ERROR;
}
}
return ERROR;
}
Data communication must start after the initialization is completed.
For more information about the frame format, see Frame format description.
After the MCU and the module are powered on, the initialization configuration starts. Initialization communication includes but is not limited to:
A heartbeat is a type of communication packet between the module and the MCU to check whether the communication was lost. We recommend that the frame of the first communication between the MCU and the module is used as the heartbeat. The communication can work properly only when the heartbeat is sent and responded successfully.
After the module builds communication with the MCU, it will query the MCU firmware version and the following information.
The module works with the MCU to process the network event or processes it itself. The working mode is determined by the hardware connection of the LED indicator and reset button on the Wi-Fi module.
The following block diagram shows the initialization communication.
In the following two network states, the device can report DP data to and receive DP commands from the app.
This section describes the OTA data communication between the MCU and the Wi-Fi module.
OTA starts
When the Wi-Fi module detects an MCU update, it will send a command to start updates.
OTA data transmission starts
After sending a package, if the Wi-Fi module does not receive a response from the MCU within five seconds, it will resend the package three times. If the MCU still does not respond, the OTA updates fail.
OTA transmission is completed
You can determine whether the OTA transmission is completed in the following two ways.
0x0004
, indicating the packet is zero bytes.We recommend using both ways to verify OTA transmission.
HomeKit certified accessories must meet all the requirements of functionality, which is defined in the HAP specification alongside succeeding in all the Apple-defined test cases. This section describes test cases about communication between the Wi-Fi module and the MCU. For more information about the certification test, visit Apple Developer.
TCF039: Test HomeKit setup QR code
Apple issues a unique setup code for each HomeKit-enabled accessory. This code is used to add an accessory to the Home app. Therefore, the value of the category name must follow the rules specified on the HAP. Otherwise, the test will fail. For example, if you create a fan on the HomeKit platform, you must define the HomeKit product type as fan. The following figure shows the sample configuration in the protocol.h
.
TCI014: Test HomeKit characteristic data transmission
With the test tool, you can query, send, and report characteristic data. The available operations depend on the characteristic permission. Query and reporting apply to read-only characteristics. Query, sending, and reporting apply to read-write characteristics.
To test read-only characteristics, the test tool will read the current status. Then, you will be prompted to let the device report a different value to test if the communication works properly. If the value is changed, the test passed. Otherwise, the communication failed. For example, if the current value is 0
, you must let the device report a value other than 0
.
To test read-write characteristics, the test tool will read the current status, send a different value, and read the current status again. For example, the set duration (D3) is a read-write characteristic, and its initial value is 0
. The test tool sends 1
to the device, and the device returns 1
. The cache of this characteristic is 1
. Then, test data reading the same way as described above. If the device reports 1
, it indicates the value is not changed, and communication fails.
It is recommended to report status to both the Tuya Smart app and Home app.
TCH096: Test the accessory prompt
After the test tool sends the command of accessory prompt, the accessory should emit a prompt within 5s, such as flickers or beeps.
If the Wi-Fi module works in the self-processing mode, the HomeKit-defined LED indicator flickers three times to indicate a HomeKit accessory is recognized. If the Wi-Fi module works with the MCU to process network events, after the Wi-Fi module sends HomeKit-defined Wi-Fi status 3, the MCU should emit a prompt within 5s. What signals are emitted depends on your needs. To ensure this accessory prompt will not affect the normal network status indication, the module will send a HomeKit-defined Wi-Fi status 2 around 5s. For more information, see Report network status.
TCS003: Stress test on characteristics Run a stress test on a specific characteristic. If you do not use the TYWE3SE module, you need to add the optional characteristic Name. Otherwise, you cannot find available characteristics for testing.
TCH091: Verify values Test if the input value is valid. For example, if the valid values of a characteristic are 1
, 3
, and 4
, you can input 2
for testing. If writing the value 2
failed, the test passed. If you do not use one of the default valid values, you must configure valid values of a characteristic.
TCV004: If you use the valve service, you must specify a name for each valve to use this test case. Pay attention to the following description. Since the Name characteristic is not supported for valves, to have the name of a valve displayed normally, you must configure the Service Label Index characteristic with valid values ranging from 1 to 255. If you have multiple valve services configured, each service is identified by a unique index specified by the Service Label Index characteristic.
For example, you add Service Label Index characteristic to three valve services respectively and assign the value 1
, 2
, and 3
to the first, second, and third service. These three valves are displayed on the Home app as valve 1, valve 2, and valve 3.
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback