#include /** * @Author: 李建 * @Date: 2025/3/25 15:23 * Description: 空调控制器 * Copyright: Copyright (©) 2025 永续绿建. All rights reserved. */ #include #include "freertos/FreeRTOS.h" #include #include #include #include "xf_controller.h" #include "sub_device/command.h" #include "modbus_master.h" #include "system/miscellaneous_interface.h" #include "lvgl_port.h" #include "main.h" #include "esp_modbus_master.h" #include "mb_endianness_utils.h" #include "sht30.h" #include "gateway/access.h" static const char *TAG = "xf_controller"; static uint8_t err_count_cs = 0;// 通讯失败次数 static uint8_t err_count_js = 0;// 通讯失败次数 static SemaphoreHandle_t report_task_sem; // 上报任务信号量,用于实现操作完成上立即上报当前状态 extern void set_xf_mode(lv_ui *ui, uint16_t mode); static TaskHandle_t cloud_report_handle; static TaskHandle_t report_trigger_handle; static TaskHandle_t status_task_handle; static TaskHandle_t Core_task_handle; #define FILTER_LIFE_TIME_H_VALVE 4320//六个月,每五分钟计数加一(4320个小时) // 初始化空调参数 xf_status_t xf_status = { .power= 0, .fan_speed=3, .mode=1, .filter_used_time=0, .set_max_hum=70, .filter_life_remaining=100, .js_error_code=0, }; xf_fault_t xf_CSFault[]={ { .code="E21", .description="混风后温度传感器异常", }, { .code="E22", .description="盘管温度传感器异常", }, { .code="E23", .description="排气温度传感器异常", }, { .code="E24", .description="低压保护传感器异常", }, { .code="E25", .description="高压保护传感器异常", }, { .code="E26", .description="排风报警", }, { .code="E27", .description="液位开关异常", }, { .code="E28", .description="防冻保护", }, { .code="E29", .description="控制器温湿度异常", }, { .code="E210", .description="高温报警", }, { .code="E211", .description="风机故障", }, { .code="E212", .description="压缩机断开保护", }, }; xf_fault_t xf_fault[] = { { .code="E11", .description="传感器故障", }, { .code="E12", .description="高水位故障", }, { .code="E13", .description="进水电磁阀故障", }, { .code="E14", .description="送风风机故障", }, { .code="E15", .description="排风风机故障", }, { .code="E16", .description="排水泵故障", }, { .code="E17", .description="通讯故障", }, }; void read_xf_status(system_setting_t *setting) { uint16_t *_power = nvs_get_uint16(NVS_POWER_CONTROLLER); uint16_t *_mode = nvs_get_uint16(NVS_MODEL_CONTROLLER); uint16_t *_fan_speed = nvs_get_uint16(NVS_FAN_SPEED_SET); uint16_t *_set_hum_max = nvs_get_uint16(NVS_MAX_HUM_SET); uint16_t *_new_fan = nvs_get_uint16(NVS_NEW_FAN); xf_status.power= _power == NULL ? 0 : *_power; xf_status.mode = _mode == NULL ? 1 : *_mode; xf_status.fan_speed = _fan_speed == NULL ? 3 : *_fan_speed; xf_status.set_max_hum = _set_hum_max == NULL ? 70 : *_set_hum_max; xf_status.new_fan = _new_fan == NULL ? 1 : *_new_fan; } // 设置电源 esp_err_t xf_set_power(bool saved) { esp_err_t err = ESP_OK; if(saved) nvs_set_uint16(xf_status.power, NVS_POWER_CONTROLLER); if (guider_ui.screen_main) { if(xf_status.power==0) { lvgl_port_lock(-1); lv_obj_add_flag(guider_ui.screen_main_cont_speedset, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(guider_ui.screen_main_cont_humSet, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(guider_ui.screen_main_cont_mode, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(guider_ui.screen_main_imgbtn_new_fan, LV_OBJ_FLAG_HIDDEN); lvgl_port_unlock(); }else{ lvgl_port_lock(-1); lv_obj_clear_flag(guider_ui.screen_main_cont_speedset, LV_OBJ_FLAG_HIDDEN); lv_obj_clear_flag(guider_ui.screen_main_cont_humSet, LV_OBJ_FLAG_HIDDEN); lv_obj_clear_flag(guider_ui.screen_main_cont_mode, LV_OBJ_FLAG_HIDDEN); lv_obj_clear_flag(guider_ui.screen_main_imgbtn_new_fan, LV_OBJ_FLAG_HIDDEN); lv_label_set_text_fmt(guider_ui.screen_main_label_humSet_vul, "%d%%", xf_status.set_max_hum); lv_slider_set_value(guider_ui.screen_main_slider_speedSet_sign, xf_status.fan_speed*20, LV_ANIM_ON); lv_label_set_text_fmt(guider_ui.screen_main_label_spedSet_vul, "%d档",xf_status.fan_speed); lv_slider_set_value(guider_ui.screen_main_slider_humSet_sign, xf_status.set_max_hum, LV_ANIM_ON); set_xf_mode(&guider_ui, xf_status.mode); lvgl_port_unlock(); } } if (cloud_connected) { xSemaphoreGive(report_task_sem); } return err; } esp_timer_handle_t esp_timer_handle = 0; //定时器句柄 // 设置最大湿度 esp_err_t xf_set_max_hum(bool saved) { esp_err_t err = ESP_OK; if(saved) nvs_set_uint16(xf_status.set_max_hum, NVS_MAX_HUM_SET); if (cloud_connected) { xSemaphoreGive(report_task_sem); } return err; } // 设置最小湿度 //esp_err_t xf_set_min_hum(bool saved) { // if(saved) // nvs_set_uint16(xf_status.set_min_hum, NVS_MIN_HUM_SET); // return mm_set_param(CID_MIN_HUMIDITY, (uint8_t *)&xf_status.set_min_hum); //} //重置滤网剩余寿命 void xf_set_filter_life_remain(bool saved) { xf_status.filter_reset_flag=1; } //设置手动新风 esp_err_t set_new_fan(bool saved) { esp_err_t err = ESP_OK; if(saved) nvs_set_uint16(xf_status.new_fan, NVS_NEW_FAN); if (cloud_connected) { xSemaphoreGive(report_task_sem); } return err; } //设置新风风速 esp_err_t xf_set_fan_speed(bool saved) { esp_err_t err = ESP_OK; if(saved) nvs_set_uint16(xf_status.fan_speed, NVS_FAN_SPEED_SET); if (cloud_connected) { xSemaphoreGive(report_task_sem); } return err; } // 设置模式 esp_err_t xf_set_mode(bool saved) { esp_err_t err = ESP_OK; if(saved) nvs_set_uint16(xf_status.mode, NVS_MODEL_CONTROLLER); if (cloud_connected) { xSemaphoreGive(report_task_sem); } return err; } static void update_power_ui(bool on_off) { // 同步更新 UI if (guider_ui.screen_main) { lvgl_port_lock(-1); lv_obj_set_state(guider_ui.screen_main_imgbtn_power, LV_IMAGEBUTTON_STATE_CHECKED_RELEASED, on_off); lvgl_port_unlock(); } } // 云端: 设置上报时间间隔 static void cloud_set_report_duration(char *params) { cJSON *data = cJSON_Parse(params); if (data != NULL) { cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value"); if (cJSON_IsNumber(value)) { system_setting.report_data_duration = value->valueint; save_system_setting(&system_setting); } } } static void cloud_set_power(char *params) { cJSON *data = cJSON_Parse(params); if (data != NULL) { cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value"); xf_status.power = value->valueint; xf_set_power(true); update_power_ui(xf_status.power); cJSON_Delete(data); } } static void cloud_set_max_hum(char *params) { cJSON *data = cJSON_Parse(params); if (data != NULL) { cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value"); if((value->valueint<=70)&&(value->valueint>=system_setting.set_min_hum)) { xf_status.set_max_hum = value->valueint; if (guider_ui.screen_main) { lvgl_port_lock(-1); lv_label_set_text_fmt(guider_ui.screen_main_label_humSet_vul, "%d%%", xf_status.set_max_hum); lv_slider_set_value(guider_ui.screen_main_slider_humSet_sign, xf_status.set_max_hum,LV_ANIM_OFF); lvgl_port_unlock(); } xf_set_max_hum(true); } cJSON_Delete(data); } } static void cloud_set_mode(char *params) { cJSON *data = cJSON_Parse(params); if (data != NULL) { cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value"); xf_status.mode = value->valueint; if (guider_ui.screen_main) { lvgl_port_lock(-1); set_xf_mode(&guider_ui, xf_status.mode); lvgl_port_unlock(); } xf_set_mode(true); cJSON_Delete(data); } } static void cloud_set_fan_level(char *params) { cJSON *data = cJSON_Parse(params); if (data != NULL) { cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value"); xf_status.fan_speed = value->valueint; if (guider_ui.screen_main) { lvgl_port_lock(-1); lv_slider_set_value(guider_ui.screen_main_slider_speedSet_sign, xf_status.fan_speed*30, LV_ANIM_ON); lv_label_set_text_fmt(guider_ui.screen_main_label_spedSet_vul, "%d档",xf_status.fan_speed); lvgl_port_unlock(); } xf_set_fan_speed(true); cJSON_Delete(data); } } static void cloud_set_filter_life(char *params) { cJSON *data = cJSON_Parse(params); if (data != NULL) { cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value"); system_setting.filter_life_time = value->valueint; save_system_setting(&system_setting); cJSON_Delete(data); } } static void cloud_reset_filter_life_remain(char *params) { cJSON *data = cJSON_Parse(params); if (data != NULL) { xf_status.filter_used_time=0; xf_set_filter_life_remain(true); cJSON_Delete(data); } } static void cloud_set_new_fan(char *params) { cJSON *data = cJSON_Parse(params); if (data != NULL) { cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value"); xf_status.new_fan = value->valueint; if (guider_ui.screen_main) { lvgl_port_lock(-1); if(xf_status.new_fan==2) { lv_obj_add_state(guider_ui.screen_main_imgbtn_new_fan,LV_STATE_CHECKED); }else{ lv_obj_remove_state(guider_ui.screen_main_imgbtn_new_fan,LV_STATE_CHECKED); } lvgl_port_unlock(); } set_new_fan(true); cJSON_Delete(data); } } static void cloud_set_min_hum(char *params) { } //注册云端指令s void register_sparrow_commands(void) { sparrow_command set_power_cmd = { .name = "setPower", .unpack = &cloud_set_power }; register_sparrow_command(set_power_cmd); sparrow_command set_max_hum_cmd = { .name = "setMaxHum", .unpack = &cloud_set_max_hum }; register_sparrow_command(set_max_hum_cmd); // setMode sparrow_command set_mode_cmd = { .name = "setMode", .unpack = &cloud_set_mode }; register_sparrow_command(set_mode_cmd); // setFanLevel sparrow_command set_fan_level_cmd = { .name = "setFanLevel", .unpack = &cloud_set_fan_level, }; register_sparrow_command(set_fan_level_cmd); // setNewFan sparrow_command set_filter_life_cmd = { .name = "setFilterLife", .unpack = &cloud_set_filter_life, }; register_sparrow_command(set_filter_life_cmd); sparrow_command set_new_fan_cmd = { .name = "setNewFan", .unpack = &cloud_set_new_fan, }; register_sparrow_command(set_new_fan_cmd); // setFanVoltage sparrow_command set_min_hum_cmd = { .name = "setMinHumCmd", .unpack = &cloud_set_min_hum, }; register_sparrow_command(set_min_hum_cmd); sparrow_command set_duration = { .name = "setReportDuration", .unpack = &cloud_set_report_duration }; register_sparrow_command(set_duration); sparrow_command reset_filter_life_remain = { .name = "setReportDuration", .unpack = &cloud_reset_filter_life_remain }; register_sparrow_command(reset_filter_life_remain); } LV_IMAGE_DECLARE(_power_open_RGB565A8_36x36); LV_IMAGE_DECLARE(_liang_RGB565A8_30x30); LV_IMAGE_DECLARE(_cha_RGB565A8_30x30); /** * TODO:处理风故障信息 */ void handle_err_code() { uint8_t error_code[2] = {0}; esp_err_t err = ESP_OK; err = mm_get_param(CID_JS_ERROR_CODE, error_code); if (err == ESP_OK) { xf_status.js_error_code=(uint8_t)(*(uint16_t *)error_code&0x0ff); } vTaskDelay(pdTICKS_TO_MS(200)); err = mm_get_param(CID_CS_ERROR_CODE, error_code); if (err == ESP_OK) { xf_status.cs_error_code=(uint8_t)(*(uint16_t *)error_code&0x0ff); } if (guider_ui.screen_main) { if(((xf_status.cs_error_code&0x07ff)==0)&&(xf_status.js_error_code&0x00ff)==0) { lvgl_port_lock(-1); lv_obj_add_flag(guider_ui.screen_main_lab_err, LV_OBJ_FLAG_HIDDEN); lvgl_port_unlock(); } else{ lvgl_port_lock(-1); lv_obj_clear_flag(guider_ui.screen_main_lab_err, LV_OBJ_FLAG_HIDDEN); lvgl_port_unlock(); } } } void Refresh_UI() { uint8_t type = PARAM_TYPE_U16; uint8_t temp_data[2] = {0}, filter_data[2] = {0};// temporary buffer to hold maximum CID size uint16_t temp_data_u16 = 500; esp_err_t err = ESP_OK; err = mm_get_param(CID_CS_INEFFICIENT_FILTER_SIGN, filter_data); if (err == ESP_OK) { err_count_cs = 0; if (guider_ui.screen_main) { lvgl_port_lock(-1); lv_obj_add_flag(guider_ui.screen_main_lab_485_err, LV_OBJ_FLAG_HIDDEN); lvgl_port_unlock(); } } else { err_count_cs++; if (err_count_cs >= 254) err_count_cs = 30; } if (err_count_cs >= 30) { if (guider_ui.screen_main) { lvgl_port_lock(-1); lv_obj_remove_flag(guider_ui.screen_main_lab_485_err, LV_OBJ_FLAG_HIDDEN); lvgl_port_unlock(); } } err = ESP_OK; vTaskDelay(pdTICKS_TO_MS(200)); err = mm_get_param(CID_JS_POWER, temp_data); if (err == ESP_OK) { err_count_js = 0; if (guider_ui.screen_main) { lvgl_port_lock(-1); lv_obj_add_flag(guider_ui.screen_main_lab_485_err_js, LV_OBJ_FLAG_HIDDEN); lvgl_port_unlock(); } } else { err_count_js++; if (err_count_js >= 254) err_count_js = 30; } if (err_count_js >= 30) { if (guider_ui.screen_main) { lvgl_port_lock(-1); lv_obj_remove_flag(guider_ui.screen_main_lab_485_err_js, LV_OBJ_FLAG_HIDDEN); lvgl_port_unlock(); } } // ESP_LOGE(TAG, "filter_life_remaining%d",xf_status.filter_life_remaining); xf_status.filter_life_remaining=100*(system_setting.filter_life_time-xf_status.filter_used_time)/system_setting.filter_life_time; if (guider_ui.screen_main) { lvgl_port_lock(-1); lv_arc_set_value(guider_ui.screen_main_arc_hum,(int)sht30Data.humidity); if (filter_data[1]+filter_data[0]==1) { lv_obj_remove_flag(guider_ui.screen_main_label_filter_error, LV_OBJ_FLAG_HIDDEN); }else { lv_obj_add_flag(guider_ui.screen_main_label_filter_error, LV_OBJ_FLAG_HIDDEN); } lvgl_port_unlock(); } if (xf_status.proof_mode==1) { lv_obj_remove_flag(guider_ui.screen_main_img_proof,LV_OBJ_FLAG_HIDDEN); }else { lv_obj_add_flag(guider_ui.screen_main_img_proof,LV_OBJ_FLAG_HIDDEN); } } static uint8_t auto_switch_flag=0; /* * 自动模式下控制,十度 */ void xf_auto_task(void *arg) { if (auto_switch_flag==0) { if (xf_status.set_max_hum>(int)sht30Data.humidity) { auto_switch_flag=1; if (xf_status.new_fan==2) { xf_status.xfcs_status.mode=XFCS_XF; }else { xf_status.xfcs_status.mode=XFCS_NXH; } xf_status.js_module_status.power=1; xf_status.js_module_status.mode=JS_JS; }else if (xf_status.set_max_hum<(int)sht30Data.humidity){ auto_switch_flag=1; if (xf_status.new_fan==2) { xf_status.xfcs_status.mode=XFCS_XFCS; }else { xf_status.xfcs_status.mode=XFCS_NXHCS; } xf_status.js_module_status.power=0; }else { auto_switch_flag=0; } }else { if ((int)sht30Data.humidity-xf_status.set_max_hum>5) { //CS模式 if (xf_status.new_fan==2) { xf_status.xfcs_status.mode=XFCS_XFCS; }else { xf_status.xfcs_status.mode=XFCS_NXHCS; } xf_status.js_module_status.power=0; }else if(xf_status.set_max_hum-(int)sht30Data.humidity>5) { //JS模式 if (xf_status.new_fan==2) { xf_status.xfcs_status.mode=XFCS_XF; }else { xf_status.xfcs_status.mode=XFCS_NXH; } xf_status.js_module_status.mode=JS_JS; xf_status.js_module_status.power=1; }else { // } } ESP_LOGE(TAG, "js_module_status.power: %d\r\njs_module_status.mode: %d\r\n js_module_status.set_max_hum: %d\r\n" ,xf_status.js_module_status.power,xf_status.js_module_status.mode,xf_status.js_module_status.set_max_hum); } uint8_t humidification_mode_end_flag=0; uint32_t humidification_mode_end_acc=0; uint8_t humidification_mode_flag=0; uint32_t humidification_mode_acc=0; uint8_t auto_mould_proof_acc=0; // 防霉运行模式开始 void mould_proof_mode_start() { //显示防霉标志 //新风除湿开启内循环模式 xf_status.xfcs_status.mode = XFCS_NXH; //新风除湿开机 xf_status.xfcs_status.power = 1; xf_status.xfcs_status.fan_speed = 1; } // 防霉运行模式结束 void mould_proof_mode_stop() { humidification_mode_end_flag = 0; auto_mould_proof_acc = 0; humidification_mode_end_acc = 0; humidification_mode_flag = 0; // 恢复工作模式为正常模式 } // 防霉运行模式检测 void mould_proof_mode_check() { // 如果加湿功能正常开启且当前是关闭状态,开始累加,开启防霉运行功能 if (humidification_mode_flag == 1) { // 启动防霉后多长时间,结束防霉 if (++auto_mould_proof_acc >= system_setting.mould_proof_runtime * 60) { ESP_LOGE(TAG,"proof stop!!!/\r\n"); mould_proof_mode_stop(); xf_status.proof_mode=0; humidification_mode_flag=0; }else { ESP_LOGE(TAG,"proof start!!!/\r\n"); ESP_LOGE(TAG,"mould_proof_runtime:%d \r\n",system_setting.mould_proof_runtime); mould_proof_mode_start(); xf_status.proof_mode=1; } }else { xf_status.proof_mode=0; xf_status.xfcs_status .power=0; xf_status.js_module_status.power=0; } } static uint8_t js_mode_flag=0; _Noreturn static void Core_task(void *arg) { esp_err_t err = ESP_OK; for (;;) { if (xf_status.power==1) { xf_status.proof_mode=0; xf_status.xfcs_status.set_hum=xf_status.set_max_hum; xf_status.js_module_status.set_max_hum=xf_status.set_max_hum; xf_status.js_module_status.set_min_hum=xf_status.js_module_status.set_max_hum>=40?xf_status.js_module_status.set_max_hum-10:30; switch (xf_status.mode) { case CS: if (xf_status.new_fan==2) { xf_status.xfcs_status.mode=XFCS_XFCS; }else { xf_status.xfcs_status.mode=XFCS_NXHCS; } if (xf_status.set_max_hum-(int)sht30Data.humidity>10) { //达标 停止除湿 xf_status.xfcs_status .power=0; }else if (xf_status.set_max_hum<(int)sht30Data.humidity){ //未达标开始除湿 xf_status.xfcs_status .power=1; }else { //保持原先状态不变 } xf_status.js_module_status.power=0; break; case JS: if (xf_status.new_fan==2) { xf_status.xfcs_status.mode=XFCS_XF; }else { xf_status.xfcs_status.mode=XFCS_NXH; } if ((int)sht30Data.humidity-xf_status.set_max_hum>10) { js_mode_flag=1; //达标 停止加湿 xf_status.xfcs_status .power=0; xf_status.js_module_status.power=0; }else if ((int)sht30Data.humidity(60)) {//测试 if (humidification_mode_acc>(60*20)) { humidification_mode_flag=1; humidification_mode_end_acc=0; } }else { //当环境湿度大于设置湿度,且环境湿度 //保持原先状态不变 } xf_status.js_module_status.mode=JS_JS; break; case SF: auto_switch_flag=0; if (xf_status.new_fan==2) { xf_status.xfcs_status.mode=XFCS_XF; }else { xf_status.xfcs_status.mode=XFCS_NXH; } xf_status.xfcs_status .power=1; xf_status.js_module_status.power=0; break; // case AUTO: // // xf_auto_task(arg); break; } }else { mould_proof_mode_check(); } xf_status.xfcs_status.fan_speed=xf_status.fan_speed; switch (xf_status.fan_speed) { case 1: xf_status.js_module_status.fan_speed=1; break; case 2: xf_status.js_module_status.fan_speed=3; break; case 3: xf_status.js_module_status.fan_speed=5; break; default: xf_status.js_module_status.fan_speed=1; break; } xf_status.xfcs_status.set_hum=xf_status.set_max_hum; vTaskDelay(1000 / portTICK_PERIOD_MS); } } /** * 状态同步任务,主要用于与分风箱主控同步当前用户的参数,并处理通讯故障 * @param arg */ _Noreturn static void status_sync_task(void *arg) { esp_err_t err = ESP_OK; uint16_t filter_reset=0x5AA5; uint8_t filter_flag[2] = {0}; for (;;) { mm_set_param(CID_CS_POWER, (uint8_t *)&xf_status.xfcs_status.power); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_JS_POWER, (uint8_t *)&xf_status.js_module_status.power); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_CS_MODE, (uint8_t *)&xf_status.xfcs_status.mode); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_JS_MODE, (uint8_t *)&xf_status.js_module_status.mode); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_CS_FAN_SPEED, (uint8_t *)&xf_status.fan_speed); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_JS_FAN_SPEED, (uint8_t *)&xf_status.js_module_status.fan_speed); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_JS_MAX_HUMIDITY, (uint8_t *)&xf_status.js_module_status.set_max_hum); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_JS_MIN_HUMIDITY, (uint8_t *)&xf_status.js_module_status.set_min_hum); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_CS_SET_HUMIDITY, (uint8_t *)&xf_status.xfcs_status.set_hum); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_CS_INEFFICIENT_FILTER_SET_TIME, (uint8_t *)&system_setting.filter_life_time); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_CS_HEPA_FILTER_SET_TIME, (uint8_t *)&system_setting.filter_life_time); vTaskDelay(pdTICKS_TO_MS(100)); if (xf_status.filter_reset_flag==1) { mm_set_param(CID_CS_INEFFICIENT_FILTER_RESET, (uint8_t *)&filter_reset); vTaskDelay(pdTICKS_TO_MS(100)); mm_set_param(CID_CS_HEPA_FILTER_RESET, (uint8_t *)&filter_reset); vTaskDelay(pdTICKS_TO_MS(100)); err=mm_get_param(CID_CS_INEFFICIENT_FILTER_RESET, filter_flag); if (err==ESP_OK) { if (*(uint16_t*)filter_flag==0) { xf_status.filter_reset_flag=0; } } } Refresh_UI(); handle_err_code(); vTaskDelay(5000 / portTICK_PERIOD_MS); } } /** * 云端上报任务 * @param arg */ _Noreturn static void cloud_report_task(void *arg) { for (;;) { if (xSemaphoreTake(report_task_sem, portMAX_DELAY) == pdTRUE) { ESP_LOGD(TAG, "cloud report"); cJSON *data = cJSON_CreateObject(); cJSON_AddNumberToObject(data, "power", xf_status.power); cJSON_AddNumberToObject(data, "set_max_hum", xf_status.set_max_hum); cJSON_AddNumberToObject(data, "filter_life_remaining", xf_status.filter_life_remaining); cJSON_AddNumberToObject(data, "set_filter_life_time", system_setting.filter_life_time); cJSON_AddNumberToObject(data, "mode", xf_status.mode); cJSON_AddNumberToObject(data, "temperature", (int) (sht30Data.temperature)); cJSON_AddNumberToObject(data, "humidity", (int) (sht30Data.humidity)); cJSON_AddNumberToObject(data, "fan_speed", xf_status.fan_speed); cJSON_AddNumberToObject(data, "new_fan", xf_status.new_fan); cJSON_AddNumberToObject(data, "filter_change_flag", xf_status.filter_change_flag); // cJSON_AddNumberToObject(data, "timer_status", system_setting.timer_status); // cJSON_AddNumberToObject(data, "duration", system_setting.duration); cJSON *root = cJSON_CreateObject(); cJSON_AddStringToObject(root, "cmd", "status"); cJSON_AddItemToObject(root, "params", data); publish_message_t msg = { .topic = "status", .data = root, }; sparrow_publish_status(msg); } } // } _Noreturn static void report_trigger_task(void *arg) { for (;;) { if (cloud_connected) { xSemaphoreGive(report_task_sem); } vTaskDelay(pdTICKS_TO_MS(system_setting.report_data_duration * 1000)); } } /** * 云端上报任务 * @param arg */ _Noreturn static void cloud_fault_report_task(void *arg) { for (;;) { if (cloud_connected) { if (xSemaphoreTake(report_task_sem, portMAX_DELAY) == pdFALSE) { ESP_LOGD(TAG, "cloud report"); cJSON *data = cJSON_CreateArray(); cJSON *fault = cJSON_CreateObject(); for (int i = 0; i < 8; i++) { if (xf_status.js_error_code & (1 << i)) { cJSON_AddStringToObject(fault, "code", (const char *) xf_fault[i].code); cJSON_AddStringToObject(fault, "desc", (const char *) xf_fault[i].description); cJSON_AddItemToArray(data, fault); } } cJSON *root = cJSON_CreateObject(); cJSON_AddStringToObject(root, "cmd", "status"); cJSON_AddItemToObject(root, "params", data); publish_message_t msg = { .topic = "status", .data = root, }; sparrow_publish_status(msg); } vTaskDelay(60*1000 / portTICK_PERIOD_MS); } } } void xf_controller_init(system_setting_t *setting) { register_sparrow_commands(); // 注册云端指令 report_task_sem = xSemaphoreCreateBinary(); // timer_init_lx(); // 启动状态同步任务 xTaskCreate(status_sync_task, "status_sync_task", 4 * 1024, NULL, 5, &status_task_handle); xTaskCreate(Core_task, "status_sync_task", 4 * 1024, NULL, 5, &Core_task_handle); // 启动云端上报任务,受信号量控制,无信号时任务不作操作,只有本地有操作或定时上报任务触发时才会上报。 xTaskCreate(cloud_report_task, "report_task", 6 * 1024, NULL, 5, &cloud_report_handle); xTaskCreate(report_trigger_task, "trigger_task", 2 * 1024, NULL, 5, &report_trigger_handle); //故障上报 // xTaskCreate(cloud_fault_report_task, "report_task", 6 * 1024, NULL, 5, &cloud_report_handle); } void stop_xf_controller() { vTaskDelete(status_task_handle); vTaskDelete(Core_task_handle); vTaskDelete(cloud_report_handle); vTaskDelete(report_trigger_handle); // 停止modbus 协议 stack modbus_master_destroy(); }