Release 2026-04-14

This commit is contained in:
2026-04-14 08:28:59 +03:00
parent 33b93e976b
commit 52eddcc2c6
3 changed files with 5153 additions and 18 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -117,6 +117,11 @@ void setup()
lv_display_set_rotation(display, LV_DISPLAY_ROTATION_180);
buildUi();
lv_tick_inc(1);
lv_timer_handler();
delay(20);
lv_tick_inc(20);
lv_timer_handler();
WiFi.mode(WIFI_OFF);
if (!wifi_data.ssid.isEmpty())

View File

@@ -4,9 +4,41 @@
#include <stdio.h>
#include <string.h>
LV_FONT_DECLARE(filament_weight_font_125);
namespace
{
constexpr lv_buttonmatrix_ctrl_t makeKeyboardCtrl(unsigned width, unsigned flags = 0U)
{
return static_cast<lv_buttonmatrix_ctrl_t>(flags | width);
}
constexpr unsigned kBatchDigitCtrlFlags = static_cast<unsigned>(LV_BUTTONMATRIX_CTRL_POPOVER);
constexpr unsigned kBatchActionCtrlFlags = static_cast<unsigned>(LV_KEYBOARD_CTRL_BUTTON_FLAGS);
static const char *const kBatchKeyboardMap[] = {
"1", "2", "3", "\n",
"4", "5", "6", "\n",
"7", "8", "9", "\n",
LV_SYMBOL_CLOSE, "0", LV_SYMBOL_BACKSPACE, "\n",
LV_SYMBOL_OK, NULL};
static const lv_buttonmatrix_ctrl_t kBatchKeyboardCtrl[] = {
makeKeyboardCtrl(1, kBatchDigitCtrlFlags),
makeKeyboardCtrl(1, kBatchDigitCtrlFlags),
makeKeyboardCtrl(1, kBatchDigitCtrlFlags),
makeKeyboardCtrl(1, kBatchDigitCtrlFlags),
makeKeyboardCtrl(1, kBatchDigitCtrlFlags),
makeKeyboardCtrl(1, kBatchDigitCtrlFlags),
makeKeyboardCtrl(1, kBatchDigitCtrlFlags),
makeKeyboardCtrl(1, kBatchDigitCtrlFlags),
makeKeyboardCtrl(1, kBatchDigitCtrlFlags),
makeKeyboardCtrl(1, kBatchActionCtrlFlags),
makeKeyboardCtrl(1, kBatchDigitCtrlFlags),
makeKeyboardCtrl(1, kBatchActionCtrlFlags),
makeKeyboardCtrl(3, kBatchActionCtrlFlags)};
lv_coord_t clampCoord(lv_coord_t value, lv_coord_t min_value, lv_coord_t max_value)
{
if (value < min_value)
@@ -76,6 +108,11 @@ void createPageHeader(lv_obj_t *page, const char *title_text, const char *subtit
alignTopCenter(subtitle, 48);
}
bool isBatchInputTarget(const lv_obj_t *target)
{
return target == ui.workflow_batch_ta || target == ui.inventree_batch_ta;
}
void applyTextEditorChanges()
{
if (ui.text_editor_target == nullptr || ui.text_editor_ta == nullptr)
@@ -173,11 +210,16 @@ void openTextEditor(lv_obj_t *target, const char *title)
}
ui.text_editor_target = target;
const bool batch_input = isBatchInputTarget(target);
setLabelTextIfChanged(ui.text_editor_title, title != nullptr ? title : "Edit");
lv_textarea_set_password_mode(ui.text_editor_ta, lv_textarea_get_password_mode(target));
lv_textarea_set_accepted_chars(ui.text_editor_ta, batch_input ? "0123456789" : nullptr);
lv_textarea_set_text(ui.text_editor_ta, lv_textarea_get_text(target));
lv_keyboard_set_textarea(ui.wifi_keyboard, ui.text_editor_ta);
lv_keyboard_set_mode(ui.wifi_keyboard, LV_KEYBOARD_MODE_TEXT_LOWER);
lv_keyboard_set_mode(ui.wifi_keyboard, batch_input ? LV_KEYBOARD_MODE_USER_1 : LV_KEYBOARD_MODE_TEXT_LOWER);
lv_obj_set_style_text_font(ui.wifi_keyboard,
batch_input ? &lv_font_montserrat_24 : &lv_font_montserrat_18,
LV_PART_ITEMS);
layoutTextEditor();
lv_obj_clear_flag(ui.text_editor_overlay, LV_OBJ_FLAG_HIDDEN);
lv_obj_move_foreground(ui.text_editor_overlay);
@@ -207,6 +249,33 @@ void setLabelFloatText(lv_obj_t *label, const char *format, float value)
setLabelTextIfChanged(label, buffer);
}
void setWeightValueText(const char *value_text, const char *unit_text)
{
if (ui.weight_label == nullptr)
{
return;
}
char buffer[48];
if (unit_text != nullptr && unit_text[0] != '\0')
{
snprintf(buffer, sizeof(buffer), "%s %s", value_text != nullptr ? value_text : "--", unit_text);
}
else
{
snprintf(buffer, sizeof(buffer), "%s", value_text != nullptr ? value_text : "--");
}
setLabelTextIfChanged(ui.weight_label, buffer);
}
void setWeightValueText(long value, const char *unit_text)
{
char value_buffer[24];
snprintf(value_buffer, sizeof(value_buffer), "%ld", value);
setWeightValueText(value_buffer, unit_text);
}
void applyCalibrationState()
{
setLabelLongText(ui.cal_offset_value, "%ld", static_cast<long>(calibration.offset));
@@ -333,7 +402,6 @@ lv_obj_t *createNavButton(lv_obj_t *parent,
constexpr lv_coord_t kButtonWidth = 116;
lv_obj_t *button = lv_button_create(parent);
lv_obj_set_size(button, kButtonWidth, 58);
lv_obj_set_pos(button, (156 - kButtonWidth) / 2, y);
lv_obj_remove_flag(button, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_style_radius(button, 18, 0);
lv_obj_set_style_bg_color(button, lv_color_hex(0x101010), 0);
@@ -341,6 +409,7 @@ lv_obj_t *createNavButton(lv_obj_t *parent,
lv_obj_set_style_border_width(button, 1, 0);
lv_obj_set_style_shadow_width(button, 0, 0);
lv_obj_add_event_cb(button, cb, LV_EVENT_CLICKED, nullptr);
lv_obj_align(button, LV_ALIGN_TOP_MID, 0, y);
lv_obj_t *label = lv_label_create(button);
lv_obj_set_style_text_font(label, &lv_font_montserrat_18, 0);
@@ -563,20 +632,21 @@ void buildWeightPage()
lv_obj_center(ui.status_label);
ui.weight_label = lv_label_create(page);
styleCenteredText(ui.weight_label, kContentInnerWidth, &lv_font_montserrat_48, lv_color_hex(0xF8FEFF));
lv_label_set_text(ui.weight_label, "--");
alignTopCenter(ui.weight_label, 82);
styleCenteredText(ui.weight_label, kContentInnerWidth, &filament_weight_font_125, lv_color_hex(0xF8FEFF));
lv_label_set_text(ui.weight_label, "-- g");
alignTopCenter(ui.weight_label, 58);
ui.weight_unit_label = lv_label_create(page);
styleCenteredText(ui.weight_unit_label, kContentInnerWidth, &lv_font_montserrat_24, lv_color_hex(0x8FA3AC));
lv_label_set_text(ui.weight_unit_label, "g");
alignTopCenter(ui.weight_unit_label, 134);
lv_obj_add_flag(ui.weight_unit_label, LV_OBJ_FLAG_HIDDEN);
ui.mode_label = lv_label_create(page);
styleCenteredText(ui.mode_label, kContentInnerWidth, &lv_font_montserrat_18, lv_color_hex(0x7FA1B2));
lv_label_set_long_mode(ui.mode_label, LV_LABEL_LONG_WRAP);
lv_label_set_text(ui.mode_label, "Waiting for HX711...");
lv_label_set_text(ui.mode_label, "");
alignTopCenter(ui.mode_label, 170);
lv_obj_add_flag(ui.mode_label, LV_OBJ_FLAG_HIDDEN);
ui.weight_raw_value = nullptr;
lv_obj_t *batch_label = lv_label_create(page);
@@ -586,6 +656,7 @@ void buildWeightPage()
lv_label_set_text(batch_label, "Batch Code");
ui.workflow_batch_ta = createTextInput(page, 24, 234, kContentInnerWidth, "Main Batch Code", "Scan or type Batch Code", false);
lv_textarea_set_accepted_chars(ui.workflow_batch_ta, "0123456789");
if (!inventree_data.batch.isEmpty())
{
lv_textarea_set_text(ui.workflow_batch_ta, inventree_data.batch.c_str());
@@ -728,6 +799,7 @@ void buildInventreePage()
lv_label_set_text(batch_label, "Batch Code");
ui.inventree_batch_ta = createTextInput(page, kLeftColumnX, 276, kColumnWidth, "InvenTree Batch Code", "Batch Code", false);
lv_textarea_set_accepted_chars(ui.inventree_batch_ta, "0123456789");
if (!inventree_data.batch.isEmpty())
{
lv_textarea_set_text(ui.inventree_batch_ta, inventree_data.batch.c_str());
@@ -801,6 +873,14 @@ void setWeightStatus(const char *text, lv_color_t color)
return;
}
if (text == nullptr || text[0] == '\0')
{
lv_obj_add_flag(ui.status_chip, LV_OBJ_FLAG_HIDDEN);
setLabelTextIfChanged(ui.status_label, "");
return;
}
lv_obj_clear_flag(ui.status_chip, LV_OBJ_FLAG_HIDDEN);
lv_obj_set_style_bg_color(ui.status_chip, color, 0);
setLabelTextIfChanged(ui.status_label, text);
}
@@ -861,9 +941,9 @@ void refreshUi()
{
applyCalibrationState();
}
setLabelTextIfChanged(ui.weight_label, "--");
setLabelTextIfChanged(ui.weight_unit_label, "g");
setLabelTextIfChanged(ui.mode_label, "HX711 offline");
setWeightValueText("--", "g");
setLabelTextIfChanged(ui.weight_unit_label, "");
setLabelTextIfChanged(ui.mode_label, "");
setLabelTextIfChanged(ui.weight_raw_value, "waiting...");
setLabelTextIfChanged(ui.cal_raw_value, "waiting...");
setWeightStatus("WAIT", lv_color_hex(0x8A6D1A));
@@ -885,17 +965,17 @@ void refreshUi()
const int32_t stable_grams = displayed_weight_valid
? displayed_weight_grams
: static_cast<int32_t>(lroundf(getCurrentWeightGrams()));
setLabelLongText(ui.weight_label, "%ld", static_cast<long>(stable_grams));
setLabelTextIfChanged(ui.weight_unit_label, "g");
setLabelTextIfChanged(ui.mode_label, "Filtered weight, ready for Batch workflow");
setWeightStatus("LIVE", lv_color_hex(0x1E7A55));
setWeightValueText(static_cast<long>(stable_grams), "g");
setLabelTextIfChanged(ui.weight_unit_label, "");
setLabelTextIfChanged(ui.mode_label, "");
setWeightStatus("", lv_color_hex(0x1E7A55));
}
else
{
displayed_weight_valid = false;
setLabelLongText(ui.weight_label, "%ld", static_cast<long>(lroundf(filtered_raw)));
setLabelTextIfChanged(ui.weight_unit_label, "cnt");
setLabelTextIfChanged(ui.mode_label, "Raw mode. Open Calibration to tare and scale.");
setWeightValueText(static_cast<long>(lroundf(filtered_raw)), "cnt");
setLabelTextIfChanged(ui.weight_unit_label, "");
setLabelTextIfChanged(ui.mode_label, "");
setWeightStatus("RAW", lv_color_hex(0x1F5E7A));
}
}
@@ -1047,6 +1127,9 @@ void buildUi()
lv_obj_set_size(ui.screen, getDisplayWidth(), getDisplayHeight());
lv_obj_set_style_bg_color(ui.screen, lv_color_black(), 0);
lv_obj_set_style_bg_grad_color(ui.screen, lv_color_black(), 0);
lv_obj_set_style_bg_opa(ui.screen, LV_OPA_COVER, 0);
lv_obj_set_style_border_width(ui.screen, 0, 0);
lv_obj_set_style_pad_all(ui.screen, 0, 0);
ui.nav_panel = lv_obj_create(ui.screen);
lv_obj_set_size(ui.nav_panel, 156, kContentHeight);
@@ -1055,17 +1138,19 @@ void buildUi()
lv_obj_set_style_radius(ui.nav_panel, kPanelRadius, 0);
lv_obj_set_style_bg_color(ui.nav_panel, lv_color_black(), 0);
lv_obj_set_style_bg_grad_color(ui.nav_panel, lv_color_black(), 0);
lv_obj_set_style_bg_opa(ui.nav_panel, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(ui.nav_panel, lv_color_hex(0x161616), 0);
lv_obj_set_style_border_width(ui.nav_panel, 1, 0);
lv_obj_set_style_shadow_width(ui.nav_panel, 0, 0);
lv_obj_set_style_pad_all(ui.nav_panel, 0, 0);
lv_obj_t *nav_title = lv_label_create(ui.nav_panel);
lv_obj_set_pos(nav_title, 18, 24);
lv_obj_set_width(nav_title, 120);
lv_obj_set_style_text_color(nav_title, lv_color_hex(0xF5FAFC), 0);
lv_obj_set_style_text_font(nav_title, &lv_font_montserrat_20, 0);
lv_obj_set_style_text_align(nav_title, LV_TEXT_ALIGN_CENTER, 0);
lv_label_set_text(nav_title, "Menu");
lv_obj_align(nav_title, LV_ALIGN_TOP_MID, 0, 24);
createNavButton(ui.nav_panel, "Main", 96, navWeightEvent, PageId::Weight);
createNavButton(ui.nav_panel, "Cal", 166, navCalibrationEvent, PageId::Calibration);
@@ -1079,6 +1164,7 @@ void buildUi()
lv_obj_set_style_radius(ui.content_panel, kPanelRadius, 0);
lv_obj_set_style_bg_color(ui.content_panel, lv_color_black(), 0);
lv_obj_set_style_bg_grad_color(ui.content_panel, lv_color_black(), 0);
lv_obj_set_style_bg_opa(ui.content_panel, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(ui.content_panel, lv_color_hex(0x161616), 0);
lv_obj_set_style_border_width(ui.content_panel, 1, 0);
lv_obj_set_style_shadow_width(ui.content_panel, 0, 0);
@@ -1105,6 +1191,7 @@ void buildUi()
lv_obj_set_style_radius(ui.text_editor_panel, kPanelRadius, 0);
lv_obj_set_style_bg_color(ui.text_editor_panel, lv_color_black(), 0);
lv_obj_set_style_bg_grad_color(ui.text_editor_panel, lv_color_black(), 0);
lv_obj_set_style_bg_opa(ui.text_editor_panel, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(ui.text_editor_panel, lv_color_hex(0x1A1A1A), 0);
lv_obj_set_style_border_width(ui.text_editor_panel, 1, 0);
lv_obj_set_style_shadow_width(ui.text_editor_panel, 0, 0);
@@ -1123,6 +1210,7 @@ void buildUi()
ui.text_editor_ta = lv_textarea_create(ui.text_editor_panel);
lv_obj_set_style_radius(ui.text_editor_ta, 14, 0);
lv_obj_set_style_bg_color(ui.text_editor_ta, lv_color_black(), 0);
lv_obj_set_style_bg_opa(ui.text_editor_ta, LV_OPA_COVER, 0);
lv_obj_set_style_border_color(ui.text_editor_ta, lv_color_hex(0x2A2A2A), 0);
lv_obj_set_style_border_width(ui.text_editor_ta, 1, 0);
lv_obj_set_style_text_color(ui.text_editor_ta, lv_color_hex(0xF5FAFC), 0);
@@ -1134,6 +1222,7 @@ void buildUi()
lv_obj_set_style_radius(ui.wifi_keyboard, 24, LV_PART_MAIN);
lv_obj_set_style_bg_color(ui.wifi_keyboard, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_grad_color(ui.wifi_keyboard, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(ui.wifi_keyboard, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_border_color(ui.wifi_keyboard, lv_color_hex(0x1A1A1A), LV_PART_MAIN);
lv_obj_set_style_border_width(ui.wifi_keyboard, 1, LV_PART_MAIN);
lv_obj_set_style_shadow_width(ui.wifi_keyboard, 0, LV_PART_MAIN);
@@ -1143,7 +1232,9 @@ void buildUi()
lv_obj_set_style_radius(ui.wifi_keyboard, 12, LV_PART_ITEMS);
lv_obj_set_style_border_width(ui.wifi_keyboard, 0, LV_PART_ITEMS);
lv_obj_set_style_shadow_width(ui.wifi_keyboard, 0, LV_PART_ITEMS);
lv_obj_set_style_text_font(ui.wifi_keyboard, &lv_font_montserrat_18, LV_PART_ITEMS);
lv_obj_remove_flag(ui.wifi_keyboard, LV_OBJ_FLAG_SCROLLABLE);
lv_keyboard_set_map(ui.wifi_keyboard, LV_KEYBOARD_MODE_USER_1, kBatchKeyboardMap, kBatchKeyboardCtrl);
lv_keyboard_set_mode(ui.wifi_keyboard, LV_KEYBOARD_MODE_TEXT_LOWER);
lv_obj_add_event_cb(ui.wifi_keyboard, textEditorKeyboardEvent, LV_EVENT_ALL, nullptr);
layoutTextEditor();