整定一版

This commit is contained in:
冯佳
2025-12-19 17:01:27 +08:00
parent 294a49f207
commit 8bddc34c88
43 changed files with 7273 additions and 956 deletions

681
demo/demo.c Normal file
View File

@ -0,0 +1,681 @@
/**
**********************************************************************************************************************
* @file demo.c
* @brief 菜单组件示例程序 - 多语言版本
* @author menu_component
* @date 2025-12-19
**********************************************************************************************************************
*/
#include "../api/menu_api.h"
#include "../port/menu_port.h"
#include "language.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined(_WIN32) || defined(_WIN64)
#include <conio.h>
#define NON_BLOCKING_GETCHAR() _getch()
#define IS_KEY_AVAILABLE() _kbhit()
#else
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <termios.h>
// 保存原始终端设置
static struct termios sg_original_termios;
/**
* @brief 设置终端为无缓冲模式
*/
static void set_nonblocking_terminal(void)
{
struct termios new_termios;
tcgetattr(STDIN_FILENO, &sg_original_termios);
new_termios = sg_original_termios;
new_termios.c_lflag &= ~(ICANON | ECHO); // 关闭行缓冲和回显
new_termios.c_cc[VMIN] = 1; // 至少读取1个字符
new_termios.c_cc[VTIME] = 0; // 无超时
tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
}
/**
* @brief 恢复终端为原始模式
*/
static void restore_terminal(void)
{
tcsetattr(STDIN_FILENO, TCSANOW, &sg_original_termios);
}
/**
* @brief 检查是否有按键输入
*/
static bool IS_KEY_AVAILABLE(void)
{
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
return select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv) > 0;
}
/**
* @brief 无缓冲获取按键
*/
static char NON_BLOCKING_GETCHAR(void)
{
return getchar();
}
#endif
/* 使用新的菜单节点ID枚举 */
#define MENU_ID_MAIN MENU_NODE_ID_MAIN
#define MENU_ID_ITEM1 MENU_NODE_ID_MEASUREMENT
#define MENU_ID_ITEM2 MENU_NODE_ID_PROTECTION
#define MENU_ID_ITEM3 MENU_NODE_ID_CONTROL
#define MENU_ID_SUB1 MENU_NODE_ID_SETTING
#define MENU_ID_SUB2 MENU_NODE_ID_RECORD
#define MENU_ID_LANGUAGE MENU_NODE_ID_HELP
#define MENU_ID_GRANDCHILD1 MENU_NODE_ID_ABOUT
#define MENU_ID_GRANDCHILD2 (MENU_NODE_ID_ABOUT + 1)
/* 测量菜单子项 */
#define MENU_ID_MEASUREMENT_VOLTAGE MENU_NODE_ID_MEASUREMENT_VOLTAGE
#define MENU_ID_MEASUREMENT_CURRENT MENU_NODE_ID_MEASUREMENT_CURRENT
#define MENU_ID_MEASUREMENT_POWER MENU_NODE_ID_MEASUREMENT_POWER
#define MENU_ID_MEASUREMENT_ENERGY MENU_NODE_ID_MEASUREMENT_ENERGY
#define MENU_ID_MEASUREMENT_FREQUENCY MENU_NODE_ID_MEASUREMENT_FREQUENCY
#define MENU_ID_MEASUREMENT_TEMPERATURE MENU_NODE_ID_MEASUREMENT_TEMPERATURE
/* 保护菜单子项 */
#define MENU_ID_PROTECTION_OVER_VOLTAGE MENU_NODE_ID_PROTECTION_OVER_VOLTAGE
#define MENU_ID_PROTECTION_UNDER_VOLTAGE MENU_NODE_ID_PROTECTION_UNDER_VOLTAGE
#define MENU_ID_PROTECTION_OVER_CURRENT MENU_NODE_ID_PROTECTION_OVER_CURRENT
#define MENU_ID_PROTECTION_SETTING MENU_NODE_ID_PROTECTION_SETTING
/* 控制菜单子项 */
#define MENU_ID_CONTROL_ON_OFF MENU_NODE_ID_CONTROL_ON_OFF
#define MENU_ID_CONTROL_START_STOP MENU_NODE_ID_CONTROL_START_STOP
#define MENU_ID_CONTROL_AUTO_MANUAL MENU_NODE_ID_CONTROL_AUTO_MANUAL
/* 设置菜单子项 */
#define MENU_ID_SETTING_LANGUAGE MENU_NODE_ID_SETTING_LANGUAGE
/* 持久化函数声明 */
static MenuErrCode demo_persistence_save(const uint8_t* data, uint16_t size);
static MenuErrCode demo_persistence_restore(uint8_t* data, uint16_t* size);
/* 全局变量 */
static uint32_t sg_tick = 0;
static bool sg_is_menu_active = false;
static SystemLang_e sg_current_language = SYSTEM_LANG_CHINESE;
/* 菜单回调函数 */
/**
* @brief 主菜单进入回调
*/
static MenuErrCode menu_enter_main(MenuNodeId node_id, struct MenuCoreCtx* core_ctx)
{
(void)node_id;
(void)core_ctx;
sg_is_menu_active = true;
printf("%s: %s\n", get_text(TEXT_ENTER), get_text(TEXT_MAIN_MENU));
return MENU_ERR_OK;
}
/**
* @brief 主菜单退出回调
*/
static MenuErrCode menu_exit_main(MenuNodeId node_id, struct MenuCoreCtx* core_ctx)
{
(void)node_id;
(void)core_ctx;
sg_is_menu_active = false;
printf("%s: %s\n", get_text(TEXT_EXIT), get_text(TEXT_MAIN_MENU));
return MENU_ERR_OK;
}
/**
* @brief 测量菜单进入回调
*/
static MenuErrCode menu_enter_item1(MenuNodeId node_id, struct MenuCoreCtx* core_ctx)
{
(void)node_id;
(void)core_ctx;
printf("%s: %s\n", get_text(TEXT_ENTER), get_text(TEXT_MAIN_MEASUREMENT));
return MENU_ERR_OK;
}
/**
* @brief 保护菜单进入回调
*/
static MenuErrCode menu_enter_item2(MenuNodeId node_id, struct MenuCoreCtx* core_ctx)
{
(void)node_id;
(void)core_ctx;
printf("%s: %s\n", get_text(TEXT_ENTER), get_text(TEXT_MAIN_PROTECTION));
return MENU_ERR_OK;
}
/**
* @brief 控制菜单进入回调
*/
static MenuErrCode menu_enter_item3(MenuNodeId node_id, struct MenuCoreCtx* core_ctx)
{
(void)node_id;
(void)core_ctx;
printf("%s: %s\n", get_text(TEXT_ENTER), get_text(TEXT_MAIN_CONTROL));
return MENU_ERR_OK;
}
/**
* @brief 语言设置进入回调(声明)
*/
static MenuErrCode menu_enter_language(MenuNodeId node_id, struct MenuCoreCtx* core_ctx);
/**
* @brief 设置菜单进入回调(声明)
*/
static MenuErrCode menu_enter_setting(MenuNodeId node_id, struct MenuCoreCtx* core_ctx);
/**
* @brief 重新注册菜单节点,用于语言切换
*/
static void re_register_menu_nodes(void)
{
// 先注销所有节点
menu_deinit();
menu_init();
// 主菜单
MenuNodeId main_node_id = menu_register_node(0, 0, get_text(TEXT_MAIN_MENU), menu_enter_main, menu_exit_main);
// 菜单项
MenuNodeId item1_node_id = menu_register_node(0, main_node_id, get_text(TEXT_MAIN_MEASUREMENT), menu_enter_item1, NULL);
MenuNodeId item2_node_id = menu_register_node(0, main_node_id, get_text(TEXT_MAIN_PROTECTION), menu_enter_item2, NULL);
MenuNodeId item3_node_id = menu_register_node(0, main_node_id, get_text(TEXT_MAIN_CONTROL), menu_enter_item3, NULL);
MenuNodeId sub1_node_id = menu_register_node(0, main_node_id, get_text(TEXT_MAIN_SETTING), menu_enter_setting, NULL);
// 测量菜单子项
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_VOLTAGE), NULL, NULL);
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_CURRENT), NULL, NULL);
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_POWER), NULL, NULL);
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_ENERGY), NULL, NULL);
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_FREQUENCY), NULL, NULL);
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_TEMPERATURE), NULL, NULL);
// 保护菜单子项
menu_register_node(0, item2_node_id, get_text(TEXT_PROTECT_OVER_VOLTAGE), NULL, NULL);
menu_register_node(0, item2_node_id, get_text(TEXT_PROTECT_UNDER_VOLTAGE), NULL, NULL);
menu_register_node(0, item2_node_id, get_text(TEXT_PROTECT_OVER_CURRENT), NULL, NULL);
menu_register_node(0, item2_node_id, get_text(TEXT_PROTECT_SETTING), NULL, NULL);
// 控制菜单子项
menu_register_node(0, item3_node_id, get_text(TEXT_CONTROL_ON_OFF), NULL, NULL);
menu_register_node(0, item3_node_id, get_text(TEXT_CONTROL_START_STOP), NULL, NULL);
menu_register_node(0, item3_node_id, get_text(TEXT_CONTROL_AUTO_MANUAL), NULL, NULL);
// 设置菜单子项
menu_register_node(0, sub1_node_id, get_text(TEXT_SETTING_LANGUAGE), menu_enter_language, NULL);
// 重新注册持久化回调函数
menu_persistence_register_callback(demo_persistence_save, demo_persistence_restore);
}
/**
* @brief 设置菜单进入回调
*/
static MenuErrCode menu_enter_setting(MenuNodeId node_id, struct MenuCoreCtx* core_ctx)
{
(void)node_id;
(void)core_ctx;
printf("%s: %s\n", get_text(TEXT_ENTER), get_text(TEXT_MAIN_SETTING));
return MENU_ERR_OK;
}
/**
* @brief 语言设置进入回调
*/
static MenuErrCode menu_enter_language(MenuNodeId node_id, struct MenuCoreCtx* core_ctx)
{
(void)node_id;
(void)core_ctx;
printf("%s: %s\n", get_text(TEXT_ENTER), get_text(TEXT_SETTING_LANGUAGE));
// 切换语言
if (sg_current_language == SYSTEM_LANG_CHINESE)
{
sg_current_language = SYSTEM_LANG_ENGLISH;
set_language(SYSTEM_LANG_ENGLISH);
printf("%s: English\n", get_text(TEXT_SETTING_LANGUAGE));
}
else
{
sg_current_language = SYSTEM_LANG_CHINESE;
set_language(SYSTEM_LANG_CHINESE);
printf("%s: 中文\n", get_text(TEXT_SETTING_LANGUAGE));
}
// 重新注册菜单节点,更新菜单名称
re_register_menu_nodes();
return MENU_ERR_OK;
}
/**
* @brief 默认获取系统时间函数
*/
static uint32_t demo_get_tick(void)
{
return sg_tick++;
}
/**
* @brief 默认打印函数
*/
static void demo_printf(const char* fmt, va_list args)
{
vprintf(fmt, args);
}
/**
* @brief 持久化数据保存回调函数
* @param data 要保存的数据
* @param size 数据大小
* @return 错误码
*/
static MenuErrCode demo_persistence_save(const uint8_t* data, uint16_t size)
{
FILE* fp = NULL;
MenuErrCode ret = MENU_ERR_OK;
// 打开文件进行写入
fp = fopen("menu_persistence.dat", "wb");
if (fp == NULL) {
printf("%s: %s\n", get_text(TEXT_ERROR), "打开文件失败");
return MENU_ERR_OPERATION_FAILED;
}
// 写入数据
if (fwrite(data, 1, size, fp) != size) {
printf("%s: %s\n", get_text(TEXT_ERROR), "写入文件失败");
ret = MENU_ERR_OPERATION_FAILED;
}
// 关闭文件
fclose(fp);
return ret;
}
/**
* @brief 持久化数据恢复回调函数
* @param data 恢复数据缓冲区
* @param size 数据大小
* @return 错误码
*/
static MenuErrCode demo_persistence_restore(uint8_t* data, uint16_t* size)
{
FILE* fp = NULL;
MenuErrCode ret = MENU_ERR_OK;
size_t read_size = 0;
// 打开文件进行读取
fp = fopen("menu_persistence.dat", "rb");
if (fp == NULL) {
printf("%s: %s\n", get_text(TEXT_WARNING), "文件不存在,使用默认设置");
return MENU_ERR_OPERATION_FAILED;
}
// 获取文件大小
fseek(fp, 0, SEEK_END);
read_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
// 检查文件大小是否合法
if (read_size > *size) {
printf("%s: %s\n", get_text(TEXT_ERROR), "文件过大");
fclose(fp);
return MENU_ERR_INVALID_PARAM;
}
// 读取数据
if (fread(data, 1, read_size, fp) != read_size) {
printf("%s: %s\n", get_text(TEXT_ERROR), "读取文件失败");
ret = MENU_ERR_OPERATION_FAILED;
} else {
// 更新实际读取的大小
*size = (uint16_t)read_size;
}
// 关闭文件
fclose(fp);
return ret;
}
/**
* @brief 硬件驱动配置
*/
static MenuPortDriver sg_demo_driver = {
.printf = demo_printf,
.get_tick = demo_get_tick,
.delay_ms = NULL,
.display = NULL,
.key_scan = NULL,
.irq_ctrl = NULL,
.error_handler = NULL,
.modbus_send = NULL,
.modbus_receive = NULL,
.persistence_save = demo_persistence_save,
.persistence_restore = demo_persistence_restore,
};
/**
* @brief 演示菜单导航
*/
/**
* @brief 显示当前菜单的子菜单项
*/
static void display_menu_items(void)
{
MenuNodeId curr_node_id = menu_get_current_node();
const MenuNode* curr_node = menu_find_node(curr_node_id);
if (curr_node == NULL) {
printf("\n无效节点\n");
return;
}
// 清屏(可选,根据终端支持情况)
printf("\033[2J\033[H");
// 显示当前菜单路径
printf("%s\n", get_text(TEXT_MAIN_MENU));
printf("==================\n");
// 显示当前菜单状态
printf("%s: %s\n", get_text(TEXT_CURRENT), curr_node->name ? curr_node->name : "Unnamed");
// 显示导航路径
uint8_t path_depth = menu_get_nav_depth();
MenuNodeId path[MENU_CONFIG_STACK_DEPTH];
menu_get_nav_path(path, MENU_CONFIG_STACK_DEPTH);
printf("%s: ", get_text(TEXT_STATUS));
for (uint8_t i = 0; i < path_depth; i++) {
const MenuNode* path_node = menu_find_node(path[i]);
if (path_node != NULL) {
printf("%s", path_node->name ? path_node->name : "Unnamed");
if (i < path_depth - 1) {
printf(" -> ");
}
}
}
printf("\n\n");
// 显示当前菜单的子菜单项
printf("%s:\n", get_text(TEXT_SUMMARY));
if (curr_node->first_child_id != 0) {
// 遍历所有子节点
const MenuNode* child_node = menu_find_node(curr_node->first_child_id);
uint8_t item_index = 1;
while (child_node != NULL) {
// 子菜单仅显示列表,不高亮选中项(高亮在同级节点中处理)
printf(" %d. %s\n", item_index, child_node->name ? child_node->name : "Unnamed");
MenuNodeId next_id = child_node->next_sibling_id;
if (next_id == 0) {
break;
}
child_node = menu_find_node(next_id);
item_index++;
}
} else {
printf(" %s\n", get_text(TEXT_EMPTY));
}
// 显示当前节点在同级节点中的位置
const MenuNode* parent_node = menu_find_node(curr_node->parent_id);
if (parent_node != NULL) {
printf("\n%s:\n", get_text(TEXT_CURRENT_SELECTION));
// 遍历所有兄弟节点
const MenuNode* sibling_node = menu_find_node(parent_node->first_child_id);
uint8_t item_index = 1;
while (sibling_node != NULL) {
// 检查当前显示的节点是否为选中节点
bool is_selected = (sibling_node->id == curr_node_id);
// 高亮显示当前选中的菜单项
if (is_selected) {
printf(" **> %d. %s <**\n",
item_index, sibling_node->name ? sibling_node->name : "Unnamed");
} else {
printf(" %d. %s\n", item_index, sibling_node->name ? sibling_node->name : "Unnamed");
}
MenuNodeId next_id = sibling_node->next_sibling_id;
if (next_id == 0) {
break;
}
sibling_node = menu_find_node(next_id);
item_index++;
}
}
// 显示菜单操作提示
printf("\n%s:\n", get_text(TEXT_OPERATIONS));
printf(" ↑/%s: %s\n", get_text(TEXT_DOWN_ARROW), get_text(TEXT_SELECT_ITEM));
printf(" %s: %s\n", get_text(TEXT_ENTER), get_text(TEXT_ENTER_SUBMENU));
printf(" Esc/%s: %s\n", get_text(TEXT_LEFT_ARROW), get_text(TEXT_RETURN_PARENT));
printf(" q: %s\n", get_text(TEXT_EXIT));
printf("==================\n");
}
/**
* @brief 演示菜单导航
*/
static void demo_menu_navigation(void)
{
char key = 0;
// 设置终端为无缓冲模式仅在非Windows平台
#ifndef _WIN32
set_nonblocking_terminal();
#endif
printf("\n%s\n", get_text(TEXT_MAIN_MENU));
printf("==================\n");
printf("%s: %s\n", get_text(TEXT_SELECT_OPTION), get_text(TEXT_MAIN_MENU));
printf("Enter: %s\n", get_text(TEXT_ENTER));
printf("Esc: %s\n", get_text(TEXT_EXIT));
printf("q: %s\n", get_text(TEXT_EXIT));
printf("%s: %s\n", get_text(TEXT_UP_ARROW), get_text(TEXT_SELECT_PREVIOUS));
printf("%s: %s\n", get_text(TEXT_DOWN_ARROW), get_text(TEXT_SELECT_NEXT));
printf("%s: %s\n", get_text(TEXT_RIGHT_ARROW), get_text(TEXT_ENTER_SUBMENU));
printf("%s: %s\n", get_text(TEXT_LEFT_ARROW), get_text(TEXT_RETURN_PARENT));
printf("==================\n");
// 初始化显示
display_menu_items();
while (1) {
// 持续处理菜单主循环,确保事件得到及时处理
menu_main_loop(demo_get_tick());
// 检查是否有按键输入
if (IS_KEY_AVAILABLE()) {
// 获取按键输入(无缓冲)
key = NON_BLOCKING_GETCHAR();
// 处理退出键
if (key == 'q' || key == 'Q') {
#ifndef _WIN32
restore_terminal();
#endif
return;
}
// 处理回车键
else if (key == '\n' || key == '\r') {
// 不管节点是否有子菜单,都处理回车事件
menu_post_event(MENU_EVENT_KEY_ENTER, 1);
// 处理菜单主循环
menu_main_loop(demo_get_tick());
// 显示当前菜单状态和菜单项
display_menu_items();
}
// 处理Esc键和箭头键
else if (key == '\x1B') {
// 读取完整的Esc序列
char esc_key = NON_BLOCKING_GETCHAR();
if (esc_key == '[') {
key = NON_BLOCKING_GETCHAR();
switch (key) {
case 'A': // 上箭头 - 选择上一项
menu_post_event(MENU_EVENT_KEY_UP, 1);
break;
case 'B': // 下箭头 - 选择下一项
menu_post_event(MENU_EVENT_KEY_DOWN, 1);
break;
case 'C': // 右箭头 - 进入子菜单
menu_post_event(MENU_EVENT_KEY_ENTER, 1);
break;
case 'D': // 左箭头 - 返回上一级菜单
menu_post_event(MENU_EVENT_KEY_ESC, 1);
break;
default:
break;
}
// 处理菜单主循环
menu_main_loop(demo_get_tick());
// 显示当前菜单状态和菜单项
display_menu_items();
} else {
// 单独的Esc键 - 返回上一级菜单
menu_post_event(MENU_EVENT_KEY_ESC, 1);
// 处理菜单主循环
menu_main_loop(demo_get_tick());
// 显示当前菜单状态和菜单项
display_menu_items();
}
}
// 处理普通字符输入
else {
// 可以根据需要添加其他字符处理逻辑
}
}
// 短延迟避免CPU占用过高
#ifdef _WIN32
Sleep(10);
#else
usleep(10000); // 10ms
#endif
}
}
/**
* @brief 主函数
*/
int main(int argc, char* argv[])
{
(void)argc;
(void)argv;
// 初始化多语言系统
set_language(SYSTEM_LANG_CHINESE);
printf("%s\n", get_text(TEXT_MAIN_MENU));
printf("==================\n");
// 初始化硬件端口层
menu_port_init(&sg_demo_driver);
// 初始化菜单组件
MenuErrCode err = menu_init();
if (err != MENU_ERR_OK) {
printf("%s\n", get_text(TEXT_TEST));
return EXIT_FAILURE;
}
// 注册菜单节点
// 主菜单
MenuNodeId main_node_id = menu_register_node(0, 0, get_text(TEXT_MAIN_MENU), menu_enter_main, menu_exit_main);
// 菜单项
MenuNodeId item1_node_id = menu_register_node(0, main_node_id, get_text(TEXT_MAIN_MEASUREMENT), menu_enter_item1, NULL);
MenuNodeId item2_node_id = menu_register_node(0, main_node_id, get_text(TEXT_MAIN_PROTECTION), menu_enter_item2, NULL);
MenuNodeId item3_node_id = menu_register_node(0, main_node_id, get_text(TEXT_MAIN_CONTROL), menu_enter_item3, NULL);
MenuNodeId sub1_node_id = menu_register_node(0, main_node_id, get_text(TEXT_MAIN_SETTING), menu_enter_setting, NULL);
// 测量菜单子项
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_VOLTAGE), NULL, NULL);
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_CURRENT), NULL, NULL);
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_POWER), NULL, NULL);
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_ENERGY), NULL, NULL);
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_FREQUENCY), NULL, NULL);
menu_register_node(0, item1_node_id, get_text(TEXT_MEASURE_TEMPERATURE), NULL, NULL);
// 保护菜单子项
menu_register_node(0, item2_node_id, get_text(TEXT_PROTECT_OVER_VOLTAGE), NULL, NULL);
menu_register_node(0, item2_node_id, get_text(TEXT_PROTECT_UNDER_VOLTAGE), NULL, NULL);
menu_register_node(0, item2_node_id, get_text(TEXT_PROTECT_OVER_CURRENT), NULL, NULL);
menu_register_node(0, item2_node_id, get_text(TEXT_PROTECT_SETTING), NULL, NULL);
// 控制菜单子项
menu_register_node(0, item3_node_id, get_text(TEXT_CONTROL_ON_OFF), NULL, NULL);
menu_register_node(0, item3_node_id, get_text(TEXT_CONTROL_START_STOP), NULL, NULL);
menu_register_node(0, item3_node_id, get_text(TEXT_CONTROL_AUTO_MANUAL), NULL, NULL);
// 设置菜单子项
menu_register_node(0, sub1_node_id, get_text(TEXT_SETTING_LANGUAGE), menu_enter_language, NULL);
// 注册持久化回调函数
err = menu_persistence_register_callback(demo_persistence_save, demo_persistence_restore);
if (err != MENU_ERR_OK) {
printf("%s: %s\n", get_text(TEXT_ERROR), get_text(TEXT_REGISTER_CALLBACK_FAILED));
}
// 尝试恢复之前的菜单状态
err = menu_persistence_restore();
if (err == MENU_ERR_OK) {
printf("%s: %s\n", get_text(TEXT_SUCCESS), get_text(TEXT_RESTORE_MENU_STATE));
} else {
printf("%s: %s: Error %d\n", get_text(TEXT_ERROR), get_text(TEXT_RESTORE_MENU_STATE_FAILED), err);
printf("%s\n", get_text(TEXT_START_DEFAULT));
}
printf("%s\n", get_text(TEXT_TEST));
// 运行菜单演示
demo_menu_navigation();
// 保存当前菜单状态
err = menu_persistence_save();
if (err == MENU_ERR_OK) {
printf("%s: %s\n", get_text(TEXT_SUCCESS), get_text(TEXT_SAVE_MENU_STATE));
} else {
printf("%s: %s: Error %d\n", get_text(TEXT_ERROR), get_text(TEXT_SAVE_MENU_STATE_FAILED), err);
}
// 清理资源
menu_deinit();
menu_port_deinit();
printf("\n%s\n", get_text(TEXT_EXIT));
return EXIT_SUCCESS;
}