/* AUTO-GENERATED by GUI Editor — do not edit manually */ #include "gui_generated.h" #include "lvgl.h" #include #include #include #include /* Fonts */ LV_FONT_DECLARE(montserrat_16_ru_en) lv_obj_t *scr_main = NULL; lv_obj_t *scr_screen1 = NULL; lv_obj_t *scr_screen2 = NULL; lv_obj_t *scr_screen3 = NULL; /* Runtime variable values */ static int32_t var_temp_room = 22; static int32_t var_hum_room = 45; static int32_t var_temp_channel = 20; static int32_t var_hum_channel = 50; static int32_t var_room_num = 101; static int32_t var_is_master = 1; static int32_t var_season = 0; // 0=Зима, 1=Лето, 2=Переход static int32_t var_mode = 1; // 0=Остановка, 1=Дежурный, 2=Рабочий /* Equipment module states */ static int32_t var_valve_inlet = 75; // Входной клапан 0-100% static int32_t var_valve_recirc = 25; // Клапан рециркуляции 0-100% static int32_t var_filter_g4 = 1; // 0=Грязный, 1=Чистый static int32_t var_kws_valve = 50; // KWS клапан 0-100% static int32_t var_pww_valve = 30; // PWW клапан 0-100% static int32_t var_heater_on = 0; // Электронагреватель 0=Выкл, 1=Вкл static int32_t var_fan_on = 1; // Вентилятор 0=Выкл, 1=Вкл static int32_t var_filter_h13 = 1; // 0=Грязный, 1=Чистый /* Module configuration for drag&drop */ typedef enum { MODULE_VALVE_INLET = 0, MODULE_VALVE_RECIRC, MODULE_FILTER_G4, MODULE_KWS, MODULE_PWW, MODULE_HEATER, MODULE_FAN, MODULE_FILTER_H13, MODULE_COUNT } module_type_t; typedef struct { module_type_t type; int enabled; // 1=показывать, 0=скрыть int position; // позиция в ряду (0-7) lv_obj_t *obj; // указатель на объект (для будущего drag&drop) } module_config_t; static module_config_t modules[MODULE_COUNT] = { {MODULE_VALVE_INLET, 1, 0, NULL}, {MODULE_VALVE_RECIRC, 1, 1, NULL}, {MODULE_FILTER_G4, 1, 2, NULL}, {MODULE_KWS, 1, 3, NULL}, {MODULE_PWW, 1, 4, NULL}, {MODULE_HEATER, 1, 5, NULL}, {MODULE_FAN, 1, 6, NULL}, {MODULE_FILTER_H13, 1, 7, NULL}, }; /* Alarm log structure */ #define MAX_ALARMS 10 typedef struct { char message[100]; char timestamp[20]; int active; } alarm_entry_t; static alarm_entry_t alarm_log[MAX_ALARMS]; static int alarm_count = 0; /* Settings/Setpoints for Work and Standby modes */ static float setpoint_work_temp = 22.0; static float setpoint_work_hum = 50.0; static float setpoint_standby_temp = 18.0; static float setpoint_standby_hum = 45.0; /* Password and settings */ #define PASSWORD "1234" static char password_input[10] = ""; static lv_obj_t *popup_password = NULL; static lv_obj_t *lbl_password_display = NULL; /* Parameter editor */ static lv_obj_t *popup_param_editor = NULL; static lv_obj_t *lbl_param_value = NULL; static char param_value_str[20] = ""; static float *param_being_edited = NULL; static char param_name[50] = ""; /* Configuration parameters */ static float config_temp_room_offset = 0.0; static float config_hum_room_offset = 0.0; static float config_temp_channel_offset = 0.0; static float config_hum_channel_offset = 0.0; /* UI element references for updates */ static lv_obj_t *lbl_temp_room = NULL; static lv_obj_t *lbl_hum_room = NULL; static lv_obj_t *lbl_temp_channel = NULL; static lv_obj_t *lbl_hum_channel = NULL; static lv_obj_t *lbl_room_num = NULL; static lv_obj_t *lbl_master_slave = NULL; static lv_obj_t *lbl_season = NULL; static lv_obj_t *lbl_mode = NULL; static lv_obj_t *lbl_datetime = NULL; /* Equipment UI references */ static lv_obj_t *lbl_valve_inlet = NULL; static lv_obj_t *lbl_valve_recirc = NULL; static lv_obj_t *lbl_filter_g4 = NULL; static lv_obj_t *lbl_kws = NULL; static lv_obj_t *lbl_pww = NULL; static lv_obj_t *lbl_heater = NULL; static lv_obj_t *lbl_fan = NULL; static lv_obj_t *lbl_filter_h13 = NULL; /* Popup windows */ static lv_obj_t *popup_readings = NULL; static lv_obj_t *popup_alarm = NULL; /* Forward declarations */ static void create_popup_readings(void); static void create_popup_alarm(const char *message); static void add_alarm_to_log(const char *message, int active); static void btn_log_cb(lv_event_t *e); static void btn_settings_cb(lv_event_t *e); static void btn_config_cb(lv_event_t *e); static void create_popup_password(void); static void password_keypad_cb(lv_event_t *e); static void create_popup_param_editor(const char *name, float *param_ptr); static void param_keypad_cb(lv_event_t *e); static void close_popup_cb(lv_event_t *e); static void btn_back_to_main_cb(lv_event_t *e); /* Button callbacks */ static void btn_stop_cb(lv_event_t *e) { (void)e; var_mode = 0; gui_update_values(); } static void btn_standby_cb(lv_event_t *e) { (void)e; var_mode = 1; gui_update_values(); } static void btn_work_cb(lv_event_t *e) { (void)e; var_mode = 2; gui_update_values(); } static void btn_menu_cb(lv_event_t *e) { (void)e; if (scr_screen1) lv_scr_load(scr_screen1); } static void btn_back_to_main_cb(lv_event_t *e) { (void)e; if (scr_main) lv_scr_load(scr_main); } static void btn_readings_cb(lv_event_t *e) { (void)e; create_popup_readings(); } static void close_popup_cb(lv_event_t *e) { lv_obj_t *popup = lv_event_get_user_data(e); if (popup) { lv_obj_del(popup); } if (popup == popup_readings) popup_readings = NULL; if (popup == popup_alarm) popup_alarm = NULL; if (popup == popup_password) { popup_password = NULL; memset(password_input, 0, sizeof(password_input)); } if (popup == popup_param_editor) { popup_param_editor = NULL; memset(param_value_str, 0, sizeof(param_value_str)); param_being_edited = NULL; } } static void btn_log_cb(lv_event_t *e) { (void)e; if (scr_screen2) lv_scr_load(scr_screen2); } static void btn_settings_cb(lv_event_t *e) { (void)e; if (scr_screen3) lv_scr_load(scr_screen3); } static void btn_config_cb(lv_event_t *e) { (void)e; create_popup_password(); } /* Edit parameter callbacks */ static void edit_work_temp_cb(lv_event_t *e) { (void)e; create_popup_param_editor("Температура (Рабочий)", &setpoint_work_temp); } static void edit_work_hum_cb(lv_event_t *e) { (void)e; create_popup_param_editor("Влажность (Рабочий)", &setpoint_work_hum); } static void edit_standby_temp_cb(lv_event_t *e) { (void)e; create_popup_param_editor("Температура (Дежурный)", &setpoint_standby_temp); } static void edit_standby_hum_cb(lv_event_t *e) { (void)e; create_popup_param_editor("Влажность (Дежурный)", &setpoint_standby_hum); } /* Password keypad callback */ static void password_keypad_cb(lv_event_t *e) { const char *key = lv_event_get_user_data(e); int len = strlen(password_input); if (strcmp(key, "C") == 0) { // Clear memset(password_input, 0, sizeof(password_input)); } else if (strcmp(key, "OK") == 0) { // Check password if (strcmp(password_input, PASSWORD) == 0) { // Correct password - close popup and show success message if (popup_password) { lv_obj_del(popup_password); popup_password = NULL; lbl_password_display = NULL; } memset(password_input, 0, sizeof(password_input)); // Show success popup lv_obj_t *popup_success = lv_obj_create(lv_screen_active()); lv_obj_set_size(popup_success, 450, 200); lv_obj_center(popup_success); lv_obj_set_style_bg_color(popup_success, lv_color_hex(0x27AE60), 0); lv_obj_set_style_radius(popup_success, 12, 0); lv_obj_t *lbl = lv_label_create(popup_success); lv_label_set_text(lbl, "✓ ДОСТУП РАЗРЕШЁН\n\nЭкран настроек будет\nдобавлен в следующей версии"); lv_obj_center(lbl); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_CENTER, 0); // Auto-close after showing message (we'll just leave X button for now) lv_obj_t *btn_close = lv_btn_create(popup_success); lv_obj_set_pos(btn_close, 405, 10); lv_obj_set_size(btn_close, 35, 35); lv_obj_set_style_bg_color(btn_close, lv_color_hex(0x1E8449), 0); lv_obj_set_style_radius(btn_close, 6, 0); lbl = lv_label_create(btn_close); lv_label_set_text(lbl, "X"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn_close, close_popup_cb, LV_EVENT_CLICKED, popup_success); } else { // Wrong password if (lbl_password_display) { lv_label_set_text(lbl_password_display, "НЕВЕРНЫЙ ПАРОЛЬ!"); lv_obj_set_style_text_color(lbl_password_display, lv_color_hex(0xE74C3C), 0); } memset(password_input, 0, sizeof(password_input)); } } else if (len < 8) { // Add digit strcat(password_input, key); } // Update display if (lbl_password_display) { char display[20] = ""; for (int i = 0; i < (int)strlen(password_input); i++) { strcat(display, "*"); } if (strlen(display) == 0) { lv_label_set_text(lbl_password_display, "Введите пароль"); lv_obj_set_style_text_color(lbl_password_display, lv_color_hex(0xBDC3C7), 0); } else { lv_label_set_text(lbl_password_display, display); lv_obj_set_style_text_color(lbl_password_display, lv_color_hex(0x2ECC71), 0); } } } /* Create password popup with keypad */ static void create_popup_password(void) { if (popup_password) return; // Already open memset(password_input, 0, sizeof(password_input)); popup_password = lv_obj_create(lv_screen_active()); lv_obj_set_size(popup_password, 400, 400); lv_obj_center(popup_password); lv_obj_set_style_bg_color(popup_password, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(popup_password, 12, 0); lv_obj_set_style_border_width(popup_password, 3, 0); lv_obj_set_style_border_color(popup_password, lv_color_hex(0xE67E22), 0); /* Title */ lv_obj_t *lbl = lv_label_create(popup_password); lv_label_set_text(lbl, "Введите пароль"); lv_obj_set_pos(lbl, 130, 15); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Close button (X) */ lv_obj_t *btn_close = lv_btn_create(popup_password); lv_obj_set_pos(btn_close, 355, 10); lv_obj_set_size(btn_close, 35, 35); lv_obj_set_style_bg_color(btn_close, lv_color_hex(0xC0392B), 0); lv_obj_set_style_radius(btn_close, 6, 0); lbl = lv_label_create(btn_close); lv_label_set_text(lbl, "X"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn_close, close_popup_cb, LV_EVENT_CLICKED, popup_password); /* Password display */ lbl_password_display = lv_label_create(popup_password); lv_label_set_text(lbl_password_display, "Введите пароль"); lv_obj_set_pos(lbl_password_display, 130, 60); lv_obj_set_style_text_color(lbl_password_display, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl_password_display, &montserrat_16_ru_en, 0); /* Numeric keypad 3x4 */ const char *keys[12] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "C", "0", "OK"}; int key_size = 70; int key_spacing = 10; int start_x = 40; int start_y = 110; for (int i = 0; i < 12; i++) { int row = i / 3; int col = i % 3; lv_obj_t *btn = lv_btn_create(popup_password); lv_obj_set_pos(btn, start_x + col * (key_size + key_spacing), start_y + row * (key_size + key_spacing)); lv_obj_set_size(btn, key_size, key_size); // Color coding if (strcmp(keys[i], "C") == 0) { lv_obj_set_style_bg_color(btn, lv_color_hex(0xE67E22), 0); } else if (strcmp(keys[i], "OK") == 0) { lv_obj_set_style_bg_color(btn, lv_color_hex(0x2ECC71), 0); } else { lv_obj_set_style_bg_color(btn, lv_color_hex(0x3498DB), 0); } lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, keys[i]); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, password_keypad_cb, LV_EVENT_CLICKED, (void*)keys[i]); } } /* Parameter editor keypad callback */ static void param_keypad_cb(lv_event_t *e) { const char *key = lv_event_get_user_data(e); int len = strlen(param_value_str); if (strcmp(key, "C") == 0) { memset(param_value_str, 0, sizeof(param_value_str)); } else if (strcmp(key, ".") == 0) { if (len > 0 && strchr(param_value_str, '.') == NULL) { strcat(param_value_str, "."); } } else if (strcmp(key, "OK") == 0) { if (param_being_edited && strlen(param_value_str) > 0) { *param_being_edited = atof(param_value_str); } if (popup_param_editor) { lv_obj_del(popup_param_editor); popup_param_editor = NULL; lbl_param_value = NULL; } memset(param_value_str, 0, sizeof(param_value_str)); param_being_edited = NULL; return; } else if (len < 18) { strcat(param_value_str, key); } if (lbl_param_value) { if (strlen(param_value_str) == 0) { lv_label_set_text(lbl_param_value, "0.0"); } else { lv_label_set_text(lbl_param_value, param_value_str); } } } /* Create parameter editor popup */ static void create_popup_param_editor(const char *name, float *param_ptr) { if (popup_param_editor) return; param_being_edited = param_ptr; strncpy(param_name, name, 49); param_name[49] = '\0'; memset(param_value_str, 0, sizeof(param_value_str)); snprintf(param_value_str, sizeof(param_value_str), "%.1f", *param_ptr); popup_param_editor = lv_obj_create(lv_screen_active()); lv_obj_set_size(popup_param_editor, 400, 430); lv_obj_center(popup_param_editor); lv_obj_set_style_bg_color(popup_param_editor, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(popup_param_editor, 12, 0); lv_obj_set_style_border_width(popup_param_editor, 3, 0); lv_obj_set_style_border_color(popup_param_editor, lv_color_hex(0x3498DB), 0); /* Title */ lv_obj_t *lbl = lv_label_create(popup_param_editor); lv_label_set_text(lbl, param_name); lv_obj_set_pos(lbl, 20, 15); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Close button (X) */ lv_obj_t *btn_close = lv_btn_create(popup_param_editor); lv_obj_set_pos(btn_close, 355, 10); lv_obj_set_size(btn_close, 35, 35); lv_obj_set_style_bg_color(btn_close, lv_color_hex(0xC0392B), 0); lv_obj_set_style_radius(btn_close, 6, 0); lbl = lv_label_create(btn_close); lv_label_set_text(lbl, "X"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn_close, close_popup_cb, LV_EVENT_CLICKED, popup_param_editor); /* Value display */ lbl_param_value = lv_label_create(popup_param_editor); lv_label_set_text(lbl_param_value, param_value_str); lv_obj_set_pos(lbl_param_value, 150, 60); lv_obj_set_style_text_color(lbl_param_value, lv_color_hex(0x2ECC71), 0); lv_obj_set_style_text_font(lbl_param_value, &montserrat_16_ru_en, 0); /* Numeric keypad with decimal point */ const char *keys[12] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "C", "0", "."}; int key_size = 70; int key_spacing = 10; int start_x = 40; int start_y = 110; for (int i = 0; i < 12; i++) { int row = i / 3; int col = i % 3; lv_obj_t *btn = lv_btn_create(popup_param_editor); lv_obj_set_pos(btn, start_x + col * (key_size + key_spacing), start_y + row * (key_size + key_spacing)); lv_obj_set_size(btn, key_size, key_size); if (strcmp(keys[i], "C") == 0) { lv_obj_set_style_bg_color(btn, lv_color_hex(0xE67E22), 0); } else if (strcmp(keys[i], ".") == 0) { lv_obj_set_style_bg_color(btn, lv_color_hex(0xF39C12), 0); } else { lv_obj_set_style_bg_color(btn, lv_color_hex(0x3498DB), 0); } lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, keys[i]); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, param_keypad_cb, LV_EVENT_CLICKED, (void*)keys[i]); } /* OK button (wider) */ lv_obj_t *btn_ok = lv_btn_create(popup_param_editor); lv_obj_set_pos(btn_ok, 130, 390); lv_obj_set_size(btn_ok, 160, 35); lv_obj_set_style_bg_color(btn_ok, lv_color_hex(0x2ECC71), 0); lv_obj_set_style_radius(btn_ok, 8, 0); lbl = lv_label_create(btn_ok); lv_label_set_text(lbl, "OK"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn_ok, param_keypad_cb, LV_EVENT_CLICKED, (void*)"OK"); } /* Create popup window for sensor readings */ static void create_popup_readings(void) { if (popup_readings) return; // Already open popup_readings = lv_obj_create(lv_screen_active()); lv_obj_set_size(popup_readings, 400, 280); lv_obj_center(popup_readings); lv_obj_set_style_bg_color(popup_readings, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(popup_readings, 12, 0); lv_obj_set_style_border_width(popup_readings, 3, 0); lv_obj_set_style_border_color(popup_readings, lv_color_hex(0x3498DB), 0); /* Title */ lv_obj_t *lbl = lv_label_create(popup_readings); lv_label_set_text(lbl, "ПОКАЗАНИЯ ДАТЧИКОВ"); lv_obj_set_pos(lbl, 20, 15); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Close button (X) */ lv_obj_t *btn_close = lv_btn_create(popup_readings); lv_obj_set_pos(btn_close, 355, 10); lv_obj_set_size(btn_close, 35, 35); lv_obj_set_style_bg_color(btn_close, lv_color_hex(0xC0392B), 0); lv_obj_set_style_radius(btn_close, 6, 0); lbl = lv_label_create(btn_close); lv_label_set_text(lbl, "X"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn_close, close_popup_cb, LV_EVENT_CLICKED, popup_readings); /* Room sensors */ int y = 60; lbl = lv_label_create(popup_readings); lv_label_set_text(lbl, "КОМНАТА:"); lv_obj_set_pos(lbl, 30, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xF39C12), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 30; lbl = lv_label_create(popup_readings); char buf[64]; snprintf(buf, sizeof(buf), "Температура комнаты: %.1f°C", var_temp_room / 1.0); lv_label_set_text(lbl, buf); lv_obj_set_pos(lbl, 40, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xE74C3C), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 30; lbl = lv_label_create(popup_readings); snprintf(buf, sizeof(buf), "Влажность комнаты: %d%%", (int)var_hum_room); lv_label_set_text(lbl, buf); lv_obj_set_pos(lbl, 40, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0x3498DB), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Channel sensors */ y += 40; lbl = lv_label_create(popup_readings); lv_label_set_text(lbl, "КАНАЛ ПРИТОКА:"); lv_obj_set_pos(lbl, 30, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xF39C12), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 30; lbl = lv_label_create(popup_readings); snprintf(buf, sizeof(buf), "Температура притока: %.1f°C", var_temp_channel / 1.0); lv_label_set_text(lbl, buf); lv_obj_set_pos(lbl, 40, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xE74C3C), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 30; lbl = lv_label_create(popup_readings); snprintf(buf, sizeof(buf), "Влажность притока: %d%%", (int)var_hum_channel); lv_label_set_text(lbl, buf); lv_obj_set_pos(lbl, 40, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0x3498DB), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); } /* Add alarm to log */ static void add_alarm_to_log(const char *message, int active) { if (alarm_count < MAX_ALARMS) { strncpy(alarm_log[alarm_count].message, message, 99); alarm_log[alarm_count].message[99] = '\0'; snprintf(alarm_log[alarm_count].timestamp, 20, "25.02.2026 09:35"); alarm_log[alarm_count].active = active; alarm_count++; } } /* Create alarm popup */ static void create_popup_alarm(const char *message) { if (popup_alarm) { lv_obj_del(popup_alarm); } /* Add to log */ add_alarm_to_log(message, 1); popup_alarm = lv_obj_create(lv_screen_active()); lv_obj_set_size(popup_alarm, 450, 200); lv_obj_center(popup_alarm); lv_obj_set_style_bg_color(popup_alarm, lv_color_hex(0xC0392B), 0); lv_obj_set_style_radius(popup_alarm, 12, 0); lv_obj_set_style_border_width(popup_alarm, 3, 0); lv_obj_set_style_border_color(popup_alarm, lv_color_hex(0xE74C3C), 0); /* Title */ lv_obj_t *lbl = lv_label_create(popup_alarm); lv_label_set_text(lbl, "⚠ АВАРИЯ ⚠"); lv_obj_set_pos(lbl, 20, 15); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Close button (X) */ lv_obj_t *btn_close = lv_btn_create(popup_alarm); lv_obj_set_pos(btn_close, 405, 10); lv_obj_set_size(btn_close, 35, 35); lv_obj_set_style_bg_color(btn_close, lv_color_hex(0x2C3E50), 0); lv_obj_set_style_radius(btn_close, 6, 0); lbl = lv_label_create(btn_close); lv_label_set_text(lbl, "X"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn_close, close_popup_cb, LV_EVENT_CLICKED, popup_alarm); /* Message */ lbl = lv_label_create(popup_alarm); lv_label_set_text(lbl, message); lv_obj_set_pos(lbl, 30, 70); lv_obj_set_width(lbl, 390); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_label_set_long_mode(lbl, LV_LABEL_LONG_WRAP); } static void create_screen_main(void) { lv_obj_t *scr = lv_obj_create(NULL); scr_main = scr; lv_obj_set_style_bg_color(scr, lv_color_hex(0x2C3E50), 0); lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0); lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE); /* === STATUS PANEL === */ lv_obj_t *panel_status = lv_obj_create(scr); lv_obj_set_pos(panel_status, 10, 320); lv_obj_set_size(panel_status, 230, 150); lv_obj_set_style_bg_color(panel_status, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(panel_status, 8, 0); lv_obj_set_style_border_width(panel_status, 0, 0); lv_obj_t *lbl = lv_label_create(panel_status); lv_label_set_text(lbl, "Состояние системы"); lv_obj_set_pos(lbl, 10, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_room_num = lv_label_create(panel_status); lv_label_set_text(lbl_room_num, "Комната: 101"); lv_obj_set_pos(lbl_room_num, 10, 30); lv_obj_set_style_text_color(lbl_room_num, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl_room_num, &montserrat_16_ru_en, 0); lbl_master_slave = lv_label_create(panel_status); lv_label_set_text(lbl_master_slave, "Мастер"); lv_obj_set_pos(lbl_master_slave, 10, 50); lv_obj_set_style_text_color(lbl_master_slave, lv_color_hex(0x2ECC71), 0); lv_obj_set_style_text_font(lbl_master_slave, &montserrat_16_ru_en, 0); lbl_season = lv_label_create(panel_status); lv_label_set_text(lbl_season, "Сезон: Зима"); lv_obj_set_pos(lbl_season, 10, 70); lv_obj_set_style_text_color(lbl_season, lv_color_hex(0x3498DB), 0); lv_obj_set_style_text_font(lbl_season, &montserrat_16_ru_en, 0); lbl_mode = lv_label_create(panel_status); lv_label_set_text(lbl_mode, "Режим: Дежурный"); lv_obj_set_pos(lbl_mode, 10, 90); lv_obj_set_style_text_color(lbl_mode, lv_color_hex(0xF39C12), 0); lv_obj_set_style_text_font(lbl_mode, &montserrat_16_ru_en, 0); lbl_datetime = lv_label_create(panel_status); lv_label_set_text(lbl_datetime, "25.02.2025 09:25"); lv_obj_set_pos(lbl_datetime, 10, 115); lv_obj_set_style_text_color(lbl_datetime, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl_datetime, &montserrat_16_ru_en, 0); /* === CLIMATE PANEL === */ lv_obj_t *panel_climate = lv_obj_create(scr); lv_obj_set_pos(panel_climate, 250, 320); lv_obj_set_size(panel_climate, 220, 150); lv_obj_set_style_bg_color(panel_climate, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(panel_climate, 8, 0); lv_obj_set_style_border_width(panel_climate, 0, 0); lbl = lv_label_create(panel_climate); lv_label_set_text(lbl, "Климат в помещении"); lv_obj_set_pos(lbl, 10, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl = lv_label_create(panel_climate); lv_label_set_text(lbl, "Температура:"); lv_obj_set_pos(lbl, 10, 40); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_temp_room = lv_label_create(panel_climate); lv_label_set_text(lbl_temp_room, "22.0°C"); lv_obj_set_pos(lbl_temp_room, 130, 40); lv_obj_set_style_text_color(lbl_temp_room, lv_color_hex(0xE74C3C), 0); lv_obj_set_style_text_font(lbl_temp_room, &montserrat_16_ru_en, 0); lbl = lv_label_create(panel_climate); lv_label_set_text(lbl, "Влажность:"); lv_obj_set_pos(lbl, 10, 70); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_hum_room = lv_label_create(panel_climate); lv_label_set_text(lbl_hum_room, "45%"); lv_obj_set_pos(lbl_hum_room, 130, 70); lv_obj_set_style_text_color(lbl_hum_room, lv_color_hex(0x3498DB), 0); lv_obj_set_style_text_font(lbl_hum_room, &montserrat_16_ru_en, 0); /* === CONTROL BUTTONS === */ /* Stop button */ lv_obj_t *btn = lv_btn_create(scr); lv_obj_set_pos(btn, 480, 320); lv_obj_set_size(btn, 100, 80); lv_obj_set_style_bg_color(btn, lv_color_hex(0xC0392B), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Останов"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_stop_cb, LV_EVENT_CLICKED, NULL); /* Standby button */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, 590, 320); lv_obj_set_size(btn, 100, 36); lv_obj_set_style_bg_color(btn, lv_color_hex(0xF39C12), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Дежурный"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_standby_cb, LV_EVENT_CLICKED, NULL); /* Work button */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, 590, 364); lv_obj_set_size(btn, 100, 36); lv_obj_set_style_bg_color(btn, lv_color_hex(0x27AE60), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Рабочий"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_work_cb, LV_EVENT_CLICKED, NULL); /* Menu button */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, 700, 320); lv_obj_set_size(btn, 90, 36); lv_obj_set_style_bg_color(btn, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Меню"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_menu_cb, LV_EVENT_CLICKED, NULL); /* Readings button */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, 700, 364); lv_obj_set_size(btn, 90, 36); lv_obj_set_style_bg_color(btn, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Показания"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_readings_cb, LV_EVENT_CLICKED, NULL); /* === EQUIPMENT SCHEMA AREA === */ lv_obj_t *panel_schema = lv_obj_create(scr); lv_obj_set_pos(panel_schema, 10, 10); lv_obj_set_size(panel_schema, 780, 300); lv_obj_set_style_bg_color(panel_schema, lv_color_hex(0x1A252F), 0); lv_obj_set_style_radius(panel_schema, 8, 0); lv_obj_set_style_border_width(panel_schema, 2, 0); lv_obj_set_style_border_color(panel_schema, lv_color_hex(0x34495E), 0); int x_pos = 15; int y_pos = 20; int module_width = 70; int module_height = 60; int spacing = 10; /* Title */ lbl = lv_label_create(panel_schema); lv_label_set_text(lbl, "Схема установки"); lv_obj_set_pos(lbl, 10, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Module 1: Входной клапан */ if (modules[MODULE_VALVE_INLET].enabled) { lv_obj_t *mod1 = lv_obj_create(panel_schema); modules[MODULE_VALVE_INLET].obj = mod1; lv_obj_set_pos(mod1, x_pos, y_pos); lv_obj_set_size(mod1, module_width, module_height); lv_obj_set_style_bg_color(mod1, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(mod1, 5, 0); lv_obj_set_style_border_width(mod1, 1, 0); lv_obj_set_style_border_color(mod1, lv_color_hex(0x7F8C8D), 0); // TODO: Add image here - lv_image_set_src(img, &img_valve); lbl = lv_label_create(mod1); lv_label_set_text(lbl, "Вход.\nклапан"); lv_obj_set_pos(lbl, 5, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_valve_inlet = lv_label_create(mod1); lv_label_set_text(lbl_valve_inlet, "75%"); lv_obj_set_pos(lbl_valve_inlet, 20, 38); lv_obj_set_style_text_color(lbl_valve_inlet, lv_color_hex(0x3498DB), 0); lv_obj_set_style_text_font(lbl_valve_inlet, &montserrat_16_ru_en, 0); x_pos += module_width + spacing; } /* Module 2: Клапан рециркуляции */ if (modules[MODULE_VALVE_RECIRC].enabled) { lv_obj_t *mod2 = lv_obj_create(panel_schema); modules[MODULE_VALVE_RECIRC].obj = mod2; lv_obj_set_pos(mod2, x_pos, y_pos); lv_obj_set_size(mod2, module_width, module_height); lv_obj_set_style_bg_color(mod2, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(mod2, 5, 0); lv_obj_set_style_border_width(mod2, 1, 0); lv_obj_set_style_border_color(mod2, lv_color_hex(0x7F8C8D), 0); // TODO: Add image here - lv_image_set_src(img, &img_valve_recirc); lbl = lv_label_create(mod2); lv_label_set_text(lbl, "Рецирк.\nклапан"); lv_obj_set_pos(lbl, 5, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_valve_recirc = lv_label_create(mod2); lv_label_set_text(lbl_valve_recirc, "25%"); lv_obj_set_pos(lbl_valve_recirc, 20, 38); lv_obj_set_style_text_color(lbl_valve_recirc, lv_color_hex(0xF39C12), 0); lv_obj_set_style_text_font(lbl_valve_recirc, &montserrat_16_ru_en, 0); x_pos += module_width + spacing; } /* Module 3: Фильтр G4 */ if (modules[MODULE_FILTER_G4].enabled) { lv_obj_t *mod3 = lv_obj_create(panel_schema); modules[MODULE_FILTER_G4].obj = mod3; lv_obj_set_pos(mod3, x_pos, y_pos); lv_obj_set_size(mod3, module_width, module_height); lv_obj_set_style_bg_color(mod3, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(mod3, 5, 0); lv_obj_set_style_border_width(mod3, 1, 0); lv_obj_set_style_border_color(mod3, lv_color_hex(0x7F8C8D), 0); // TODO: Add image here - lv_image_set_src(img, &img_filter); lbl = lv_label_create(mod3); lv_label_set_text(lbl, "Фильтр\nG4"); lv_obj_set_pos(lbl, 10, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_filter_g4 = lv_label_create(mod3); lv_label_set_text(lbl_filter_g4, "Чистый"); lv_obj_set_pos(lbl_filter_g4, 8, 38); lv_obj_set_style_text_color(lbl_filter_g4, lv_color_hex(0x2ECC71), 0); lv_obj_set_style_text_font(lbl_filter_g4, &montserrat_16_ru_en, 0); x_pos += module_width + spacing; } /* Module 4: KWS */ if (modules[MODULE_KWS].enabled) { lv_obj_t *mod4 = lv_obj_create(panel_schema); modules[MODULE_KWS].obj = mod4; lv_obj_set_pos(mod4, x_pos, y_pos); lv_obj_set_size(mod4, module_width, module_height); lv_obj_set_style_bg_color(mod4, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(mod4, 5, 0); lv_obj_set_style_border_width(mod4, 1, 0); lv_obj_set_style_border_color(mod4, lv_color_hex(0x7F8C8D), 0); // TODO: Add image here - lv_image_set_src(img, &img_heater_cooler); lbl = lv_label_create(mod4); lv_label_set_text(lbl, "KWS"); lv_obj_set_pos(lbl, 20, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_kws = lv_label_create(mod4); lv_label_set_text(lbl_kws, "50%"); lv_obj_set_pos(lbl_kws, 20, 25); lv_obj_set_style_text_color(lbl_kws, lv_color_hex(0xE74C3C), 0); lv_obj_set_style_text_font(lbl_kws, &montserrat_16_ru_en, 0); lbl = lv_label_create(mod4); lv_label_set_text(lbl, "Нагрев"); lv_obj_set_pos(lbl, 10, 42); lv_obj_set_style_text_color(lbl, lv_color_hex(0xE67E22), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); x_pos += module_width + spacing; } /* Module 5: PWW */ if (modules[MODULE_PWW].enabled) { lv_obj_t *mod5 = lv_obj_create(panel_schema); modules[MODULE_PWW].obj = mod5; lv_obj_set_pos(mod5, x_pos, y_pos); lv_obj_set_size(mod5, module_width, module_height); lv_obj_set_style_bg_color(mod5, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(mod5, 5, 0); lv_obj_set_style_border_width(mod5, 1, 0); lv_obj_set_style_border_color(mod5, lv_color_hex(0x7F8C8D), 0); // TODO: Add image here - lv_image_set_src(img, &img_heater_cooler); lbl = lv_label_create(mod5); lv_label_set_text(lbl, "PWW"); lv_obj_set_pos(lbl, 20, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_pww = lv_label_create(mod5); lv_label_set_text(lbl_pww, "30%"); lv_obj_set_pos(lbl_pww, 20, 25); lv_obj_set_style_text_color(lbl_pww, lv_color_hex(0xE74C3C), 0); lv_obj_set_style_text_font(lbl_pww, &montserrat_16_ru_en, 0); lbl = lv_label_create(mod5); lv_label_set_text(lbl, "Нагрев"); lv_obj_set_pos(lbl, 10, 42); lv_obj_set_style_text_color(lbl, lv_color_hex(0xE67E22), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); x_pos += module_width + spacing; } /* Module 6: Электронагреватель */ if (modules[MODULE_HEATER].enabled) { lv_obj_t *mod6 = lv_obj_create(panel_schema); modules[MODULE_HEATER].obj = mod6; lv_obj_set_pos(mod6, x_pos, y_pos); lv_obj_set_size(mod6, module_width, module_height); lv_obj_set_style_bg_color(mod6, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(mod6, 5, 0); lv_obj_set_style_border_width(mod6, 1, 0); lv_obj_set_style_border_color(mod6, lv_color_hex(0x7F8C8D), 0); // TODO: Add image here - lv_image_set_src(img, &img_electric_heater); lbl = lv_label_create(mod6); lv_label_set_text(lbl, "Электро\nнагрев"); lv_obj_set_pos(lbl, 5, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_heater = lv_label_create(mod6); lv_label_set_text(lbl_heater, "ВЫКЛ"); lv_obj_set_pos(lbl_heater, 15, 38); lv_obj_set_style_text_color(lbl_heater, lv_color_hex(0x7F8C8D), 0); lv_obj_set_style_text_font(lbl_heater, &montserrat_16_ru_en, 0); x_pos += module_width + spacing; } /* Module 7: Вентилятор */ if (modules[MODULE_FAN].enabled) { lv_obj_t *mod7 = lv_obj_create(panel_schema); modules[MODULE_FAN].obj = mod7; lv_obj_set_pos(mod7, x_pos, y_pos); lv_obj_set_size(mod7, module_width, module_height); lv_obj_set_style_bg_color(mod7, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(mod7, 5, 0); lv_obj_set_style_border_width(mod7, 1, 0); lv_obj_set_style_border_color(mod7, lv_color_hex(0x7F8C8D), 0); // TODO: Add image here - lv_image_set_src(img, &img_fan); lbl = lv_label_create(mod7); lv_label_set_text(lbl, "Вентил."); lv_obj_set_pos(lbl, 5, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_fan = lv_label_create(mod7); lv_label_set_text(lbl_fan, "ВКЛ"); lv_obj_set_pos(lbl_fan, 20, 38); lv_obj_set_style_text_color(lbl_fan, lv_color_hex(0x2ECC71), 0); lv_obj_set_style_text_font(lbl_fan, &montserrat_16_ru_en, 0); x_pos += module_width + spacing; } /* Module 8: Фильтр H13 */ if (modules[MODULE_FILTER_H13].enabled) { lv_obj_t *mod8 = lv_obj_create(panel_schema); modules[MODULE_FILTER_H13].obj = mod8; lv_obj_set_pos(mod8, x_pos, y_pos); lv_obj_set_size(mod8, module_width, module_height); lv_obj_set_style_bg_color(mod8, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(mod8, 5, 0); lv_obj_set_style_border_width(mod8, 1, 0); lv_obj_set_style_border_color(mod8, lv_color_hex(0x7F8C8D), 0); // TODO: Add image here - lv_image_set_src(img, &img_filter); lbl = lv_label_create(mod8); lv_label_set_text(lbl, "Фильтр\nH13"); lv_obj_set_pos(lbl, 10, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_filter_h13 = lv_label_create(mod8); lv_label_set_text(lbl_filter_h13, "Чистый"); lv_obj_set_pos(lbl_filter_h13, 8, 38); lv_obj_set_style_text_color(lbl_filter_h13, lv_color_hex(0x2ECC71), 0); lv_obj_set_style_text_font(lbl_filter_h13, &montserrat_16_ru_en, 0); } /* Bottom row: Канал и Комната */ y_pos = 100; x_pos = 15; /* Module 9: Канал (после установки) */ lv_obj_t *mod9 = lv_obj_create(panel_schema); lv_obj_set_pos(mod9, x_pos, y_pos); lv_obj_set_size(mod9, 120, 80); lv_obj_set_style_bg_color(mod9, lv_color_hex(0x2C3E50), 0); lv_obj_set_style_radius(mod9, 8, 0); lv_obj_set_style_border_width(mod9, 2, 0); lv_obj_set_style_border_color(mod9, lv_color_hex(0x3498DB), 0); lbl = lv_label_create(mod9); lv_label_set_text(lbl, "КАНАЛ"); lv_obj_set_pos(lbl, 10, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl = lv_label_create(mod9); lv_label_set_text(lbl, "Температура:"); lv_obj_set_pos(lbl, 5, 28); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_temp_channel = lv_label_create(mod9); lv_label_set_text(lbl_temp_channel, "20.0°C"); lv_obj_set_pos(lbl_temp_channel, 10, 45); lv_obj_set_style_text_color(lbl_temp_channel, lv_color_hex(0x3498DB), 0); lv_obj_set_style_text_font(lbl_temp_channel, &montserrat_16_ru_en, 0); lbl = lv_label_create(mod9); lv_label_set_text(lbl, "Влажность:"); lv_obj_set_pos(lbl, 5, 60); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl_hum_channel = lv_label_create(mod9); lv_label_set_text(lbl_hum_channel, "50%"); lv_obj_set_pos(lbl_hum_channel, 80, 60); lv_obj_set_style_text_color(lbl_hum_channel, lv_color_hex(0x3498DB), 0); lv_obj_set_style_text_font(lbl_hum_channel, &montserrat_16_ru_en, 0); /* Module 10: Комната */ x_pos += 140; lv_obj_t *mod10 = lv_obj_create(panel_schema); lv_obj_set_pos(mod10, x_pos, y_pos); lv_obj_set_size(mod10, 250, 180); lv_obj_set_style_bg_color(mod10, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(mod10, 10, 0); lv_obj_set_style_border_width(mod10, 3, 0); lv_obj_set_style_border_color(mod10, lv_color_hex(0x2ECC71), 0); lbl = lv_label_create(mod10); lv_label_set_text(lbl, "ПОМЕЩЕНИЕ"); lv_obj_set_pos(lbl, 10, 10); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl = lv_label_create(mod10); lv_label_set_text(lbl, "Комната 101"); lv_obj_set_pos(lbl, 10, 35); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl = lv_label_create(mod10); lv_label_set_text(lbl, "Температура: 22.0°C"); lv_obj_set_pos(lbl, 10, 60); lv_obj_set_style_text_color(lbl, lv_color_hex(0xE74C3C), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl = lv_label_create(mod10); lv_label_set_text(lbl, "Влажность: 45%"); lv_obj_set_pos(lbl, 10, 85); lv_obj_set_style_text_color(lbl, lv_color_hex(0x3498DB), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl = lv_label_create(mod10); lv_label_set_text(lbl, "Режим: Дежурный"); lv_obj_set_pos(lbl, 10, 110); lv_obj_set_style_text_color(lbl, lv_color_hex(0xF39C12), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lbl = lv_label_create(mod10); lv_label_set_text(lbl, "Уставка: 21.0°C"); lv_obj_set_pos(lbl, 10, 135); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Air flow line (визуальная линия потока воздуха) */ lv_obj_t *line_obj = lv_obj_create(panel_schema); lv_obj_set_pos(line_obj, 15, 85); lv_obj_set_size(line_obj, 670, 4); lv_obj_set_style_bg_color(line_obj, lv_color_hex(0x3498DB), 0); lv_obj_set_style_radius(line_obj, 2, 0); lv_obj_set_style_border_width(line_obj, 0, 0); /* Arrow to room */ lv_obj_t *arrow = lv_obj_create(panel_schema); lv_obj_set_pos(arrow, 145, 130); lv_obj_set_size(arrow, 4, 70); lv_obj_set_style_bg_color(arrow, lv_color_hex(0x2ECC71), 0); lv_obj_set_style_radius(arrow, 2, 0); lv_obj_set_style_border_width(arrow, 0, 0); } static void create_screen_screen1(void) { lv_obj_t *scr = lv_obj_create(NULL); scr_screen1 = scr; lv_obj_set_style_bg_color(scr, lv_color_hex(0x2C3E50), 0); lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0); lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE); /* Title */ lv_obj_t *lbl = lv_label_create(scr); lv_label_set_text(lbl, "МЕНЮ"); lv_obj_set_pos(lbl, 350, 30); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); int btn_width = 300; int btn_height = 50; int x = 250; int y = 100; int spacing = 20; /* Button: Back to Main Screen */ lv_obj_t *btn = lv_btn_create(scr); lv_obj_set_pos(btn, x, y); lv_obj_set_size(btn, btn_width, btn_height); lv_obj_set_style_bg_color(btn, lv_color_hex(0x3498DB), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Главный экран"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_back_to_main_cb, LV_EVENT_CLICKED, NULL); y += btn_height + spacing; /* Button: Log (Журнал) */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, x, y); lv_obj_set_size(btn, btn_width, btn_height); lv_obj_set_style_bg_color(btn, lv_color_hex(0xE67E22), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Журнал аварий"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_log_cb, LV_EVENT_CLICKED, NULL); y += btn_height + spacing; /* Button: Settings Parameters (Уставка параметров) */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, x, y); lv_obj_set_size(btn, btn_width, btn_height); lv_obj_set_style_bg_color(btn, lv_color_hex(0x27AE60), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Уставка параметров"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_settings_cb, LV_EVENT_CLICKED, NULL); y += btn_height + spacing; /* Button: Configuration (Настройки - требует пароль) */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, x, y); lv_obj_set_size(btn, btn_width, btn_height); lv_obj_set_style_bg_color(btn, lv_color_hex(0xC0392B), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Настройки 🔒"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_config_cb, LV_EVENT_CLICKED, NULL); /* Footer info */ lbl = lv_label_create(scr); lv_label_set_text(lbl, "(для настроек пароль: 1234)"); lv_obj_set_pos(lbl, 270, 420); lv_obj_set_style_text_color(lbl, lv_color_hex(0x7F8C8D), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); } static void create_screen_screen2(void) { lv_obj_t *scr = lv_obj_create(NULL); scr_screen2 = scr; lv_obj_set_style_bg_color(scr, lv_color_hex(0x2C3E50), 0); lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0); lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE); /* Title */ lv_obj_t *lbl = lv_label_create(scr); lv_label_set_text(lbl, "ЖУРНАЛ АВАРИЙ"); lv_obj_set_pos(lbl, 300, 20); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Date/Time display */ lbl = lv_label_create(scr); lv_label_set_text(lbl, "25.02.2026 09:35"); lv_obj_set_pos(lbl, 650, 20); lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Log panel */ lv_obj_t *log_panel = lv_obj_create(scr); lv_obj_set_pos(log_panel, 20, 60); lv_obj_set_size(log_panel, 760, 300); lv_obj_set_style_bg_color(log_panel, lv_color_hex(0x34495E), 0); lv_obj_set_style_radius(log_panel, 8, 0); lv_obj_set_style_border_width(log_panel, 2, 0); lv_obj_set_style_border_color(log_panel, lv_color_hex(0x7F8C8D), 0); /* Display log entries */ int y = 10; if (alarm_count == 0) { lbl = lv_label_create(log_panel); lv_label_set_text(lbl, "Аварий нет"); lv_obj_set_pos(lbl, 320, 130); lv_obj_set_style_text_color(lbl, lv_color_hex(0x2ECC71), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); } else { for (int i = 0; i < alarm_count && i < 8; i++) { char buf[150]; snprintf(buf, sizeof(buf), "%s - %s", alarm_log[i].message, alarm_log[i].timestamp); lbl = lv_label_create(log_panel); lv_label_set_text(lbl, buf); lv_obj_set_pos(lbl, 10, y); lv_obj_set_width(lbl, 730); if (alarm_log[i].active) { lv_obj_set_style_text_color(lbl, lv_color_hex(0xE74C3C), 0); } else { lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); } lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 35; } } /* Buttons */ int btn_y = 380; /* Clear Log button */ lv_obj_t *btn = lv_btn_create(scr); lv_obj_set_pos(btn, 50, btn_y); lv_obj_set_size(btn, 150, 40); lv_obj_set_style_bg_color(btn, lv_color_hex(0xC0392B), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Очистить журнал"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); /* Reset Alarm button */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, 220, btn_y); lv_obj_set_size(btn, 150, 40); lv_obj_set_style_bg_color(btn, lv_color_hex(0xE67E22), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Сбросить аварию"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); /* Back to Menu button */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, 600, btn_y); lv_obj_set_size(btn, 150, 40); lv_obj_set_style_bg_color(btn, lv_color_hex(0x3498DB), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Меню"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_menu_cb, LV_EVENT_CLICKED, NULL); } static void create_screen_screen3(void) { lv_obj_t *scr = lv_obj_create(NULL); scr_screen3 = scr; lv_obj_set_style_bg_color(scr, lv_color_hex(0x2C3E50), 0); lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0); lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE); /* Title */ lv_obj_t *lbl = lv_label_create(scr); lv_label_set_text(lbl, "УСТАВКА ПАРАМЕТРОВ"); lv_obj_set_pos(lbl, 270, 20); lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Left panel - Work mode */ lv_obj_t *panel_work = lv_obj_create(scr); lv_obj_set_pos(panel_work, 20, 60); lv_obj_set_size(panel_work, 360, 300); lv_obj_set_style_bg_color(panel_work, lv_color_hex(0x27AE60), 0); lv_obj_set_style_radius(panel_work, 8, 0); lv_obj_set_style_border_width(panel_work, 2, 0); lbl = lv_label_create(panel_work); lv_label_set_text(lbl, "РАБОЧИЙ РЕЖИМ"); lv_obj_set_pos(lbl, 10, 10); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); int y = 50; char buf[64]; /* Temperature - clickable */ lv_obj_t *btn_temp = lv_btn_create(panel_work); lv_obj_set_pos(btn_temp, 10, y); lv_obj_set_size(btn_temp, 320, 30); lv_obj_set_style_bg_color(btn_temp, lv_color_hex(0x2C3E50), 0); lv_obj_set_style_radius(btn_temp, 5, 0); snprintf(buf, sizeof(buf), "Температура: %.1f°C", setpoint_work_temp); lbl = lv_label_create(btn_temp); lv_label_set_text(lbl, buf); lv_obj_set_pos(lbl, 10, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_add_event_cb(btn_temp, edit_work_temp_cb, LV_EVENT_CLICKED, NULL); y += 40; /* Humidity - clickable */ lv_obj_t *btn_hum = lv_btn_create(panel_work); lv_obj_set_pos(btn_hum, 10, y); lv_obj_set_size(btn_hum, 320, 30); lv_obj_set_style_bg_color(btn_hum, lv_color_hex(0x2C3E50), 0); lv_obj_set_style_radius(btn_hum, 5, 0); snprintf(buf, sizeof(buf), "Влажность: %.1f%%", setpoint_work_hum); lbl = lv_label_create(btn_hum); lv_label_set_text(lbl, buf); lv_obj_set_pos(lbl, 10, 5); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_add_event_cb(btn_hum, edit_work_hum_cb, LV_EVENT_CLICKED, NULL); y += 40; lbl = lv_label_create(panel_work); lv_label_set_text(lbl, "Клапан притока: 75%"); lv_obj_set_pos(lbl, 20, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 40; lbl = lv_label_create(panel_work); lv_label_set_text(lbl, "Вентилятор: ВКЛ"); lv_obj_set_pos(lbl, 20, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 40; lbl = lv_label_create(panel_work); lv_label_set_text(lbl, "KWS: АВТО"); lv_obj_set_pos(lbl, 20, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Right panel - Standby mode */ lv_obj_t *panel_standby = lv_obj_create(scr); lv_obj_set_pos(panel_standby, 400, 60); lv_obj_set_size(panel_standby, 360, 300); lv_obj_set_style_bg_color(panel_standby, lv_color_hex(0xF39C12), 0); lv_obj_set_style_radius(panel_standby, 8, 0); lv_obj_set_style_border_width(panel_standby, 2, 0); lbl = lv_label_create(panel_standby); lv_label_set_text(lbl, "ДЕЖУРНЫЙ РЕЖИМ"); lv_obj_set_pos(lbl, 10, 10); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y = 50; snprintf(buf, sizeof(buf), "Температура: %.1f°C", setpoint_standby_temp); lbl = lv_label_create(panel_standby); lv_label_set_text(lbl, buf); lv_obj_set_pos(lbl, 20, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 40; snprintf(buf, sizeof(buf), "Влажность: %.1f%%", setpoint_standby_hum); lbl = lv_label_create(panel_standby); lv_label_set_text(lbl, buf); lv_obj_set_pos(lbl, 20, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 40; lbl = lv_label_create(panel_standby); lv_label_set_text(lbl, "Клапан притока: 35%"); lv_obj_set_pos(lbl, 20, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 40; lbl = lv_label_create(panel_standby); lv_label_set_text(lbl, "Вентилятор: ВКЛ"); lv_obj_set_pos(lbl, 20, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); y += 40; lbl = lv_label_create(panel_standby); lv_label_set_text(lbl, "KWS: АВТО"); lv_obj_set_pos(lbl, 20, y); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Info */ lbl = lv_label_create(scr); lv_label_set_text(lbl, "(нажмите на параметр для редактирования - этап 5)"); lv_obj_set_pos(lbl, 200, 370); lv_obj_set_style_text_color(lbl, lv_color_hex(0x7F8C8D), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); /* Buttons */ int btn_y = 410; /* Save button */ lv_obj_t *btn = lv_btn_create(scr); lv_obj_set_pos(btn, 200, btn_y); lv_obj_set_size(btn, 120, 40); lv_obj_set_style_bg_color(btn, lv_color_hex(0x2ECC71), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Сохранить"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); /* Default button */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, 340, btn_y); lv_obj_set_size(btn, 140, 40); lv_obj_set_style_bg_color(btn, lv_color_hex(0xE67E22), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "По умолчанию"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); /* Back to Menu button */ btn = lv_btn_create(scr); lv_obj_set_pos(btn, 500, btn_y); lv_obj_set_size(btn, 100, 40); lv_obj_set_style_bg_color(btn, lv_color_hex(0x3498DB), 0); lv_obj_set_style_radius(btn, 8, 0); lbl = lv_label_create(btn); lv_label_set_text(lbl, "Меню"); lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); lv_obj_center(lbl); lv_obj_add_event_cb(btn, btn_menu_cb, LV_EVENT_CLICKED, NULL); } void gui_update_values(void) { char buf[64]; /* Update room climate */ if (lbl_temp_room) { snprintf(buf, sizeof(buf), "%.1f°C", var_temp_room / 1.0); lv_label_set_text(lbl_temp_room, buf); } if (lbl_hum_room) { snprintf(buf, sizeof(buf), "%d%%", (int)var_hum_room); lv_label_set_text(lbl_hum_room, buf); } /* Update channel climate */ if (lbl_temp_channel) { snprintf(buf, sizeof(buf), "%.1f°C", var_temp_channel / 1.0); lv_label_set_text(lbl_temp_channel, buf); } if (lbl_hum_channel) { snprintf(buf, sizeof(buf), "%d%%", (int)var_hum_channel); lv_label_set_text(lbl_hum_channel, buf); } /* Update system status */ if (lbl_room_num) { snprintf(buf, sizeof(buf), "Комната: %d", (int)var_room_num); lv_label_set_text(lbl_room_num, buf); } if (lbl_master_slave) { lv_label_set_text(lbl_master_slave, var_is_master ? "Мастер" : "Слейв"); lv_obj_set_style_text_color(lbl_master_slave, var_is_master ? lv_color_hex(0x2ECC71) : lv_color_hex(0xE67E22), 0); } if (lbl_season) { const char *seasons[] = {"Зима", "Лето", "Переход"}; const uint32_t colors[] = {0x3498DB, 0xE74C3C, 0xF39C12}; snprintf(buf, sizeof(buf), "Сезон: %s", seasons[var_season % 3]); lv_label_set_text(lbl_season, buf); lv_obj_set_style_text_color(lbl_season, lv_color_hex(colors[var_season % 3]), 0); } if (lbl_mode) { const char *modes[] = {"Остановка", "Дежурный", "Рабочий"}; const uint32_t colors[] = {0xC0392B, 0xF39C12, 0x27AE60}; snprintf(buf, sizeof(buf), "Режим: %s", modes[var_mode % 3]); lv_label_set_text(lbl_mode, buf); lv_obj_set_style_text_color(lbl_mode, lv_color_hex(colors[var_mode % 3]), 0); } /* Update equipment modules */ if (lbl_valve_inlet) { snprintf(buf, sizeof(buf), "%d%%", (int)var_valve_inlet); lv_label_set_text(lbl_valve_inlet, buf); } if (lbl_valve_recirc) { snprintf(buf, sizeof(buf), "%d%%", (int)var_valve_recirc); lv_label_set_text(lbl_valve_recirc, buf); } if (lbl_filter_g4) { lv_label_set_text(lbl_filter_g4, var_filter_g4 ? "Чистый" : "Грязный"); lv_obj_set_style_text_color(lbl_filter_g4, var_filter_g4 ? lv_color_hex(0x2ECC71) : lv_color_hex(0xE74C3C), 0); } if (lbl_kws) { snprintf(buf, sizeof(buf), "%d%%", (int)var_kws_valve); lv_label_set_text(lbl_kws, buf); } if (lbl_pww) { snprintf(buf, sizeof(buf), "%d%%", (int)var_pww_valve); lv_label_set_text(lbl_pww, buf); } if (lbl_heater) { lv_label_set_text(lbl_heater, var_heater_on ? "ВКЛ" : "ВЫКЛ"); lv_obj_set_style_text_color(lbl_heater, var_heater_on ? lv_color_hex(0xE74C3C) : lv_color_hex(0x7F8C8D), 0); } if (lbl_fan) { lv_label_set_text(lbl_fan, var_fan_on ? "ВКЛ" : "ВЫКЛ"); lv_obj_set_style_text_color(lbl_fan, var_fan_on ? lv_color_hex(0x2ECC71) : lv_color_hex(0xC0392B), 0); } if (lbl_filter_h13) { lv_label_set_text(lbl_filter_h13, var_filter_h13 ? "Чистый" : "Грязный"); lv_obj_set_style_text_color(lbl_filter_h13, var_filter_h13 ? lv_color_hex(0x2ECC71) : lv_color_hex(0xE74C3C), 0); } /* Check for alarm conditions */ static int alarm_check_counter = 0; alarm_check_counter++; // Example: Show alarm if temperature is too low (freeze risk) if (alarm_check_counter > 50 && var_temp_channel < 5 && var_mode != 0) { create_popup_alarm("Угроза заморозки!\nУстановка остановлена.\n\nПроверьте журнал и примите меры."); var_mode = 0; // Stop system alarm_check_counter = 0; } // Example: Show alarm if filter is dirty if (alarm_check_counter > 100 && var_filter_g4 == 0) { create_popup_alarm("Фильтр G4 засорился!\n\nЗамените фильтр для нормальной работы."); alarm_check_counter = 0; } } void gui_init(void) { /* Add some example alarms to the log */ add_alarm_to_log("Система запущена", 0); add_alarm_to_log("Фильтр G4 заменен", 0); create_screen_main(); create_screen_screen1(); create_screen_screen2(); create_screen_screen3(); lv_scr_load(scr_main); } /* ── ModBus ──────────────────────────────────────── */ /* ModBus disabled for simulation - use dummy values */ void gui_modbus_init(void) { /* No-op for simulation */ } void gui_modbus_task(void *arg) { (void)arg; /* Simulation: update with dummy values */ while (1) { var_temp_room = 22 + (rand() % 4); var_hum_room = 45 + (rand() % 10); var_temp_channel = 20 + (rand() % 3); var_hum_channel = 50 + (rand() % 8); /* Simulate valve changes based on mode */ if (var_mode == 2) { // Рабочий режим var_valve_inlet = 70 + (rand() % 30); var_valve_recirc = 10 + (rand() % 20); var_kws_valve = 40 + (rand() % 30); var_pww_valve = 30 + (rand() % 25); var_fan_on = 1; } else if (var_mode == 1) { // Дежурный var_valve_inlet = 30 + (rand() % 20); var_valve_recirc = 40 + (rand() % 20); var_kws_valve = 20 + (rand() % 15); var_pww_valve = 15 + (rand() % 15); var_fan_on = 1; } else { // Остановка var_valve_inlet = 0; var_valve_recirc = 0; var_kws_valve = 0; var_pww_valve = 0; var_fan_on = 0; var_heater_on = 0; } gui_update_values(); /* Sleep simulation - requires FreeRTOS or use SDL delay */ } }