运行/自检记录与待机屏:sys_log定长64B日志引擎(/log/*.log,FTP可直下)+记录页x2+待机屏+密码错误提示;字体122字/217字形

This commit is contained in:
2026-09-14 19:05:00 +08:00
parent bc4a7da8a0
commit 9eb1bd63b4
37 changed files with 2110 additions and 109 deletions
+18 -7
View File
@@ -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();
+2
View File
@@ -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
View File
@@ -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
}
};
+9 -2
View File
@@ -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));
}
+47 -5
View File
@@ -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;
}
/*
+99
View File
@@ -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,
};
+24
View File
@@ -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 */
+99
View File
@@ -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,
};
+24
View File
@@ -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 */
+356
View File
@@ -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();
}
+67
View File
@@ -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 */