xf_controller.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. #include <sys/cdefs.h>
  2. /**
  3. * @Author: 李建
  4. * @Date: 2025/3/25 15:23
  5. * Description: 空调控制器
  6. * Copyright: Copyright (©) 2025 永续绿建. All rights reserved.
  7. */
  8. #include <esp_log.h>
  9. #include "freertos/FreeRTOS.h"
  10. #include <freertos/task.h>
  11. #include <cJSON.h>
  12. #include <esp_timer.h>
  13. #include "xf_controller.h"
  14. #include "sub_device/command.h"
  15. #include "modbus_master.h"
  16. #include "system/miscellaneous_interface.h"
  17. #include "lvgl_port.h"
  18. #include "main.h"
  19. #include "esp_modbus_master.h"
  20. #include "mb_endianness_utils.h"
  21. #include "sht30.h"
  22. #include "gateway/access.h"
  23. static const char *TAG = "xf_controller";
  24. static uint8_t err_count_cs = 0;// 通讯失败次数
  25. static uint8_t err_count_js = 0;// 通讯失败次数
  26. static SemaphoreHandle_t report_task_sem; // 上报任务信号量,用于实现操作完成上立即上报当前状态
  27. extern void set_xf_mode(lv_ui *ui, uint16_t mode);
  28. static TaskHandle_t cloud_report_handle;
  29. static TaskHandle_t report_trigger_handle;
  30. static TaskHandle_t status_task_handle;
  31. static TaskHandle_t Core_task_handle;
  32. #define FILTER_LIFE_TIME_H_VALVE 4320//六个月,每五分钟计数加一(4320个小时)
  33. // 初始化空调参数
  34. xf_status_t xf_status = {
  35. .power= 0,
  36. .fan_speed=3,
  37. .mode=1,
  38. .filter_used_time=0,
  39. .set_max_hum=70,
  40. .filter_life_remaining=100,
  41. .js_error_code=0,
  42. };
  43. xf_fault_t xf_CSFault[]={
  44. {
  45. .code="E21",
  46. .description="混风后温度传感器异常",
  47. },
  48. {
  49. .code="E22",
  50. .description="盘管温度传感器异常",
  51. },
  52. {
  53. .code="E23",
  54. .description="排气温度传感器异常",
  55. },
  56. {
  57. .code="E24",
  58. .description="低压保护传感器异常",
  59. },
  60. {
  61. .code="E25",
  62. .description="高压保护传感器异常",
  63. },
  64. {
  65. .code="E26",
  66. .description="排风报警",
  67. },
  68. {
  69. .code="E27",
  70. .description="液位开关异常",
  71. },
  72. {
  73. .code="E28",
  74. .description="防冻保护",
  75. },
  76. {
  77. .code="E29",
  78. .description="控制器温湿度异常",
  79. },
  80. {
  81. .code="E210",
  82. .description="高温报警",
  83. },
  84. {
  85. .code="E211",
  86. .description="风机故障",
  87. },
  88. {
  89. .code="E212",
  90. .description="压缩机断开保护",
  91. },
  92. };
  93. xf_fault_t xf_fault[] = {
  94. {
  95. .code="E11",
  96. .description="传感器故障",
  97. },
  98. {
  99. .code="E12",
  100. .description="高水位故障",
  101. },
  102. {
  103. .code="E13",
  104. .description="进水电磁阀故障",
  105. },
  106. {
  107. .code="E14",
  108. .description="送风风机故障",
  109. },
  110. {
  111. .code="E15",
  112. .description="排风风机故障",
  113. },
  114. {
  115. .code="E16",
  116. .description="排水泵故障",
  117. },
  118. {
  119. .code="E17",
  120. .description="通讯故障",
  121. },
  122. };
  123. void read_xf_status(system_setting_t *setting) {
  124. uint16_t *_power = nvs_get_uint16(NVS_POWER_CONTROLLER);
  125. uint16_t *_mode = nvs_get_uint16(NVS_MODEL_CONTROLLER);
  126. uint16_t *_fan_speed = nvs_get_uint16(NVS_FAN_SPEED_SET);
  127. uint16_t *_set_hum_max = nvs_get_uint16(NVS_MAX_HUM_SET);
  128. uint16_t *_new_fan = nvs_get_uint16(NVS_NEW_FAN);
  129. xf_status.power= _power == NULL ? 0 : *_power;
  130. xf_status.mode = _mode == NULL ? 1 : *_mode;
  131. xf_status.fan_speed = _fan_speed == NULL ? 3 : *_fan_speed;
  132. xf_status.set_max_hum = _set_hum_max == NULL ? 70 : *_set_hum_max;
  133. xf_status.new_fan = _new_fan == NULL ? 1 : *_new_fan;
  134. }
  135. // 设置电源
  136. esp_err_t xf_set_power(bool saved) {
  137. esp_err_t err = ESP_OK;
  138. if(saved)
  139. nvs_set_uint16(xf_status.power, NVS_POWER_CONTROLLER);
  140. if (guider_ui.screen_main) {
  141. if(xf_status.power==0)
  142. {
  143. lvgl_port_lock(-1);
  144. lv_obj_add_flag(guider_ui.screen_main_cont_speedset, LV_OBJ_FLAG_HIDDEN);
  145. lv_obj_add_flag(guider_ui.screen_main_cont_humSet, LV_OBJ_FLAG_HIDDEN);
  146. lv_obj_add_flag(guider_ui.screen_main_cont_mode, LV_OBJ_FLAG_HIDDEN);
  147. lv_obj_add_flag(guider_ui.screen_main_imgbtn_new_fan, LV_OBJ_FLAG_HIDDEN);
  148. lvgl_port_unlock();
  149. }else{
  150. lvgl_port_lock(-1);
  151. lv_obj_clear_flag(guider_ui.screen_main_cont_speedset, LV_OBJ_FLAG_HIDDEN);
  152. lv_obj_clear_flag(guider_ui.screen_main_cont_humSet, LV_OBJ_FLAG_HIDDEN);
  153. lv_obj_clear_flag(guider_ui.screen_main_cont_mode, LV_OBJ_FLAG_HIDDEN);
  154. lv_obj_clear_flag(guider_ui.screen_main_imgbtn_new_fan, LV_OBJ_FLAG_HIDDEN);
  155. lv_label_set_text_fmt(guider_ui.screen_main_label_humSet_vul, "%d%%", xf_status.set_max_hum);
  156. lv_slider_set_value(guider_ui.screen_main_slider_speedSet_sign, xf_status.fan_speed*20, LV_ANIM_ON);
  157. lv_label_set_text_fmt(guider_ui.screen_main_label_spedSet_vul, "%d档",xf_status.fan_speed);
  158. lv_slider_set_value(guider_ui.screen_main_slider_humSet_sign, xf_status.set_max_hum, LV_ANIM_ON);
  159. set_xf_mode(&guider_ui, xf_status.mode);
  160. lvgl_port_unlock();
  161. }
  162. }
  163. if (cloud_connected) {
  164. xSemaphoreGive(report_task_sem);
  165. }
  166. return err;
  167. }
  168. esp_timer_handle_t esp_timer_handle = 0; //定时器句柄
  169. // 设置最大湿度
  170. esp_err_t xf_set_max_hum(bool saved) {
  171. esp_err_t err = ESP_OK;
  172. if(saved)
  173. nvs_set_uint16(xf_status.set_max_hum, NVS_MAX_HUM_SET);
  174. if (cloud_connected) {
  175. xSemaphoreGive(report_task_sem);
  176. }
  177. return err;
  178. }
  179. // 设置最小湿度
  180. //esp_err_t xf_set_min_hum(bool saved) {
  181. // if(saved)
  182. // nvs_set_uint16(xf_status.set_min_hum, NVS_MIN_HUM_SET);
  183. // return mm_set_param(CID_MIN_HUMIDITY, (uint8_t *)&xf_status.set_min_hum);
  184. //}
  185. //重置滤网剩余寿命
  186. void xf_set_filter_life_remain(bool saved) {
  187. xf_status.filter_reset_flag=1;
  188. }
  189. //设置手动新风
  190. esp_err_t set_new_fan(bool saved) {
  191. esp_err_t err = ESP_OK;
  192. if(saved)
  193. nvs_set_uint16(xf_status.new_fan, NVS_NEW_FAN);
  194. if (cloud_connected) {
  195. xSemaphoreGive(report_task_sem);
  196. }
  197. return err;
  198. }
  199. //设置新风风速
  200. esp_err_t xf_set_fan_speed(bool saved) {
  201. esp_err_t err = ESP_OK;
  202. if(saved)
  203. nvs_set_uint16(xf_status.fan_speed, NVS_FAN_SPEED_SET);
  204. if (cloud_connected) {
  205. xSemaphoreGive(report_task_sem);
  206. }
  207. return err;
  208. }
  209. // 设置模式
  210. esp_err_t xf_set_mode(bool saved) {
  211. esp_err_t err = ESP_OK;
  212. if(saved)
  213. nvs_set_uint16(xf_status.mode, NVS_MODEL_CONTROLLER);
  214. if (cloud_connected) {
  215. xSemaphoreGive(report_task_sem);
  216. }
  217. return err;
  218. }
  219. static void update_power_ui(bool on_off) {
  220. // 同步更新 UI
  221. if (guider_ui.screen_main) {
  222. lvgl_port_lock(-1);
  223. lv_obj_set_state(guider_ui.screen_main_imgbtn_power, LV_IMAGEBUTTON_STATE_CHECKED_RELEASED, on_off);
  224. lvgl_port_unlock();
  225. }
  226. }
  227. // 云端: 设置上报时间间隔
  228. static void cloud_set_report_duration(char *params) {
  229. cJSON *data = cJSON_Parse(params);
  230. if (data != NULL) {
  231. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  232. if (cJSON_IsNumber(value)) {
  233. system_setting.report_data_duration = value->valueint;
  234. save_system_setting(&system_setting);
  235. }
  236. }
  237. }
  238. static void cloud_set_power(char *params) {
  239. cJSON *data = cJSON_Parse(params);
  240. if (data != NULL) {
  241. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  242. xf_status.power = value->valueint;
  243. xf_set_power(true);
  244. update_power_ui(xf_status.power);
  245. cJSON_Delete(data);
  246. }
  247. }
  248. static void cloud_set_max_hum(char *params) {
  249. cJSON *data = cJSON_Parse(params);
  250. if (data != NULL) {
  251. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  252. if((value->valueint<=70)&&(value->valueint>=system_setting.set_min_hum))
  253. {
  254. xf_status.set_max_hum = value->valueint;
  255. if (guider_ui.screen_main) {
  256. lvgl_port_lock(-1);
  257. lv_label_set_text_fmt(guider_ui.screen_main_label_humSet_vul, "%d%%", xf_status.set_max_hum);
  258. lv_slider_set_value(guider_ui.screen_main_slider_humSet_sign, xf_status.set_max_hum,LV_ANIM_OFF);
  259. lvgl_port_unlock();
  260. }
  261. xf_set_max_hum(true);
  262. }
  263. cJSON_Delete(data);
  264. }
  265. }
  266. static void cloud_set_mode(char *params) {
  267. cJSON *data = cJSON_Parse(params);
  268. if (data != NULL) {
  269. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  270. xf_status.mode = value->valueint;
  271. if (guider_ui.screen_main) {
  272. lvgl_port_lock(-1);
  273. set_xf_mode(&guider_ui, xf_status.mode);
  274. lvgl_port_unlock();
  275. }
  276. xf_set_mode(true);
  277. cJSON_Delete(data);
  278. }
  279. }
  280. static void cloud_set_fan_level(char *params) {
  281. cJSON *data = cJSON_Parse(params);
  282. if (data != NULL) {
  283. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  284. xf_status.fan_speed = value->valueint;
  285. if (guider_ui.screen_main) {
  286. lvgl_port_lock(-1);
  287. lv_slider_set_value(guider_ui.screen_main_slider_speedSet_sign, xf_status.fan_speed*30, LV_ANIM_ON);
  288. lv_label_set_text_fmt(guider_ui.screen_main_label_spedSet_vul, "%d档",xf_status.fan_speed);
  289. lvgl_port_unlock();
  290. }
  291. xf_set_fan_speed(true);
  292. cJSON_Delete(data);
  293. }
  294. }
  295. static void cloud_set_filter_life(char *params) {
  296. cJSON *data = cJSON_Parse(params);
  297. if (data != NULL) {
  298. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  299. system_setting.filter_life_time = value->valueint;
  300. save_system_setting(&system_setting);
  301. cJSON_Delete(data);
  302. }
  303. }
  304. static void cloud_reset_filter_life_remain(char *params) {
  305. cJSON *data = cJSON_Parse(params);
  306. if (data != NULL) {
  307. xf_status.filter_used_time=0;
  308. xf_set_filter_life_remain(true);
  309. cJSON_Delete(data);
  310. }
  311. }
  312. static void cloud_set_new_fan(char *params) {
  313. cJSON *data = cJSON_Parse(params);
  314. if (data != NULL) {
  315. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  316. xf_status.new_fan = value->valueint;
  317. if (guider_ui.screen_main) {
  318. lvgl_port_lock(-1);
  319. if(xf_status.new_fan==2)
  320. {
  321. lv_obj_add_state(guider_ui.screen_main_imgbtn_new_fan,LV_STATE_CHECKED);
  322. }else{
  323. lv_obj_remove_state(guider_ui.screen_main_imgbtn_new_fan,LV_STATE_CHECKED);
  324. }
  325. lvgl_port_unlock();
  326. }
  327. set_new_fan(true);
  328. cJSON_Delete(data);
  329. }
  330. }
  331. static void cloud_set_min_hum(char *params) {
  332. }
  333. //注册云端指令s
  334. void register_sparrow_commands(void) {
  335. sparrow_command set_power_cmd = {
  336. .name = "setPower",
  337. .unpack = &cloud_set_power
  338. };
  339. register_sparrow_command(set_power_cmd);
  340. sparrow_command set_max_hum_cmd = {
  341. .name = "setMaxHum",
  342. .unpack = &cloud_set_max_hum
  343. };
  344. register_sparrow_command(set_max_hum_cmd);
  345. // setMode
  346. sparrow_command set_mode_cmd = {
  347. .name = "setMode",
  348. .unpack = &cloud_set_mode
  349. };
  350. register_sparrow_command(set_mode_cmd);
  351. // setFanLevel
  352. sparrow_command set_fan_level_cmd = {
  353. .name = "setFanLevel",
  354. .unpack = &cloud_set_fan_level,
  355. };
  356. register_sparrow_command(set_fan_level_cmd);
  357. // setNewFan
  358. sparrow_command set_filter_life_cmd = {
  359. .name = "setFilterLife",
  360. .unpack = &cloud_set_filter_life,
  361. }; register_sparrow_command(set_filter_life_cmd);
  362. sparrow_command set_new_fan_cmd = {
  363. .name = "setNewFan",
  364. .unpack = &cloud_set_new_fan,
  365. };
  366. register_sparrow_command(set_new_fan_cmd);
  367. // setFanVoltage
  368. sparrow_command set_min_hum_cmd = {
  369. .name = "setMinHumCmd",
  370. .unpack = &cloud_set_min_hum,
  371. };
  372. register_sparrow_command(set_min_hum_cmd);
  373. sparrow_command set_duration = {
  374. .name = "setReportDuration",
  375. .unpack = &cloud_set_report_duration
  376. };
  377. register_sparrow_command(set_duration);
  378. sparrow_command reset_filter_life_remain = {
  379. .name = "setReportDuration",
  380. .unpack = &cloud_reset_filter_life_remain
  381. };
  382. register_sparrow_command(reset_filter_life_remain);
  383. }
  384. LV_IMAGE_DECLARE(_power_open_RGB565A8_36x36);
  385. LV_IMAGE_DECLARE(_liang_RGB565A8_30x30);
  386. LV_IMAGE_DECLARE(_cha_RGB565A8_30x30);
  387. /**
  388. * TODO:处理风故障信息
  389. */
  390. void handle_err_code()
  391. {
  392. uint8_t error_code[2] = {0};
  393. esp_err_t err = ESP_OK;
  394. err = mm_get_param(CID_JS_ERROR_CODE, error_code);
  395. if (err == ESP_OK) {
  396. xf_status.js_error_code=(uint8_t)(*(uint16_t *)error_code&0x0ff);
  397. }
  398. vTaskDelay(pdTICKS_TO_MS(200));
  399. err = mm_get_param(CID_CS_ERROR_CODE, error_code);
  400. if (err == ESP_OK)
  401. {
  402. xf_status.cs_error_code=(uint8_t)(*(uint16_t *)error_code&0x0ff);
  403. }
  404. if (guider_ui.screen_main)
  405. {
  406. if(((xf_status.cs_error_code&0x07ff)==0)&&(xf_status.js_error_code&0x00ff)==0)
  407. {
  408. lvgl_port_lock(-1);
  409. lv_obj_add_flag(guider_ui.screen_main_lab_err, LV_OBJ_FLAG_HIDDEN);
  410. lvgl_port_unlock();
  411. } else{
  412. lvgl_port_lock(-1);
  413. lv_obj_clear_flag(guider_ui.screen_main_lab_err, LV_OBJ_FLAG_HIDDEN);
  414. lvgl_port_unlock();
  415. }
  416. }
  417. }
  418. void Refresh_UI()
  419. {
  420. uint8_t type = PARAM_TYPE_U16;
  421. uint8_t temp_data[2] = {0}, filter_data[2] = {0};// temporary buffer to hold maximum CID size
  422. uint16_t temp_data_u16 = 500;
  423. esp_err_t err = ESP_OK;
  424. err = mm_get_param(CID_CS_INEFFICIENT_FILTER_SIGN, filter_data);
  425. if (err == ESP_OK) {
  426. err_count_cs = 0;
  427. if (guider_ui.screen_main) {
  428. lvgl_port_lock(-1);
  429. lv_obj_add_flag(guider_ui.screen_main_lab_485_err, LV_OBJ_FLAG_HIDDEN);
  430. lvgl_port_unlock();
  431. }
  432. } else {
  433. err_count_cs++;
  434. if (err_count_cs >= 254)
  435. err_count_cs = 30;
  436. }
  437. if (err_count_cs >= 30) {
  438. if (guider_ui.screen_main) {
  439. lvgl_port_lock(-1);
  440. lv_obj_remove_flag(guider_ui.screen_main_lab_485_err, LV_OBJ_FLAG_HIDDEN);
  441. lvgl_port_unlock();
  442. }
  443. }
  444. err = ESP_OK;
  445. vTaskDelay(pdTICKS_TO_MS(200));
  446. err = mm_get_param(CID_JS_POWER, temp_data);
  447. if (err == ESP_OK) {
  448. err_count_js = 0;
  449. if (guider_ui.screen_main) {
  450. lvgl_port_lock(-1);
  451. lv_obj_add_flag(guider_ui.screen_main_lab_485_err_js, LV_OBJ_FLAG_HIDDEN);
  452. lvgl_port_unlock();
  453. }
  454. } else {
  455. err_count_js++;
  456. if (err_count_js >= 254)
  457. err_count_js = 30;
  458. }
  459. if (err_count_js >= 30) {
  460. if (guider_ui.screen_main) {
  461. lvgl_port_lock(-1);
  462. lv_obj_remove_flag(guider_ui.screen_main_lab_485_err_js, LV_OBJ_FLAG_HIDDEN);
  463. lvgl_port_unlock();
  464. }
  465. }
  466. // ESP_LOGE(TAG, "filter_life_remaining%d",xf_status.filter_life_remaining);
  467. xf_status.filter_life_remaining=100*(system_setting.filter_life_time-xf_status.filter_used_time)/system_setting.filter_life_time;
  468. if (guider_ui.screen_main) {
  469. lvgl_port_lock(-1);
  470. lv_arc_set_value(guider_ui.screen_main_arc_hum,(int)sht30Data.humidity);
  471. if (filter_data[1]+filter_data[0]==1) {
  472. lv_obj_remove_flag(guider_ui.screen_main_label_filter_error, LV_OBJ_FLAG_HIDDEN);
  473. }else {
  474. lv_obj_add_flag(guider_ui.screen_main_label_filter_error, LV_OBJ_FLAG_HIDDEN);
  475. }
  476. lvgl_port_unlock();
  477. }
  478. if (xf_status.proof_mode==1) {
  479. lv_obj_remove_flag(guider_ui.screen_main_img_proof,LV_OBJ_FLAG_HIDDEN);
  480. }else {
  481. lv_obj_add_flag(guider_ui.screen_main_img_proof,LV_OBJ_FLAG_HIDDEN);
  482. }
  483. }
  484. static uint8_t auto_switch_flag=0;
  485. /*
  486. * 自动模式下控制,十度
  487. */
  488. void xf_auto_task(void *arg) {
  489. if (auto_switch_flag==0) {
  490. if (xf_status.set_max_hum>(int)sht30Data.humidity) {
  491. auto_switch_flag=1;
  492. if (xf_status.new_fan==2) {
  493. xf_status.xfcs_status.mode=XFCS_XF;
  494. }else {
  495. xf_status.xfcs_status.mode=XFCS_NXH;
  496. }
  497. xf_status.js_module_status.power=1;
  498. xf_status.js_module_status.mode=JS_JS;
  499. }else if (xf_status.set_max_hum<(int)sht30Data.humidity){
  500. auto_switch_flag=1;
  501. if (xf_status.new_fan==2) {
  502. xf_status.xfcs_status.mode=XFCS_XFCS;
  503. }else {
  504. xf_status.xfcs_status.mode=XFCS_NXHCS;
  505. }
  506. xf_status.js_module_status.power=0;
  507. }else {
  508. auto_switch_flag=0;
  509. }
  510. }else {
  511. if ((int)sht30Data.humidity-xf_status.set_max_hum>5) {
  512. //CS模式
  513. if (xf_status.new_fan==2) {
  514. xf_status.xfcs_status.mode=XFCS_XFCS;
  515. }else {
  516. xf_status.xfcs_status.mode=XFCS_NXHCS;
  517. }
  518. xf_status.js_module_status.power=0;
  519. }else if(xf_status.set_max_hum-(int)sht30Data.humidity>5) {
  520. //JS模式
  521. if (xf_status.new_fan==2) {
  522. xf_status.xfcs_status.mode=XFCS_XF;
  523. }else {
  524. xf_status.xfcs_status.mode=XFCS_NXH;
  525. }
  526. xf_status.js_module_status.mode=JS_JS;
  527. xf_status.js_module_status.power=1;
  528. }else {
  529. //
  530. }
  531. }
  532. 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"
  533. ,xf_status.js_module_status.power,xf_status.js_module_status.mode,xf_status.js_module_status.set_max_hum);
  534. }
  535. uint8_t humidification_mode_end_flag=0;
  536. uint32_t humidification_mode_end_acc=0;
  537. uint8_t humidification_mode_flag=0;
  538. uint32_t humidification_mode_acc=0;
  539. uint8_t auto_mould_proof_acc=0;
  540. // 防霉运行模式开始
  541. void mould_proof_mode_start() {
  542. //显示防霉标志
  543. //新风除湿开启内循环模式
  544. xf_status.xfcs_status.mode = XFCS_NXH;
  545. //新风除湿开机
  546. xf_status.xfcs_status.power = 1;
  547. xf_status.xfcs_status.fan_speed = 1;
  548. }
  549. // 防霉运行模式结束
  550. void mould_proof_mode_stop() {
  551. humidification_mode_end_flag = 0;
  552. auto_mould_proof_acc = 0;
  553. humidification_mode_end_acc = 0;
  554. humidification_mode_flag = 0;
  555. // 恢复工作模式为正常模式
  556. }
  557. // 防霉运行模式检测
  558. void mould_proof_mode_check() { // 如果加湿功能正常开启且当前是关闭状态,开始累加,开启防霉运行功能
  559. if (humidification_mode_flag == 1) {
  560. // 启动防霉后多长时间,结束防霉
  561. if (++auto_mould_proof_acc >= system_setting.mould_proof_runtime * 60) {
  562. ESP_LOGE(TAG,"proof stop!!!/\r\n");
  563. mould_proof_mode_stop();
  564. xf_status.proof_mode=0;
  565. humidification_mode_flag=0;
  566. }else {
  567. ESP_LOGE(TAG,"proof start!!!/\r\n");
  568. ESP_LOGE(TAG,"mould_proof_runtime:%d \r\n",system_setting.mould_proof_runtime);
  569. mould_proof_mode_start();
  570. xf_status.proof_mode=1;
  571. }
  572. }else {
  573. xf_status.proof_mode=0;
  574. xf_status.xfcs_status .power=0;
  575. xf_status.js_module_status.power=0;
  576. }
  577. }
  578. static uint8_t js_mode_flag=0;
  579. _Noreturn static void Core_task(void *arg) {
  580. esp_err_t err = ESP_OK;
  581. for (;;) {
  582. if (xf_status.power==1) {
  583. xf_status.proof_mode=0;
  584. xf_status.xfcs_status.set_hum=xf_status.set_max_hum;
  585. xf_status.js_module_status.set_max_hum=xf_status.set_max_hum;
  586. 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;
  587. switch (xf_status.mode) {
  588. case CS:
  589. if (xf_status.new_fan==2) {
  590. xf_status.xfcs_status.mode=XFCS_XFCS;
  591. }else {
  592. xf_status.xfcs_status.mode=XFCS_NXHCS;
  593. }
  594. if (xf_status.set_max_hum-(int)sht30Data.humidity>10) {
  595. //达标 停止除湿
  596. xf_status.xfcs_status .power=0;
  597. }else if (xf_status.set_max_hum<(int)sht30Data.humidity){
  598. //未达标开始除湿
  599. xf_status.xfcs_status .power=1;
  600. }else {
  601. //保持原先状态不变
  602. }
  603. xf_status.js_module_status.power=0;
  604. break;
  605. case JS:
  606. if (xf_status.new_fan==2) {
  607. xf_status.xfcs_status.mode=XFCS_XF;
  608. }else {
  609. xf_status.xfcs_status.mode=XFCS_NXH;
  610. }
  611. if ((int)sht30Data.humidity-xf_status.set_max_hum>10) {
  612. js_mode_flag=1;
  613. //达标 停止加湿
  614. xf_status.xfcs_status .power=0;
  615. xf_status.js_module_status.power=0;
  616. }else if ((int)sht30Data.humidity<xf_status.set_max_hum){
  617. //未达标开始加湿
  618. xf_status.xfcs_status .power=1;
  619. xf_status.js_module_status.power=1;
  620. if (humidification_mode_flag==0) {
  621. humidification_mode_acc++;
  622. }
  623. // if (humidification_mode_acc>(60)) {//测试
  624. if (humidification_mode_acc>(60*20)) {
  625. humidification_mode_flag=1;
  626. humidification_mode_end_acc=0;
  627. }
  628. }else {
  629. //当环境湿度大于设置湿度,且环境湿度
  630. //保持原先状态不变
  631. }
  632. xf_status.js_module_status.mode=JS_JS;
  633. break;
  634. case SF:
  635. auto_switch_flag=0;
  636. if (xf_status.new_fan==2) {
  637. xf_status.xfcs_status.mode=XFCS_XF;
  638. }else {
  639. xf_status.xfcs_status.mode=XFCS_NXH;
  640. }
  641. xf_status.xfcs_status .power=1;
  642. xf_status.js_module_status.power=0;
  643. break;
  644. // case AUTO:
  645. // // xf_auto_task(arg);
  646. break;
  647. }
  648. }else {
  649. mould_proof_mode_check();
  650. }
  651. xf_status.xfcs_status.fan_speed=xf_status.fan_speed;
  652. switch (xf_status.fan_speed) {
  653. case 1:
  654. xf_status.js_module_status.fan_speed=1;
  655. break;
  656. case 2:
  657. xf_status.js_module_status.fan_speed=3;
  658. break;
  659. case 3:
  660. xf_status.js_module_status.fan_speed=5;
  661. break;
  662. default:
  663. xf_status.js_module_status.fan_speed=1;
  664. break;
  665. }
  666. xf_status.xfcs_status.set_hum=xf_status.set_max_hum;
  667. vTaskDelay(1000 / portTICK_PERIOD_MS);
  668. }
  669. }
  670. /**
  671. * 状态同步任务,主要用于与分风箱主控同步当前用户的参数,并处理通讯故障
  672. * @param arg
  673. */
  674. _Noreturn static void status_sync_task(void *arg) {
  675. esp_err_t err = ESP_OK;
  676. uint16_t filter_reset=0x5AA5;
  677. uint8_t filter_flag[2] = {0};
  678. for (;;) {
  679. mm_set_param(CID_CS_POWER, (uint8_t *)&xf_status.xfcs_status.power);
  680. vTaskDelay(pdTICKS_TO_MS(100));
  681. mm_set_param(CID_JS_POWER, (uint8_t *)&xf_status.js_module_status.power);
  682. vTaskDelay(pdTICKS_TO_MS(100));
  683. mm_set_param(CID_CS_MODE, (uint8_t *)&xf_status.xfcs_status.mode);
  684. vTaskDelay(pdTICKS_TO_MS(100));
  685. mm_set_param(CID_JS_MODE, (uint8_t *)&xf_status.js_module_status.mode);
  686. vTaskDelay(pdTICKS_TO_MS(100));
  687. mm_set_param(CID_CS_FAN_SPEED, (uint8_t *)&xf_status.fan_speed);
  688. vTaskDelay(pdTICKS_TO_MS(100));
  689. mm_set_param(CID_JS_FAN_SPEED, (uint8_t *)&xf_status.js_module_status.fan_speed);
  690. vTaskDelay(pdTICKS_TO_MS(100));
  691. mm_set_param(CID_JS_MAX_HUMIDITY, (uint8_t *)&xf_status.js_module_status.set_max_hum);
  692. vTaskDelay(pdTICKS_TO_MS(100));
  693. mm_set_param(CID_JS_MIN_HUMIDITY, (uint8_t *)&xf_status.js_module_status.set_min_hum);
  694. vTaskDelay(pdTICKS_TO_MS(100));
  695. mm_set_param(CID_CS_SET_HUMIDITY, (uint8_t *)&xf_status.xfcs_status.set_hum);
  696. vTaskDelay(pdTICKS_TO_MS(100));
  697. mm_set_param(CID_CS_INEFFICIENT_FILTER_SET_TIME, (uint8_t *)&system_setting.filter_life_time);
  698. vTaskDelay(pdTICKS_TO_MS(100));
  699. mm_set_param(CID_CS_HEPA_FILTER_SET_TIME, (uint8_t *)&system_setting.filter_life_time);
  700. vTaskDelay(pdTICKS_TO_MS(100));
  701. if (xf_status.filter_reset_flag==1) {
  702. mm_set_param(CID_CS_INEFFICIENT_FILTER_RESET, (uint8_t *)&filter_reset);
  703. vTaskDelay(pdTICKS_TO_MS(100));
  704. mm_set_param(CID_CS_HEPA_FILTER_RESET, (uint8_t *)&filter_reset);
  705. vTaskDelay(pdTICKS_TO_MS(100));
  706. err=mm_get_param(CID_CS_INEFFICIENT_FILTER_RESET, filter_flag);
  707. if (err==ESP_OK) {
  708. if (*(uint16_t*)filter_flag==0) {
  709. xf_status.filter_reset_flag=0;
  710. }
  711. }
  712. }
  713. Refresh_UI();
  714. handle_err_code();
  715. vTaskDelay(5000 / portTICK_PERIOD_MS);
  716. }
  717. }
  718. /**
  719. * 云端上报任务
  720. * @param arg
  721. */
  722. _Noreturn static void cloud_report_task(void *arg) {
  723. for (;;) {
  724. if (xSemaphoreTake(report_task_sem, portMAX_DELAY) == pdTRUE) {
  725. ESP_LOGD(TAG, "cloud report");
  726. cJSON *data = cJSON_CreateObject();
  727. cJSON_AddNumberToObject(data, "power", xf_status.power);
  728. cJSON_AddNumberToObject(data, "set_max_hum", xf_status.set_max_hum);
  729. cJSON_AddNumberToObject(data, "filter_life_remaining", xf_status.filter_life_remaining);
  730. cJSON_AddNumberToObject(data, "set_filter_life_time", system_setting.filter_life_time);
  731. cJSON_AddNumberToObject(data, "mode", xf_status.mode);
  732. cJSON_AddNumberToObject(data, "temperature", (int) (sht30Data.temperature));
  733. cJSON_AddNumberToObject(data, "humidity", (int) (sht30Data.humidity));
  734. cJSON_AddNumberToObject(data, "fan_speed", xf_status.fan_speed);
  735. cJSON_AddNumberToObject(data, "new_fan", xf_status.new_fan);
  736. cJSON_AddNumberToObject(data, "filter_change_flag", xf_status.filter_change_flag);
  737. // cJSON_AddNumberToObject(data, "timer_status", system_setting.timer_status);
  738. // cJSON_AddNumberToObject(data, "duration", system_setting.duration);
  739. cJSON *root = cJSON_CreateObject();
  740. cJSON_AddStringToObject(root, "cmd", "status");
  741. cJSON_AddItemToObject(root, "params", data);
  742. publish_message_t msg = {
  743. .topic = "status",
  744. .data = root,
  745. };
  746. sparrow_publish_status(msg);
  747. }
  748. }
  749. //
  750. }
  751. _Noreturn static void report_trigger_task(void *arg) {
  752. for (;;) {
  753. if (cloud_connected) {
  754. xSemaphoreGive(report_task_sem);
  755. }
  756. vTaskDelay(pdTICKS_TO_MS(system_setting.report_data_duration * 1000));
  757. }
  758. }
  759. /**
  760. * 云端上报任务
  761. * @param arg
  762. */
  763. _Noreturn static void cloud_fault_report_task(void *arg) {
  764. for (;;) {
  765. if (cloud_connected) {
  766. if (xSemaphoreTake(report_task_sem, portMAX_DELAY) == pdFALSE) {
  767. ESP_LOGD(TAG, "cloud report");
  768. cJSON *data = cJSON_CreateArray();
  769. cJSON *fault = cJSON_CreateObject();
  770. for (int i = 0; i < 8; i++) {
  771. if (xf_status.js_error_code & (1 << i)) {
  772. cJSON_AddStringToObject(fault, "code", (const char *) xf_fault[i].code);
  773. cJSON_AddStringToObject(fault, "desc", (const char *) xf_fault[i].description);
  774. cJSON_AddItemToArray(data, fault);
  775. }
  776. }
  777. cJSON *root = cJSON_CreateObject();
  778. cJSON_AddStringToObject(root, "cmd", "status");
  779. cJSON_AddItemToObject(root, "params", data);
  780. publish_message_t msg = {
  781. .topic = "status",
  782. .data = root,
  783. };
  784. sparrow_publish_status(msg);
  785. }
  786. vTaskDelay(60*1000 / portTICK_PERIOD_MS);
  787. }
  788. }
  789. }
  790. void xf_controller_init(system_setting_t *setting) {
  791. register_sparrow_commands(); // 注册云端指令
  792. report_task_sem = xSemaphoreCreateBinary();
  793. // timer_init_lx();
  794. // 启动状态同步任务
  795. xTaskCreate(status_sync_task, "status_sync_task", 4 * 1024, NULL, 5, &status_task_handle);
  796. xTaskCreate(Core_task, "status_sync_task", 4 * 1024, NULL, 5, &Core_task_handle);
  797. // 启动云端上报任务,受信号量控制,无信号时任务不作操作,只有本地有操作或定时上报任务触发时才会上报。
  798. xTaskCreate(cloud_report_task, "report_task", 6 * 1024, NULL, 5, &cloud_report_handle);
  799. xTaskCreate(report_trigger_task, "trigger_task", 2 * 1024, NULL, 5, &report_trigger_handle);
  800. //故障上报
  801. // xTaskCreate(cloud_fault_report_task, "report_task", 6 * 1024, NULL, 5, &cloud_report_handle);
  802. }
  803. void stop_xf_controller() {
  804. vTaskDelete(status_task_handle);
  805. vTaskDelete(Core_task_handle);
  806. vTaskDelete(cloud_report_handle);
  807. vTaskDelete(report_trigger_handle);
  808. // 停止modbus 协议 stack
  809. modbus_master_destroy();
  810. }