更新时间:2024-11-20 02:13:23下载pdf
HomeKit MCU SDK 是根据涂鸦开发者平台定义的产品功能自动生成的 MCU 代码,能够协助您快速完成 MCU 程序的开发。本文为您介绍移植 HomeKit MCU SDK 的流程以及注意事项。
HomeKit MCU SDK 是根据涂鸦开发平台定义的产品功能,自动生成的 MCU 代码。为了减少您使用涂鸦 Wi-Fi HomeKit 通用串口协议的对接成本,HomeKit MCU SDK 已搭建通讯及协议解析架构。将HomeKit MCU SDK 添加至工程并配置相关信息后,既可以快速的完成 MCU 程序开发。
涂鸦 SDK 包对 MCU 的要求如下。资源不足的用户,可自行对接串口协议,SDK 包中的函数可以作为使用参考。
文件 | 说明 |
---|---|
mcu_api.c |
包含可供调用的函数。 |
mcu_api.h |
mcu_api.c 中的函数声明。 |
protocol.c |
包含协议数据体的内容处理函数。您可以根据项目需求,在相应函数内添加代码,获取 Wi-Fi 模组向 MCU 发送的数据。 |
protocol.h |
protocol.h 包含以下信息:
|
system.c |
串口通讯协议解析的具体实现。 |
system.h |
system.h 包含以下信息:
|
wifi.h |
包含 Wi-Fi 相关宏定义。 |
homekit.c |
包含HomeKit相关配置和数据处理。需要用户根据实际应用做适当修改。 |
homekit.h |
homekit.h 包含以下信息:
|
tuya_type.h |
包含了数据类型的定义,数据类型定义默认单片机为32位,若用户使用的单片机是其他类型,可在此头文件中自行调整数据类型。 |
protocol.h
宏定义。protocol.c
文件及函数调用。homekit.c
文件中配置 HomeKit 服务和特性。在原项目工程中,完成 MCU 相关外设初始化,包括:串口、外部中断(按键)、定时器(指示灯闪烁)等。
将 MCU SDK 文件夹中的 .c
和 .h
文件添加至相应头文件引用路径。
protocol.h
宏定义定义 PID。PRODUCT_KEY
为产品 PID 宏定义。PID 即产品 ID,为每个产品的唯一标识,可在 涂鸦开发者平台 的产品详情页面获取。
#define PRODUCT_KEY "ax23rawjo4np****"
如果 PRODUCT_KEY
和产品 PID 不一致,请在开发者平台的 硬件开发>下载资料 下载最新 SDK 开发包后重试。
定义版本号。MCU_VER
为软件版本,默认为 1.0.0
。若 MCU 需要 OTA 功能,需要添加新的 MCU 版本号。
#define MCU_VER "1.0.0"
选择 HomeKit 产品品类。需要和在苹果平台创建的品类一致。例如,在苹果平台创建的品类是空气净化器,此处便选择空气净化器品类。
/* HomeKit产品品类选择。 服务配置选择和特性配置选择请在homekit.c中进行 */
//#define HOMEKIT_PRODUCT_TYPE 3 //风扇
//#define HOMEKIT_PRODUCT_TYPE 4 //车库门开启器
//#define HOMEKIT_PRODUCT_TYPE 5 //照明
//#define HOMEKIT_PRODUCT_TYPE 9 //恒温器
//#define HOMEKIT_PRODUCT_TYPE 12 //门
//#define HOMEKIT_PRODUCT_TYPE 13 //窗户
//#define HOMEKIT_PRODUCT_TYPE 14 //窗帘
#define HOMEKIT_PRODUCT_TYPE 19 //空气净化器
//#define HOMEKIT_PRODUCT_TYPE 20 //加热器冷却器(取暖器,cooler)
//#define HOMEKIT_PRODUCT_TYPE 22 //加湿器
//#define HOMEKIT_PRODUCT_TYPE 23 //除湿器
//#define HOMEKIT_PRODUCT_TYPE 28 //洒水器
//#define HOMEKIT_PRODUCT_TYPE 29 //水龙头
//#define HOMEKIT_PRODUCT_TYPE 30 //淋浴系统
选择是否进行特性有效值配置。
/* 是否需要配置特性有效值 */
//#define HOMEKIT_CHARACTER_VALID_CFG_ENABLE
特性有效值配置命令在 char_valid_value_cfg
函数中配置。
/**
* @brief 特性有效值配置
* @param Null
* @return Null
* @note
*/
static void char_valid_value_cfg(void)
{
//#error "请自行完成特性有效值配置代码,完成后请删除该行"
static u8 cfg_count = 0;
u16 send_len = 0;
char strbuff[80] = {0};
u8 strlen = 0;
switch(cfg_count++) {
case 0:
//请在此处配置有效值配置字符串
//例如:strlen = sprintf(strbuff, "{\"service_serial\":7,\"char_str\":\"A9\",\"val_type\":0,\"valid_val\":[0,2]}");
break;
//如果需要配置多个,请添加case
// case 1:
// //请在此处配置有效值配置字符串
// break;
default:
//有效值配置完成,结束服务配置
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);
}
开启 OTA 升级功能。如果需要支持 OTA 固件升级,请定义 SUPPORT_MCU_FIRM_UPDATE
,默认关闭。
#define SUPPORT_MCU_FIRM_UPDATE
定义单次发送固件包的大小。
#ifdef SUPPORT_MCU_FIRM_UPDATE
#define PACKAGE_SIZE 0 //单个固件包大小为 256 字节
//#define PACKAGE_SIZE 1 //单个固件包大小为 512 字节
//#define PACKAGE_SIZE 2 //单个固件包大小为 1024 字节
#endif
OTA 升级流程参见 OTA 升级说明-平台配置。
MCU固件备份区配置。
/* MCU固件区类型 */
#define MCU_FIRMWARE_BACKUP_AREA_TYPE 0 //MCU是双固件区(默认)
//#define MCU_FIRMWARE_BACKUP_AREA_TYPE 1 //MCU是单固件区
如果选用MCU单固件区方式,OTA数据包处理逻辑会有所不同,详细信息见:OTA 升级指导。
串口接收缓存:大小受到串口数据处理被调用的频率影响。如果 MCU 对串口数据的处理较快,串口接收缓存大小可适当减小。
串口发送缓存:大小要大于数据最长的 DP 数据长度。
串口数据处理缓存:大小需要大于数据最长的 DP 数据长度,还要根据是否需要 OTA 功能和是否需要天气服务、天气服务类型数量和天数来调整大小,需要大于最大数据量的大小。
/******************************************************************************
3:定义收发缓存:
如当前使用MCU的RAM不够,可修改为24
******************************************************************************/
#ifndef SUPPORT_MCU_FIRM_UPDATE
#define WIFI_UART_RECV_BUF_LMT 16 //串口数据接收缓存区大小,如MCU的RAM不够,可根据MCU实际情况适当缩小
#define WIFI_DATA_PROCESS_LMT 24 //串口数据处理缓存区大小,根据用户DP数据大小量定,建议大于24
#else
#define WIFI_UART_RECV_BUF_LMT 128 //串口数据接收缓存区大小,如MCU的RAM不够,可缩小
//请在此处选择合适的串口数据处理缓存大小(根据上面MCU固件升级包选择的大小和是否开启天气服务来选择开启多大的缓存)
#define WIFI_DATA_PROCESS_LMT 300 //串口数据处理缓存大小,如需MCU固件升级,若单包大小选择256,则缓存必须大于260,若开启天气服务,则需要更大
//#define WIFI_DATA_PROCESS_LMT 600 //串口数据处理缓存大小,如需MCU固件升级,若单包大小选择512,则缓存必须大于520,若开启天气服务,则需要更大
//#define WIFI_DATA_PROCESS_LMT 1200 //串口数据处理缓存大小,如需MCU固件升级,若单包大小选择1024,则缓存必须大于1030,若开启天气服务,则需要更大
#endif
#define WIFIR_UART_SEND_BUF_LMT 60 //根据用户DP数据大小量定,必须大于51
如果配网按键和 LED 接在 MCU 端,即选择模组和 MCU 配合处理工作模式(常用),保持 WIFI_CONTROL_SELF_MODE
宏定义处于被注释状态。
//#define WIFI_CONTROL_SELF_MODE //使用wifi自处理请开启该宏,并指定tuya-WiFi指示灯、HomeKit-WiFi指示灯、按键的模组IO。若使用MCU与模块配合处理,请关闭该宏
如果配网指示灯和按键是接在 Wi-Fi 模组上的,即选择模组自处理工作模式,开启 WIFI_CONTROL_SELF_MODE
宏定义,然后根据实际的硬件连接,将指示灯和按键所连接的 GPIO 脚位填入下面两个宏定义。
#ifdef WIFI_CONTROL_SELF_MODE //模块自处理
#define TY_STATE_LED 0 //wifi模块tuya网络状态指示,请根据实际使用的模块IO管脚设置
#define HK_STATE_LED 4 //wifi模块HomeKit网络状态指示,请根据实际使用的模块IO管脚设置
#define WF_RESERT_KEY 5 //wifi模块重置按键,请根据实际使用的模块IO管脚设置
#endif
Wi-Fi 产测功能默认开启。为保证最终量产效率及品质,建议开启该功能。
#define WIFI_TEST_ENABLE //开启 Wi-Fi 产测功能(扫描指定路由)
详细产测流程,可查看 生产测试说明。
其他功能可以通过完善相应函数实现。
protocol.c
文件及函数调用将 wifi.h
文件保存至存放 Wi-Fi 相关文件的文件夹中,例如 main.c
文件夹。
在 MCU 串口及其他外设初始化后调用 mcu_api.c
文件中的 wifi_protocol_init()
函数。
将 MCU 串口单字节发送函数填入 protocol.c
文件中 uart_transmit_output
函数内,并删除 #error
。示例如下:
/**
* @brief 串口发送数据
* @param[in] {value} 串口要发送的1字节数据
* @return Null
*/
void uart_transmit_output(u8 value)
{
//#error "请将MCU串口发送函数填入该函数,并删除该行"
UART3_SendByte(value);
}
在串口接收中断服务函数里面调用 mcu_api.c
文件内的 uart_receive_input
函数,并将接收到的字符作为参数传入。示例如下:
void UART3_SendByte(unsigned char data)
{
while((USART3->SR&UART_FLAG_TXE)!=UART_FLAG_TXE);
USART3->DR = data;
}
单片机进入 while(1)
循环后调用 mcu_api.c
文件内的 wifi_uart_service()
函数。main.c
中示例代码结构如下:
#include "wifi.h"
...
void main(void)
{
wifi_protocol_init();
...
while(1) {
wifi_uart_service();
...
}
...
}
MCU 必须在 while(1)
中直接调用 mcu_api.c
内的 wifi_uart_service()
函数。程序正常初始化完成后,建议不进行关中断,如必须关中断,关中断时间必须短。关中断会引起串口数据包丢失,请勿在中断内调用上报函数。
DP 类型主要有 6 种:
如果某些 DP 状态需要同步到HomeKit,请调用 homekit_character_upload
函数。
在模组重启或者重新配网后,Wi-Fi 模组主动下发状态查询指令,此时需要 MCU 上报设备所有 DP 状态给 Wi-Fi 模组进行同步。
打开 protocol.c
找到函数 all_data_update(void)
。
把所有需要上报的 DP 初值填入相应上报函数,为面板提供开机显示初值。
用户请勿随意调用 all_data_update()
函数,该函数会在特定时间主动调用。
/**
* @brief 系统所有dp点信息上传,实现APP和muc数据同步
* @param Null
* @return Null
* @note 此函数SDK内部需调用,MCU必须实现该函数内数据上报功能,包括只上报和可上报可下发型数据
*/
void all_data_update(void)
{
//#error "请在此处理可下发可上报数据及只上报数据示例,处理完成后删除该行"
//此代码为平台自动生成,请按照实际数据修改每个可下发可上报函数和只上报函数
mcu_dp_bool_update(DPID_SWITCH,当前开关); //BOOL型数据上报;
mcu_dp_enum_update(DPID_MODE,当前模式); //枚举型数据上报;
mcu_dp_fault_update(DPID_FAULT,当前故障告警); //故障型数据上报;
mcu_dp_value_update(DPID_PM25,当前PM2.5); //VALUE型数据上报;
mcu_dp_value_update(DPID_PM10,当前PM10); //VALUE型数据上报;
mcu_dp_enum_update(DPID_TIMER,当前定时); //枚举型数据上报;
mcu_dp_value_update(DPID_FILTER_PERCENT,当前滤芯剩余百分比); //VALUE型数据上报;
mcu_dp_value_update(DPID_FILTER_USEH,当前滤芯使用时间); //VALUE型数据上报;
mcu_dp_bool_update(DPID_PHYSICAL_LOCKED,当前儿童锁); //BOOL型数据上报;
#ifdef HOMEKIT_PRODUCT_TYPE
homekit_character_upload_all();
#endif
}
在单个 DP 状态发生变化时,MCU 需要主动上报,App 更新显示内容。上报格式为 mcu_dp_xxxx_updata(DPID_X,n)
,其中DPID_X
为状态改变的 DP。all_data_update()
内的函数,均可单独调用。例如:
mcu_dp_bool_update(DPID_SWITCH,1); //BOOL型数据上报
mcu_dp_value_update(DPID_PM25,15); //VALUE型数据上报
mcu_dp_enum_update(DPID_MODE,2); //枚举型数据上报
mcu_dp_fault_update(DPID_FAULT,0x01); //故障型数据上报
mcu_dp_string_update(DPID_DAY,"1234",4); //STRING 型数据上报
在 protocol.c
文件中,每个可下发的 DP,都有一个单独下发数据处理函数。格式为 dp_download_xxx_handle()
,xxx
为可下发 DP。函数解析功能点之后,MCU 需在相应位置完成逻辑控制。
以接收到开关 DP 数据为例:
/*****************************************************************************
函数名称 : dp_download_switch_handle
功能描述 : 针对DPID_SWITCH的处理函数
输入参数 : value:数据源数据
: length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static u8 dp_download_switch_handle(const u8 value[], u16 length)
{
//示例:当前DP类型为BOOL
u8 ret;
//0:关/1:开
u8 switch_1;
switch_1 = mcu_get_dp_download_bool(value,length);
if(switch_1 == 0) {
//开关关
}else {
//开关开
}
//处理完DP数据后应有反馈
ret = mcu_dp_bool_update(DPID_SWITCH,switch_1);
if(ret == SUCCESS)
return SUCCESS;
else
return ERROR;
}
当设备状态在非 App 控制下发生变化时,MCU 中需要调用 mcu_dp_bool_update(DPID_SWITCH_1,switch_1);
上传功能点(开关)状态实时状态,形成反馈。您也可以根据实际需要选择上报时机。
仅 MCU 与模组配合处理模式工作模式需要设置配网功能及指示灯函数。
移植协议成功后,如果需要设备配网,还需要添加配网指令以及指示灯功能。配合处理模式的 MCU、配网触发方式和指示方式,可以根据实际情况自行决定,通常为按键触发和 LED 指示。
配网指令(mcu_reset_wifi()
)通常在按键触发配网后,在按键处理函数中调用。
mcu_reset_wifi()
:调用后复位 Wi-Fi 模组,复位后之前的配网信息全部清除。
通常在 while(1)
调用 get_wifi_tuya_state()
和 get_wifi_homekit_state()
函数获取 Wi-Fi 状态。根据 Wi-Fi 状态,写入相应闪灯的模式。
涂鸦网络状态:
设备联网状态 | 描述 | 状态值 |
---|---|---|
状态1 | 处于配网状态 | 间隔250ms亮灭 |
状态2 | 模组已配置但未未连上路由器 | 常灭 |
状态3 | 连上路由器但未连上云端 | 常灭 |
状态4 | 连接到云端 | 常亮 |
HomeKit 网络状态:
设备联网状态 | 描述 | 状态值 |
---|---|---|
状态1 | 待绑定或绑定中 | 间隔250ms亮灭 |
状态2 | 未连接 | 常灭 |
状态3 | 已连接 | 常亮 |
调用函数 get_wifi_tuya_state()
和 get_wifi_homekit_state()
获取连接状态,函数架构如下:
void main(void){
...
while(1)
{
...
switch(get_wifi_tuya_state()) {
case CONFIG_STATE: //0x00
if(Timer3_Value % 2 == 0) //LED快闪
{
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Ϩ熄灭
break;
case WIFI_CONNECTED: //0x03
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);//LED常亮
break;
case WIFI_CONN_CLOUD: //0x04
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET); //LED常亮
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快闪
{
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Ϩ熄灭
break;
case WIFI_CONNECTED: //0x03
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);//LED常亮
break;
default:
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
break;
}
}
}
扫描指定路由。具体流程查看:生产测试说明 。
homekit.c
文件及 HomeKit 服务和特性配置配置服务。
用户可以根据自己的需要配置服务,需要用哪个就打开哪个宏。例如选择一个风扇服务。
/******************************************************************************
1.HomeKit服务配置选择
用户可根据产品功能需求打开对应宏
******************************************************************************/
#ifdef HOMEKIT_PRODUCT_TYPE
#define HOMEKIT_SERV_FAN_V2 //风扇
//#define HOMEKIT_SERV_GARAGE_DOOR_OPENER //车库门开启器
//#define HOMEKIT_SERV_LIGHTBULB //灯泡
//#define HOMEKIT_SERV_THERMOSTAT //恒温器
//#define HOMEKIT_SERV_DOOR //门
//#define HOMEKIT_SERV_WINDOW //窗户
//#define HOMEKIT_SERV_WINDOW_COVERING //窗帘
//#define HOMEKIT_SERV_AIR_PURIFIER //空气净化器
//#define HOMEKIT_SERV_FILTER_MAINTENANCE //过滤器维护
//#define HOMEKIT_SERV_AIR_QUALITY_SENSOR //空气质量传感器
//#define HOMEKIT_SERV_SLAT //板条
//#define HOMEKIT_SERV_HEATER_COOLER //加热器冷却器
//#define HOMEKIT_SERV_HUMIDIFIER_DEHUMIDIFIER //加湿器除湿机
//#define HOMEKIT_SERV_IRRIGATION_SYSTEM //灌溉系统
//#define HOMEKIT_SERV_VALVE //阀门
//#define HOMEKIT_SERV_FAUCET //水龙头
#endif
配置可选特性。
选择服务后,需要对每个服务选择可选特性。例如选择当前风扇状态、目标风扇状态、转动方向、转速。
/* FAN_V2 风扇服务的可选特性选择 */
#ifdef HOMEKIT_SERV_FAN_V2//
#define FAN_V2_CHAR_NAME //名称
#define FAN_V2_CHAR_CURRENT_FAN_STATE //当前风扇状态
#define FAN_V2_CHAR_TARGET_FAN_STATE //目标风扇状态
#define FAN_V2_CHAR_ROTATION_DIRECTION //转动方向
#define FAN_V2_CHAR_ROTATION_SPEED //转速
//#define FAN_V2_CHAR_SWING_MODE //摇摆模式
//#define FAN_V2_CHAR_LOCK_PHYSICAL_CONTROLS //锁定物理控制(童锁)
#endif
配置特性的初值。
可选特性配置完成之后,需要配置特性点的初值,MCCU SDK默认填的是取值范围的最小值,用户可自行修改。
HOMEKIT_CHARACTER_S fan_v2_character[] = {
{fan_v2_char_uuid_active_str, TRUE, TRUE, HAP_DATA_TYPE_UINT, .hap_val.u = 0 /* 在此处可以给特性赋初值 */ },
#ifdef FAN_V2_CHAR_NAME
{fan_v2_char_uuid_name_str, FALSE, FALSE, HAP_DATA_TYPE_STRING, .hap_val.s = /* 在此处可以给特性赋初值 */ },
#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 /* 在此处可以给特性赋初值 */ },
#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 /* 在此处可以给特性赋初值 */ },
#endif
#ifdef FAN_V2_CHAR_ROTATION_DIRECTION
{fan_v2_char_uuid_rotation_direction_str, FALSE, FALSE, HAP_DATA_TYPE_INT, .hap_val.i = 0 /* 在此处可以给特性赋初值 */ },
#endif
#ifdef FAN_V2_CHAR_ROTATION_SPEED
{fan_v2_char_uuid_rotation_speed_str, FALSE, FALSE, HAP_DATA_TYPE_FLOAT, .hap_val.f = 0 /* 在此处可以给特性赋初值 */ },
#endif
#ifdef FAN_V2_CHAR_SWING_MODE
{fan_v2_char_uuid_swing_mode_str, FALSE, FALSE, HAP_DATA_TYPE_UINT, .hap_val.u = 0 /* 在此处可以给特性赋初值 */ },
#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 /* 在此处可以给特性赋初值 */ },
#endif
};
服务序号配置。
如果配置了多个服务,需要把每个服务配置成不同的服务序号,用来区分不同的服务。这样做的原因是为了能够识别那些需要配置多个相同服务的产品。例如:灌溉器。如果需要配置多个相同的服务,可根据现有代码格式自行添加。
#ifdef HOMEKIT_SERV_FAN_V2
{
0, //需要用户自行修改服务序号,且不能与其他相同
hap_serv_uuid_fan_v2_str,
FALSE,
CNTSOF(fan_v2_character),
fan_v2_character,
},
#endif
处理HomeKit特性命令下发。
MCU收到命令下发时,需要及时处理并回复结果,请在 homekit_character_ctrl
函数中进行补充。如果特性点中有需要同步给涂鸦 App 的,还需要增加涂鸦 DP 的上报函数,可调用 mcu_dp_bool_update
、mcu_dp_value_update
、mcu_dp_enum_update
等函数将状态同步到涂鸦。
/**
* @brief HomeKit特性命令下发
* @param[in] {serv_serial} 服务序号
* @param[in] {p_char_str} 特性字符串标识
* @param[in] {char_data_type} 特性数据类型
* @param[in] {char_val_len} 特性数据长度
* @param[in] {p_char_val} 特性数据
* @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 "请自行完成 homekit 命令下发处理代码,并删除该行"
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) {
//请在此添加特性下发命令处理代码
//homekit_service[serv_i].p_service_str:服务
//homekit_service[serv_i].p_character_arr[char_j].p_character_str:特性
//char_data_type:数据类型
//char_val_len:数据长度
//p_char_val:数据
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);
}
//可在此添加状态上报。例如:
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;
}
请在初始化完成后再进行数据交互,避免不可预测的问题。
帧格式参考 帧格式说明。
在 MCU 和模组上电后,需要进行初始化配置。初始化通信包括但不限于以下内容:
心跳包是 MCU 和模组之间定时通信的数据,可作为验证 MCU 或者模组是否正常工作的依据。建议将 MCU 和模组上电后的第一次通信的帧作为心跳包。只有在心跳包发送和回复都正常的情况下,才可以进行通信。
心跳包正常交互后,模组需要查询 MCU 固件以下信息。
用来设置模组工作方式,选择 MCU 与模组配合处理方式或者模组自处理方式。可根据 Wi-Fi 网络状态指示灯和模组重置按键的硬件连接位置选择。
涂鸦 App 和设备之间能够实现 DP 下发和上报,有两种情况:
MCU 与 Wi-Fi 模组在进行 OTA 数据交互时,数据包交互的数据量比较多,会出现一些异常情况。本章节介绍 Wi-Fi 模组的处理逻辑,您可以根据。
OTA 启动
Wi-Fi 模组在检测到有 MCU OTA 时,会发送启动升级包。
OTA 数据传输
Wi-Fi 模组在发送一包 OTA 数据之后,如果 5s 内没有收到 MCU 的回复,会进行重发。若重发 3 次之后 MCU 依旧没有回复,就认为 OTA 失败。
OTA 传输完成
支持以下两种方式判断 OTA 传输是否完成。
建议同时使用以上两种方式检测 OTA 传输情况。
在开发MCU时,不止要实现与模组的串口对接协议通信,还要注意苹果的认证要求。此章节对部分苹果认证测试用例MCU如何配合做出说明,认证测试具体要求请访问苹果官网查看。
TCF039:此用例是进行测试配网二维码的。
配网码是根据苹果平台申请的PPID以及其他的校验信息而生成的,所以,MCU的品类配置需要和苹果平台上的配置的品类一致,否则此用例会失败。例如,在苹果平台创建的品类是风扇,那么MCU配置中,品类就要配置为风扇。下图为MCU SDK中 protocol.h
文件中的配置示例。
TCI014:此用例主要进行特性点的上报以及下发。
测试工具会对部分用例进行特性点的查询、下发、等待上报,需要执行哪些额被测特性的操作类型有关,如果是只读的,会有查询、等待上报,如果是可读可写的,查询、下发、等待上报都会有。
如果是只读,测试工具会读取当前状态,然后弹出一个窗口提示,此时需要设备根据窗口提示内容主动上报一个不一样的值,上报成功之后就会通过,如果上报的值与测试工具一开始读到的值一样,就没有反应。也就是说,如果之前的状态值是0,就要上报1或者其他值,如果之前的状态值是1,就要上报0或者其他值。
如果是读写,测试工具会读取当前状态,然后根据当前状态下发一个不一样的值,下发之后再一次读取。例如设置时间(D3)的类型是读写,按照这个逻辑,初始状态是0,测试工具读到之后会下发1,然后设备回复1,完成之后,这个特性的状态缓存记录就是1了。然后就会进行和上述1一样的测试步骤。此时如果还是上报1,就和一开始读到的值是一样的了,就没反应,上报0反而是可以通过的。
为方便某些特性点的状态更改,建议MCU上报状态时,涂鸦和HomeKit都要上报。
TCH096:此用例要求设备有配件提示功能。
根据用例要求,设备需要在测试工具发出配件提示指令后,在5s内有提示信息(例如:指示灯闪烁几次,或者蜂鸣器响几声)。
用MCU通用对接方案,模组有自处理和配合处理两种工作模式。如果使用模组自处理,此逻辑模组已做成HomeKit状态指示灯闪烁3次,随后回复常亮状态。如果使用配合处理,模组会给MCU发送HomeKit状态为03的网络状态通知命令,MCU在收到此命令后5s内需作出提示逻辑,此逻辑需要用户的MCU自行实现,并且为防止此提示命令会影响到用户网络指示逻辑,在5s左右之后模组会再发送一个HomeKit状态为02的命令,详细说明可查看协议文档报告设备联网状态章节。
TCS003:此用例是特性点压测。此用例需要压测某个特性点。如果使用的 不是TYWE3SE 模组,需要在配置可选特性时将名称(name)特性添加上,否则在测此用例时将会找不到可以压测的特性点。
TCH091:此用例根据特性有效值和数据范围进行校验。根据此用例的说明,如果某特性的有效值为0、1、2、3,则写入4。如果有效值为1、3、4,则写入2,若写入失败,则测试通过,所以,当某个特性默认取值范围内的值不使用,MCU务必要发送特性有效值配置命令。
TCV004:此用例需要设置阀门名称,使用阀门(Valve)服务需要关心此说明。由于目前不支持配置阀门的名称(Name)特性,所以为了让名称显示正常,需要配置服务标签索引(Service Label Index)特性,取值范围是1~255。如果有配置多个阀门服务,则需要每个服务标签索引的值不一样,以作相同服务的区分。
例如:配置了3个阀门服务,并且都配置了服务标签索引特性,第一个服务的服务标签索引特性的值配置为1,第二个服务的服务标签索引特性的值配置为2,第三个服务的服务标签索引特性的值配置为3,那么设备绑定到HomeKit之后,在家庭APP上显示的三个阀门服务的名称分别是valve 1、valve 2、valve 3 。
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈