123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- /**
- * @Author: 李建
- * @Date: 2025/9/9 13:55
- * Description: 热泵控制器
- * Copyright: Copyright (©) 2025 永续绿建. All rights reserved.
- */
- #include "heatpump_controller.h"
- #include "system/miscellaneous_interface.h"
- #include "freertos/FreeRTOS.h"
- #include <freertos/task.h>
- #include <cJSON.h>
- #include <esp_log.h>
- #include "freertos/semphr.h"
- #include "sht30.h"
- #include "gateway/access.h"
- #include "sub_device/command.h"
- #include "lvgl_port.h"
- #include "modbus_master.h"
- hp_controller_t hp_controller = {0};
- static SemaphoreHandle_t report_task_sem; // 上报任务信号量,用于实现操作完成上立即上报当前状态
- static TaskHandle_t cloud_report_handle;
- static const char *TAG = "hp_controller";
- static TaskHandle_t report_trigger_handle;
- static TaskHandle_t status_task_handle;
- void set_bit(uint16_t *num, uint8_t bit, bool value) {
- if (bit > 15) return;
- if (value) {
- *num |= (1 << bit);
- } else {
- *num &= ~(1 << bit);
- }
- }
- bool get_bit(uint16_t num, uint8_t bit) {
- if (bit > 15) return false;
- return (num >> bit) & 1;
- }
- esp_err_t set_relay_status(uint8_t no, uint8_t value) {
- esp_err_t err = ESP_OK;
- set_bit(&hp_controller.relay_status, no, value);
- nvs_set_uint16(hp_controller.relay_status, NVS_RELEY_STATUS_KEY);
- if (cloud_connected) {
- xSemaphoreGive(report_task_sem);
- }
- return err;
- }
- static void update_power_ui(bool on_off) {
- // 同步更新 UI
- if (guider_ui.screen) {
- lvgl_port_lock(-1);
- //lv_obj_set_state(guider_ui.screen_ib_power, LV_IMAGEBUTTON_STATE_CHECKED_RELEASED, on_off);
- if (on_off) {
- lv_obj_remove_flag(guider_ui.screen_cont_power_on, LV_OBJ_FLAG_HIDDEN);
- lv_obj_add_flag(guider_ui.screen_cont_power_off, LV_OBJ_FLAG_HIDDEN);
- } else {
- lv_obj_remove_flag(guider_ui.screen_cont_power_off, LV_OBJ_FLAG_HIDDEN);
- lv_obj_add_flag(guider_ui.screen_cont_power_on, LV_OBJ_FLAG_HIDDEN);
- }
- lvgl_port_unlock();
- }
- }
- /******************************************云端指令开始*************************************************************/
- // 云端指令:设置电源开关
- static void cloud_set_power(char *params) {
- cJSON *data = cJSON_Parse(params);
- if (data != NULL) {
- cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
- hp_controller.power = value->valueint;
- heatpump_set_power(true);
- update_power_ui(hp_controller.power);
- cJSON_Delete(data);
- }
- }
- // 云端指令:设置模式
- static void cloud_set_mode(char *params) {
- cJSON *data = cJSON_Parse(params);
- if (data != NULL) {
- cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
- hp_controller.mode = value->valueint;
- if (guider_ui.screen) {
- if (hp_controller.mode == 1) {
- lvgl_port_lock(0);
- lv_label_set_text_static(guider_ui.screen_lab_mode, "制冷");
- lv_obj_set_style_arc_color(guider_ui.screen_arc_temp, lv_color_hex(0x00d9ff),
- LV_PART_INDICATOR | LV_STATE_DEFAULT);
- lv_label_set_text_fmt(guider_ui.screen_lab_ac_temp, "%d", hp_controller.cool_set_temp);
- lv_obj_add_state(guider_ui.screen_ib_cool, LV_STATE_CHECKED);
- lv_obj_remove_state(guider_ui.screen_ib_heat, LV_STATE_CHECKED);
- lv_arc_set_range(guider_ui.screen_arc_temp, 7 * 2, 22 * 2);
- lv_arc_set_value(guider_ui.screen_arc_temp, hp_controller.cool_set_temp * 2);
- lvgl_port_unlock();
- } else if (hp_controller.mode == 2) {
- lvgl_port_lock(0);
- lv_obj_set_style_arc_color(guider_ui.screen_arc_temp, lv_color_hex(0xfa890a),
- LV_PART_INDICATOR | LV_STATE_DEFAULT);
- lv_label_set_text_static(guider_ui.screen_lab_mode, "制热");
- lv_label_set_text_fmt(guider_ui.screen_lab_ac_temp, "%d", hp_controller.heat_set_temp);
- lv_obj_remove_state(guider_ui.screen_ib_cool, LV_STATE_CHECKED);
- lv_obj_add_state(guider_ui.screen_ib_heat, LV_STATE_CHECKED);
- lv_arc_set_range(guider_ui.screen_arc_temp, 30 * 2, 60 * 2);
- lv_arc_set_value(guider_ui.screen_arc_temp, hp_controller.heat_set_temp * 2);
- lvgl_port_unlock();
- }
- }
- heatpump_set_mode(hp_controller.mode);
- cJSON_Delete(data);
- }
- }
- // 云端指令:设置水温
- static void cloud_set_water_temp(char *params) {
- cJSON *data = cJSON_Parse(params);
- if (data != NULL) {
- cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
- heatpump_set_temp(value->valueint);
- // 更新UI
- if (guider_ui.screen) {
- lvgl_port_lock(0);
- lv_label_set_text_fmt(guider_ui.screen_lab_ac_temp, "%d", value->valueint);
- lv_arc_set_value(guider_ui.screen_arc_temp, value->valueint);
- lvgl_port_unlock();
- }
- cJSON_Delete(data);
- }
- }
- // 云端指令 :设置分集水器某一路开关
- static void cloud_set_IO(char *params) {
- cJSON *data = cJSON_Parse(params);
- if (data != NULL) {
- cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
- cJSON *no = cJSON_GetObjectItemCaseSensitive(data, "no");
- set_relay_status(no->valueint - 1, value->valueint); // 要减1
- cJSON_Delete(data);
- }
- }
- // 云端指令:联动开关
- static void cloud_set_link(char *params) {
- cJSON *data = cJSON_Parse(params);
- if (data != NULL) {
- cJSON *value = cJSON_GetObjectItemCaseSensitive(data, "value");
- hp_controller.linkage = value->valueint;
- heatpump_set_linkage();
- cJSON_Delete(data);
- }
- }
- /******************************************云端指令END*************************************************************/
- static void register_sparrow_commands() {
- sparrow_command set_power_cmd = {
- .name = "setPower",
- .unpack = &cloud_set_power
- };
- register_sparrow_command(set_power_cmd);
- // setMode
- sparrow_command set_mode_cmd = {
- .name = "setMode",
- .unpack = &cloud_set_mode
- };
- register_sparrow_command(set_mode_cmd);
- // setWaterTemp
- sparrow_command set_water_temp = {
- .name = "setWaterTemp",
- .unpack = &cloud_set_water_temp
- };
- register_sparrow_command(set_water_temp);
- // setIO
- sparrow_command set_io = {
- .name = "setIO",
- .unpack = &cloud_set_IO
- };
- register_sparrow_command(set_io);
- // setLinkage
- sparrow_command set_link = {
- .name = "setLinkage",
- .unpack = &cloud_set_link
- };
- register_sparrow_command(set_link);
- }
- _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 status_sync_task(void *arg) {
- esp_err_t err = ESP_OK;
- for (;;) {
- // mm_set_param(CID_HP_POWER, &hp_controller.power);
- // mm_set_param(CID_HP_SET_MODE, &hp_controller.mode);
- // if (hp_controller.mode == MODE_COOL) mm_set_param(CID_HP_COOL_SET_TEMP, &hp_controller.cool_set_temp);
- // if (hp_controller.mode == MODE_HEAT) mm_set_param(CID_HP_HEAT_SET_TEMP, &hp_controller.heat_set_temp);
- // mm_get_param(CID_HP_OUTDOOR_TEMP, &hp_controller.outdoor_temp);
- // mm_get_param(CID_HP_OUT_WATER_TEMP, &hp_controller.out_water_temp);
- // mm_get_param(CID_HP_IN_WATER_TEMP, &hp_controller.in_water_temp);
- uint8_t status = get_bit(hp_controller.relay_status, 0);
- mm_set_param(CID_RELAY_1_STATUS, &status);
- status = get_bit(hp_controller.relay_status, 1);
- mm_set_param(CID_RELAY_2_STATUS, &status);
- status = get_bit(hp_controller.relay_status, 2);
- mm_set_param(CID_RELAY_3_STATUS, &status);
- status = get_bit(hp_controller.relay_status, 3);
- mm_set_param(CID_RELAY_4_STATUS, &status);
- status = get_bit(hp_controller.relay_status, 4);
- mm_set_param(CID_RELAY_5_STATUS, &status);
- status = get_bit(hp_controller.relay_status, 5);
- mm_set_param(CID_RELAY_6_STATUS, &status);
- status = get_bit(hp_controller.relay_status, 6);
- mm_set_param(CID_RELAY_7_STATUS, &status);
- status = get_bit(hp_controller.relay_status, 7);
- mm_set_param(CID_RELAY_8_STATUS, &status);
- 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", hp_controller.power);
- cJSON_AddNumberToObject(data, "cool_set_water_temp", hp_controller.cool_set_temp);
- cJSON_AddNumberToObject(data, "heat_set_water_temp", hp_controller.heat_set_temp);
- cJSON_AddNumberToObject(data, "mode", hp_controller.mode);
- cJSON_AddNumberToObject(data, "temperature", (int) sht30Data.temperature);
- cJSON_AddNumberToObject(data, "humidity", (int) sht30Data.humidity);
- cJSON_AddNumberToObject(data, "outdoor_temp", hp_controller.outdoor_temp);
- cJSON_AddNumberToObject(data, "out_water_temp", hp_controller.out_water_temp);
- cJSON_AddNumberToObject(data, "in_water_temp", hp_controller.in_water_temp);
- cJSON_AddNumberToObject(data, "fjsq_exist", hp_controller.fjsq_exist);
- cJSON_AddNumberToObject(data, "fjsq_status", hp_controller.relay_status);
- 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);
- }
- }
- }
- void heatpump_controller_init(system_setting_t *setting) {
- hp_controller.mode = setting->hp_mode;
- hp_controller.power = setting->hp_power;
- hp_controller.cool_set_temp = setting->hp_cool_set_temp;
- hp_controller.heat_set_temp = setting->hp_heat_set_temp;
- hp_controller.relay_status = setting->reley_status;
- hp_controller.linkage = setting->allow_linkage;
- register_sparrow_commands();
- report_task_sem = xSemaphoreCreateBinary();
- // 启动状态同步任务
- xTaskCreate(status_sync_task, "status_sync_task", 4 * 1024, NULL, 5, &status_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);
- }
- esp_err_t heatpump_set_power(bool saved) {
- esp_err_t err = ESP_OK;
- if (saved)
- nvs_set_uint16(hp_controller.power, NVS_HP_POWER_KEY);
- if (cloud_connected) {
- xSemaphoreGive(report_task_sem);
- }
- return err;
- }
- esp_err_t heatpump_set_mode(uint8_t mode) {
- esp_err_t err = ESP_OK;
- nvs_set_uint16(hp_controller.mode, NVS_HP_MODE_KEY);
- if (cloud_connected) {
- xSemaphoreGive(report_task_sem);
- }
- return err;
- }
- esp_err_t heatpump_set_temp(uint16_t temp) {
- esp_err_t err = ESP_OK;
- if (hp_controller.mode == MODE_COOL)nvs_set_uint16(hp_controller.cool_set_temp, NVS_HP_COOL_SET_TEMP_KEY);
- if (hp_controller.mode == MODE_HEAT)nvs_set_uint16(hp_controller.heat_set_temp, NVS_HP_HEAT_SET_TEMP_KEY);
- if (cloud_connected) {
- xSemaphoreGive(report_task_sem);
- }
- return err;
- }
- esp_err_t heatpump_set_linkage() {
- esp_err_t err = ESP_OK;
- nvs_set_uint16(hp_controller.linkage, NVS_ALLOW_LINKAGE_KEY);
- return err;
- }
|