lvgl-hmi-display-ui/src/gui_generated.c
2026-02-25 17:07:18 +07:00

1655 lines
65 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* AUTO-GENERATED by GUI Editor — do not edit manually */
#include "gui_generated.h"
#include "lvgl.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/* 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 */
}
}