运行/自检记录与待机屏:sys_log定长64B日志引擎(/log/*.log,FTP可直下)+记录页x2+待机屏+密码错误提示;字体122字/217字形
This commit is contained in:
@@ -43,6 +43,12 @@
|
||||
|
||||
#include "ui_page_net_cfg.h"
|
||||
|
||||
#include "ui_page_runlog.h"
|
||||
|
||||
#include "ui_page_selftest.h"
|
||||
|
||||
#include "ui_standby.h"
|
||||
|
||||
#include "ui_pwd_def.h"
|
||||
|
||||
#include "ui_menu_view.h"
|
||||
@@ -76,11 +82,13 @@
|
||||
* 框架机制不变,见 内容页架构.md §七)
|
||||
*/
|
||||
static const content_page_def_t *const s_defs[CONTENT_PAGE_COUNT] = {
|
||||
[CONTENT_PAGE_DEVICE_INFO] = &ui_page_device_info_desc,
|
||||
[CONTENT_PAGE_AC] = &ui_page_ac_desc,
|
||||
[CONTENT_PAGE_DC] = &ui_page_dc_desc,
|
||||
[CONTENT_PAGE_PASSWORD] = &ui_page_password_desc,
|
||||
[CONTENT_PAGE_NET_CFG] = &ui_page_net_cfg_desc,
|
||||
[CONTENT_PAGE_DEVICE_INFO] = &ui_page_device_info_desc,
|
||||
[CONTENT_PAGE_AC] = &ui_page_ac_desc,
|
||||
[CONTENT_PAGE_DC] = &ui_page_dc_desc,
|
||||
[CONTENT_PAGE_PASSWORD] = &ui_page_password_desc,
|
||||
[CONTENT_PAGE_NET_CFG] = &ui_page_net_cfg_desc,
|
||||
[CONTENT_PAGE_RUN_LOG] = &ui_page_runlog_desc,
|
||||
[CONTENT_PAGE_SELFTEST_LOG] = &ui_page_selftest_desc,
|
||||
};
|
||||
|
||||
static content_page_id_t s_open = CONTENT_PAGE_COUNT; /* 当前打开的页(COUNT = 未打开) */
|
||||
@@ -176,8 +184,9 @@ static void cp_draw_centered_text(lv_layer_t *layer, const char *text, int32_t y
|
||||
ld.text = text;
|
||||
ld.text_static = 1; /* Flash 字符串:不拷内存 */
|
||||
ld.color = lv_color_white();
|
||||
/* 本 LVGL 版 lv_text_get_width 的 length=0 表示"不测量",必须传 strlen */
|
||||
ld.ofs_x = (CP_SCREEN_W - lv_text_get_width(text, (uint32_t)strlen(text), LV_FONT_DEFAULT, 0)) / 2;
|
||||
/* 本 LVGL 版 lv_text_get_width:length=0 表示"不测量"(返回 0);
|
||||
* length≠0 时循环无 NUL 检查,传 -1 会越串尾死循环——必须传 strlen */
|
||||
ld.ofs_x = (CP_SCREEN_W - lv_text_get_width(text, (uint32_t)strlen(text), LV_FONT_DEFAULT, 0)) / 2;
|
||||
ld.ofs_y = 0;
|
||||
lv_draw_label(layer, &ld, &area);
|
||||
}
|
||||
@@ -432,6 +441,8 @@ static void cp_key_cb(lv_event_t *e) {
|
||||
const content_page_def_t *d = s_defs[s_open];
|
||||
lv_key_t key = (lv_key_t)lv_event_get_key(e);
|
||||
|
||||
ui_standby_notify_activity(); /* 用户活动:重置待机空闲计时 */
|
||||
|
||||
/* ESC:关闭页面返回菜单屏(焦点/导航状态还原;恒不可拦截) */
|
||||
if (key == LV_KEY_ESC) {
|
||||
ui_content_page_close();
|
||||
|
||||
@@ -42,6 +42,8 @@ typedef enum {
|
||||
CONTENT_PAGE_DC, /* 直流量(node 4):数据列表,3 项单页 */
|
||||
CONTENT_PAGE_PASSWORD, /* 用户密钥(密码页):3 位密码,表单/操作页首个实例 */
|
||||
CONTENT_PAGE_NET_CFG, /* 网口设置(node 30):地址列表 + 保存行,可编辑(修改权限) */
|
||||
CONTENT_PAGE_RUN_LOG, /* 运行记录(node 40):动态列表,每记录 2 行(时间戳+描述) */
|
||||
CONTENT_PAGE_SELFTEST_LOG, /* 自检记录(node 39):动态列表,每记录 2 行(时间戳+故障) */
|
||||
CONTENT_PAGE_COUNT /* 哨兵:无效 ID / 未打开 */
|
||||
} content_page_id_t;
|
||||
|
||||
|
||||
+139
-71
@@ -311,6 +311,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80,
|
||||
|
||||
/* U+4E0A "上" */
|
||||
0x8, 0x1, 0x0, 0x20, 0x4, 0x0, 0xfc, 0x10,
|
||||
0x2, 0x0, 0x40, 0x8, 0x1, 0x0, 0x20, 0x7f,
|
||||
0xf0,
|
||||
|
||||
/* U+4E3B "主" */
|
||||
0x8, 0x0, 0x80, 0x0, 0x3f, 0xe0, 0x40, 0x8,
|
||||
0x1, 0x3, 0xfe, 0x4, 0x0, 0x80, 0x10, 0x7f,
|
||||
@@ -351,6 +356,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0x92, 0x12, 0x7e, 0x48, 0x49, 0xf9, 0x21, 0x2f,
|
||||
0xf0,
|
||||
|
||||
/* U+5165 "入" */
|
||||
0x30, 0x1, 0x0, 0x10, 0x2, 0x0, 0xa0, 0x14,
|
||||
0x2, 0x80, 0x88, 0x11, 0x4, 0x11, 0x1, 0x40,
|
||||
0x10,
|
||||
|
||||
/* U+5171 "共" */
|
||||
0x11, 0x2, 0x20, 0x44, 0x3f, 0xe1, 0x10, 0x22,
|
||||
0x4, 0x47, 0xff, 0x0, 0x2, 0x20, 0x82, 0x20,
|
||||
@@ -466,11 +476,21 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0x63, 0xe9, 0x80, 0x4, 0x8, 0x89, 0x11, 0x3f,
|
||||
0xe0,
|
||||
|
||||
/* U+5E38 "常" */
|
||||
0x24, 0x82, 0xa3, 0xff, 0xc0, 0x13, 0xf8, 0x41,
|
||||
0xf, 0xe0, 0x20, 0x7f, 0xc8, 0x89, 0x13, 0x2,
|
||||
0x0,
|
||||
|
||||
/* U+5E8F "序" */
|
||||
0x2, 0xf, 0xfd, 0x0, 0x2f, 0xe4, 0x8, 0x9a,
|
||||
0x10, 0x83, 0xff, 0x42, 0x28, 0x49, 0x8, 0x43,
|
||||
0x0,
|
||||
|
||||
/* U+5F02 "异" */
|
||||
0x7f, 0xc8, 0x9, 0xff, 0x20, 0x4, 0x2, 0x7f,
|
||||
0xc4, 0x20, 0x84, 0xff, 0xe2, 0x10, 0x82, 0x20,
|
||||
0x40,
|
||||
|
||||
/* U+5F0F "式" */
|
||||
0x1, 0x40, 0x24, 0x4, 0x7f, 0xf0, 0x10, 0x2,
|
||||
0x1f, 0x40, 0x88, 0x10, 0x82, 0x14, 0x79, 0xf0,
|
||||
@@ -637,6 +657,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0x90, 0x12, 0x2, 0x7f, 0xc0, 0x1, 0x49, 0x44,
|
||||
0x90,
|
||||
|
||||
/* U+7247 "片" */
|
||||
0x1, 0x4, 0x20, 0x84, 0x10, 0x83, 0xfe, 0x40,
|
||||
0x8, 0x1, 0xfc, 0x20, 0x88, 0x11, 0x2, 0x40,
|
||||
0x40,
|
||||
|
||||
/* U+7248 "版" */
|
||||
0x10, 0x6a, 0xf1, 0x50, 0x2a, 0x7, 0xfe, 0x8a,
|
||||
0x51, 0x4b, 0xaa, 0x55, 0x4a, 0x91, 0x65, 0x49,
|
||||
@@ -646,6 +671,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0x7f, 0xd1, 0x14, 0x45, 0xff, 0x44, 0x51, 0x17,
|
||||
0xfd, 0x11, 0x44, 0x51, 0x18, 0x1c,
|
||||
|
||||
/* U+7535 "电" */
|
||||
0x8, 0x1, 0x3, 0xfe, 0x44, 0x48, 0x89, 0xff,
|
||||
0x22, 0x24, 0x44, 0xff, 0x91, 0x4, 0x20, 0x83,
|
||||
0xf0,
|
||||
|
||||
/* U+754C "界" */
|
||||
0x7f, 0xc8, 0x89, 0xff, 0x22, 0x27, 0xfc, 0x8,
|
||||
0x6, 0xc7, 0x7, 0x11, 0x2, 0x20, 0x84, 0x20,
|
||||
@@ -723,6 +753,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0x8, 0x8, 0x3f, 0xf0, 0x18, 0xf, 0xfe, 0x3,
|
||||
0x1, 0xff, 0xc0, 0x60, 0x3f, 0xf0,
|
||||
|
||||
/* U+82AF "芯" */
|
||||
0x11, 0x2, 0x23, 0xff, 0x88, 0x80, 0x0, 0x8,
|
||||
0x4, 0x82, 0x92, 0x50, 0x2a, 0x16, 0x42, 0x87,
|
||||
0xc0,
|
||||
|
||||
/* U+884C "行" */
|
||||
0x10, 0x4, 0xf9, 0x0, 0x48, 0x2, 0xfe, 0xc1,
|
||||
0x28, 0x21, 0x4, 0x20, 0x84, 0x10, 0x82, 0x11,
|
||||
@@ -763,11 +798,21 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0x53, 0xea, 0x45, 0x48, 0xad, 0xf5, 0x20, 0x80,
|
||||
0x60,
|
||||
|
||||
/* U+8BEF "误" */
|
||||
0x8f, 0x89, 0x10, 0x22, 0x7, 0xcc, 0x0, 0xbf,
|
||||
0x90, 0x83, 0xff, 0x42, 0xc, 0xa1, 0x22, 0x8,
|
||||
0x30,
|
||||
|
||||
/* U+8F6F "软" */
|
||||
0x22, 0x4, 0x43, 0xcf, 0xa2, 0x16, 0x45, 0x52,
|
||||
0x3c, 0x41, 0x8, 0x32, 0x9c, 0x50, 0x91, 0x14,
|
||||
0x10,
|
||||
|
||||
/* U+8F93 "输" */
|
||||
0x21, 0x4, 0x53, 0xd1, 0x25, 0xda, 0x1, 0xfc,
|
||||
0x4a, 0xa9, 0xf5, 0xea, 0xa5, 0xd4, 0xa8, 0x95,
|
||||
0x30,
|
||||
|
||||
/* U+8FD0 "运" */
|
||||
0x40, 0x4, 0xf8, 0x0, 0x0, 0xe, 0xfe, 0x42,
|
||||
0x8, 0x81, 0x22, 0x2f, 0xe4, 0x5, 0x40, 0x47,
|
||||
@@ -783,6 +828,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0x17, 0xfa, 0x8, 0x49, 0x29, 0xfd, 0x0, 0x5f,
|
||||
0xf0,
|
||||
|
||||
/* U+91CD "重" */
|
||||
0x3, 0xcf, 0x80, 0x10, 0x7f, 0xf4, 0x44, 0xff,
|
||||
0x91, 0x13, 0xfe, 0x4, 0xf, 0xf8, 0x10, 0x7f,
|
||||
0xf0,
|
||||
|
||||
/* U+91CF "量" */
|
||||
0x7f, 0xc8, 0x89, 0x9, 0x7f, 0xf4, 0x44, 0xff,
|
||||
0x91, 0x13, 0xfe, 0x4, 0xf, 0xf8, 0x10, 0x7f,
|
||||
@@ -798,6 +848,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0x48, 0x8f, 0xdf, 0x22, 0x25, 0x44, 0xc8, 0x92,
|
||||
0x70,
|
||||
|
||||
/* U+9519 "错" */
|
||||
0x42, 0x48, 0x49, 0xdf, 0xc1, 0x2e, 0xfe, 0x80,
|
||||
0x11, 0xff, 0xa1, 0x47, 0xea, 0x85, 0x9f, 0xa2,
|
||||
0x10,
|
||||
|
||||
/* U+9632 "防" */
|
||||
0x2, 0x1e, 0x22, 0x7f, 0xc9, 0xa, 0x21, 0x47,
|
||||
0xe4, 0x8c, 0x91, 0x92, 0x3c, 0x86, 0x10, 0xc4,
|
||||
@@ -962,21 +1017,21 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
{.bitmap_index = 689, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 706, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 723, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 740, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 754, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 770, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 787, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 803, .adv_w = 192, .box_w = 9, .box_h = 10, .ofs_x = 1, .ofs_y = -1},
|
||||
{.bitmap_index = 815, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 832, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 740, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 757, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 774, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 788, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 804, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 821, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 837, .adv_w = 192, .box_w = 9, .box_h = 10, .ofs_x = 1, .ofs_y = -1},
|
||||
{.bitmap_index = 849, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 866, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 883, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 900, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 917, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 934, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 950, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 967, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 934, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 951, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 968, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 984, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1001, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1018, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
@@ -984,11 +1039,11 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
{.bitmap_index = 1052, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1069, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1086, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1103, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 1117, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1134, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1151, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1168, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1103, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1120, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1137, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1154, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1171, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 1185, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1202, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1219, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
@@ -999,46 +1054,46 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
{.bitmap_index = 1304, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1321, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1338, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1355, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1371, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 1384, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1401, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1418, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1435, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1355, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1372, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1389, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1406, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1423, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1439, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 1452, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1469, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1486, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1503, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1520, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1536, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1553, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1570, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1587, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1520, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1537, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1554, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1571, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1588, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1604, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1621, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1638, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1652, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1669, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 1684, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1701, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1718, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1734, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1751, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1768, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1785, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1802, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1819, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1638, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1655, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1672, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1689, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1706, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1723, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1737, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1754, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1771, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 1786, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1803, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1820, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1836, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1853, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1870, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1887, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1904, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 1918, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1935, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1952, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1969, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1986, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2003, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1904, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1921, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1938, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1955, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1972, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 1989, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2006, .adv_w = 192, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 2020, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2037, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2054, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
@@ -1050,15 +1105,26 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
{.bitmap_index = 2156, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2173, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2190, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2207, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2223, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2240, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2257, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2274, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2291, .adv_w = 192, .box_w = 2, .box_h = 4, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2292, .adv_w = 192, .box_w = 2, .box_h = 6, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2294, .adv_w = 165, .box_w = 8, .box_h = 10, .ofs_x = 1, .ofs_y = -1} /* U+25B6 */,
|
||||
{.bitmap_index = 2304, .adv_w = 192, .box_w = 2, .box_h = 4, .ofs_x = 2, .ofs_y = 0} /* U+FF0C */
|
||||
{.bitmap_index = 2207, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2224, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2241, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2258, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2275, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2292, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2309, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2326, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2343, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2360, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2377, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2394, .adv_w = 192, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2410, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2427, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2444, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2461, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2478, .adv_w = 192, .box_w = 2, .box_h = 4, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2479, .adv_w = 192, .box_w = 2, .box_h = 6, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2481, .adv_w = 165, .box_w = 8, .box_h = 10, .ofs_x = 1, .ofs_y = -1} /* U+25B6 */,
|
||||
{.bitmap_index = 2491, .adv_w = 192, .box_w = 2, .box_h = 4, .ofs_x = 2, .ofs_y = 0} /* U+FF0C */
|
||||
};
|
||||
|
||||
/*---------------------
|
||||
@@ -1066,20 +1132,22 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
*--------------------*/
|
||||
|
||||
static const uint16_t unicode_list_1[] = {
|
||||
0x0, 0x32, 0x82, 0x9b, 0xed, 0x153, 0x1d4, 0x1d8,
|
||||
0x233, 0x368, 0x36a, 0x42d, 0x444, 0x49f, 0x50d, 0x531,
|
||||
0x582, 0x5b9, 0x5c3, 0x5da, 0x5ee, 0x626, 0x641, 0x927,
|
||||
0x937, 0x982, 0xb04, 0xd47, 0xd4e, 0xd4f, 0xd91, 0xd95,
|
||||
0xdbd, 0x1086, 0x1106, 0x1131, 0x1149, 0x114a, 0x114c, 0x1266,
|
||||
0x142e, 0x1442, 0x148d, 0x149b, 0x149c, 0x1565, 0x159e, 0x15a0,
|
||||
0x16c4, 0x173c, 0x1767, 0x176b, 0x17d7, 0x17dc, 0x17ed, 0x1916,
|
||||
0x1923, 0x1976, 0x19dc, 0x1a18, 0x1ab7, 0x1c18, 0x1d72, 0x1ed9,
|
||||
0x1f38, 0x1f42, 0x1ffc, 0x22b0, 0x243f, 0x271f, 0x2743, 0x28eb,
|
||||
0x2902, 0x29f8, 0x2a63, 0x2c02, 0x2ce6, 0x2d23, 0x2e72, 0x2ef2,
|
||||
0x30b6, 0x30bf, 0x30eb, 0x3148, 0x3165, 0x33e1, 0x3a43, 0x3abc,
|
||||
0x3d5d, 0x3d9b, 0x3da6, 0x3da7, 0x3db5, 0x3dd9, 0x4166, 0x41c7,
|
||||
0x4211, 0x425c, 0x43c6, 0x4696, 0x469c, 0x4829, 0x485b, 0x4959,
|
||||
0x4a6c, 0x4b7f, 0x4c83, 0x50cf, 0xb103, 0xb111
|
||||
0x0, 0x1, 0x32, 0x82, 0x9b, 0xed, 0x153, 0x1d4,
|
||||
0x1d8, 0x233, 0x35c, 0x368, 0x36a, 0x42d, 0x444, 0x49f,
|
||||
0x50d, 0x531, 0x582, 0x5b9, 0x5c3, 0x5da, 0x5ee, 0x626,
|
||||
0x641, 0x927, 0x937, 0x982, 0xb04, 0xd47, 0xd4e, 0xd4f,
|
||||
0xd91, 0xd95, 0xdbd, 0x102f, 0x1086, 0x10f9, 0x1106, 0x1131,
|
||||
0x1149, 0x114a, 0x114c, 0x1266, 0x142e, 0x1442, 0x148d, 0x149b,
|
||||
0x149c, 0x1565, 0x159e, 0x15a0, 0x16c4, 0x173c, 0x1767, 0x176b,
|
||||
0x17d7, 0x17dc, 0x17ed, 0x1916, 0x1923, 0x1976, 0x19dc, 0x1a18,
|
||||
0x1ab7, 0x1c18, 0x1d72, 0x1ed9, 0x1f38, 0x1f42, 0x1ffc, 0x22b0,
|
||||
0x243e, 0x243f, 0x271f, 0x272c, 0x2743, 0x28eb, 0x2902, 0x29f8,
|
||||
0x2a63, 0x2c02, 0x2ce6, 0x2d23, 0x2e72, 0x2ef2, 0x30b6, 0x30bf,
|
||||
0x30eb, 0x3148, 0x3165, 0x33e1, 0x34a6, 0x3a43, 0x3abc, 0x3d5d,
|
||||
0x3d9b, 0x3da6, 0x3da7, 0x3db5, 0x3dd9, 0x3de6, 0x4166, 0x418a,
|
||||
0x41c7, 0x4211, 0x425c, 0x43c4, 0x43c6, 0x4696, 0x469c, 0x4710,
|
||||
0x4829, 0x485b, 0x4959, 0x4a6c, 0x4b7f, 0x4c83, 0x50cf, 0xb103,
|
||||
0xb111
|
||||
};
|
||||
|
||||
/*Collect the unicode lists and glyph_id offsets*/
|
||||
@@ -1091,14 +1159,14 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
|
||||
},
|
||||
{
|
||||
.range_start = 19977, .range_length = 45330, .glyph_id_start = 96,
|
||||
.unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 110, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
||||
.unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 121, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
||||
},
|
||||
{
|
||||
.range_start = 9654, .range_length = 1, .glyph_id_start = 206,
|
||||
.range_start = 9654, .range_length = 1, .glyph_id_start = 217,
|
||||
.unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
|
||||
},
|
||||
{
|
||||
.range_start = 65292, .range_length = 1, .glyph_id_start = 207,
|
||||
.range_start = 65292, .range_length = 1, .glyph_id_start = 218,
|
||||
.unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
* 列改布尔"需密码"(行尾 #P);密码页按所输密码授权(查看→只读
|
||||
* / 修改→可修改),授权经回调随开页传给内容页(页面经
|
||||
* is_editable 判编辑);无密码叶子直接进、默认只读
|
||||
* 2026-09-14 王建锋 运行记录/自检记录内容页映射(node 40/39)+ 键事件挂钩待机空闲通知
|
||||
*/
|
||||
|
||||
/* 头文件包含区 */
|
||||
@@ -33,6 +34,8 @@
|
||||
|
||||
#include "ui_page_password.h"
|
||||
|
||||
#include "ui_standby.h"
|
||||
|
||||
#include "ui_menu_tab.h"
|
||||
|
||||
#include "ui_pwd_def.h"
|
||||
@@ -107,9 +110,10 @@ static void menu_back(void) {
|
||||
* 入口参数:node - 菜单节点下标 uint8_t
|
||||
* 返回值:内容页 ID content_page_id_t;无内容页 = CONTENT_PAGE_COUNT
|
||||
* 限定条件:无
|
||||
* 函数说明:仅部分叶子有内容页(参考图 10/20/21 + 网口设置);下标对应
|
||||
* 函数说明:仅部分叶子有内容页(参考图 10/20/21 + 网口设置 + 记录查询);下标对应
|
||||
* ui_menu_tab.c
|
||||
* node 1=装置信息、3=交流量、4=直流量、30=网口设置(表序变更时须同步本映射)
|
||||
* node 1=装置信息、3=交流量、4=直流量、30=网口设置、39=自检记录、40=运行记录
|
||||
* (表序变更时须同步本映射)
|
||||
*/
|
||||
static content_page_id_t menu_content_page_for(uint8_t node) {
|
||||
switch (node) {
|
||||
@@ -117,6 +121,8 @@ static content_page_id_t menu_content_page_for(uint8_t node) {
|
||||
case 3u: return CONTENT_PAGE_AC; /* 交流量(实时数据子项) */
|
||||
case 4u: return CONTENT_PAGE_DC; /* 直流量(实时数据子项) */
|
||||
case 30u: return CONTENT_PAGE_NET_CFG; /* 网口设置(通讯参数子项,需密码) */
|
||||
case 39u: return CONTENT_PAGE_SELFTEST_LOG; /* 自检记录(记录查询子项) */
|
||||
case 40u: return CONTENT_PAGE_RUN_LOG; /* 运行记录(记录查询子项) */
|
||||
default: return (content_page_id_t)CONTENT_PAGE_COUNT; /* 无内容页 */
|
||||
}
|
||||
}
|
||||
@@ -234,6 +240,7 @@ static void menu_key_handle(uint8_t depth, lv_key_t key) {
|
||||
* (焦点恒为持久容器,焦点框深度即 s_depth,无需 user_data 传层)
|
||||
*/
|
||||
static void menu_key_cb(lv_event_t *e) {
|
||||
ui_standby_notify_activity(); /* 用户活动:重置待机空闲计时 */
|
||||
menu_key_handle(s_depth, (lv_key_t)lv_event_get_key(e));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,14 @@
|
||||
* 2026-09-09 王建锋 改权限模型:arm 只载回调(不再载期望密码);页面比对
|
||||
* ui_pwd_def.h 两个编译期密码(先查修改),一致时回调携
|
||||
* 授予的权限(UI_PERM_MODIFY / UI_PERM_VIEW)
|
||||
* 2026-09-14 王建锋 输错提示:ENTER 不一致显示"密码输入错误",方向键清除后重输
|
||||
* 2026-09-14 王建锋 修 lv_text_get_width 传 -1 死循环(本 LVGL 版 length≠0 时
|
||||
* while(i<length) 无 NUL 检查,越串尾读野内存;改传 strlen)
|
||||
*/
|
||||
|
||||
/* 头文件包含区 */
|
||||
#include <string.h>
|
||||
|
||||
#include "ui_page_password.h"
|
||||
|
||||
#include "ui_pwd_def.h"
|
||||
@@ -39,6 +44,9 @@
|
||||
|
||||
#define PW_TITLE_Y 44 /* 标题放置 y(中上;0 = 框架默认,实机明显低于其余各页的 y=2) */
|
||||
|
||||
#define PW_ERR_Y 104 /* "密码输入错误"提示行顶 y(数字框行之下) */
|
||||
#define PW_SCREEN_W 160 /* 屏幕宽(px,与 ui_port.h / 模拟器一致;提示文本居中用) */
|
||||
|
||||
/* 静态变量定义区 */
|
||||
|
||||
/* 单位数字文本(Flash):数字 0..9 各 1 字符(text_static,不拷内存) */
|
||||
@@ -46,9 +54,10 @@ static const char *const s_digit_str[10] = {
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||
};
|
||||
|
||||
/* 页面运行状态(RAM,约 9 B):3 位值 + 光标位 + 完成回调 */
|
||||
/* 页面运行状态(RAM,约 10 B):3 位值 + 光标位 + 错误标志 + 完成回调 */
|
||||
static uint8_t s_digits[PW_DIGITS]; /* 3 位密码值(0..9) */
|
||||
static uint8_t s_cur; /* 光标位 0..2(反显框) */
|
||||
static uint8_t s_err; /* 错误提示标志(1 = 显示"密码输入错误",方向键清除) */
|
||||
static void (*s_on_ok)(uint8_t); /* 完成回调(逻辑层预装,实参=授予权限;NULL = 一致时仅关页) */
|
||||
|
||||
/* 函数定义区 */
|
||||
@@ -132,6 +141,33 @@ static void pw_draw_cb(lv_layer_t *layer, const lv_area_t *clip) {
|
||||
lv_draw_rect(layer, &fd, &box);
|
||||
pw_draw_digit(layer, &box, s_digits[i], (i == s_cur) ? lv_color_black() : lv_color_white());
|
||||
}
|
||||
|
||||
if (s_err != 0u) {
|
||||
/* "密码输入错误"提示(水平居中;1bpp:white=暗墨) */
|
||||
lv_draw_label_dsc_t ld;
|
||||
/* 本 LVGL 版 lv_text_get_width:length=0 = 不测量(返回 0)、length≠0 时
|
||||
* while(i<length) 无 NUL 检查——必须传 strlen,传 -1 会越串尾死循环 */
|
||||
int32_t w = lv_text_get_width("密码输入错误", (uint32_t)strlen("密码输入错误"), LV_FONT_DEFAULT, 0);
|
||||
|
||||
if (w > 0) {
|
||||
lv_area_t err_box;
|
||||
|
||||
err_box.x1 = (PW_SCREEN_W - w) / 2;
|
||||
err_box.x2 = (int32_t)(err_box.x1 + w - 1u);
|
||||
err_box.y1 = PW_ERR_Y;
|
||||
err_box.y2 = (int32_t)(err_box.y1 + 15u); /* 覆盖字体行高(13)+ 余量(同框架约定) */
|
||||
if (pw_areas_intersect(&err_box, clip)) {
|
||||
lv_draw_label_dsc_init(&ld);
|
||||
ld.base.layer = layer;
|
||||
ld.text = "密码输入错误";
|
||||
ld.text_static = 1;
|
||||
ld.color = lv_color_white();
|
||||
ld.ofs_x = 0;
|
||||
ld.ofs_y = 0;
|
||||
lv_draw_label(layer, &ld, &err_box);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -139,13 +175,17 @@ static void pw_draw_cb(lv_layer_t *layer, const lv_area_t *clip) {
|
||||
* 入口参数:key - LVGL 键值 lv_key_t
|
||||
* 返回值:true - 页已处理(框架跳过内置语义);false - 未处理
|
||||
* 限定条件:页面打开;经框架键分发调用(uiTask 上下文)
|
||||
* 函数说明: 1. ↑/↓:调整光标位数字(+1/-1,9↔0 环绕)
|
||||
* 2. ←/→:移动光标(首↔末环绕;← 键经框架拦截标志转入本函数)
|
||||
* 函数说明: 1. ↑/↓:调整光标位数字(+1/-1,9↔0 环绕);错误提示态下先清除提示
|
||||
* 2. ←/→:移动光标(首↔末环绕;← 键经框架拦截标志转入本函数);同上清提示
|
||||
* 3. ENTER:修改密码 → 完成回调(授修改权限);查看密码 → 完成回调
|
||||
* (授只读权限);不一致 → 清空重输
|
||||
* (授只读权限);不一致 → 清空重输 + 显示"密码输入错误"
|
||||
* 4. ESC 不经本函数(框架最优先恒关页);其余键值未处理
|
||||
*/
|
||||
static bool pw_key_cb(lv_key_t key) {
|
||||
if (key != LV_KEY_ENTER && s_err != 0u) {
|
||||
s_err = 0u; /* 错误提示态:方向键先清除提示,再正常执行该键(重新输入) */
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case LV_KEY_UP:
|
||||
s_digits[s_cur] = (uint8_t)((s_digits[s_cur] + 1u) % 10u); /* 值 +1,9 环绕 0 */
|
||||
@@ -172,11 +212,12 @@ static bool pw_key_cb(lv_key_t key) {
|
||||
perm = (uint8_t)UI_PERM_VIEW; /* 查看密码:授只读权限 */
|
||||
}
|
||||
else {
|
||||
/* 不一致:清空重输(3 框回 0、光标回首框) */
|
||||
/* 不一致:清空重输(3 框回 0、光标回首框)+ 显示错误提示 */
|
||||
s_digits[0] = 0u;
|
||||
s_digits[1] = 0u;
|
||||
s_digits[2] = 0u;
|
||||
s_cur = 0u;
|
||||
s_err = 1u;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -211,6 +252,7 @@ void ui_page_password_arm(void (*on_ok)(uint8_t perm)) {
|
||||
s_digits[1] = 0u;
|
||||
s_digits[2] = 0u;
|
||||
s_cur = 0u;
|
||||
s_err = 0u;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 模块名称:UI Page RunLog (运行记录内容页)
|
||||
* 模块功能:运行记录叶子节点(node 40)的内容页数据——动态列表,每条记录 2 行
|
||||
* (偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据源 = sys_log API
|
||||
* (/log/run.log,上电/重启事件);空日志显示单条伪行"无记录";
|
||||
* 向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
|
||||
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-09-14
|
||||
* 修改记录:
|
||||
* v1.0 2026-09-14 王建锋 创建初始版本(设计见 docs/运行与自检记录设计说明.md §5.3)
|
||||
*/
|
||||
|
||||
/* 头文件包含区 */
|
||||
#include <string.h>
|
||||
|
||||
#include "ui_page_runlog.h"
|
||||
|
||||
#include "sys_log.h"
|
||||
|
||||
/* 静态变量定义区 */
|
||||
|
||||
/* 最近读取的记录缓存(偶数行读盘后,奇数行复用;避免同记录重复 I/O) */
|
||||
static uint8_t s_cache_valid; /* 缓存有效标志(0 = 无缓存) */
|
||||
static uint32_t s_last_rec; /* 已缓存的记录序号 */
|
||||
static char s_ts[SYSLOG_TS_LEN + 1u];
|
||||
static char s_desc[SYSLOG_DESC_MAX + 1u];
|
||||
|
||||
/* 函数定义区 */
|
||||
|
||||
/*
|
||||
* 函数功能:总行数(动态;每条记录 2 行,空日志 = 单条伪行"无记录")
|
||||
* 入口参数:无
|
||||
* 返回值:总行数 uint16_t
|
||||
*/
|
||||
static uint16_t rl_count_cb(void) {
|
||||
uint32_t n = syslog_count(SYSLOG_RUN);
|
||||
|
||||
if (n == 0u) {
|
||||
return 1u; /* 空态伪行(页脚"共 1 页",避免"共 0 页") */
|
||||
}
|
||||
return (uint16_t)(n * 2u);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:逐行取数(偶数行 = 时间戳、奇数行 = 描述;值列恒空)
|
||||
* 入口参数:row - 全局行下标 uint16_t
|
||||
* name - 名输出缓冲(框架栈缓冲 CP_ROW_BUF_LEN=32,含 NUL) char *
|
||||
* value - 值输出缓冲(同上;本页恒写空串) char *
|
||||
* 限定条件:页面打开中(框架绘制/按键上下文,uiTask)
|
||||
*/
|
||||
static void rl_refresh(uint16_t row, char *name, char *value) {
|
||||
uint32_t n = syslog_count(SYSLOG_RUN);
|
||||
|
||||
value[0] = '\0';
|
||||
if (n == 0u) {
|
||||
(void)memcpy(name, "无记录", sizeof("无记录"));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t rec = row / 2u;
|
||||
|
||||
if (!s_cache_valid || rec != s_last_rec) {
|
||||
if (syslog_get_record(SYSLOG_RUN, rec, s_ts, sizeof(s_ts), s_desc, sizeof(s_desc)) != 0) {
|
||||
name[0] = '\0'; /* 读失败(越界/存储异常):空行防御 */
|
||||
return;
|
||||
}
|
||||
s_last_rec = rec;
|
||||
s_cache_valid = 1u;
|
||||
}
|
||||
if ((row % 2u) == 0u) {
|
||||
(void)memcpy(name, s_ts, sizeof(s_ts));
|
||||
}
|
||||
else {
|
||||
(void)memcpy(name, s_desc, sizeof(s_desc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 页面描述符(外部链接:框架描述符表 s_defs[] 直接引用):
|
||||
* 动态列表页——每记录 2 行、8 行/页 = 4 条/页;band_h=13(同 AC/DC 约定:
|
||||
* selectable 页选中行黑字必须配白带,band_h=0 会致选中行不可见);
|
||||
* 时间戳 19 ASCII ≈114px < 屏宽可容
|
||||
*/
|
||||
const content_page_def_t ui_page_runlog_desc = {
|
||||
.title = "运行记录",
|
||||
.selectable = 1u,
|
||||
.top_y = 24,
|
||||
.pitch = 14,
|
||||
.band_h = 13,
|
||||
.text_dy = 0,
|
||||
.left_x = 7,
|
||||
.right_x = 101,
|
||||
.rows_per_page = 8u,
|
||||
.count_cb = rl_count_cb,
|
||||
.refresh = rl_refresh,
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 模块名称:UI Page RunLog (运行记录内容页)
|
||||
* 模块功能:运行记录叶子节点(node 40)的内容页数据——动态列表,每条记录 2 行
|
||||
* (偶数行 = 时间戳、奇数行 = 描述),可移选分页;数据源 = sys_log API
|
||||
* (/log/run.log,上电/重启事件);空日志显示单条伪行"无记录";
|
||||
* 向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
|
||||
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-09-14
|
||||
* 修改记录:
|
||||
* v1.0 2026-09-14 王建锋 创建初始版本(设计见 docs/运行与自检记录设计说明.md §5.3)
|
||||
*/
|
||||
#ifndef UI_PAGE_RUNLOG_H
|
||||
#define UI_PAGE_RUNLOG_H
|
||||
|
||||
#include "ui_content_page.h"
|
||||
|
||||
/*
|
||||
* 页面描述符(Flash const):运行记录页 = CONTENT_PAGE_RUN_LOG;
|
||||
* 接入框架描述符表 s_defs[](定义于 ui_page_runlog.c)
|
||||
*/
|
||||
extern const content_page_def_t ui_page_runlog_desc;
|
||||
|
||||
#endif /* UI_PAGE_RUNLOG_H */
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 模块名称:UI Page SelfTest (自检记录内容页)
|
||||
* 模块功能:自检记录叶子节点(node 39)的内容页数据——动态列表,每条记录 2 行
|
||||
* (偶数行 = 时间戳、奇数行 = 故障描述),可移选分页;数据源 = sys_log API
|
||||
* (/log/selftest.log,开机自检故障,仅故障才写);空日志显示单条伪行"无记录";
|
||||
* 向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
|
||||
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-09-14
|
||||
* 修改记录:
|
||||
* v1.0 2026-09-14 王建锋 创建初始版本(设计见 docs/运行与自检记录设计说明.md §5.4)
|
||||
*/
|
||||
|
||||
/* 头文件包含区 */
|
||||
#include <string.h>
|
||||
|
||||
#include "ui_page_selftest.h"
|
||||
|
||||
#include "sys_log.h"
|
||||
|
||||
/* 静态变量定义区 */
|
||||
|
||||
/* 最近读取的记录缓存(偶数行读盘后,奇数行复用;避免同记录重复 I/O) */
|
||||
static uint8_t s_cache_valid; /* 缓存有效标志(0 = 无缓存) */
|
||||
static uint32_t s_last_rec; /* 已缓存的记录序号 */
|
||||
static char s_ts[SYSLOG_TS_LEN + 1u];
|
||||
static char s_desc[SYSLOG_DESC_MAX + 1u];
|
||||
|
||||
/* 函数定义区 */
|
||||
|
||||
/*
|
||||
* 函数功能:总行数(动态;每条记录 2 行,空日志 = 单条伪行"无记录")
|
||||
* 入口参数:无
|
||||
* 返回值:总行数 uint16_t
|
||||
*/
|
||||
static uint16_t st_count_cb(void) {
|
||||
uint32_t n = syslog_count(SYSLOG_SELFTEST);
|
||||
|
||||
if (n == 0u) {
|
||||
return 1u; /* 空态伪行(页脚"共 1 页",避免"共 0 页") */
|
||||
}
|
||||
return (uint16_t)(n * 2u);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:逐行取数(偶数行 = 时间戳、奇数行 = 故障描述;值列恒空)
|
||||
* 入口参数:row - 全局行下标 uint16_t
|
||||
* name - 名输出缓冲(框架栈缓冲 CP_ROW_BUF_LEN=32,含 NUL) char *
|
||||
* value - 值输出缓冲(同上;本页恒写空串) char *
|
||||
* 限定条件:页面打开中(框架绘制/按键上下文,uiTask)
|
||||
*/
|
||||
static void st_refresh(uint16_t row, char *name, char *value) {
|
||||
uint32_t n = syslog_count(SYSLOG_SELFTEST);
|
||||
|
||||
value[0] = '\0';
|
||||
if (n == 0u) {
|
||||
(void)memcpy(name, "无记录", sizeof("无记录"));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t rec = row / 2u;
|
||||
|
||||
if (!s_cache_valid || rec != s_last_rec) {
|
||||
if (syslog_get_record(SYSLOG_SELFTEST, rec, s_ts, sizeof(s_ts), s_desc, sizeof(s_desc)) != 0) {
|
||||
name[0] = '\0'; /* 读失败(越界/存储异常):空行防御 */
|
||||
return;
|
||||
}
|
||||
s_last_rec = rec;
|
||||
s_cache_valid = 1u;
|
||||
}
|
||||
if ((row % 2u) == 0u) {
|
||||
(void)memcpy(name, s_ts, sizeof(s_ts));
|
||||
}
|
||||
else {
|
||||
(void)memcpy(name, s_desc, sizeof(s_desc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 页面描述符(外部链接:框架描述符表 s_defs[] 直接引用):
|
||||
* 动态列表页——每记录 2 行、8 行/页 = 4 条/页;band_h=13(同 AC/DC 约定:
|
||||
* selectable 页选中行黑字必须配白带,band_h=0 会致选中行不可见);
|
||||
* 时间戳 19 ASCII ≈114px < 屏宽可容
|
||||
*/
|
||||
const content_page_def_t ui_page_selftest_desc = {
|
||||
.title = "自检记录",
|
||||
.selectable = 1u,
|
||||
.top_y = 24,
|
||||
.pitch = 14,
|
||||
.band_h = 13,
|
||||
.text_dy = 0,
|
||||
.left_x = 7,
|
||||
.right_x = 101,
|
||||
.rows_per_page = 8u,
|
||||
.count_cb = st_count_cb,
|
||||
.refresh = st_refresh,
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 模块名称:UI Page SelfTest (自检记录内容页)
|
||||
* 模块功能:自检记录叶子节点(node 39)的内容页数据——动态列表,每条记录 2 行
|
||||
* (偶数行 = 时间戳、奇数行 = 故障描述),可移选分页;数据源 = sys_log API
|
||||
* (/log/selftest.log,开机自检故障,仅故障才写);空日志显示单条伪行"无记录";
|
||||
* 向框架 ui_content_page 提供页面描述符(零 LVGL 对象)
|
||||
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-09-14
|
||||
* 修改记录:
|
||||
* v1.0 2026-09-14 王建锋 创建初始版本(设计见 docs/运行与自检记录设计说明.md §5.4)
|
||||
*/
|
||||
#ifndef UI_PAGE_SELFTEST_H
|
||||
#define UI_PAGE_SELFTEST_H
|
||||
|
||||
#include "ui_content_page.h"
|
||||
|
||||
/*
|
||||
* 页面描述符(Flash const):自检记录页 = CONTENT_PAGE_SELFTEST_LOG;
|
||||
* 接入框架描述符表 s_defs[](定义于 ui_page_selftest.c)
|
||||
*/
|
||||
extern const content_page_def_t ui_page_selftest_desc;
|
||||
|
||||
#endif /* UI_PAGE_SELFTEST_H */
|
||||
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* 模块名称:UI Standby (待机显示页)
|
||||
* 模块功能:长时间无按键操作时自动切入的默认界面(6 路电流值 + 分隔线 + 底部时钟);
|
||||
* 屏幕覆盖层模式——进入保存前屏与焦点、ENTER(确认键)还原,其余键忽略;
|
||||
* 空闲检测 = lv_timer(1s 周期),活动通知由菜单/内容页键事件挂钩
|
||||
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-09-14
|
||||
* 修改记录:
|
||||
* v1.0 2026-09-14 王建锋 创建初始版本(设计见 docs/运行与自检记录设计说明.md §5.2)
|
||||
*/
|
||||
|
||||
/* 头文件包含区 */
|
||||
#include <string.h>
|
||||
|
||||
#include "ui_standby.h"
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "ui_menu_view.h"
|
||||
|
||||
#define DBG_TAG "[UI_STANDBY]"
|
||||
#include "dbg_log.h"
|
||||
|
||||
/* 私有宏定义区 */
|
||||
|
||||
/*
|
||||
* 布局常量(设备像素;参考 mockups/待机显示页面.jpg):
|
||||
* 6 路电流值行自 y=28 起、行距 18(末行 y=118..130);分隔线 y=132;底部时钟 y=140 居中
|
||||
*/
|
||||
#define SB_SCREEN_W 160 /* 屏幕宽(px,与 ui_port.h / 模拟器一致) */
|
||||
#define SB_SCREEN_H 160 /* 屏幕高(px) */
|
||||
|
||||
#define SB_CH_COUNT 6u /* 电流通道数 */
|
||||
#define SB_ROW_Y0 28 /* 首数据行顶 y */
|
||||
#define SB_PITCH 18 /* 行距(相邻行槽顶间距) */
|
||||
#define SB_LABEL_X 24 /* 通道名 x(Ib/Ic/...) */
|
||||
#define SB_EQ_X 72 /* "=" 号 x */
|
||||
#define SB_VALUE_X 96 /* 数值 x(0.00A;v1 占位,待交流量标定管线接入实时值) */
|
||||
|
||||
#define SB_LINE_Y 132 /* 分隔线 y(高 1px) */
|
||||
#define SB_TIME_Y 140 /* 底部时钟放置 y(居中) */
|
||||
|
||||
/* 静态变量定义区 */
|
||||
|
||||
/* 通道名与占位数值(Flash;全 ASCII,无需中文字形) */
|
||||
static const char *const s_ch_name[SB_CH_COUNT] = { "Ib", "Ic", "Io", "Ia2", "Ib2", "Ic2" };
|
||||
static const char *const s_ch_value[SB_CH_COUNT] = { "0.00A", "0.00A", "0.00A", "0.00A", "0.00A", "0.00A" };
|
||||
|
||||
static lv_obj_t *s_scr; /* 待机屏(init 时建、常驻不销毁) */
|
||||
static lv_obj_t *s_cont; /* 全屏容器(焦点/键入口 + 自绘载体,无子对象) */
|
||||
static uint32_t s_timeout_ms; /* 空闲超时阈值 */
|
||||
static uint32_t s_last_ms; /* 最近一次用户活动时刻(lv_tick ms) */
|
||||
static bool s_active; /* 是否处于待机屏 */
|
||||
static lv_obj_t *s_prev_scr; /* 进入待机前的活动屏(ENTER 还原用) */
|
||||
static lv_obj_t *s_prev_focus; /* 进入待机前组内焦点对象 */
|
||||
static ui_standby_time_cb s_time_cb;
|
||||
|
||||
/* flat:透明、无边框/圆角/内边距——剥离 mono 主题给普通 lv_obj 附加的 card 样式(同 ui_content_page.c) */
|
||||
static const lv_style_const_prop_t sb_flat_props[] = {
|
||||
{ .prop = LV_STYLE_BG_OPA, .value = { .num = LV_OPA_TRANSP } },
|
||||
{ .prop = LV_STYLE_BORDER_WIDTH, .value = { .num = 0 } },
|
||||
{ .prop = LV_STYLE_RADIUS, .value = { .num = 0 } },
|
||||
{ .prop = LV_STYLE_PAD_LEFT, .value = { .num = 0 } },
|
||||
{ .prop = LV_STYLE_PAD_RIGHT, .value = { .num = 0 } },
|
||||
{ .prop = LV_STYLE_PAD_TOP, .value = { .num = 0 } },
|
||||
{ .prop = LV_STYLE_PAD_BOTTOM, .value = { .num = 0 } },
|
||||
{ .prop = LV_STYLE_PAD_ROW, .value = { .num = 0 } },
|
||||
{ .prop = LV_STYLE_PAD_COLUMN, .value = { .num = 0 } },
|
||||
LV_STYLE_CONST_PROPS_END
|
||||
};
|
||||
|
||||
LV_STYLE_CONST_INIT(sb_style_flat, sb_flat_props);
|
||||
|
||||
/* 函数定义区 */
|
||||
|
||||
/*
|
||||
* 函数功能:判断两区域是否相交(等价 lv_area_intersect 非空判断;避免依赖 LVGL 私有头)
|
||||
* 入口参数:a - 区域 1 const lv_area_t *
|
||||
* b - 区域 2 const lv_area_t *
|
||||
* 返回值:true - 相交;false - 不相交
|
||||
*/
|
||||
static bool sb_areas_intersect(const lv_area_t *a, const lv_area_t *b) {
|
||||
int32_t x1 = (a->x1 > b->x1) ? a->x1 : b->x1;
|
||||
int32_t y1 = (a->y1 > b->y1) ? a->y1 : b->y1;
|
||||
int32_t x2 = (a->x2 < b->x2) ? a->x2 : b->x2;
|
||||
int32_t y2 = (a->y2 < b->y2) ? a->y2 : b->y2;
|
||||
|
||||
return (x1 <= x2 && y1 <= y2);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:绘制居中单行文本(底部时钟)
|
||||
* 入口参数:layer - 绘制层 lv_layer_t *
|
||||
* text - 文本(栈缓冲,同帧有效) const char *
|
||||
* y - 放置 y int32_t
|
||||
*/
|
||||
static void sb_draw_centered_text(lv_layer_t *layer, const char *text, int32_t y) {
|
||||
lv_area_t area;
|
||||
lv_draw_label_dsc_t ld;
|
||||
|
||||
area.x1 = 0;
|
||||
area.x2 = SB_SCREEN_W - 1;
|
||||
area.y1 = y;
|
||||
area.y2 = y + 15; /* 覆盖字体行高(13)+ 余量 */
|
||||
|
||||
lv_draw_label_dsc_init(&ld);
|
||||
ld.base.layer = layer;
|
||||
ld.text = text;
|
||||
ld.color = lv_color_white();
|
||||
ld.ofs_x = (SB_SCREEN_W - lv_text_get_width(text, (uint32_t)strlen(text), LV_FONT_DEFAULT, 0)) / 2;
|
||||
ld.ofs_y = 0;
|
||||
lv_draw_label(layer, &ld, &area);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:待机屏自绘(6 路电流值 + 分隔线 + 底部时钟;逐行 culling)
|
||||
* 入口参数:e - 事件指针 lv_event_t *
|
||||
* 返回值:无
|
||||
* 限定条件:事件为 LV_EVENT_DRAW_MAIN,待机模块已初始化
|
||||
* 函数说明:1bpp 极性 white=暗墨——文本/分隔线均白色;数值 v1 占位 0.00A
|
||||
*/
|
||||
static void sb_draw_cb(lv_event_t *e) {
|
||||
lv_layer_t *layer = lv_event_get_layer(e);
|
||||
|
||||
for (uint32_t i = 0u; i < SB_CH_COUNT; i++) {
|
||||
int32_t row_y = SB_ROW_Y0 + (int32_t)i * SB_PITCH;
|
||||
lv_area_t strip;
|
||||
lv_draw_label_dsc_t ld;
|
||||
|
||||
strip.x1 = 0;
|
||||
strip.x2 = SB_SCREEN_W - 1;
|
||||
strip.y1 = row_y;
|
||||
strip.y2 = (int32_t)(row_y + SB_PITCH - 1u);
|
||||
if (!sb_areas_intersect(&strip, &layer->_clip_area)) {
|
||||
continue; /* 行不在重绘区:跳过(culling) */
|
||||
}
|
||||
|
||||
lv_draw_label_dsc_init(&ld);
|
||||
ld.base.layer = layer;
|
||||
ld.text = s_ch_name[i];
|
||||
ld.text_static = 1;
|
||||
ld.color = lv_color_white();
|
||||
ld.ofs_x = SB_LABEL_X;
|
||||
ld.ofs_y = 0;
|
||||
lv_draw_label(layer, &ld, &strip);
|
||||
|
||||
lv_draw_label_dsc_init(&ld);
|
||||
ld.base.layer = layer;
|
||||
ld.text = "=";
|
||||
ld.text_static = 1;
|
||||
ld.color = lv_color_white();
|
||||
ld.ofs_x = SB_EQ_X;
|
||||
ld.ofs_y = 0;
|
||||
lv_draw_label(layer, &ld, &strip);
|
||||
|
||||
lv_draw_label_dsc_init(&ld);
|
||||
ld.base.layer = layer;
|
||||
ld.text = s_ch_value[i];
|
||||
ld.text_static = 1;
|
||||
ld.color = lv_color_white();
|
||||
ld.ofs_x = SB_VALUE_X;
|
||||
ld.ofs_y = 0;
|
||||
lv_draw_label(layer, &ld, &strip);
|
||||
}
|
||||
|
||||
/* 分隔线(高 1px) */
|
||||
{
|
||||
lv_area_t line;
|
||||
lv_draw_rect_dsc_t fd;
|
||||
|
||||
line.x1 = 8;
|
||||
line.x2 = SB_SCREEN_W - 9;
|
||||
line.y1 = SB_LINE_Y;
|
||||
line.y2 = SB_LINE_Y;
|
||||
if (sb_areas_intersect(&line, &layer->_clip_area)) {
|
||||
lv_draw_rect_dsc_init(&fd);
|
||||
fd.base.layer = layer;
|
||||
fd.bg_color = lv_color_white();
|
||||
fd.bg_opa = LV_OPA_COVER;
|
||||
lv_draw_rect(layer, &fd, &line);
|
||||
}
|
||||
}
|
||||
|
||||
/* 底部时钟(每秒重绘;time_cb 平台提供) */
|
||||
{
|
||||
lv_area_t t;
|
||||
|
||||
t.x1 = 0;
|
||||
t.x2 = SB_SCREEN_W - 1;
|
||||
t.y1 = SB_TIME_Y;
|
||||
t.y2 = (int32_t)(SB_TIME_Y + 15);
|
||||
if (sb_areas_intersect(&t, &layer->_clip_area)) {
|
||||
char ts[24];
|
||||
|
||||
s_time_cb(ts, sizeof(ts));
|
||||
sb_draw_centered_text(layer, ts, SB_TIME_Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:进入待机屏(保存前屏与焦点 → 聚焦容器并切屏)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:UI 任务上下文;未处于待机
|
||||
*/
|
||||
static void sb_enter(void) {
|
||||
lv_group_t *g;
|
||||
|
||||
if (s_active || s_scr == NULL) {
|
||||
return;
|
||||
}
|
||||
s_prev_scr = lv_screen_active();
|
||||
g = lv_group_get_default();
|
||||
s_prev_focus = (g != NULL) ? lv_group_get_focused(g) : NULL;
|
||||
if (g != NULL) {
|
||||
lv_group_add_obj(g, s_cont); /* 幂等:已在组内则忽略 */
|
||||
lv_group_focus_obj(s_cont); /* 先获焦再切屏,按键立即由本模块接管 */
|
||||
}
|
||||
lv_screen_load(s_scr);
|
||||
s_active = true;
|
||||
DBG_INFO("standby: enter");
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:退出待机屏(还原前屏与焦点;重置空闲计时)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:UI 任务上下文;处于待机
|
||||
*/
|
||||
static void sb_exit(void) {
|
||||
if (!s_active) {
|
||||
return;
|
||||
}
|
||||
s_active = false;
|
||||
s_last_ms = lv_tick_get();
|
||||
|
||||
if (s_prev_focus != NULL && lv_obj_is_valid(s_prev_focus)) {
|
||||
lv_group_focus_obj(s_prev_focus);
|
||||
}
|
||||
else {
|
||||
/* 前焦点已失效(如内容页被销毁):回落菜单容器 */
|
||||
lv_obj_t *mc = ui_menu_view_container();
|
||||
if (mc != NULL) {
|
||||
lv_group_focus_obj(mc);
|
||||
}
|
||||
}
|
||||
if (s_prev_scr != NULL && lv_obj_is_valid(s_prev_scr)) {
|
||||
lv_screen_load(s_prev_scr);
|
||||
}
|
||||
DBG_INFO("standby: exit");
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:待机屏按键事件(仅 ENTER 退出;其余键忽略但重置空闲计时)
|
||||
* 入口参数:e - 事件指针 lv_event_t *
|
||||
* 返回值:无
|
||||
* 限定条件:容器已获焦
|
||||
*/
|
||||
static void sb_key_cb(lv_event_t *e) {
|
||||
lv_key_t key = (lv_key_t)lv_event_get_key(e);
|
||||
|
||||
ui_standby_notify_activity();
|
||||
if (key == LV_KEY_ENTER) {
|
||||
sb_exit(); /* 确认键:返回进入前的界面(菜单/内容页原样还原) */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:空闲检测定时器回调(1s 周期;待机中同时驱动时钟每秒重绘)
|
||||
* 入口参数:t - 定时器句柄 lv_timer_t *
|
||||
* 返回值:无
|
||||
*/
|
||||
static void sb_idle_timer_cb(lv_timer_t *t) {
|
||||
(void)t;
|
||||
|
||||
if (!s_active && s_timeout_ms > 0u && lv_tick_elaps(s_last_ms) >= s_timeout_ms) {
|
||||
sb_enter();
|
||||
}
|
||||
else if (s_active) {
|
||||
lv_obj_invalidate(s_cont); /* 底部时钟每秒刷新 */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:初始化待机模块(建常驻屏/容器 + 空闲检测定时器)
|
||||
* 入口参数:idle_timeout_ms - 无操作超时阈值(ms;0 = 拒绝初始化) uint32_t
|
||||
* time_cb - 底部时钟字符串提供回调(不可为 NULL) ui_standby_time_cb
|
||||
* 返回值:0 - 成功;-1 - 失败(已初始化/参数无效/LVGL 池耗尽) int
|
||||
*/
|
||||
int ui_standby_init(uint32_t idle_timeout_ms, ui_standby_time_cb time_cb) {
|
||||
if (s_scr != NULL || idle_timeout_ms == 0u || time_cb == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
s_timeout_ms = idle_timeout_ms;
|
||||
s_time_cb = time_cb;
|
||||
|
||||
s_scr = lv_obj_create(NULL); /* parent=NULL → 新建屏幕(常驻,不随切屏销毁) */
|
||||
if (s_scr == NULL) {
|
||||
return -1; /* LVGL 池耗尽 */
|
||||
}
|
||||
s_cont = lv_obj_create(s_scr);
|
||||
if (s_cont == NULL) {
|
||||
lv_obj_delete(s_scr);
|
||||
s_scr = NULL;
|
||||
return -1;
|
||||
}
|
||||
lv_obj_add_flag(s_cont, LV_OBJ_FLAG_IGNORE_LAYOUT);
|
||||
lv_obj_set_size(s_cont, SB_SCREEN_W, SB_SCREEN_H);
|
||||
lv_obj_add_style(s_cont, &sb_style_flat, 0);
|
||||
lv_obj_add_flag(s_cont, LV_OBJ_FLAG_CLICK_FOCUSABLE);
|
||||
lv_obj_add_event_cb(s_cont, sb_key_cb, LV_EVENT_KEY, NULL);
|
||||
lv_obj_add_event_cb(s_cont, sb_draw_cb, LV_EVENT_DRAW_MAIN, NULL);
|
||||
|
||||
s_last_ms = lv_tick_get();
|
||||
if (lv_timer_create(sb_idle_timer_cb, 1000u, NULL) == NULL) {
|
||||
lv_obj_delete(s_cont);
|
||||
lv_obj_delete(s_scr);
|
||||
s_scr = NULL;
|
||||
s_cont = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DBG_INFO("standby: ready (idle=%ums)", (unsigned)idle_timeout_ms);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:通知用户活动(重置空闲计时)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
*/
|
||||
void ui_standby_notify_activity(void) {
|
||||
if (s_scr != NULL) {
|
||||
s_last_ms = lv_tick_get();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:查询是否处于待机屏
|
||||
* 入口参数:无
|
||||
* 返回值:true - 待机中;false - 否
|
||||
*/
|
||||
bool ui_standby_is_active(void) {
|
||||
return s_active;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:强制进入待机屏(测试钩子,绕过空闲计时)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
*/
|
||||
void ui_standby_force_enter(void) {
|
||||
sb_enter();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 模块名称:UI Standby (待机显示页)
|
||||
* 模块功能:长时间无按键操作时自动切入的默认界面(6 路电流值 + 分隔线 + 底部时钟);
|
||||
* 屏幕覆盖层模式——进入保存前屏与焦点、ENTER(确认键)还原,其余键忽略;
|
||||
* 空闲检测 = lv_timer(1s 周期),活动通知由菜单/内容页键事件挂钩
|
||||
* 适用平台:STM32F407ZGTx / PC 模拟器(两端共用)
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-09-14
|
||||
* 修改记录:
|
||||
* v1.0 2026-09-14 王建锋 创建初始版本(设计见 docs/运行与自检记录设计说明.md §5.2)
|
||||
*/
|
||||
|
||||
#ifndef UI_STANDBY_H
|
||||
#define UI_STANDBY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* 时间字符串提供回调(平台差异:MCU = sys_clock_get_str,模拟器 = 宿主 time())
|
||||
*/
|
||||
typedef void (*ui_standby_time_cb)(char *buf, size_t len);
|
||||
|
||||
/*
|
||||
* 函数功能:初始化待机模块(建常驻屏/容器 + 空闲检测定时器)
|
||||
* 入口参数:idle_timeout_ms - 无操作超时阈值(ms;0 = 拒绝初始化) uint32_t
|
||||
* time_cb - 底部时钟字符串提供回调(不可为 NULL) ui_standby_time_cb
|
||||
* 返回值:0 - 成功;-1 - 失败(已初始化/参数无效/LVGL 池耗尽) int
|
||||
* 限定条件:ui_menu_init() 已完成(默认输入组存在);lv_tick_inc/lv_timer_handler 已被驱动
|
||||
*/
|
||||
int ui_standby_init(uint32_t idle_timeout_ms, ui_standby_time_cb time_cb);
|
||||
|
||||
/*
|
||||
* 函数功能:通知用户活动(重置空闲计时)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:ui_standby_init() 已成功;任意任务上下文(仅写一个时间戳)
|
||||
* 函数说明:菜单/内容页每收到一个键调用一次;待机屏上的按键同样经此重置
|
||||
*/
|
||||
void ui_standby_notify_activity(void);
|
||||
|
||||
/*
|
||||
* 函数功能:查询是否处于待机屏
|
||||
* 入口参数:无
|
||||
* 返回值:true - 待机中;false - 否
|
||||
* 限定条件:无
|
||||
*/
|
||||
bool ui_standby_is_active(void);
|
||||
|
||||
/*
|
||||
* 函数功能:强制进入待机屏(测试钩子,绕过空闲计时)
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 限定条件:ui_standby_init() 已成功;UI 任务上下文(模拟器无头回归用)
|
||||
*/
|
||||
void ui_standby_force_enter(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* UI_STANDBY_H */
|
||||
Reference in New Issue
Block a user