/** * @file protocol.c * @brief this file contains protocol analysis and construct response function when received zigbee module send message * @author qinlang * @date 2022.05.06 * @par email:qinlang.chen@tuya.com * @copyright HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD * @par company * http://www.tuya.com */ ////must modify #include "./mcu_sdk/zigbee.h" //directory by ddw //#include "GLOBAL.h" #include #include "systick.h" #include "gd32f30x.h" #include "GLOBAL.h" #include "gpio_ctl.h" #include "uart.h" #include "key_proc.h" #include "lcd_task.h" #include "key_operate.h" #include "MB_RTU_deal_task.h" #include "gd32f30x_it.h" #include "All_define.h" #include "modbus.h" #include "MB_RTU_deal_task.h" #include "led.h" #include "MB_RTU_task.h" Zigbee_cmd zigbee_cmd; // #include "../uart.h" extern unsigned char gRelayOnOff; ////must modify /****************************************************************************** 移植须知: 1:MCU必须在while中直接调用mcu_api.c内的zigbee_uart_service()函数 2:程序正常初始化完成后,建议不进行关串口中断,如必须关中断,关中断时间必须短,关中断会引起串口数据包丢失 3:请勿在中断/定时器中断内调用上报函数 ******************************************************************************/ /****************************************************************************** 第一步:初始化 1:在需要使用到zigbee相关文件的文件中include "zigbee.h" 2:在MCU初始化中调用mcu_api.c文件中的zigbee_protocol_init()函数 3:将MCU串口单字节发送函数填入protocol.c文件中uart_transmit_output函数内,并删除#error 4:在MCU串口接收函数中调用mcu_api.c文件内的uart_receive_input函数,并将接收到的字节作为参数传入 5:单片机进入while循环后调用mcu_api.c文件内的zigbee_uart_service()函数 6:mcu何时开启zigbee模块配网,当zigbee模块查询到mcu的产品信息之后,或者zigbee模块发送了当前网络状态 给到mcu,查询pid信息会在上电5秒之后发送,对接部分zigbee老版本通用对接固件低功耗版本尤其需要注意不要 在第一次确认波特率的时候提前唤醒或者发送串口给zigbee模组,有概率导致zigbee模组波特率存储失败。 7:上电之后,mcu何时上报数据给网关合适,在收到网络状态为已配网,或者接收到读取dp数据的时候。 8: 在mcu ota过程中发送固件内容请求未收到zigbee模块的应答时,需要mcu端做好超时重新请求的处理,和存储image 处理,校验和可以自行设计或者使用参考。 ******************************************************************************/ /****************************************************************************** 1:dp数据点序列类型对照表 **此为自动生成代码,如在开发平台有相关修改请重新下载MCU_SDK** ******************************************************************************/ #ifdef ZIGBEE_ZS_T4 const DOWNLOAD_CMD_S download_cmd[] = { {DPID_SWITCH, DP_TYPE_BOOL}, {DPID_MODE, DP_TYPE_ENUM}, {DPID_WORK_STATE, DP_TYPE_ENUM}, {DPID_TEMP_SET, DP_TYPE_VALUE}, {DPID_TEMP_CURRENT, DP_TYPE_VALUE}, {DPID_LEVEL, DP_TYPE_ENUM}, {DPID_WORK_STATE1, DP_TYPE_ENUM}, {DPID_TEMP_DN, DP_TYPE_VALUE}, {DPID_SWITCH_FLOOR_HEAT, DP_TYPE_BOOL}, {DPID_SWITCH_FAN, DP_TYPE_BOOL}, {DPID_LEVEL_FAN, DP_TYPE_ENUM}, }; #endif #ifdef FLOORHEATER_T4_CS const DOWNLOAD_CMD_S download_cmd[] = { {DPID_SWITCH, DP_TYPE_BOOL}, {DPID_MODE, DP_TYPE_ENUM}, {DPID_WORK_STATE, DP_TYPE_ENUM}, {DPID_TEMP_SET, DP_TYPE_VALUE}, {DPID_TEMP_CURRENT, DP_TYPE_VALUE}, {DPID_LEVEL, DP_TYPE_ENUM}, {DPID_SET_LIGHT_3, DP_TYPE_ENUM}, }; #endif /****************************************************************************** 2:串口单字节发送函数 请将MCU串口发送函数填入该函数内,并将接收到的数据作为参数传入串口发送函数 ******************************************************************************/ ////must modify extern void start_usart0_tx(unsigned char tx_buffer[], unsigned char length); ////must modify static void report_mcu_ota_result(unsigned char res); /** * @brief encapsulates a generic send function, developer should use their own function to completing this fuction * @param[in] {value} send signle data * @return void */ ////must modify void uart_transmit_output(unsigned char value) { //printf("uart_transmit_output 0x%x\r\n",value); static unsigned char buf; buf = value; // #error "please use your own uart send fuction complete this fuction, exmaple" /* * //demo: * extern void Uart_PutChar(unsigned char value); * Uart_PutChar(value); */ start_usart0_tx(&buf, 1); // 串口发送单字节函数 } ////must modify /****************************************************************************** 第二步:实现具体用户函数 1:APP下发数据处理 2:数据上报处理 ******************************************************************************/ /****************************************************************************** 1:所有数据上报处理 当前函数处理全部数据上报(包括可下发/可上报和只上报) 需要用户按照实际情况实现: 1:需要实现可下发/可上报数据点上报 2:需要实现只上报数据点上报 此函数为MCU内部必须调用 用户也可调用此函数实现全部数据上报 ******************************************************************************/ // 自动化生成数据上报函数 /** * @brief Upload all dp information of the system, and realize the synchronization of APP and muc data * @param[in] {void} * @return void */ ////must modify #if (defined ZIGBEE_ZS_T4) || (defined ZIGBEE_ZS_T4_CS) // #if (defined ZIGBEE_ZS_T4) || (defined ZIGBEE_ZS_T3) || (defined ZIGBEE_ZS_T2) || (defined ZIGBEE_ZS_T1) void all_data_update(void) { /*dis_air_Conditioning = 0, dis_floor_heating , dis_fresh_air , * these fucntion will be generated by cloud platform, but when use these function must reference the function in mcu_api.c */ //zigbee_cmd.Is_From_485=0; uint16_t level; if(zigbee_cmd.Is_From_485==1||zigbee_cmd.Is_zigbee_cmd==0) zigbee_cmd.work_state_cur=dis_page_num.display_page ; mcu_dp_enum_update(DPID_WORK_STATE1, zigbee_cmd.work_state_cur); zigbee_cmd.work_state_info.air_condition.switch_onoff=dis_page_param.face_plate_param.Air_condition_switch; zigbee_cmd.work_state_info.air_condition.mode=dis_page_param.face_plate_param.Air_condition_mode; zigbee_cmd.work_state_info.air_condition.temp_set=dis_page_param.face_plate_param.Air_set_temp; switch(dis_page_param.face_plate_param.Air_wind_speed) { case 0x0100: zigbee_cmd.work_state_info.air_condition.level=0x0100; level=0x00; break; case 0x0001: zigbee_cmd.work_state_info.air_condition.level=0x0001; level=0x01; break; case 0x0002: zigbee_cmd.work_state_info.air_condition.level=0x0002; level=0x02; break; case 0x0003: zigbee_cmd.work_state_info.air_condition.level=0x0003; level=0x03; break; default: break; } //zigbee_cmd.work_state_info.air_condition.level=dis_page_param.face_plate_param.Air_wind_speed; zigbee_cmd.work_state_info.floor_condition.switch_onoff=dis_page_param.face_plate_param.Floor_heating_switch; zigbee_cmd.work_state_info.floor_condition.temp_set=dis_page_param.face_plate_param.Floor_heating_set_temp; zigbee_cmd.work_state_info.fresh_air_condition.switch_onoff=dis_page_param.face_plate_param.Fresh_air_switch; zigbee_cmd.work_state_info.fresh_air_condition.level=dis_page_param.face_plate_param.Fresh_air_speed; switch(zigbee_cmd.work_state_cur) { case 0: mcu_dp_bool_update(DPID_SWITCH, zigbee_cmd.work_state_info.air_condition.switch_onoff); mcu_dp_enum_update(DPID_MODE, zigbee_cmd.work_state_info.air_condition.mode); mcu_dp_value_update(DPID_TEMP_SET, zigbee_cmd.work_state_info.air_condition.temp_set); mcu_dp_enum_update(DPID_LEVEL, level); break; case 1: mcu_dp_bool_update(DPID_SWITCH_FLOOR_HEAT, zigbee_cmd.work_state_info.floor_condition.switch_onoff); mcu_dp_value_update(DPID_TEMP_DN, zigbee_cmd.work_state_info.floor_condition.temp_set); break; case 2: mcu_dp_bool_update(DPID_SWITCH_FAN, zigbee_cmd.work_state_info.fresh_air_condition.switch_onoff); mcu_dp_enum_update(DPID_LEVEL_FAN, zigbee_cmd.work_state_info.fresh_air_condition.level); break; default: break; } mcu_dp_value_update(DPID_TEMP_CURRENT, dis_page_param.face_plate_param.Real_time_Temp); /* mcu_dp_bool_update(DPID_SWITCH, Smartbox_On_Off_State); // BOOL型数据上报; if (ModeType != 0) { mcu_dp_enum_update(DPID_MODE, ModeType - 1); // 枚举型数据上报; } else { mcu_dp_enum_update(DPID_MODE, ModeType); // 枚举型数据上报; } if (DeviceType != 0) { mcu_dp_enum_update(DPID_WORK_STATE, DeviceType - 1); // 枚举型数据上报; } else { mcu_dp_enum_update(DPID_WORK_STATE, DeviceType); // 枚举型数据上报; } mcu_dp_value_update(DPID_TEMP_SET, Set_Temperature_IntegerData / 2); // VALUE型数据上报; // mcu_dp_value_update(DPID_TEMP_CURRENT, Now_Temperature_IntegerData); // VALUE型数据上报; mcu_dp_value_update(DPID_TEMP_CURRENT, dis_page_param.face_plate_param.Real_time_Temp); // VALUE型数据上报; if (WindSpeedData != 0) { mcu_dp_enum_update(DPID_LEVEL, WindSpeedData - 1); // 枚举型数据上报; } else { mcu_dp_enum_update(DPID_LEVEL, WindSpeedData); // 枚举型数据上报; } mcu_dp_enum_update(DPID_WORK_STATE1,zigbee_cmd.work_state); //枚举型数据上报;*/ } #endif /****************************************************************************** WARNING!!! 2:所有数据上报处理 自动化代码模板函数,具体请用户自行实现数据处理 ******************************************************************************/ // #ifdef ZIGBEE_ZS_T4 /***************************************************************************** 函数名称 : dp_download_switch_1_handle 功能描述 : 针对DPID_SWITCH_1的处理函数 输入参数 : value:数据源数据 : length:数据长度 返回参数 : 成功返回:SUCCESS/失败返回:ERROR 使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app *****************************************************************************/ static unsigned char dp_download_switch_handle(const unsigned char value[], unsigned short length) { zigbee_cmd.Is_From_485=0; // 示例:当前DP类型为BOOL unsigned char ret; // 0:off/1:on unsigned char switch_1; //zigbee_cmd.Is_Out_sleep=1; //zigbee_cmd.Is_Wakeup=1; PullOutOf_SleepPage(); zigbee_cmd.Is_zigbee_cmd=1; switch_1 = mcu_get_dp_download_bool(value, length); /* if (switch_1 == 0) { switch(zigbee_cmd.work_state_cur) { case 0: dis_page_param.face_plate_param.Open_device_mode = 0x00; dis_page_param.face_plate_param.Air_condition_switch = 0; Air_Open_data_Send(); zigbee_cmd.work_state_info.air_condition.switch_onoff=0; break; case 1: dis_page_param.face_plate_param.Floor_heating_switch =0; Floor_heating_Open_data_Send(); zigbee_cmd.work_state_info.floor_condition.switch_onoff=0; break; case 2: dis_page_param.face_plate_param.Fresh_air_switch=0; Fresh_air_Open_data_Send(); zigbee_cmd.work_state_info.fresh_air_condition.switch_onoff=0; break; default: break; } } else { switch(zigbee_cmd.work_state_cur) { case 0: dis_page_param.face_plate_param.Open_device_mode = 0x00; dis_page_param.face_plate_param.Air_condition_switch = 1; Air_Open_data_Send(); zigbee_cmd.work_state_info.air_condition.switch_onoff=1; break; case 1: dis_page_param.face_plate_param.Floor_heating_switch =1; Floor_heating_Open_data_Send(); zigbee_cmd.work_state_info.floor_condition.switch_onoff=1; break; case 2: dis_page_param.face_plate_param.Fresh_air_switch=1; Fresh_air_Open_data_Send(); zigbee_cmd.work_state_info.fresh_air_condition.switch_onoff=1; break; default: break; } }*/ if (switch_1 == 0) { dis_page_param.face_plate_param.Open_device_mode = 0x00; dis_page_param.face_plate_param.Air_condition_switch = 0; Air_Open_data_Send(); zigbee_cmd.work_state_info.air_condition.switch_onoff=0; } else { zigbee_cmd.Is_clear_lcd=1; dis_page_param.face_plate_param.Open_device_mode = 0x00; dis_page_param.face_plate_param.Air_condition_switch = 1; Air_Open_data_Send(); zigbee_cmd.work_state_info.air_condition.switch_onoff=1; } xTaskNotify((TaskHandle_t )LEDTask_Handler, (uint32_t )Wake_up, (eNotifyAction )eSetBits); // There should be a report after processing the DP ret = mcu_dp_bool_update(DPID_SWITCH, switch_1); if (ret == SUCCESS) return SUCCESS; else return ERROR; } /***************************************************************************** 函数名称 : dp_download_mode_handle 功能描述 : 针对DPID_MODE的处理函数 输入参数 : value:数据源数据 : length:数据长度 返回参数 : 成功返回:SUCCESS/失败返回:ERROR 使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app *****************************************************************************/ static unsigned char dp_download_mode_handle(const unsigned char value[], unsigned short length) { zigbee_cmd.Is_From_485=0; // 示例:当前DP类型为ENUM unsigned char ret; unsigned char mode; PullOutOf_SleepPage(); mode = mcu_get_dp_download_enum(value, length); zigbee_cmd.Is_zigbee_cmd=1; //zigbee_cmd.mode=mode; zigbee_cmd.Is_Out_sleep=1; switch(zigbee_cmd.work_state_cur) { case 0: zigbee_cmd.work_state_info.air_condition.mode=(uint32_t)mode; dis_page_param.face_plate_param.Air_condition_mode = (uint16_t)mode; Air_Mode_data_Send(); break; default: break; } if(mode==2&&dis_page_param.face_plate_param.Air_wind_speed==0x0100) dis_page_param.face_plate_param.Air_wind_speed=0x0001; all_data_update(); return SUCCESS; // ModeType = mode + 1; // 模式图标显示 value:1-制冷,2-制热,3-除湿,4-吹风, 0-关闭 // There should be a report after processing the DP /* ret = mcu_dp_enum_update(DPID_MODE, mode); if (ret == SUCCESS) return SUCCESS; else return ERROR;*/ } /***************************************************************************** 函数名称 : dp_download_temp_set_handle 功能描述 : 针对DPID_TEMP_SET的处理函数 输入参数 : value:数据源数据 : length:数据长度 返回参数 : 成功返回:SUCCESS/失败返回:ERROR 使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app *****************************************************************************/ static unsigned char dp_download_temp_set_handle(const unsigned char value[], unsigned short length) { zigbee_cmd.Is_From_485=0; // 示例:当前DP类型为VALUE unsigned char ret; unsigned long temp_set; zigbee_cmd.Is_Out_sleep=1; temp_set = mcu_get_dp_download_value(value, length); PullOutOf_SleepPage(); zigbee_cmd.Is_zigbee_cmd=1; /* //VALUE type data processing */ switch(zigbee_cmd.work_state_cur) { case 0: zigbee_cmd.work_state_info.air_condition.temp_set=(uint32_t)temp_set; dis_page_param.face_plate_param.Air_set_temp=(uint16_t)temp_set; Air_set_temp_data_Send(); break; case 1: //zigbee_cmd.work_state_info.floor_condition.temp_set=(uint32_t)temp_set; // dis_page_param.face_plate_param.Floor_heating_set_temp=(uint32_t)temp_set; //Floor_heating_set_temp_data_Send(); break; default: break; } // Set_Temperature_IntegerData = temp_set * 2; ////设置温度整数部分 // switchState.setcounter = 20; // 2秒倒计时 // There should be a report after processing the DP ret = mcu_dp_value_update(DPID_TEMP_SET, temp_set); if (ret == SUCCESS) return SUCCESS; else return ERROR; } /***************************************************************************** 函数名称 : dp_download_level_handle 功能描述 : 针对DPID_LEVEL的处理函数 输入参数 : value:数据源数据 : length:数据长度 返回参数 : 成功返回:SUCCESS/失败返回:ERROR 使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app *****************************************************************************/ static unsigned char dp_download_level_handle(const unsigned char value[], unsigned short length) { zigbee_cmd.Is_From_485=0; // 示例:当前DP类型为ENUM unsigned char ret; unsigned char level; zigbee_cmd.Is_Out_sleep=1; zigbee_cmd.Is_zigbee_cmd=1; PullOutOf_SleepPage(); level = mcu_get_dp_download_enum(value, length); //printf("\r\n112122331\r\n"); switch(zigbee_cmd.work_state_cur) { case 0: dis_page_num.display_page=dis_air_Conditioning; zigbee_cmd.work_state_info.air_condition.level=level; switch(level) { case 0: zigbee_cmd.work_state_info.air_condition.level=0x0100; dis_page_param.face_plate_param.Air_wind_speed=0x0100; Air_speed_data_Send(); // Air_speed_data_Sendtemp(0x01,0x00); break; case 1: zigbee_cmd.work_state_info.air_condition.level=0x0001; dis_page_param.face_plate_param.Air_wind_speed=0x0001; Air_speed_data_Send(); // Air_speed_data_Sendtemp(0x00,0x01); break; case 2: zigbee_cmd.work_state_info.air_condition.level=0x0002; dis_page_param.face_plate_param.Air_wind_speed=0x0002; Air_speed_data_Send(); // Air_speed_data_Sendtemp(0x00,0x02); break; case 3: zigbee_cmd.work_state_info.air_condition.level=0x0003; dis_page_param.face_plate_param.Air_wind_speed=0x0003; Air_speed_data_Send(); // Air_speed_data_Sendtemp(0x00,0x03); break; default: break; } break; case 2: zigbee_cmd.work_state_info.fresh_air_condition.level=level; switch(level) { case 0: dis_page_param.face_plate_param.Fresh_air_speed=0; Fresh_air_speed_data_Sendtemp(0x01,0x00); break; case 1: dis_page_param.face_plate_param.Fresh_air_speed=1; Fresh_air_speed_data_Sendtemp(0x00,0x01); break; case 2: dis_page_param.face_plate_param.Fresh_air_speed=2; Fresh_air_speed_data_Sendtemp(0x00,0x02); break; case 3: dis_page_param.face_plate_param.Fresh_air_speed=3; Fresh_air_speed_data_Sendtemp(0x00,0x03); break; default: break; } break; default: break; } // WindSpeedData = level + 1; // 风速显示界面, value,1-自动,2-低,3-中,4-高,0-关闭所有图标 // There should be a report after processing the DP ret = mcu_dp_enum_update(DPID_LEVEL, level); if (ret == SUCCESS) return SUCCESS; else return ERROR; } /***************************************************************************** 函数名称 : dp_download_work_state1_handle 功能描述 : 针对DPID_WORK_STATE1的处理函数 输入参数 : value:数据源数据 : length:数据长度 返回参数 : 成功返回:SUCCESS/失败返回:ERROR 使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app *****************************************************************************/ static unsigned char dp_download_work_state1_handle(const unsigned char value[], unsigned short length) { zigbee_cmd.Is_From_485=0; unsigned char ret; unsigned char work_state1; zigbee_cmd.Is_Out_sleep=1; work_state1 = mcu_get_dp_download_enum(value, length); zigbee_cmd.Is_zigbee_cmd=1; PullOutOf_SleepPage(); zigbee_cmd.work_state_cur=work_state1; switch (work_state1) { case 0: break; case 1: break; case 2: break; case 3: break; default: break; } all_data_update(); return SUCCESS; //There should be a report after processing the DP // ret = mcu_dp_enum_update(DPID_WORK_STATE1, work_state1); // if(ret == SUCCESS) // return SUCCESS; // else // return ERROR; } /***************************************************************************** 函数名称 : dp_download_temp_dn_handle 功能描述 : 针对DPID_TEMP_DN的处理函数 输入参数 : value:数据源数据 : length:数据长度 返回参数 : 成功返回:SUCCESS/失败返回:ERROR 使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app *****************************************************************************/ static unsigned char dp_download_temp_dn_handle(const unsigned char value[], unsigned short length) { // 示例:当前DP类型为VALUE unsigned char ret; unsigned long temp_set; zigbee_cmd.Is_Out_sleep=1; zigbee_cmd.Is_zigbee_cmd=1; temp_set = mcu_get_dp_download_value(value, length); PullOutOf_SleepPage(); /* //VALUE type data processing */ switch(zigbee_cmd.work_state_cur) { case 0: //zigbee_cmd.work_state_info.air_condition.temp_set=(uint32_t)temp_set; // dis_page_param.face_plate_param.Air_set_temp=(uint16_t)temp_set; // Air_set_temp_data_Send(); break; case 1: zigbee_cmd.work_state_info.floor_condition.temp_set=(uint32_t)temp_set; dis_page_param.face_plate_param.Floor_heating_set_temp=(uint32_t)temp_set; Floor_heating_set_temp_data_Send(); break; default: break; } // Set_Temperature_IntegerData = temp_set * 2; ////设置温度整数部分 // switchState.setcounter = 20; // 2秒倒计时 // There should be a report after processing the DP ret = mcu_dp_value_update(DPID_TEMP_DN, temp_set); if (ret == SUCCESS) return SUCCESS; else return ERROR; } /***************************************************************************** 函数名称 : dp_download_switch_floor_heat_handle 功能描述 : 针对DPID_SWITCH_FLOOR_HEAT的处理函数 输入参数 : value:数据源数据 : length:数据长度 返回参数 : 成功返回:SUCCESS/失败返回:ERROR 使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app *****************************************************************************/ static unsigned char dp_download_switch_floor_heat_handle(const unsigned char value[], unsigned short length) { zigbee_cmd.Is_From_485=0; // 示例:当前DP类型为BOOL unsigned char ret; // 0:off/1:on unsigned char switch_1; //zigbee_cmd.Is_Out_sleep=1; //zigbee_cmd.Is_Wakeup=1; PullOutOf_SleepPage(); zigbee_cmd.Is_zigbee_cmd=1; switch_1 = mcu_get_dp_download_bool(value, length); if (switch_1 == 0) { dis_page_param.face_plate_param.Floor_heating_switch =0; Floor_heating_Open_data_Send(); zigbee_cmd.work_state_info.floor_condition.switch_onoff=0; } else { zigbee_cmd.Is_clear_lcd=1; dis_page_param.face_plate_param.Floor_heating_switch =1; Floor_heating_Open_data_Send(); zigbee_cmd.work_state_info.floor_condition.switch_onoff=1; } xTaskNotify((TaskHandle_t )LEDTask_Handler, (uint32_t )Wake_up, (eNotifyAction )eSetBits); // There should be a report after processing the DP ret = mcu_dp_bool_update(DPID_SWITCH_FLOOR_HEAT, switch_1); if (ret == SUCCESS) return SUCCESS; else return ERROR; } /***************************************************************************** 函数名称 : dp_download_switch_fan_handle 功能描述 : 针对DPID_SWITCH_FAN的处理函数 输入参数 : value:数据源数据 : length:数据长度 返回参数 : 成功返回:SUCCESS/失败返回:ERROR 使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app *****************************************************************************/ static unsigned char dp_download_switch_fan_handle(const unsigned char value[], unsigned short length) { zigbee_cmd.Is_From_485=0; // 示例:当前DP类型为BOOL unsigned char ret; // 0:off/1:on unsigned char switch_1; //zigbee_cmd.Is_Out_sleep=1; //zigbee_cmd.Is_Wakeup=1; PullOutOf_SleepPage(); zigbee_cmd.Is_zigbee_cmd=1; switch_1 = mcu_get_dp_download_bool(value, length); if (switch_1 == 0) { dis_page_param.face_plate_param.Fresh_air_switch=0; Fresh_air_Open_data_Send(); zigbee_cmd.work_state_info.fresh_air_condition.switch_onoff=0; } else { zigbee_cmd.Is_clear_lcd=1; dis_page_param.face_plate_param.Fresh_air_switch=1; Fresh_air_Open_data_Send(); zigbee_cmd.work_state_info.fresh_air_condition.switch_onoff=1; } xTaskNotify((TaskHandle_t )LEDTask_Handler, (uint32_t )Wake_up, (eNotifyAction )eSetBits); // There should be a report after processing the DP ret = mcu_dp_bool_update(DPID_SWITCH_FAN, switch_1); if (ret == SUCCESS) return SUCCESS; else return ERROR; } /***************************************************************************** 函数名称 : dp_download_level_fan_handle 功能描述 : 针对DPID_LEVEL_FAN的处理函数 输入参数 : value:数据源数据 : length:数据长度 返回参数 : 成功返回:SUCCESS/失败返回:ERROR 使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app *****************************************************************************/ static unsigned char dp_download_level_fan_handle(const unsigned char value[], unsigned short length) { zigbee_cmd.Is_From_485=0; // 示例:当前DP类型为ENUM unsigned char ret; unsigned char level; zigbee_cmd.Is_Out_sleep=1; zigbee_cmd.Is_zigbee_cmd=1; PullOutOf_SleepPage(); level = mcu_get_dp_download_enum(value, length); //printf("\r\n112122331\r\n"); zigbee_cmd.work_state_info.fresh_air_condition.level=level; switch(level) { case 0: dis_page_param.face_plate_param.Fresh_air_speed=0; Fresh_air_speed_data_Sendtemp(0x01,0x00); break; case 1: dis_page_param.face_plate_param.Fresh_air_speed=1; Fresh_air_speed_data_Sendtemp(0x00,0x01); break; case 2: dis_page_param.face_plate_param.Fresh_air_speed=2; Fresh_air_speed_data_Sendtemp(0x00,0x02); break; case 3: dis_page_param.face_plate_param.Fresh_air_speed=3; Fresh_air_speed_data_Sendtemp(0x00,0x03); break; default: break; } zigbee_cmd.work_state_info.fresh_air_condition.level=level; // WindSpeedData = level + 1; // 风速显示界面, value,1-自动,2-低,3-中,4-高,0-关闭所有图标 // There should be a report after processing the DP ret = mcu_dp_enum_update(DPID_LEVEL_FAN, level); if (ret == SUCCESS) return SUCCESS; else return ERROR; } #if (defined ZIGBEE_ZS_T4) || (defined ZIGBEE_ZS_T4_CS) #endif #ifdef SUPPORT_MCU_RTC_CHECK /** * @brief mcu check local RTC time * @param[in] {time} timestamp * @return void */ void mcu_write_rtctime(unsigned char time[]) { #error "mcu should realize RTC time wtriting fuction, and delete this line" /* time[0]~time[3]:standard time time[4]~time[7]: Local time */ my_memcpy((void *)timestamp, (const char *)time, 4); // get timestamp zigbee_timestamp_to_time(); /* year = _time.w_year; //year month = _time.w_month; //month date = _time.w_date; //date hour = _time.hour + 8; //hour(8:BeiJing time) min = _time.min; //minute sec = _time.sec; //second */ } #endif /** * @brief Zigbee functional test feedback * @param[in] {void} * @return void */ void zigbee_test_result(void) { ////must modify // #error "this test is makesure the rf fuction of zigbee module, if test pass or not should do something, mcu should realize" unsigned char rssi = zigbee_uart_rx_buf[DATA_START + 1]; if (zigbee_uart_rx_buf[DATA_START] == 0x01) { if (rssi > 0x3C) { // test sucess the range of rssi is 0% ~ 100% } else { // test failure } } else { // test failure } } /****************************************************************************** WARNING!!! 以下函数用户请勿修改!! ******************************************************************************/ /** * @brief this function will handle uart received frame data * @param[in] {dpid} dp id * @param[in] {value} dp data * @param[in] {length} lenght of dp data * @return handle result */ // #ifdef ZIGBEE_ZS_T4 #if (defined ZIGBEE_ZS_T4) || (defined ZIGBEE_ZS_T4_CS) unsigned char dp_download_handle(unsigned char dpid, const unsigned char value[], unsigned short length) { /* only list of function, mcu need realize these fuction*/ unsigned char ret; switch(dpid){ case DPID_SWITCH: //开关处理函数 ret = dp_download_switch_handle(value,length); break; case DPID_MODE: //工作模式处理函数 ret = dp_download_mode_handle(value,length); break; case DPID_TEMP_SET: //目标温度处理函数 ret = dp_download_temp_set_handle(value,length); break; case DPID_LEVEL: //档位处理函数 ret = dp_download_level_handle(value,length); break; case DPID_WORK_STATE1: //工作状态处理函数 ret = dp_download_work_state1_handle(value,length); break; case DPID_TEMP_DN: //地暖目标温度处理函数 ret = dp_download_temp_dn_handle(value,length); break; case DPID_SWITCH_FLOOR_HEAT: //地暖开关处理函数 ret = dp_download_switch_floor_heat_handle(value,length); break; case DPID_SWITCH_FAN: //新风开关处理函数 ret = dp_download_switch_fan_handle(value,length); break; case DPID_LEVEL_FAN: //新风风速档位处理函数 ret = dp_download_level_fan_handle(value,length); break; default: break;} return ret; } #endif /** * @brief get received cmd total number * @param[in] {void} * @return received cmd total number */ unsigned char get_download_cmd_total(void) { return (sizeof(download_cmd) / sizeof(download_cmd[0])); } /** * @brief received zigbee net_work state handle * @param[in] {zigbee_work_state} zigbee current network state * @return void */ void zigbee_work_state_event(unsigned char zigbee_work_state) { unsigned short length = 0; zigbee_uart_write_frame(ZIGBEE_STATE_CMD, length); switch (zigbee_work_state) { case ZIGBEE_NOT_JION: // 设备不在网 // if(ZG_Joining == CONDITION_BEFOR_JOINING_TO_JOINING) // { // switchState.zigbee_work_state = 0; // switchState.time = 1000; // 10秒 // ledSetParam(25, 200); // } break; case ZIGBEE_JOIN_GATEWAY: // 入网成功 Is_blink=0; // ZG_JoinCounter = 1000; // 入网成功,入网计数器置最大值 //switchState.zigbee_work_state = 1; break; case ZIGBEE_JOIN_ERROR: switchState.zigbee_work_state = 0; switchState.time = 1000; // 10秒 ledSetParam(25, 200); break; case ZIGBEE_JOINING: break; default: break; } } /** * @brief received reset zigbee response * @param[in] {state} response state * @return void */ void mcu_reset_zigbee_event(unsigned char state) { switch (state) { case RESET_ZIGBEE_OK: break; case RESET_ZIGBEE_ERROR: break; default: break; } } /** * @brief check mcu version response * @param[in] {void} * @return void */ void response_mcu_ota_version_event(void) { unsigned short length = 0; length = set_zigbee_uart_byte(length, get_current_mcu_fw_ver()); // current fw version zigbee_uart_write_frame(MCU_OTA_VERSION_CMD, length); } #ifdef SUPPORT_MCU_OTA /** * @brief mcu ota update notify response * @param[in] {offset} data offset * @return void */ void response_mcu_ota_notify_event(unsigned char offset) { unsigned char i = 0; unsigned short length = 0; unsigned char update = 0; unsigned long app_newcode_add = 0; unsigned char j = 0; uint32_t temp_buff[256]; int k=0; current_mcu_fw_pid(); // current PID while (i < 8) { ota_fw_info.mcu_ota_pid[i] = zigbee_uart_rx_buf[offset + DATA_START + i]; // ota fw PID i++; } ota_fw_info.mcu_ota_ver = zigbee_uart_rx_buf[offset + DATA_START + 8]; // ota fw version ota_fw_info.mcu_ota_fw_size = zigbee_uart_rx_buf[offset + DATA_START + 9] << 24 | zigbee_uart_rx_buf[offset + DATA_START + 10] << 16 | zigbee_uart_rx_buf[offset + DATA_START + 11] << 8 | zigbee_uart_rx_buf[offset + DATA_START + 12]; // ota fw size ota_fw_info.mcu_ota_checksum = zigbee_uart_rx_buf[offset + DATA_START + 13] << 24 | zigbee_uart_rx_buf[offset + DATA_START + 14] << 16 | zigbee_uart_rx_buf[offset + DATA_START + 15] << 8 | zigbee_uart_rx_buf[offset + DATA_START + 16]; // ota fw checksum if ((!strcmp_barry(&ota_fw_info.mcu_ota_pid[0], ¤t_mcu_pid[0], 8)) && (ota_fw_info.mcu_ota_ver > get_current_mcu_fw_ver() && ota_fw_info.mcu_ota_fw_size > 0)) { // check fw pid and fw version and fw size length = set_zigbee_uart_byte(length, 0x00); // OK update = 1; // 校验通过,可进行固件升级 } else { length = set_zigbee_uart_byte(length, 0x01); // error } ota_fw_info.mcu_current_offset = 0; zigbee_uart_write_frame(MCU_OTA_NOTIFY_CMD, length); delay_1ms(20); // add by zzw 升级通知接收成功,第一次调用接收固件命令 if (update) { // 在读取数据之前先对FLASH进行擦除,从第38页开始 app_newcode_add = OTA_NEW_CODE_START_ADD; fmc_unlock(); /*for (k = 0; k < 256; k++) { temp_buff[k] = flash_word_read(OTA_STATE_DATA_ADD + (4 * k)); // 1.取出程序运行区代码数据 } temp_buff[0] = 0;//参数初始化 //delay_1ms(10); flash_page_write(OTA_STATE_DATA_ADD, temp_buff); // 2.将取出的运行区代码写入临时区 delay_1ms(20);*/ for (i = 0; i < 26; i++) { fmc_page_erase(app_newcode_add + i * 1024); } fmc_lock(); mcu_ota_fw_request(); // 固件升级 } } /** * @brief received mcu ota data request response * @param[in] {fw_offset} offset of file * @param[in] {data} received data * @return void */ /*void reveived_mcu_ota_data_handle(unsigned int fw_offset, char *data) { // "received frame data, should save in flash, mcu should realize this fuction, and delete this line " //未使用 }*/ /** * @brief mcu send ota data request * @param[in] {void} * @return void */ void mcu_ota_fw_request_event(unsigned char offset) { unsigned int fw_offset = 0; char fw_data[FW_SINGLE_PACKET_SIZE] = {-1}; // unsigned char i = 0; unsigned char last_package_len = 0; static unsigned int current_checksum = 0; if (zigbee_uart_rx_buf[offset + DATA_START] == 0x01) // status check return; while (i < 8) { if (current_mcu_pid[i] != zigbee_uart_rx_buf[offset + DATA_START + 1 + i]) // pid check return; i++; } if (ota_fw_info.mcu_ota_ver != zigbee_uart_rx_buf[offset + DATA_START + 9]) // version check return; i = 0; while (i < 4) { fw_offset |= (zigbee_uart_rx_buf[offset + DATA_START + 10 + i] << (24 - i * 8)); // offset i++; } i = 0; if (ota_fw_info.mcu_current_offset == fw_offset) { // if ((ota_fw_info.mcu_ota_fw_size - fw_offset) / FW_SINGLE_PACKET_SIZE != 0) if (((ota_fw_info.mcu_ota_fw_size - fw_offset) / FW_SINGLE_PACKET_SIZE != 0) && (ota_fw_info.mcu_ota_fw_size != (fw_offset + FW_SINGLE_PACKET_SIZE))) // if (((ota_fw_info.mcu_ota_fw_size - fw_offset) / FW_SINGLE_PACKET_SIZE != 0)&&((ota_fw_info.mcu_ota_fw_size - fw_offset) % FW_SINGLE_PACKET_SIZE != 0)) { if (ota_fw_info.mcu_current_offset == 0) { current_checksum = 0; } while (i < FW_SINGLE_PACKET_SIZE) { fw_data[i] = zigbee_uart_rx_buf[offset + DATA_START + 14 + i]; // fw data current_checksum += fw_data[i]; i++; } ota_fw_info.mcu_current_offset += FW_SINGLE_PACKET_SIZE; ota_fw_data_handle(fw_offset, &fw_data[0], FW_SINGLE_PACKET_SIZE); // OTA paket data handle } else { i = 0; // last_package_len = ota_fw_info.mcu_ota_fw_size - fw_offset; if ((ota_fw_info.mcu_ota_fw_size - fw_offset) % FW_SINGLE_PACKET_SIZE != 0) { last_package_len = ota_fw_info.mcu_ota_fw_size - fw_offset; } else { last_package_len = FW_SINGLE_PACKET_SIZE; } while (i < last_package_len) { fw_data[i] = zigbee_uart_rx_buf[offset + DATA_START + 14 + i]; current_checksum += fw_data[i]; i++; } ota_fw_info.mcu_current_offset += last_package_len; if (ota_fw_info.mcu_ota_checksum != current_checksum) { // ota failure report ota failure and clear ota struct mcu_ota_result_report(1); // failed } else { // ota sucess mcu_ota_result_report(0); // seccess } ota_fw_data_handle(fw_offset, &fw_data[0], last_package_len); // OTA paket data handle current_checksum = 0; } } else { // ota request timeout, then restart ota request from ota_fw_info.mcu_ota_fw_size } } static void report_mcu_ota_result(unsigned char res) { unsigned short length; if ((res == 0) || (res == 1)) { length = set_zigbee_uart_byte(length, res); zigbee_uart_write_frame(MCU_OTA_NOTIFY_CMD, length); } } /** * @brief mcu ota data result notify * @param[in] {void} * @return void */ void mcu_ota_result_event(unsigned char offset) { unsigned short k, Ret; uint32_t temp_buff[256]; unsigned char status = zigbee_uart_rx_buf[offset + DATA_START]; if (status == 0x00) { // 升级成功,用户提示 IAPUpdateFlag = 1; /*for (k = 0; k < 256; k++) { temp_buff[k] = flash_word_read(OTA_STATE_DATA_ADD + (4 * k)); // 1.取出程序运行区代码数据 } temp_buff[0] = IAPUpdateFlag; delay_1ms(10); Ret = flash_page_write(OTA_STATE_DATA_ADD, temp_buff); // 2.将取出的运行区代码写入临时区 delay_1ms(20);*/ flash_word_write((OTA_STATE_DATA_ADD), IAPUpdateFlag); /*if(Ret == 0) { Ret = 0; }*/ // flash_word_write (OTA_STATE_DATA_ADD,IAPUpdateFlag); delay_1ms(500); NVIC_SystemReset(); // add by zzw 系统复位函数 } else if (status == 0x01) { } } /** * @brief mcu ota data handle * @param[in] {fw_offset} frame offset * @param[in] {data} received data * @return void */ void ota_fw_data_handle(unsigned int fw_offset, char *data, unsigned char data_len) // 一整包数据48字节 { unsigned short i = 0; unsigned short update = 1; unsigned long app_newcode_add = 0; // 读flash的时候的地址变量,新代码区 unsigned short temp = 0; unsigned long write_data; //"请在该函数处理固件包数据" //"received frame data, should save in flash, mcu should realize this fuction, and delete this line " // 取出数据存入falsh,建议延用‘ota_fw_info’全局变量,不需定义其他全局变量,可维护数据包长度等 if (fw_offset == 0) { app_newcode_add = OTA_NEW_CODE_START_ADD; /*fmc_unlock(); for (i = 0; i < 26; i++) { fmc_page_erase(app_newcode_add + i * 1024); } fmc_lock();*/ } OTA_Reciv_Datalen = OTA_Reciv_Datalen + data_len; app_newcode_add = OTA_NEW_CODE_START_ADD + fw_offset; if (data_len == FW_SINGLE_PACKET_SIZE) // 整包数据 { for (i = 0; i < (FW_SINGLE_PACKET_SIZE / 4); i++) { write_data = 0; write_data = data[i * 4 + 3]; write_data = (write_data << 8) + data[i * 4 + 2]; write_data = (write_data << 8) + data[i * 4 + 1]; write_data = (write_data << 8) + data[i * 4]; flash_word_write(app_newcode_add, write_data); app_newcode_add = app_newcode_add + 4; } } else // 最后一包非整包数据 { temp = data_len % 4; if (temp == 0) { for (i = 0; i < (data_len / 4); i++) { write_data = 0; write_data = data[i * 4 + 3]; write_data = (write_data << 8) + data[i * 4 + 2]; write_data = (write_data << 8) + data[i * 4 + 1]; write_data = (write_data << 8) + data[i * 4]; flash_word_write(app_newcode_add, write_data); app_newcode_add = app_newcode_add + 4; } } } // if(OTA_Reciv_Datalen == ota_fw_info.mcu_ota_fw_size) //接收数据完成停止获取 // { // update = 0; // } if (update) // 数据存储完毕,继续调用获取数据命令 { mcu_ota_fw_request(); // 固件升级 } } #endif #ifdef BEACON_TEST /** * @brief beacon test notify,which used in testing * @param[in] {void} * @return void */ void mcu_received_beacon_test_handle(void) { unsigned short length = 0; length = set_zigbee_uart_byte(length, 0x00); zigbee_uart_write_frame(SEND_BEACON_NOTIFY_CMD, length); // then start test } #endif #ifdef CHECK_ZIGBEE_NETWORK /** * @brief check zigbee nwkstate,before start join nwk, check nwk if state is not 0x02,can start jion, * else delay 5s * * @param[in] {void} * @return void */ void mcu_check_zigbee_nwk_state(void) { unsigned short length = 0; zigbee_uart_write_frame(CHECK_ZIGBEE_NETWORK_CMD, length); // then start test } #endif void zigbee_notify_factory_new_hanlde(void) { unsigned short length = 0; length = set_zigbee_uart_byte(length, 0x01); zigbee_uart_write_frame(ZIGBEE_FACTORY_NEW_CMD, length); // then start test } #ifdef READ_DP_DATA_NOTIFY /** * @brief when gateway repower or relink clould, or zigbee module join sucess, repower, this commod will notify * mcu, to sys dp data, mcu itself decide whether report. * * @param[in] {void} * @return void */ void read_dp_data_notify_hanlde(void) { unsigned short length = 0; length = set_zigbee_uart_byte(length, 0x01); zigbee_uart_write_frame(ZIGBEE_FACTORY_NEW_CMD, length); // then start test } #endif