1655 lines
65 KiB
C
1655 lines
65 KiB
C
/* 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 */
|
||
}
|
||
}
|