xf_controller.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  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 = 0;// 通讯失败次数
  25. static SemaphoreHandle_t report_task_sem; // 上报任务信号量,用于实现操作完成上立即上报当前状态
  26. extern void set_xf_mode(lv_ui *ui, uint16_t mode);
  27. static TaskHandle_t cloud_report_handle;
  28. static TaskHandle_t report_trigger_handle;
  29. static TaskHandle_t status_task_handle;
  30. // 初始化空调参数
  31. xf_status_t xf_status = {
  32. .power= 0,
  33. .fan_speed=3,
  34. .mode=1,
  35. .filter_used_time=0,
  36. .set_max_hum=70,
  37. .filter_life_remaining=100,
  38. .error_code=0,
  39. };
  40. xf_fault_t xf_fault[9] = {
  41. {
  42. .code="E1",
  43. .description="传感器故障",
  44. },
  45. {
  46. .code="E2",
  47. .description="高水位故障",
  48. },
  49. {
  50. .code="E3",
  51. .description="进水电磁阀故障",
  52. },
  53. {
  54. .code="E4",
  55. .description="送风风机故障",
  56. },
  57. {
  58. .code="E5",
  59. .description="排风风机故障",
  60. },
  61. {
  62. .code="E6",
  63. .description="排水泵故障",
  64. },
  65. {
  66. .code="E7",
  67. .description="通讯故障",
  68. },
  69. {
  70. .code="E8",
  71. .description="预留",
  72. }
  73. };
  74. void read_xf_status(system_setting_t *setting) {
  75. uint16_t *_power = nvs_get_uint16(NVS_POWER_CONTROLLER);
  76. uint16_t *_mode = nvs_get_uint16(NVS_MODEL_CONTROLLER);
  77. uint16_t *_fan_speed = nvs_get_uint16(NVS_FAN_SPEED_SET);
  78. uint16_t *_filter_used_time = nvs_get_uint16(NVS_FILTER_USED_TIME);
  79. uint16_t *_set_hum_max = nvs_get_uint16(NVS_MAX_HUM_SET);
  80. // uint16_t *_set_hum_min = nvs_get_uint16(NVS_MIN_HUM_SET);
  81. xf_status.power= _power == NULL ? 0 : *_power;
  82. xf_status.mode = _mode == NULL ? 1 : *_mode;
  83. xf_status.fan_speed = _fan_speed == NULL ? 3 : *_fan_speed;
  84. xf_status.filter_used_time = _filter_used_time == NULL ? 0 : *_filter_used_time;
  85. xf_status.set_max_hum = _set_hum_max == NULL ? 70 : *_set_hum_max;
  86. }
  87. // 设置电源
  88. esp_err_t xf_set_power(bool saved) {
  89. esp_err_t err = ESP_OK;
  90. if(saved)
  91. nvs_set_uint16(xf_status.power, NVS_POWER_CONTROLLER);
  92. if (guider_ui.screen_main) {
  93. if(xf_status.power==0)
  94. {
  95. lvgl_port_lock(-1);
  96. lv_obj_add_flag(guider_ui.screen_main_cont_speedset, LV_OBJ_FLAG_HIDDEN);
  97. lv_obj_add_flag(guider_ui.screen_main_cont_humSet, LV_OBJ_FLAG_HIDDEN);
  98. lv_obj_add_flag(guider_ui.screen_main_cont_mode, LV_OBJ_FLAG_HIDDEN);
  99. lvgl_port_unlock();
  100. }else{
  101. lvgl_port_lock(-1);
  102. lv_obj_clear_flag(guider_ui.screen_main_cont_speedset, LV_OBJ_FLAG_HIDDEN);
  103. lv_obj_clear_flag(guider_ui.screen_main_cont_humSet, LV_OBJ_FLAG_HIDDEN);
  104. lv_obj_clear_flag(guider_ui.screen_main_cont_mode, LV_OBJ_FLAG_HIDDEN);
  105. lv_label_set_text_fmt(guider_ui.screen_main_label_humSet_vul, "%d%%", xf_status.set_max_hum);
  106. lv_slider_set_value(guider_ui.screen_main_slider_speedSet_sign, xf_status.fan_speed*20, LV_ANIM_ON);
  107. lv_label_set_text_fmt(guider_ui.screen_main_label_spedSet_vul, "%d档",xf_status.fan_speed);
  108. lv_slider_set_value(guider_ui.screen_main_slider_humSet_sign, xf_status.set_max_hum, LV_ANIM_ON);
  109. set_xf_mode(&guider_ui, xf_status.mode);
  110. lvgl_port_unlock();
  111. }
  112. }
  113. if (cloud_connected) {
  114. xSemaphoreGive(report_task_sem);
  115. }
  116. return err;
  117. }
  118. void esp_timer_cb()
  119. {
  120. if(xf_status.power==1)
  121. {
  122. xf_status.filter_used_time++;
  123. }else{
  124. }
  125. if(xf_status.filter_used_time>=system_setting.filter_life_time)
  126. {
  127. xf_status.filter_used_time=system_setting.filter_life_time;
  128. }
  129. xf_set_filter_life_remain(true);
  130. }
  131. esp_timer_handle_t esp_timer_handle = 0; //定时器句柄
  132. void timer_init_lx() {
  133. //定时器结构体初始化
  134. esp_timer_create_args_t fw_timer = {
  135. .callback = &esp_timer_cb, //定时器回调函数
  136. .arg = NULL, //传递给回调函数的参数
  137. .name = "esp_timer", //定时器名称
  138. };
  139. //创建定时器
  140. esp_timer_create(&fw_timer, &esp_timer_handle);
  141. //启动定时器,定时器周期为60*5秒
  142. esp_timer_start_periodic(esp_timer_handle, 5*60000 * 1000);
  143. // esp_timer_start_periodic(esp_timer_handle, 5000 * 1000);
  144. }
  145. // 设置最大湿度
  146. esp_err_t xf_set_max_hum(bool saved) {
  147. esp_err_t err = ESP_OK;
  148. if(saved)
  149. nvs_set_uint16(xf_status.set_max_hum, NVS_MAX_HUM_SET);
  150. if (cloud_connected) {
  151. xSemaphoreGive(report_task_sem);
  152. }
  153. return err;
  154. }
  155. // 设置最小湿度
  156. //esp_err_t xf_set_min_hum(bool saved) {
  157. // if(saved)
  158. // nvs_set_uint16(xf_status.set_min_hum, NVS_MIN_HUM_SET);
  159. // return mm_set_param(CID_MIN_HUMIDITY, (uint8_t *)&xf_status.set_min_hum);
  160. //}
  161. //设置滤网剩余寿命
  162. void xf_set_filter_life_remain(bool saved) {
  163. esp_err_t str=ESP_OK;
  164. if(saved)
  165. nvs_set_uint16(xf_status.filter_used_time, NVS_FILTER_USED_TIME);
  166. }
  167. //设置新风风速
  168. esp_err_t xf_set_fan_speed(bool saved) {
  169. esp_err_t err = ESP_OK;
  170. if(saved)
  171. nvs_set_uint16(xf_status.fan_speed, NVS_FAN_SPEED_SET);
  172. if (cloud_connected) {
  173. xSemaphoreGive(report_task_sem);
  174. }
  175. return err;
  176. }
  177. // 设置模式
  178. esp_err_t xf_set_mode(bool saved) {
  179. esp_err_t err = ESP_OK;
  180. if(saved)
  181. nvs_set_uint16(xf_status.mode, NVS_MODEL_CONTROLLER);
  182. if (cloud_connected) {
  183. xSemaphoreGive(report_task_sem);
  184. }
  185. return err;
  186. }
  187. static void update_power_ui(bool on_off) {
  188. // 同步更新 UI
  189. if (guider_ui.screen_main) {
  190. lvgl_port_lock(-1);
  191. lv_obj_set_state(guider_ui.screen_main_imgbtn_power, LV_IMAGEBUTTON_STATE_CHECKED_RELEASED, on_off);
  192. lvgl_port_unlock();
  193. }
  194. }
  195. esp_err_t set_exhaust_fan_vol(uint8_t gear, uint8_t *value)
  196. {
  197. uint16_t addr = CID_AIR_EXHAUST_FIRST_VOL;
  198. switch (gear) {
  199. case 1:
  200. addr = CID_AIR_EXHAUST_FIRST_VOL;
  201. break;
  202. case 2:
  203. addr = CID_AIR_EXHAUST_SECOND_VOL;
  204. break;
  205. case 3:
  206. addr = CID_AIR_EXHAUST_THIRD_VOL;
  207. break;
  208. case 4:
  209. addr = CID_AIR_EXHAUST_FOURTH_VOL;
  210. break;
  211. case 5:
  212. addr = CID_AIR_EXHAUST_FIFTH_VOL;
  213. break;
  214. default:
  215. break;
  216. }
  217. return mm_set_param(addr, value);
  218. }
  219. esp_err_t set_supply_fan_vol(uint8_t gear, uint8_t *value)
  220. {
  221. uint16_t addr = CID_AIR_SUPPLY_FIRST_VOL;
  222. switch (gear) {
  223. case 1:
  224. addr = CID_AIR_SUPPLY_FIRST_VOL;
  225. break;
  226. case 2:
  227. addr = CID_AIR_SUPPLY_SECOND_VOL;
  228. break;
  229. case 3:
  230. addr = CID_AIR_SUPPLY_THIRD_VOL;
  231. break;
  232. case 4:
  233. addr = CID_AIR_SUPPLY_FOURTH_VOL;
  234. break;
  235. case 5:
  236. addr = CID_AIR_SUPPLY_FIFTH_VOL;
  237. break;
  238. default:
  239. break;
  240. }
  241. return mm_set_param(addr, value);
  242. }
  243. // 云端: 设置上报时间间隔
  244. static void cloud_set_report_duration(char *params) {
  245. cJSON *data = cJSON_Parse(params);
  246. if (data != NULL) {
  247. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  248. if (cJSON_IsNumber(value)) {
  249. system_setting.report_data_duration = value->valueint;
  250. save_system_setting(&system_setting);
  251. }
  252. }
  253. }
  254. static void cloud_set_power(char *params) {
  255. cJSON *data = cJSON_Parse(params);
  256. if (data != NULL) {
  257. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  258. xf_status.power = value->valueint;
  259. xf_set_power(true);
  260. update_power_ui(xf_status.power);
  261. cJSON_Delete(data);
  262. }
  263. }
  264. static void cloud_set_max_hum(char *params) {
  265. cJSON *data = cJSON_Parse(params);
  266. if (data != NULL) {
  267. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  268. if((value->valueint<=70)&&(value->valueint>=system_setting.set_min_hum))
  269. {
  270. xf_status.set_max_hum = value->valueint;
  271. if (guider_ui.screen_main) {
  272. lvgl_port_lock(-1);
  273. lv_label_set_text_fmt(guider_ui.screen_main_label_humSet_vul, "%d%%", xf_status.set_max_hum);
  274. lv_slider_set_value(guider_ui.screen_main_slider_humSet_sign, xf_status.set_max_hum,LV_ANIM_OFF);
  275. lvgl_port_unlock();
  276. }
  277. xf_set_max_hum(true);
  278. }
  279. cJSON_Delete(data);
  280. }
  281. }
  282. static void cloud_set_mode(char *params) {
  283. cJSON *data = cJSON_Parse(params);
  284. if (data != NULL) {
  285. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  286. xf_status.mode = value->valueint;
  287. if (guider_ui.screen_main) {
  288. lvgl_port_lock(-1);
  289. set_xf_mode(&guider_ui, xf_status.mode);
  290. lvgl_port_unlock();
  291. }
  292. xf_set_mode(true);
  293. cJSON_Delete(data);
  294. }
  295. }
  296. static void cloud_set_fan_level(char *params) {
  297. cJSON *data = cJSON_Parse(params);
  298. if (data != NULL) {
  299. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  300. xf_status.fan_speed = value->valueint;
  301. if (guider_ui.screen_main) {
  302. lvgl_port_lock(-1);
  303. lv_slider_set_value(guider_ui.screen_main_slider_speedSet_sign, xf_status.fan_speed*20, LV_ANIM_ON);
  304. lv_label_set_text_fmt(guider_ui.screen_main_label_spedSet_vul, "%d档",xf_status.fan_speed);
  305. lvgl_port_unlock();
  306. }
  307. xf_set_fan_speed(true);
  308. cJSON_Delete(data);
  309. }
  310. }
  311. static void cloud_set_filter_life(char *params) {
  312. cJSON *data = cJSON_Parse(params);
  313. if (data != NULL) {
  314. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  315. system_setting.filter_life_time = value->valueint;
  316. save_system_setting(&system_setting);
  317. cJSON_Delete(data);
  318. }
  319. }
  320. static void cloud_reset_filter_life_remain(char *params) {
  321. cJSON *data = cJSON_Parse(params);
  322. if (data != NULL) {
  323. xf_status.filter_used_time=0;
  324. xf_set_filter_life_remain(true);
  325. cJSON_Delete(data);
  326. }
  327. }
  328. static void cloud_set_exhaust_fan_vol(char *params) {
  329. cJSON *data = cJSON_Parse(params);
  330. if (data != NULL) {
  331. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  332. cJSON *gear = cJSON_GetObjectItemCaseSensitive(data, "gear");
  333. set_exhaust_fan_vol(gear->valueint, (uint8_t *) &value->valueint);
  334. cJSON_Delete(data);
  335. }
  336. }
  337. static void cloud_set_supply_fan_vol(char *params) {
  338. cJSON *data = cJSON_Parse(params);
  339. if (data != NULL) {
  340. cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
  341. cJSON *gear = cJSON_GetObjectItemCaseSensitive(data, "gear");
  342. set_supply_fan_vol(gear->valueint, (uint8_t *) &value->valueint);
  343. cJSON_Delete(data);
  344. }
  345. }
  346. static void cloud_set_min_hum(char *params) {
  347. }
  348. //注册云端指令s
  349. void register_sparrow_commands(void) {
  350. sparrow_command set_power_cmd = {
  351. .name = "setPower",
  352. .unpack = &cloud_set_power
  353. };
  354. register_sparrow_command(set_power_cmd);
  355. sparrow_command set_max_hum_cmd = {
  356. .name = "setMaxHum",
  357. .unpack = &cloud_set_max_hum
  358. };
  359. register_sparrow_command(set_max_hum_cmd);
  360. // setMode
  361. sparrow_command set_mode_cmd = {
  362. .name = "setMode",
  363. .unpack = &cloud_set_mode
  364. };
  365. register_sparrow_command(set_mode_cmd);
  366. // setFanLevel
  367. sparrow_command set_fan_level_cmd = {
  368. .name = "setFanLevel",
  369. .unpack = &cloud_set_fan_level,
  370. };
  371. register_sparrow_command(set_fan_level_cmd);
  372. // setNewFan
  373. sparrow_command set_filter_life_cmd = {
  374. .name = "setFilterLife",
  375. .unpack = &cloud_set_filter_life,
  376. };
  377. register_sparrow_command(set_filter_life_cmd);
  378. // setFanVoltage
  379. sparrow_command set_min_hum_cmd = {
  380. .name = "setMinHumCmd",
  381. .unpack = &cloud_set_min_hum,
  382. };
  383. register_sparrow_command(set_min_hum_cmd);
  384. sparrow_command set_duration = {
  385. .name = "setReportDuration",
  386. .unpack = &cloud_set_report_duration
  387. };
  388. register_sparrow_command(set_duration);
  389. sparrow_command reset_filter_life_remain = {
  390. .name = "setReportDuration",
  391. .unpack = &cloud_reset_filter_life_remain
  392. };
  393. register_sparrow_command(reset_filter_life_remain);
  394. sparrow_command set_exhaust_fan_vol = {
  395. .name = "setexhaustFanVoltage",
  396. .unpack = &cloud_set_exhaust_fan_vol
  397. };
  398. register_sparrow_command(set_exhaust_fan_vol);
  399. sparrow_command set_supply_fan_vol = {
  400. .name = "setsupplyFanVoltage",
  401. .unpack = &cloud_set_supply_fan_vol
  402. };
  403. register_sparrow_command(set_supply_fan_vol);
  404. }
  405. LV_IMAGE_DECLARE(_power_open_RGB565A8_36x36);
  406. LV_IMAGE_DECLARE(_liang_RGB565A8_30x30);
  407. LV_IMAGE_DECLARE(_cha_RGB565A8_30x30);
  408. /**
  409. * TODO:处理风故障信息
  410. */
  411. void handle_err_code()
  412. {
  413. uint8_t error_code[2] = {0};
  414. esp_err_t err = ESP_OK;
  415. err = mm_get_param(CID_ERROR_CODE, error_code);
  416. if (err == ESP_OK)
  417. {
  418. // ESP_LOGE(TAG, "error_code1:%d",*(uint16_t *)error_code);
  419. if (guider_ui.screen_main)
  420. {
  421. if((*(uint16_t *)error_code&0x0ff)==0)
  422. {
  423. lvgl_port_lock(-1);
  424. lv_obj_add_flag(guider_ui.screen_main_lab_err, LV_OBJ_FLAG_HIDDEN);
  425. lvgl_port_unlock();
  426. } else{
  427. lvgl_port_lock(-1);
  428. lv_obj_clear_flag(guider_ui.screen_main_lab_err, LV_OBJ_FLAG_HIDDEN);
  429. lvgl_port_unlock();
  430. }
  431. }
  432. xf_status.error_code=(uint8_t)(*(uint16_t *)error_code&0x0ff);
  433. // ESP_LOGE(TAG, "error_code:%d",xf_status.error_code);
  434. }
  435. }
  436. void Refresh_UI()
  437. {
  438. uint8_t type = PARAM_TYPE_U16;
  439. uint8_t temp_data[2] = {0}; // temporary buffer to hold maximum CID size
  440. uint16_t temp_data_u16 = 500;
  441. esp_err_t err = ESP_OK;
  442. const mb_parameter_descriptor_t *param_descriptor = NULL;
  443. err = mm_get_param(CID_RETURN_AIR_PM25, temp_data);
  444. if (err == ESP_OK) {
  445. sht30Data.air_quality=*(uint16_t *)temp_data;
  446. if (guider_ui.screen_main) {
  447. lvgl_port_lock(-1);
  448. lv_arc_set_value(guider_ui.screen_main_arc_AIQ, 500);
  449. if (*(uint16_t *) temp_data < 50) {
  450. // lv_arc_set_value(guider_ui.screen_main_arc_AIQ, *(uint16_t *) temp_data);
  451. lv_obj_set_style_bg_image_src(guider_ui.screen_main_label_AIQ_sign, &_you_RGB565A8_30x30,
  452. LV_PART_MAIN | LV_STATE_DEFAULT);
  453. lv_obj_set_style_arc_color(guider_ui.screen_main_arc_AIQ, lv_color_hex(0x2FDA64),
  454. LV_PART_INDICATOR | LV_STATE_DEFAULT);
  455. } else if (*(uint16_t *) temp_data < 150) {
  456. // lv_arc_set_value(guider_ui.screen_main_arc_AIQ, *(uint16_t *) temp_data);
  457. lv_obj_set_style_bg_image_src(guider_ui.screen_main_label_AIQ_sign, &_liang_RGB565A8_30x30,
  458. LV_PART_MAIN | LV_STATE_DEFAULT);
  459. lv_obj_set_style_arc_color(guider_ui.screen_main_arc_AIQ, lv_color_hex(0xFFF502),
  460. LV_PART_INDICATOR | LV_STATE_DEFAULT);
  461. } else if (*(uint16_t *) temp_data <= 500) {
  462. // lv_arc_set_value(guider_ui.screen_main_arc_AIQ, *(uint16_t *) temp_data);
  463. lv_obj_set_style_bg_image_src(guider_ui.screen_main_label_AIQ_sign, &_cha_RGB565A8_30x30,
  464. LV_PART_MAIN | LV_STATE_DEFAULT);
  465. lv_obj_set_style_arc_color(guider_ui.screen_main_arc_AIQ, lv_color_hex(0xd81e06),
  466. LV_PART_INDICATOR | LV_STATE_DEFAULT);
  467. } else if (*(uint16_t *) temp_data > 500) {
  468. // lv_arc_set_value(guider_ui.screen_main_arc_AIQ, temp_data_u16);
  469. lv_obj_set_style_bg_image_src(guider_ui.screen_main_label_AIQ_sign, &_cha_RGB565A8_30x30,
  470. LV_PART_MAIN | LV_STATE_DEFAULT);
  471. lv_obj_set_style_arc_color(guider_ui.screen_main_arc_AIQ, lv_color_hex(0xd81e06),
  472. LV_PART_INDICATOR | LV_STATE_DEFAULT);
  473. } else {
  474. }
  475. lv_label_set_text_fmt(guider_ui.screen_main_label_AIQ_vul, "%d", *(uint16_t *) temp_data);
  476. lvgl_port_unlock();
  477. }
  478. }
  479. err = mm_get_param(CID_RETURN_AIR_CO2, temp_data);
  480. if (err == ESP_OK) {
  481. err_count = 0;
  482. sht30Data.co2=*(uint16_t *)temp_data;
  483. if (guider_ui.screen_main) {
  484. lvgl_port_lock(-1);
  485. lv_label_set_text_fmt(guider_ui.screen_main_label_co2, "%d", *(uint16_t *) temp_data);
  486. lv_obj_add_flag(guider_ui.screen_main_lab_485_err, LV_OBJ_FLAG_HIDDEN);
  487. lvgl_port_unlock();
  488. }
  489. } else {
  490. err_count++;
  491. if (err_count >= 254)
  492. err_count = 30;
  493. }
  494. if (err_count >= 30) {
  495. if (guider_ui.screen_main) {
  496. lvgl_port_lock(-1);
  497. lv_obj_remove_flag(guider_ui.screen_main_lab_485_err, LV_OBJ_FLAG_HIDDEN);
  498. lvgl_port_unlock();
  499. }
  500. }
  501. xf_status.filter_life_remaining=(100-100*xf_status.filter_used_time/system_setting.filter_life_time);
  502. // ESP_LOGE(TAG, "filter_life_remaining%d",xf_status.filter_life_remaining);
  503. if (guider_ui.screen_main) {
  504. lvgl_port_lock(-1);
  505. if(xf_status.filter_life_remaining<=10)
  506. {
  507. lv_obj_remove_flag(guider_ui.screen_main_label_filter_error, LV_OBJ_FLAG_HIDDEN);
  508. }else{
  509. lv_obj_add_flag(guider_ui.screen_main_label_filter_error, LV_OBJ_FLAG_HIDDEN);
  510. }
  511. lv_label_set_text_fmt(guider_ui.screen_main_label_lvxin, "%d%%", xf_status.filter_life_remaining);
  512. lvgl_port_unlock();
  513. }
  514. }
  515. /**
  516. * 状态同步任务,主要用于与分风箱主控同步当前用户的参数,并处理通讯故障
  517. * @param arg
  518. */
  519. _Noreturn static void status_sync_task(void *arg) {
  520. esp_err_t err = ESP_OK;
  521. for (;;) {
  522. mm_set_param(CID_POWER, (uint8_t *)&xf_status.power);
  523. vTaskDelay(pdTICKS_TO_MS(500));
  524. mm_set_param(CID_MODE, (uint8_t *)&xf_status.mode);
  525. vTaskDelay(pdTICKS_TO_MS(500));
  526. mm_set_param(CID_FAN_SPEED, (uint8_t *)&xf_status.fan_speed);
  527. vTaskDelay(pdTICKS_TO_MS(500));
  528. mm_set_param(CID_MAX_HUMIDITY, (uint8_t *)&xf_status.set_max_hum);
  529. vTaskDelay(pdTICKS_TO_MS(500));
  530. //
  531. // err = xf_set_power(false);
  532. // err = xf_set_mode(true);
  533. // err = xf_set_fan_speed(true);
  534. // err =xf_set_max_hum(true);
  535. // err =xf_set_min_hum(true);
  536. Refresh_UI();
  537. handle_err_code();
  538. vTaskDelay(5000 / portTICK_PERIOD_MS);
  539. }
  540. }
  541. /**
  542. * 云端上报任务
  543. * @param arg
  544. */
  545. _Noreturn static void cloud_report_task(void *arg) {
  546. for (;;) {
  547. if (xSemaphoreTake(report_task_sem, portMAX_DELAY) == pdTRUE) {
  548. ESP_LOGD(TAG, "cloud report");
  549. cJSON *data = cJSON_CreateObject();
  550. cJSON_AddNumberToObject(data, "power", xf_status.power);
  551. cJSON_AddNumberToObject(data, "set_max_hum", xf_status.set_max_hum);
  552. cJSON_AddNumberToObject(data, "filter_life_remaining", xf_status.filter_life_remaining);
  553. cJSON_AddNumberToObject(data, "set_filter_life_time", system_setting.filter_life_time);
  554. cJSON_AddNumberToObject(data, "mode", xf_status.mode);
  555. cJSON_AddNumberToObject(data, "temperature", (int) (sht30Data.temperature));
  556. cJSON_AddNumberToObject(data, "humidity", (int) (sht30Data.humidity));
  557. cJSON_AddNumberToObject(data, "air_quality", (int)sht30Data.air_quality);
  558. cJSON_AddNumberToObject(data, "co2", (int)sht30Data.co2);
  559. cJSON_AddNumberToObject(data, "fan_speed", xf_status.fan_speed);
  560. cJSON_AddNumberToObject(data, "timer_status", system_setting.timer_status);
  561. cJSON_AddNumberToObject(data, "duration", system_setting.duration);
  562. cJSON *root = cJSON_CreateObject();
  563. cJSON_AddStringToObject(root, "cmd", "status");
  564. cJSON_AddItemToObject(root, "params", data);
  565. publish_message_t msg = {
  566. .topic = "status",
  567. .data = root,
  568. };
  569. sparrow_publish_status(msg);
  570. }
  571. }
  572. //
  573. }
  574. _Noreturn static void report_trigger_task(void *arg) {
  575. for (;;) {
  576. if (cloud_connected) {
  577. xSemaphoreGive(report_task_sem);
  578. }
  579. vTaskDelay(pdTICKS_TO_MS(system_setting.report_data_duration * 1000));
  580. }
  581. }
  582. /**
  583. * 云端上报任务
  584. * @param arg
  585. */
  586. _Noreturn static void cloud_fault_report_task(void *arg) {
  587. for (;;) {
  588. if (cloud_connected) {
  589. if (xSemaphoreTake(report_task_sem, portMAX_DELAY) == pdFALSE) {
  590. ESP_LOGD(TAG, "cloud report");
  591. cJSON *data = cJSON_CreateArray();
  592. cJSON *fault = cJSON_CreateObject();
  593. for (int i = 0; i < 8; i++) {
  594. if (xf_status.error_code & (1 << i)) {
  595. cJSON_AddStringToObject(fault, "code", (const char *) xf_fault[i].code);
  596. cJSON_AddStringToObject(fault, "desc", (const char *) xf_fault[i].description);
  597. cJSON_AddItemToArray(data, fault);
  598. }
  599. }
  600. cJSON *root = cJSON_CreateObject();
  601. cJSON_AddStringToObject(root, "cmd", "status");
  602. cJSON_AddItemToObject(root, "params", data);
  603. publish_message_t msg = {
  604. .topic = "status",
  605. .data = root,
  606. };
  607. sparrow_publish_status(msg);
  608. }
  609. vTaskDelay(60*1000 / portTICK_PERIOD_MS);
  610. }
  611. }
  612. }
  613. void xf_controller_init(system_setting_t *setting) {
  614. register_sparrow_commands(); // 注册云端指令
  615. report_task_sem = xSemaphoreCreateBinary();
  616. // timer_init_lx();
  617. // 启动状态同步任务
  618. xTaskCreate(status_sync_task, "status_sync_task", 4 * 1024, NULL, 5, &status_task_handle);
  619. // 启动云端上报任务,受信号量控制,无信号时任务不作操作,只有本地有操作或定时上报任务触发时才会上报。
  620. xTaskCreate(cloud_report_task, "report_task", 6 * 1024, NULL, 5, &cloud_report_handle);
  621. xTaskCreate(report_trigger_task, "trigger_task", 2 * 1024, NULL, 5, &report_trigger_handle);
  622. //故障上报
  623. // xTaskCreate(cloud_fault_report_task, "report_task", 6 * 1024, NULL, 5, &cloud_report_handle);
  624. }
  625. void stop_xf_controller() {
  626. vTaskDelete(status_task_handle);
  627. vTaskDelete(cloud_report_handle);
  628. vTaskDelete(report_trigger_handle);
  629. // 停止modbus 协议 stack
  630. modbus_master_destroy();
  631. }