diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 00ac6c0..0000000 --- a/.gitignore +++ /dev/null @@ -1,89 +0,0 @@ -# ---> C -# Prerequisites -*.d - -# Object files -*.o -*.ko -*.obj -*.elf - -# Linker output -*.ilk -*.map -*.exp - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - -# Debug files -*.dSYM/ -*.su -*.idb -*.pdb - -# Kernel Module Compile Results -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf - -# ---> C++ -# Prerequisites -*.d - -# Compiled Object files -*.slo -*.lo -*.o -*.obj - -# Precompiled Headers -*.gch -*.pch - -# Compiled Dynamic libraries -*.so -*.dylib -*.dll - -# Fortran module files -*.mod -*.smod - -# Compiled Static libraries -*.lai -*.la -*.a -*.lib - -# Executables -*.exe -*.out -*.app - -build/* diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 513686a..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,112 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -project(menu VERSION 1.3.0 LANGUAGES C) - -# 设置C标准 -set(CMAKE_C_STANDARD 99) -set(CMAKE_C_STANDARD_REQUIRED ON) - -# 核心层源文件 -set(CORE_SOURCES - src/core/menu_core.c - src/core/menu_event.c - src/core/menu_hash.c - src/core/menu_stack.c - src/core/menu_permission.c - src/core/menu_persistence.c -) - -# 功能扩展层源文件 -set(FEATURE_SOURCES - src/param/menu_param.c - src/lang/menu_lang.c -) - -# API层源文件 -set(API_SOURCES - api/menu_api.c -) - -# 硬件端口层源文件 -set(PORT_SOURCES - port/menu_port.c -) - -# 所有源文件 -set(MENU_SOURCES - ${CORE_SOURCES} - ${FEATURE_SOURCES} - ${API_SOURCES} - ${PORT_SOURCES} -) - -# 核心层头文件 -set(CORE_HEADERS - src/core/menu_config.h - src/core/menu_types.h - src/core/menu_permission.h - src/core/menu_persistence.h -) - -# 功能扩展层头文件 -set(FEATURE_HEADERS - src/param/menu_param.h - src/lang/menu_lang.h -) - -# API层头文件 -set(API_HEADERS - api/menu_api.h -) - -# 硬件端口层头文件 -set(PORT_HEADERS - port/menu_port.h -) - -# 所有头文件 -set(MENU_HEADERS - ${CORE_HEADERS} - ${FEATURE_HEADERS} - ${API_HEADERS} - ${PORT_HEADERS} -) - -# 创建静态库 -add_library(menu STATIC ${MENU_SOURCES}) - -# 设置库的公共头文件 -set_target_properties(menu PROPERTIES - PUBLIC_HEADER "${MENU_HEADERS}" -) - -# 包含目录 -target_include_directories(menu PUBLIC - $ - $ - $ - $ - $ - $ - $ -) - -# 示例程序 -option(BUILD_EXAMPLES "Build examples" OFF) - -if(BUILD_EXAMPLES) - # 添加示例目录 - add_subdirectory(examples) -endif() - -# 添加demo目录 -add_subdirectory(demo) - -# 添加test目录 -add_subdirectory(test) - -# 安装规则 -install(TARGETS menu - ARCHIVE DESTINATION lib - PUBLIC_HEADER DESTINATION include -) diff --git a/api/menu_api.c b/api/menu_api.c deleted file mode 100644 index 160e528..0000000 --- a/api/menu_api.c +++ /dev/null @@ -1,260 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_api.c - * @brief 菜单组件对外API接口实现 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_api.h" -#include "../src/core/menu_core.h" -#include "../src/core/menu_event.h" -#include "../src/core/menu_hash.h" - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -/* 菜单初始化与反初始化 ---------------------------------------------------------------------------------------------*/ - -MenuErrCode menu_init(void) -{ - return menu_core_init(); -} - -MenuErrCode menu_deinit(void) -{ - return menu_core_deinit(); -} - -/* 菜单节点管理 -----------------------------------------------------------------------------------------------------*/ - -MenuNodeId menu_register_node(MenuNodeId node_id, MenuNodeId parent_id, const char* name, MenuCallback enter_cb, MenuCallback exit_cb) -{ - // 参数验证 - if (name == NULL) { - return 0; // 保持原有API兼容,0表示注册失败 - } - - // 调用核心层的节点注册功能 - return menu_core_register_node(node_id, parent_id, name, enter_cb, exit_cb); -} - -MenuErrCode menu_register_nodes(const struct MenuNode* nodes, uint16_t count) -{ - // 暂未实现批量注册功能 - (void)nodes; - (void)count; - return MENU_ERR_OPERATION_FAILED; -} - -MenuErrCode menu_unregister_node(MenuNodeId node_id) -{ - // 调用核心层的节点注销功能 - return menu_core_unregister_node(node_id); -} - -MenuErrCode menu_update_node(MenuNodeId node_id, const char* name, MenuCallback enter_cb, MenuCallback exit_cb) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - MenuNode* node = menu_hash_find(core_ctx, node_id); - - if (node == NULL || !node->flags.is_registered) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 更新节点信息 - if (name != NULL) { - node->name = name; - } - - if (enter_cb != NULL) { - node->enter_cb = enter_cb; - } - - if (exit_cb != NULL) { - node->exit_cb = exit_cb; - } - - return MENU_ERR_OK; -} - -const struct MenuNode* menu_find_node(MenuNodeId node_id) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - return menu_hash_find(core_ctx, node_id); -} - -/* 菜单事件处理 -----------------------------------------------------------------------------------------------------*/ - -MenuErrCode menu_post_event(MenuEventType event_type, uint8_t priority) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - MenuEvent event; - - event.type = event_type; - event.priority = priority; - event.target_node_id = core_ctx->current_node_id; - event.data = NULL; - event.timestamp = core_ctx->last_refresh_tick; - - return menu_event_queue_push(&core_ctx->event_queue, &event); -} - -MenuErrCode menu_post_event_with_data(MenuEventType event_type, uint8_t priority, void* data) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - MenuEvent event; - - event.type = event_type; - event.priority = priority; - event.target_node_id = core_ctx->current_node_id; - event.data = data; - event.timestamp = core_ctx->last_refresh_tick; - - return menu_event_queue_push(&core_ctx->event_queue, &event); -} - -/* 菜单导航操作 -----------------------------------------------------------------------------------------------------*/ - -MenuErrCode menu_main_loop(uint32_t tick) -{ - // 调用核心层的主循环功能 - return menu_core_main_loop(tick); -} - -MenuErrCode menu_enter(void) -{ - return menu_post_event(MENU_EVENT_KEY_ENTER, 1); -} - -MenuErrCode menu_exit(void) -{ - return menu_post_event(MENU_EVENT_KEY_ESC, 1); -} - -MenuErrCode menu_up(void) -{ - return menu_post_event(MENU_EVENT_KEY_UP, 1); -} - -MenuErrCode menu_down(void) -{ - return menu_post_event(MENU_EVENT_KEY_DOWN, 1); -} - -MenuErrCode menu_select(MenuNodeId node_id) -{ - // 暂未实现直接选择指定节点功能 - (void)node_id; - return MENU_ERR_OPERATION_FAILED; -} - -MenuErrCode menu_reset(void) -{ - // 暂未实现重置功能 - return MENU_ERR_OPERATION_FAILED; -} - -/* 菜单状态查询 -----------------------------------------------------------------------------------------------------*/ - -MenuState menu_get_state(void) -{ - return menu_get_current_state(); -} - -MenuNodeId menu_get_current_node(void) -{ - return menu_get_current_node_id(); -} - -uint8_t menu_get_nav_depth(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - return core_ctx->nav_path.depth; -} - -uint8_t menu_get_nav_path(MenuNodeId* path, uint8_t max_depth) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - uint8_t actual_depth = core_ctx->nav_path.depth; - - if (actual_depth > max_depth) { - actual_depth = max_depth; - } - - for (uint8_t i = 0; i < actual_depth; i++) { - path[i] = core_ctx->nav_path.path[i]; - } - - return actual_depth; -} - -/* 状态机扩展接口 ---------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_STATE_MACHINE_EXT -MenuErrCode menu_state_register_transition(const MenuStateTransition* transition) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx->custom_transition_count >= MENU_CONFIG_MAX_STATE_TRANSITIONS) { - return MENU_ERR_OUT_OF_MEMORY; - } - - core_ctx->custom_transitions[core_ctx->custom_transition_count] = *transition; - core_ctx->custom_transition_count++; - - return MENU_ERR_OK; -} - -MenuErrCode menu_state_unregister_transition(MenuState current_state, MenuEventType event) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - bool found = false; - - // 查找并删除匹配的状态转换规则 - for (uint16_t i = 0; i < core_ctx->custom_transition_count; i++) { - if (core_ctx->custom_transitions[i].current_state == current_state && - core_ctx->custom_transitions[i].event == event) { - // 找到匹配的规则,将后续规则前移 - for (uint16_t j = i; j < core_ctx->custom_transition_count - 1; j++) { - core_ctx->custom_transitions[j] = core_ctx->custom_transitions[j + 1]; - } - core_ctx->custom_transition_count--; - found = true; - break; - } - } - - return found ? MENU_ERR_OK : MENU_ERR_INVALID_STATE; -} - -MenuErrCode menu_state_switch(MenuState state) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - core_ctx->current_state = state; - return MENU_ERR_OK; -} -#endif - -/* 内存监控接口 -----------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_MEM_MONITOR -uint16_t menu_mem_get_used_nodes(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - return core_ctx->node_count; -} - -uint16_t menu_mem_get_free_nodes(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - return core_ctx->free_node_count; -} - -uint16_t menu_mem_get_max_nodes(void) -{ - return MENU_CONFIG_MAX_NODES; -} -#endif - diff --git a/api/menu_api.h b/api/menu_api.h deleted file mode 100644 index 801b5e1..0000000 --- a/api/menu_api.h +++ /dev/null @@ -1,332 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_api.h - * @brief 菜单组件对外API接口定义 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_API_H -#define MENU_API_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "../src/core/menu_config.h" -#include "../src/core/menu_types.h" - -/* 宏定义 -----------------------------------------------------------------------------------------------------------*/ -#define MENU_API_VERSION "1.0.1" - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -/* 菜单初始化与反初始化 ---------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化菜单组件 - * @return 错误码 - */ -MenuErrCode menu_init(void); - -/** - * @brief 反初始化菜单组件 - * @return 错误码 - */ -MenuErrCode menu_deinit(void); - -/* 菜单节点管理 -----------------------------------------------------------------------------------------------------*/ - -/** - * @brief 注册菜单节点 - * @param node_id 节点ID(0表示自动分配) - * @param parent_id 父节点ID - * @param name 节点名称 - * @param enter_cb 进入回调 - * @param exit_cb 退出回调 - * @return 实际分配的节点ID - */ -MenuNodeId menu_register_node(MenuNodeId node_id, MenuNodeId parent_id, const char* name, MenuCallback enter_cb, MenuCallback exit_cb); - -/** - * @brief 批量注册菜单节点 - * @param nodes 节点数组 - * @param count 节点数量 - * @return 错误码 - */ -MenuErrCode menu_register_nodes(const struct MenuNode* nodes, uint16_t count); - -/** - * @brief 注销菜单节点 - * @param node_id 节点ID - * @return 错误码 - */ -MenuErrCode menu_unregister_node(MenuNodeId node_id); - -/** - * @brief 更新菜单节点 - * @param node_id 节点ID - * @param name 节点名称(NULL表示不更新) - * @param enter_cb 进入回调(NULL表示不更新) - * @param exit_cb 退出回调(NULL表示不更新) - * @return 错误码 - */ -MenuErrCode menu_update_node(MenuNodeId node_id, const char* name, MenuCallback enter_cb, MenuCallback exit_cb); - -/** - * @brief 查找菜单节点 - * @param node_id 节点ID - * @return 节点指针,未找到返回NULL - */ -const struct MenuNode* menu_find_node(MenuNodeId node_id); - -/* 菜单事件处理 -----------------------------------------------------------------------------------------------------*/ - -/** - * @brief 发送菜单事件 - * @param event_type 事件类型 - * @param priority 事件优先级(0-3,0最高) - * @return 错误码 - */ -MenuErrCode menu_post_event(MenuEventType event_type, uint8_t priority); - -/** - * @brief 发送带数据的菜单事件 - * @param event_type 事件类型 - * @param priority 事件优先级(0-3,0最高) - * @param data 事件数据 - * @return 错误码 - */ -MenuErrCode menu_post_event_with_data(MenuEventType event_type, uint8_t priority, void* data); - -/* 菜单导航操作 -----------------------------------------------------------------------------------------------------*/ - -/** - * @brief 菜单主循环,处理事件和刷新显示 - * @param tick 当前系统时间(ms) - * @return 错误码 - */ -MenuErrCode menu_main_loop(uint32_t tick); - -/** - * @brief 进入菜单 - * @return 错误码 - */ -MenuErrCode menu_enter(void); - -/** - * @brief 退出菜单 - * @return 错误码 - */ -MenuErrCode menu_exit(void); - -/** - * @brief 上移菜单项 - * @return 错误码 - */ -MenuErrCode menu_up(void); - -/** - * @brief 下移菜单项 - * @return 错误码 - */ -MenuErrCode menu_down(void); - -/** - * @brief 选择菜单项 - * @param node_id 节点ID - * @return 错误码 - */ -MenuErrCode menu_select(MenuNodeId node_id); - -/** - * @brief 重置菜单,回到主菜单 - * @return 错误码 - */ -MenuErrCode menu_reset(void); - -/* 菜单状态查询 -----------------------------------------------------------------------------------------------------*/ - -/** - * @brief 获取当前菜单状态 - * @return 当前菜单状态 - */ -MenuState menu_get_state(void); - -/** - * @brief 获取当前选中的节点ID - * @return 当前节点ID - */ -MenuNodeId menu_get_current_node(void); - -/** - * @brief 获取导航深度 - * @return 导航深度 - */ -uint8_t menu_get_nav_depth(void); - -/** - * @brief 获取导航路径 - * @param path 用于存储导航路径的数组 - * @param max_depth 数组最大深度 - * @return 实际获取的深度 - */ -uint8_t menu_get_nav_path(MenuNodeId* path, uint8_t max_depth); - -/* 状态机扩展接口 ---------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_STATE_MACHINE_EXT -/** - * @brief 注册自定义状态转换规则 - * @param transition 状态转换规则 - * @return 错误码 - */ -MenuErrCode menu_state_register_transition(const MenuStateTransition* transition); - -/** - * @brief 注销自定义状态转换规则 - * @param current_state 当前状态 - * @param event 触发事件 - * @return 错误码 - */ -MenuErrCode menu_state_unregister_transition(MenuState current_state, MenuEventType event); - -/** - * @brief 切换到指定状态 - * @param state 目标状态 - * @return 错误码 - */ -MenuErrCode menu_state_switch(MenuState state); -#endif - -/* 内存监控接口 -----------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_MEM_MONITOR -/** - * @brief 获取已使用节点数量 - * @return 已使用节点数量 - */ -uint16_t menu_mem_get_used_nodes(void); - -/** - * @brief 获取空闲节点数量 - * @return 空闲节点数量 - */ -uint16_t menu_mem_get_free_nodes(void); - -/** - * @brief 获取最大节点数量 - * @return 最大节点数量 - */ -uint16_t menu_mem_get_max_nodes(void); -#endif - -/* 权限管理接口 -----------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_PERMISSION -/** - * @brief 注册角色 - * @param role 角色结构体指针 - * @return 错误码 - */ -MenuErrCode menu_permission_register_role(const MenuRole* role); - -/** - * @brief 注销角色 - * @param role_id 角色ID - * @return 错误码 - */ -MenuErrCode menu_permission_unregister_role(MenuRoleId role_id); - -/** - * @brief 设置当前角色 - * @param role_id 角色ID - * @return 错误码 - */ -MenuErrCode menu_permission_set_current_role(MenuRoleId role_id); - -/** - * @brief 获取当前角色 - * @return 当前角色ID - */ -MenuRoleId menu_permission_get_current_role(void); - -/** - * @brief 更新节点权限级别 - * @param node_id 节点ID - * @param permission_level 权限级别 - * @return 错误码 - */ -MenuErrCode menu_permission_update_node_level(MenuNodeId node_id, MenuPermissionLevel permission_level); - -/** - * @brief 获取节点权限级别 - * @param node_id 节点ID - * @return 节点权限级别 - */ -MenuPermissionLevel menu_permission_get_node_level(MenuNodeId node_id); - -/** - * @brief 检查节点是否可访问 - * @param node_id 节点ID - * @return true表示可访问,false表示不可访问 - */ -bool menu_permission_check_node_access(MenuNodeId node_id); - -/** - * @brief 获取角色信息 - * @param role_id 角色ID - * @return 角色结构体指针,NULL表示角色不存在 - */ -const MenuRole* menu_permission_get_role(MenuRoleId role_id); -#endif - -/* 状态持久化接口 ---------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_PERSISTENCE -/** - * @brief 注册持久化回调函数 - * @param save_cb 保存回调函数 - * @param restore_cb 恢复回调函数 - * @return 错误码 - */ -MenuErrCode menu_persistence_register_callback(MenuPersistenceCallback save_cb, MenuRestoreCallback restore_cb); - -/** - * @brief 启用或禁用自动保存 - * @param enable true表示启用,false表示禁用 - * @return 错误码 - */ -MenuErrCode menu_persistence_set_auto_save(bool enable); - -/** - * @brief 获取自动保存状态 - * @return true表示启用,false表示禁用 - */ -bool menu_persistence_get_auto_save(void); - -/** - * @brief 设置自动保存间隔 - * @param interval 自动保存间隔(ms) - * @return 错误码 - */ -MenuErrCode menu_persistence_set_auto_save_interval(uint32_t interval); - -/** - * @brief 获取自动保存间隔 - * @return 自动保存间隔(ms) - */ -uint32_t menu_persistence_get_auto_save_interval(void); - -/** - * @brief 手动保存菜单状态 - * @return 错误码 - */ -MenuErrCode menu_persistence_save(void); - -/** - * @brief 恢复菜单状态 - * @return 错误码 - */ -MenuErrCode menu_persistence_restore(void); -#endif - -#endif /* MENU_API_H */ diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt deleted file mode 100644 index 33b0fd7..0000000 --- a/demo/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -project(menu_demo C) - -# 设置C标准 -set(CMAKE_C_STANDARD 99) -set(CMAKE_C_STANDARD_REQUIRED ON) - -# 添加当前目录和上级目录作为包含目录 -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} -) - -# 收集示例所需的源文件 -set(DEMO_SOURCES - demo.c - language.c -) - -# 创建demo可执行程序 -add_executable(menu_demo ${DEMO_SOURCES}) - -# 链接menu库 -target_link_libraries(menu_demo PRIVATE menu) - -# 安装规则 -install(TARGETS menu_demo - RUNTIME DESTINATION bin -) diff --git a/demo/build/CMakeCache.txt b/demo/build/CMakeCache.txt deleted file mode 100644 index 3916575..0000000 --- a/demo/build/CMakeCache.txt +++ /dev/null @@ -1,92 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: e:/Jfen_work/local_git_code/menu/demo/build -# It was generated by CMake: C:/Users/ZHIZHANKEJI/AppData/Local/Programs/Python/Python311/Lib/site-packages/cmake/data/bin/cmake.exe -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//Value Computed by CMake. -CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=E:/Jfen_work/local_git_code/menu/demo/build/CMakeFiles/pkgRedirects - -//Program used to build from makefiles. -CMAKE_MAKE_PROGRAM:STRING=nmake - -//Value Computed by CMake -CMAKE_PROJECT_DESCRIPTION:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_HOMEPAGE_URL:STATIC= - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=menu_demo - -//Value Computed by CMake -demo_BINARY_DIR:STATIC=E:/Jfen_work/local_git_code/menu/demo/build - -//Value Computed by CMake -demo_IS_TOP_LEVEL:STATIC=ON - -//Value Computed by CMake -demo_SOURCE_DIR:STATIC=E:/Jfen_work/local_git_code/menu/demo - -//Value Computed by CMake -menu_demo_BINARY_DIR:STATIC=E:/Jfen_work/local_git_code/menu/demo/build - -//Value Computed by CMake -menu_demo_IS_TOP_LEVEL:STATIC=ON - -//Value Computed by CMake -menu_demo_SOURCE_DIR:STATIC=E:/Jfen_work/local_git_code/menu/demo - - -######################## -# INTERNAL cache entries -######################## - -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=e:/Jfen_work/local_git_code/menu/demo/build -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=31 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=2 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=C:/Users/ZHIZHANKEJI/AppData/Local/Programs/Python/Python311/Lib/site-packages/cmake/data/bin/cmake.exe -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=C:/Users/ZHIZHANKEJI/AppData/Local/Programs/Python/Python311/Lib/site-packages/cmake/data/bin/cpack.exe -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=C:/Users/ZHIZHANKEJI/AppData/Local/Programs/Python/Python311/Lib/site-packages/cmake/data/bin/ctest.exe -//Path to cache edit program executable. -CMAKE_EDIT_COMMAND:INTERNAL=C:/Users/ZHIZHANKEJI/AppData/Local/Programs/Python/Python311/Lib/site-packages/cmake/data/bin/cmake-gui.exe -//Name of external makefile project generator. -CMAKE_EXTRA_GENERATOR:INTERNAL= -//Name of generator. -CMAKE_GENERATOR:INTERNAL=NMake Makefiles -//Generator instance identifier. -CMAKE_GENERATOR_INSTANCE:INTERNAL= -//Name of generator platform. -CMAKE_GENERATOR_PLATFORM:INTERNAL= -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Source directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=E:/Jfen_work/local_git_code/menu/demo -//ADVANCED property for variable: CMAKE_MAKE_PROGRAM -CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 -//Platform information initialized -CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=C:/Users/ZHIZHANKEJI/AppData/Local/Programs/Python/Python311/Lib/site-packages/cmake/data/share/cmake-3.31 - diff --git a/demo/build/CMakeFiles/3.31.2/CMakeSystem.cmake b/demo/build/CMakeFiles/3.31.2/CMakeSystem.cmake deleted file mode 100644 index 88ce365..0000000 --- a/demo/build/CMakeFiles/3.31.2/CMakeSystem.cmake +++ /dev/null @@ -1,15 +0,0 @@ -set(CMAKE_HOST_SYSTEM "Windows-10.0.26200") -set(CMAKE_HOST_SYSTEM_NAME "Windows") -set(CMAKE_HOST_SYSTEM_VERSION "10.0.26200") -set(CMAKE_HOST_SYSTEM_PROCESSOR "AMD64") - - - -set(CMAKE_SYSTEM "Windows-10.0.26200") -set(CMAKE_SYSTEM_NAME "Windows") -set(CMAKE_SYSTEM_VERSION "10.0.26200") -set(CMAKE_SYSTEM_PROCESSOR "AMD64") - -set(CMAKE_CROSSCOMPILING "FALSE") - -set(CMAKE_SYSTEM_LOADED 1) diff --git a/demo/build/CMakeFiles/CMakeConfigureLog.yaml b/demo/build/CMakeFiles/CMakeConfigureLog.yaml deleted file mode 100644 index e6a6fbe..0000000 --- a/demo/build/CMakeFiles/CMakeConfigureLog.yaml +++ /dev/null @@ -1,11 +0,0 @@ - ---- -events: - - - kind: "message-v1" - backtrace: - - "C:/Users/ZHIZHANKEJI/AppData/Local/Programs/Python/Python311/Lib/site-packages/cmake/data/share/cmake-3.31/Modules/CMakeDetermineSystem.cmake:205 (message)" - - "CMakeLists.txt:3 (project)" - message: | - The system is: Windows - 10.0.26200 - AMD64 -... diff --git a/demo/build/CMakeFiles/cmake.check_cache b/demo/build/CMakeFiles/cmake.check_cache deleted file mode 100644 index 3dccd73..0000000 --- a/demo/build/CMakeFiles/cmake.check_cache +++ /dev/null @@ -1 +0,0 @@ -# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/demo/demo.c b/demo/demo.c deleted file mode 100644 index ab8e104..0000000 --- a/demo/demo.c +++ /dev/null @@ -1,681 +0,0 @@ -/** - ********************************************************************************************************************** - * @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 -#include -#include -#include - -#if defined(_WIN32) || defined(_WIN64) - #include - #define NON_BLOCKING_GETCHAR() _getch() - #define IS_KEY_AVAILABLE() _kbhit() -#else - #include - #include - #include - #include - - // 保存原始终端设置 - 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; -} \ No newline at end of file diff --git a/demo/language.c b/demo/language.c deleted file mode 100644 index 480172a..0000000 --- a/demo/language.c +++ /dev/null @@ -1,525 +0,0 @@ -#include "language.h" - -/* 全局变量定义 ---------------------------------------------------------------------------------------------------*/ - -/** - * @brief 当前系统语言 - */ -static SystemLang_e sg_current_language = SYSTEM_LANG_CHINESE; - -/** - * @brief 中文文本数组 - */ -static const char *sg_chinese_text[] = { - [TEXT_ENTER] = "进入", - [TEXT_EXIT] = "退出", - [TEXT_RETURN] = "返回", - [TEXT_OK] = "确定", - [TEXT_CANCEL] = "取消", - [TEXT_SAVE] = "保存", - [TEXT_LOAD] = "加载", - - [TEXT_MAIN_MENU] = "主菜单", - [TEXT_MAIN_MEASUREMENT] = "测量", - [TEXT_MAIN_PROTECTION] = "保护", - [TEXT_MAIN_CONTROL] = "控制", - [TEXT_MAIN_SETTING] = "设置", - [TEXT_MAIN_RECORD] = "记录", - [TEXT_MAIN_HELP] = "帮助", - [TEXT_MAIN_ABOUT] = "关于", - - [TEXT_MEASURE_VOLTAGE] = "电压", - [TEXT_MEASURE_CURRENT] = "电流", - [TEXT_MEASURE_POWER] = "功率", - [TEXT_MEASURE_ENERGY] = "能量", - [TEXT_MEASURE_FREQUENCY] = "频率", - [TEXT_MEASURE_TEMPERATURE] = "温度", - - [TEXT_PROTECT_OVER_VOLTAGE] = "过电压保护", - [TEXT_PROTECT_UNDER_VOLTAGE] = "欠电压保护", - [TEXT_PROTECT_OVER_CURRENT] = "过电流保护", - [TEXT_PROTECT_SETTING] = "保护设置", - - [TEXT_CONTROL_ON_OFF] = "开关控制", - [TEXT_CONTROL_START_STOP] = "启停控制", - [TEXT_CONTROL_AUTO_MANUAL] = "自动/手动", - - [TEXT_SETTING_LANGUAGE] = "语言设置", - - [TEXT_RECORD_EVENT] = "事件记录", - - [TEXT_HELP_GUIDE] = "指南", - - [TEXT_ABOUT_VERSION] = "版本信息", - - [TEXT_PERSIST_SAVE_STATE] = "保存菜单状态", - [TEXT_PERSIST_RESTORE_STATE] = "恢复菜单状态", - [TEXT_PERSIST_SAVE_SUCCESS] = "保存成功", - [TEXT_PERSIST_SAVE_FAILED] = "保存失败", - [TEXT_PERSIST_RESTORE_SUCCESS] = "恢复成功", - [TEXT_PERSIST_RESTORE_FAILED] = "恢复失败", - - [TEXT_ERROR] = "错误", - [TEXT_WARNING] = "警告", - [TEXT_SUCCESS] = "成功", - [TEXT_INFO] = "信息", - [TEXT_TEST] = "测试", - [TEXT_SELECT_OPTION] = "选择操作", - [TEXT_CURRENT] = "当前", - [TEXT_STATUS] = "状态", - [TEXT_SUMMARY] = "摘要", - [TEXT_EMPTY] = "空", - [TEXT_CURRENT_SELECTION] = "当前选择", - [TEXT_OPERATIONS] = "操作", - [TEXT_SELECT_ITEM] = "选择项", - [TEXT_ENTER_SUBMENU] = "进入子菜单", - [TEXT_RETURN_PARENT] = "返回父菜单", - [TEXT_SELECT_PREVIOUS] = "选择上一项", - [TEXT_SELECT_NEXT] = "选择下一项", - [TEXT_START_DEFAULT] = "从默认开始", - [TEXT_REGISTER_CALLBACK_FAILED] = "注册回调失败", - [TEXT_RESTORE_MENU_STATE] = "恢复菜单状态", - [TEXT_RESTORE_MENU_STATE_FAILED] = "恢复菜单状态失败", - [TEXT_SAVE_MENU_STATE_FAILED] = "保存菜单状态失败", - - [TEXT_UP_ARROW] = "上箭头", - [TEXT_DOWN_ARROW] = "下箭头", - [TEXT_LEFT_ARROW] = "左箭头", - [TEXT_RIGHT_ARROW] = "右箭头", -}; - -/** - * @brief 英文文本数组 - */ -static const char *sg_english_text[] = { - [TEXT_ENTER] = "Enter", - [TEXT_EXIT] = "Exit", - [TEXT_RETURN] = "Return", - [TEXT_OK] = "OK", - [TEXT_CANCEL] = "Cancel", - [TEXT_SAVE] = "Save", - [TEXT_LOAD] = "Load", - - [TEXT_MAIN_MENU] = "Main Menu", - [TEXT_MAIN_MEASUREMENT] = "Measurement", - [TEXT_MAIN_PROTECTION] = "Protection", - [TEXT_MAIN_CONTROL] = "Control", - [TEXT_MAIN_SETTING] = "Setting", - [TEXT_MAIN_RECORD] = "Record", - [TEXT_MAIN_HELP] = "Help", - [TEXT_MAIN_ABOUT] = "About", - - [TEXT_MEASURE_VOLTAGE] = "Voltage", - [TEXT_MEASURE_CURRENT] = "Current", - [TEXT_MEASURE_POWER] = "Power", - [TEXT_MEASURE_ENERGY] = "Energy", - [TEXT_MEASURE_FREQUENCY] = "Frequency", - [TEXT_MEASURE_TEMPERATURE] = "Temperature", - - [TEXT_PROTECT_OVER_VOLTAGE] = "Over Voltage Protection", - [TEXT_PROTECT_UNDER_VOLTAGE] = "Under Voltage Protection", - [TEXT_PROTECT_OVER_CURRENT] = "Over Current Protection", - [TEXT_PROTECT_SETTING] = "Protection Setting", - - [TEXT_CONTROL_ON_OFF] = "On/Off", - [TEXT_CONTROL_START_STOP] = "Start/Stop", - [TEXT_CONTROL_AUTO_MANUAL] = "Auto/Manual", - - [TEXT_SETTING_LANGUAGE] = "Language Setting", - - [TEXT_RECORD_EVENT] = "Event Record", - - [TEXT_HELP_GUIDE] = "Guide", - - [TEXT_ABOUT_VERSION] = "Version Info", - - [TEXT_PERSIST_SAVE_STATE] = "Save Menu State", - [TEXT_PERSIST_RESTORE_STATE] = "Restore Menu State", - [TEXT_PERSIST_SAVE_SUCCESS] = "Save Success", - [TEXT_PERSIST_SAVE_FAILED] = "Save Failed", - [TEXT_PERSIST_RESTORE_SUCCESS] = "Restore Success", - [TEXT_PERSIST_RESTORE_FAILED] = "Restore Failed", - - [TEXT_ERROR] = "Error", - [TEXT_WARNING] = "Warning", - [TEXT_SUCCESS] = "Success", - [TEXT_INFO] = "Info", - [TEXT_TEST] = "Test", - [TEXT_SELECT_OPTION] = "Select Option", - [TEXT_CURRENT] = "Current", - [TEXT_STATUS] = "Status", - [TEXT_SUMMARY] = "Summary", - [TEXT_EMPTY] = "Empty", - [TEXT_CURRENT_SELECTION] = "Current Selection", - [TEXT_OPERATIONS] = "Operations", - [TEXT_SELECT_ITEM] = "Select Item", - [TEXT_ENTER_SUBMENU] = "Enter Submenu", - [TEXT_RETURN_PARENT] = "Return Parent", - [TEXT_SELECT_PREVIOUS] = "Select Previous", - [TEXT_SELECT_NEXT] = "Select Next", - [TEXT_START_DEFAULT] = "Start Default", - [TEXT_REGISTER_CALLBACK_FAILED] = "Register Callback Failed", - [TEXT_RESTORE_MENU_STATE] = "Restore Menu State", - [TEXT_RESTORE_MENU_STATE_FAILED] = "Restore Menu State Failed", - [TEXT_SAVE_MENU_STATE_FAILED] = "Save Menu State Failed", - - [TEXT_UP_ARROW] = "Up Arrow", - [TEXT_DOWN_ARROW] = "Down Arrow", - [TEXT_LEFT_ARROW] = "Left Arrow", - [TEXT_RIGHT_ARROW] = "Right Arrow", -}; - -/** - * @brief 日语文本数组 - */ -static const char *sg_japanese_text[] = { - [TEXT_ENTER] = "入る", - [TEXT_EXIT] = "退出", - [TEXT_RETURN] = "戻る", - [TEXT_OK] = "OK", - [TEXT_CANCEL] = "キャンセル", - [TEXT_SAVE] = "保存", - [TEXT_LOAD] = "読み込む", - - [TEXT_MAIN_MENU] = "メインメニュー", - [TEXT_MAIN_MEASUREMENT] = "計測", - [TEXT_MAIN_PROTECTION] = "保護", - [TEXT_MAIN_CONTROL] = "制御", - [TEXT_MAIN_SETTING] = "設定", - [TEXT_MAIN_RECORD] = "記録", - [TEXT_MAIN_HELP] = "ヘルプ", - [TEXT_MAIN_ABOUT] = "について", - - [TEXT_MEASURE_VOLTAGE] = "電圧", - [TEXT_MEASURE_CURRENT] = "電流", - [TEXT_MEASURE_POWER] = "電力", - [TEXT_MEASURE_ENERGY] = "エネルギー", - [TEXT_MEASURE_FREQUENCY] = "周波数", - [TEXT_MEASURE_TEMPERATURE] = "温度", - - [TEXT_PROTECT_OVER_VOLTAGE] = "過電圧保護", - [TEXT_PROTECT_UNDER_VOLTAGE] = "不足電圧保護", - [TEXT_PROTECT_OVER_CURRENT] = "過電流保護", - [TEXT_PROTECT_SETTING] = "保護設定", - - [TEXT_CONTROL_ON_OFF] = "オン/オフ", - [TEXT_CONTROL_START_STOP] = "スタート/ストップ", - [TEXT_CONTROL_AUTO_MANUAL] = "オート/マニュアル", - - [TEXT_SETTING_LANGUAGE] = "言語設定", - - [TEXT_RECORD_EVENT] = "イベント記録", - - [TEXT_HELP_GUIDE] = "ガイド", - - [TEXT_ABOUT_VERSION] = "バージョン情報", - - [TEXT_PERSIST_SAVE_STATE] = "メニュー状態を保存", - [TEXT_PERSIST_RESTORE_STATE] = "メニュー状態を復元", - [TEXT_PERSIST_SAVE_SUCCESS] = "保存成功", - [TEXT_PERSIST_SAVE_FAILED] = "保存失敗", - [TEXT_PERSIST_RESTORE_SUCCESS] = "復元成功", - [TEXT_PERSIST_RESTORE_FAILED] = "復元失敗", - - [TEXT_ERROR] = "エラー", - [TEXT_WARNING] = "警告", - [TEXT_SUCCESS] = "成功", - [TEXT_INFO] = "情報", - [TEXT_TEST] = "テスト", - [TEXT_SELECT_OPTION] = "オプションを選択", - [TEXT_CURRENT] = "現在", - [TEXT_STATUS] = "ステータス", - [TEXT_SUMMARY] = "サマリー", - [TEXT_EMPTY] = "空", - [TEXT_CURRENT_SELECTION] = "現在の選択", - [TEXT_OPERATIONS] = "操作", - [TEXT_SELECT_ITEM] = "項目を選択", - [TEXT_ENTER_SUBMENU] = "サブメニューに入る", - [TEXT_RETURN_PARENT] = "親メニューに戻る", - [TEXT_SELECT_PREVIOUS] = "前の項目を選択", - [TEXT_SELECT_NEXT] = "次の項目を選択", - [TEXT_START_DEFAULT] = "デフォルトから開始", - [TEXT_REGISTER_CALLBACK_FAILED] = "コールバック登録失敗", - [TEXT_RESTORE_MENU_STATE] = "メニュー状態を復元", - [TEXT_RESTORE_MENU_STATE_FAILED] = "メニュー状態復元失敗", - [TEXT_SAVE_MENU_STATE_FAILED] = "メニュー状態保存失敗", - - [TEXT_UP_ARROW] = "上矢印", - [TEXT_DOWN_ARROW] = "下矢印", - [TEXT_LEFT_ARROW] = "左矢印", - [TEXT_RIGHT_ARROW] = "右矢印", -}; - -/** - * @brief 德语文本数组 - */ -static const char *sg_german_text[] = { - [TEXT_ENTER] = "Eingeben", - [TEXT_EXIT] = "Verlassen", - [TEXT_RETURN] = "Zurück", - [TEXT_OK] = "OK", - [TEXT_CANCEL] = "Abbrechen", - [TEXT_SAVE] = "Speichern", - [TEXT_LOAD] = "Laden", - - [TEXT_MAIN_MENU] = "Hauptmenü", - [TEXT_MAIN_MEASUREMENT] = "Messung", - [TEXT_MAIN_PROTECTION] = "Schutz", - [TEXT_MAIN_CONTROL] = "Steuerung", - [TEXT_MAIN_SETTING] = "Einstellung", - [TEXT_MAIN_RECORD] = "Aufzeichnung", - [TEXT_MAIN_HELP] = "Hilfe", - [TEXT_MAIN_ABOUT] = "Über", - - [TEXT_MEASURE_VOLTAGE] = "Spannung", - [TEXT_MEASURE_CURRENT] = "Strom", - [TEXT_MEASURE_POWER] = "Leistung", - [TEXT_MEASURE_ENERGY] = "Energie", - [TEXT_MEASURE_FREQUENCY] = "Frequenz", - [TEXT_MEASURE_TEMPERATURE] = "Temperatur", - - [TEXT_PROTECT_OVER_VOLTAGE] = "Überspannungsschutz", - [TEXT_PROTECT_UNDER_VOLTAGE] = "Unterspannungsschutz", - [TEXT_PROTECT_OVER_CURRENT] = "Überstromschutz", - [TEXT_PROTECT_SETTING] = "Schutz-Einstellung", - - [TEXT_CONTROL_ON_OFF] = "Ein/Aus", - [TEXT_CONTROL_START_STOP] = "Start/Stopp", - [TEXT_CONTROL_AUTO_MANUAL] = "Auto/Manuell", - - [TEXT_SETTING_LANGUAGE] = "Spracheinstellung", - - [TEXT_RECORD_EVENT] = "Ereignisaufzeichnung", - - [TEXT_HELP_GUIDE] = "Anleitung", - - [TEXT_ABOUT_VERSION] = "Versionsinfo", - - [TEXT_PERSIST_SAVE_STATE] = "Menüzustand speichern", - [TEXT_PERSIST_RESTORE_STATE] = "Menüzustand wiederherstellen", - [TEXT_PERSIST_SAVE_SUCCESS] = "Speichern erfolgreich", - [TEXT_PERSIST_SAVE_FAILED] = "Speichern fehlgeschlagen", - [TEXT_PERSIST_RESTORE_SUCCESS] = "Wiederherstellen erfolgreich", - [TEXT_PERSIST_RESTORE_FAILED] = "Wiederherstellen fehlgeschlagen", - - [TEXT_ERROR] = "Fehler", - [TEXT_WARNING] = "Warnung", - [TEXT_SUCCESS] = "Erfolg", - [TEXT_INFO] = "Info", - [TEXT_TEST] = "Test", - [TEXT_SELECT_OPTION] = "Option wählen", - [TEXT_CURRENT] = "Aktuell", - [TEXT_STATUS] = "Status", - [TEXT_SUMMARY] = "Zusammenfassung", - [TEXT_EMPTY] = "Leer", - [TEXT_CURRENT_SELECTION] = "Aktuelle Auswahl", - [TEXT_OPERATIONS] = "Operationen", - [TEXT_SELECT_ITEM] = "Element auswählen", - [TEXT_ENTER_SUBMENU] = "In Untermenü eintreten", - [TEXT_RETURN_PARENT] = "Zu übergeordnetem Menü zurückkehren", - [TEXT_SELECT_PREVIOUS] = "Vorheriges auswählen", - [TEXT_SELECT_NEXT] = "Nächstes auswählen", - [TEXT_START_DEFAULT] = "Standard starten", - [TEXT_REGISTER_CALLBACK_FAILED] = "Rückrufregistrierung fehlgeschlagen", - [TEXT_RESTORE_MENU_STATE] = "Menüzustand wiederherstellen", - [TEXT_RESTORE_MENU_STATE_FAILED] = "Wiederherstellung des Menüzustands fehlgeschlagen", - [TEXT_SAVE_MENU_STATE_FAILED] = "Speichern des Menüzustands fehlgeschlagen", - - [TEXT_UP_ARROW] = "Pfeil nach oben", - [TEXT_DOWN_ARROW] = "Pfeil nach unten", - [TEXT_LEFT_ARROW] = "Pfeil nach links", - [TEXT_RIGHT_ARROW] = "Pfeil nach rechts", -}; - -/** - * @brief 语言文本映射表 - */ -static const char **sg_language_text_map[] = { - [SYSTEM_LANG_CHINESE] = sg_chinese_text, - [SYSTEM_LANG_ENGLISH] = sg_english_text, - [SYSTEM_LANG_JAPANESE] = sg_japanese_text, - [SYSTEM_LANG_GERMAN] = sg_german_text, -}; - -/** - * @brief 全局菜单节点映射表 - */ -const MenuNodeInfo_t menu_node_map[] = { - // 一级菜单 - {MENU_NODE_ID_MAIN, MENU_NODE_ID_NONE, TEXT_MAIN_MENU, 1, MENU_NODE_ATTR_HAS_CHILDREN | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_MEASUREMENT, MENU_NODE_ID_MAIN, TEXT_MAIN_MEASUREMENT, 1, MENU_NODE_ATTR_HAS_CHILDREN | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_PROTECTION, MENU_NODE_ID_MAIN, TEXT_MAIN_PROTECTION, 1, MENU_NODE_ATTR_HAS_CHILDREN | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_CONTROL, MENU_NODE_ID_MAIN, TEXT_MAIN_CONTROL, 1, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_SETTING, MENU_NODE_ID_MAIN, TEXT_MAIN_SETTING, 1, MENU_NODE_ATTR_HAS_CHILDREN | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_RECORD, MENU_NODE_ID_MAIN, TEXT_MAIN_RECORD, 1, MENU_NODE_ATTR_HAS_CHILDREN | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_HELP, MENU_NODE_ID_MAIN, TEXT_MAIN_HELP, 1, MENU_NODE_ATTR_HAS_CHILDREN | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_ABOUT, MENU_NODE_ID_MAIN, TEXT_MAIN_ABOUT, 1, MENU_NODE_ATTR_HAS_CHILDREN | MENU_NODE_ATTR_VISIBLE}, - - // 二级菜单:测量菜单子项 - {MENU_NODE_ID_MEASUREMENT_VOLTAGE, MENU_NODE_ID_MEASUREMENT, TEXT_MEASURE_VOLTAGE, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_MEASUREMENT_CURRENT, MENU_NODE_ID_MEASUREMENT, TEXT_MEASURE_CURRENT, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_MEASUREMENT_POWER, MENU_NODE_ID_MEASUREMENT, TEXT_MEASURE_POWER, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_MEASUREMENT_ENERGY, MENU_NODE_ID_MEASUREMENT, TEXT_MEASURE_ENERGY, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_MEASUREMENT_FREQUENCY, MENU_NODE_ID_MEASUREMENT, TEXT_MEASURE_FREQUENCY, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_MEASUREMENT_TEMPERATURE, MENU_NODE_ID_MEASUREMENT, TEXT_MEASURE_TEMPERATURE, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - - // 二级菜单:保护菜单子项 - {MENU_NODE_ID_PROTECTION_OVER_VOLTAGE, MENU_NODE_ID_PROTECTION, TEXT_PROTECT_OVER_VOLTAGE, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_PROTECTION_UNDER_VOLTAGE, MENU_NODE_ID_PROTECTION, TEXT_PROTECT_UNDER_VOLTAGE, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_PROTECTION_OVER_CURRENT, MENU_NODE_ID_PROTECTION, TEXT_PROTECT_OVER_CURRENT, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_PROTECTION_SETTING, MENU_NODE_ID_PROTECTION, TEXT_PROTECT_SETTING, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - - // 二级菜单:控制菜单子项 - {MENU_NODE_ID_CONTROL_ON_OFF, MENU_NODE_ID_CONTROL, TEXT_CONTROL_ON_OFF, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_CONTROL_START_STOP, MENU_NODE_ID_CONTROL, TEXT_CONTROL_START_STOP, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_CONTROL_AUTO_MANUAL, MENU_NODE_ID_CONTROL, TEXT_CONTROL_AUTO_MANUAL, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - - // 二级菜单:其他子项 - {MENU_NODE_ID_SETTING_LANGUAGE, MENU_NODE_ID_SETTING, TEXT_SETTING_LANGUAGE, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_RECORD_EVENT, MENU_NODE_ID_RECORD, TEXT_RECORD_EVENT, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_HELP_GUIDE, MENU_NODE_ID_HELP, TEXT_HELP_GUIDE, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, - {MENU_NODE_ID_ABOUT_VERSION, MENU_NODE_ID_ABOUT, TEXT_ABOUT_VERSION, 2, MENU_NODE_ATTR_OPERABLE | MENU_NODE_ATTR_VISIBLE}, -}; - -/** - * @brief 菜单节点映射表大小 - */ -const uint32_t menu_node_map_size = sizeof(menu_node_map) / sizeof(menu_node_map[0]); - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化语言模块 - */ -MenuErrCode language_init(void) -{ - // 初始化核心菜单库语言模块 - MenuErrCode ret = menu_lang_init(); - if (ret != MENU_ERR_OK) - { - return ret; - } - - // 设置默认语言 - return set_language(SYSTEM_LANG_CHINESE); -} - -/** - * @brief 根据文本ID获取对应语言的文本字符串 - */ -const char* get_text(TextId_e text_id) -{ - if (text_id >= TEXT_MAX) - { - return NULL; - } - - if (sg_current_language >= SYSTEM_LANG_MAX) - { - return NULL; - } - - return sg_language_text_map[sg_current_language][text_id]; -} - -/** - * @brief 设置当前系统语言 - */ -MenuErrCode set_language(SystemLang_e lang) -{ - if (lang >= SYSTEM_LANG_MAX) - { - return MENU_ERR_INVALID_PARAM; - } - - sg_current_language = lang; - - // 同步到核心菜单库 - return menu_lang_set_current((LangId)lang); -} - -/** - * @brief 获取当前系统语言 - */ -SystemLang_e get_current_language(void) -{ - return sg_current_language; -} - -/** - * @brief 根据菜单节点ID获取对应的文本ID - */ -TextId_e get_menu_text_id(MenuNodeId_e node_id) -{ - for (uint32_t i = 0; i < menu_node_map_size; i++) - { - if (menu_node_map[i].node_id == node_id) - { - return menu_node_map[i].text_id; - } - } - - return TEXT_MAX; -} - -/** - * @brief 根据菜单节点ID获取对应的父节点ID - */ -MenuNodeId_e get_menu_parent_id(MenuNodeId_e node_id) -{ - for (uint32_t i = 0; i < menu_node_map_size; i++) - { - if (menu_node_map[i].node_id == node_id) - { - return menu_node_map[i].parent_id; - } - } - - return MENU_NODE_ID_NONE; -} - -/** - * @brief 检查菜单节点是否有子节点 - */ -uint8_t menu_node_has_children(MenuNodeId_e node_id) -{ - for (uint32_t i = 0; i < menu_node_map_size; i++) - { - if (menu_node_map[i].node_id == node_id) - { - return MENU_NODE_HAS_ATTR(menu_node_map[i].attributes, MENU_NODE_ATTR_HAS_CHILDREN); - } - } - - return 0; -} - -/** - * @brief 检查菜单节点是否可操作 - */ -uint8_t menu_node_is_operable(MenuNodeId_e node_id) -{ - for (uint32_t i = 0; i < menu_node_map_size; i++) - { - if (menu_node_map[i].node_id == node_id) - { - return MENU_NODE_HAS_ATTR(menu_node_map[i].attributes, MENU_NODE_ATTR_OPERABLE); - } - } - - return 0; -} - -/** - * @brief 获取菜单节点的显示文本 - */ -const char* get_menu_node_text(MenuNodeId_e node_id) -{ - TextId_e text_id = get_menu_text_id(node_id); - if (text_id == TEXT_MAX) - { - return NULL; - } - - return get_text(text_id); -} diff --git a/demo/language.h b/demo/language.h deleted file mode 100644 index 14f7546..0000000 --- a/demo/language.h +++ /dev/null @@ -1,311 +0,0 @@ -#ifndef LANGUAGE_H -#define LANGUAGE_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "../../src/lang/menu_lang.h" -#include "../../src/core/menu_core.h" - -/* 类型定义 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 系统语言枚举 - * @note 与核心菜单库语言ID映射,便于扩展 - */ -typedef enum -{ - SYSTEM_LANG_CHINESE = 0, // 中文(默认) - SYSTEM_LANG_ENGLISH, // 英文 - SYSTEM_LANG_JAPANESE, // 日语 - SYSTEM_LANG_GERMAN, // 德语 - SYSTEM_LANG_MAX, // 语言类型总数(仅用于遍历/边界判断) -} SystemLang_e; - -/** - * @brief 文本ID枚举(按模块分级) - * @note 采用模块化命名,便于扩展和维护 - * 分级规则: - * - 基础文本(0x0000~0x00FF) - * - 主菜单(0x0100~0x01FF) - * - 测量菜单(0x0200~0x02FF) - * - 保护菜单(0x0300~0x03FF) - * - 控制菜单(0x0400~0x04FF) - * - 设置菜单(0x0500~0x05FF) - * - 记录菜单(0x0600~0x06FF) - * - 帮助菜单(0x0700~0x07FF) - * - 关于菜单(0x0800~0x08FF) - * - 持久化相关(0x0900~0x09FF) - */ -typedef enum -{ - // 基础文本(0x0000 ~ 0x00FF) - TEXT_ENTER = 0x0000, // 进入 - TEXT_EXIT, // 退出 - TEXT_RETURN, // 返回 - TEXT_OK, // 确定 - TEXT_CANCEL, // 取消 - TEXT_SAVE, // 保存 - TEXT_LOAD, // 加载 - - // 主菜单文本(0x0100 ~ 0x01FF) - TEXT_MAIN_MENU = 0x0100, // 主菜单 - TEXT_MAIN_MEASUREMENT, // 测量 - TEXT_MAIN_PROTECTION, // 保护 - TEXT_MAIN_CONTROL, // 控制 - TEXT_MAIN_SETTING, // 设置 - TEXT_MAIN_RECORD, // 记录 - TEXT_MAIN_HELP, // 帮助 - TEXT_MAIN_ABOUT, // 关于 - - // 测量菜单文本(0x0200 ~ 0x02FF) - TEXT_MEASURE_VOLTAGE = 0x0200, // 电压 - TEXT_MEASURE_CURRENT, // 电流 - TEXT_MEASURE_POWER, // 功率 - TEXT_MEASURE_ENERGY, // 能量 - TEXT_MEASURE_FREQUENCY, // 频率 - TEXT_MEASURE_TEMPERATURE, // 温度 - - // 保护菜单文本(0x0300 ~ 0x03FF) - TEXT_PROTECT_OVER_VOLTAGE = 0x0300, // 过电压保护 - TEXT_PROTECT_UNDER_VOLTAGE, // 欠电压保护 - TEXT_PROTECT_OVER_CURRENT, // 过电流保护 - TEXT_PROTECT_SETTING, // 保护设置 - - // 控制菜单文本(0x0400 ~ 0x04FF) - TEXT_CONTROL_ON_OFF = 0x0400, // 开关控制 - TEXT_CONTROL_START_STOP, // 启停控制 - TEXT_CONTROL_AUTO_MANUAL, // 自动/手动切换 - - // 设置菜单文本(0x0500 ~ 0x05FF) - TEXT_SETTING_LANGUAGE = 0x0500, // 语言设置 - - // 记录菜单文本(0x0600 ~ 0x06FF) - TEXT_RECORD_EVENT = 0x0600, // 事件记录 - - // 帮助菜单文本(0x0700 ~ 0x07FF) - TEXT_HELP_GUIDE = 0x0700, // 指南 - - // 关于菜单文本(0x0800 ~ 0x08FF) - TEXT_ABOUT_VERSION = 0x0800, // 版本信息 - - // 持久化相关文本(0x0900 ~ 0x09FF) - TEXT_PERSIST_SAVE_STATE = 0x0900, // 保存菜单状态 - TEXT_PERSIST_RESTORE_STATE, // 恢复菜单状态 - TEXT_PERSIST_SAVE_SUCCESS, // 保存成功 - TEXT_PERSIST_SAVE_FAILED, // 保存失败 - TEXT_PERSIST_RESTORE_SUCCESS, // 恢复成功 - TEXT_PERSIST_RESTORE_FAILED, // 恢复失败 - - // 提示信息(0x0A00 ~ 0x0AFF) - TEXT_ERROR = 0x0A00, // 错误 - TEXT_WARNING, // 警告 - TEXT_SUCCESS, // 成功 - TEXT_INFO, // 信息 - TEXT_TEST, // 测试 - TEXT_SELECT_OPTION, // 选择操作 - TEXT_CURRENT, // 当前 - TEXT_STATUS, // 状态 - TEXT_SUMMARY, // 摘要 - TEXT_EMPTY, // 空 - TEXT_CURRENT_SELECTION, // 当前选择 - TEXT_OPERATIONS, // 操作 - TEXT_SELECT_ITEM, // 选择项 - TEXT_ENTER_SUBMENU, // 进入子菜单 - TEXT_RETURN_PARENT, // 返回父菜单 - TEXT_SELECT_PREVIOUS, // 选择上一项 - TEXT_SELECT_NEXT, // 选择下一项 - TEXT_START_DEFAULT, // 从默认开始 - TEXT_REGISTER_CALLBACK_FAILED, // 注册回调失败 - TEXT_RESTORE_MENU_STATE, // 恢复菜单状态 - TEXT_RESTORE_MENU_STATE_FAILED, // 恢复菜单状态失败 - TEXT_SAVE_MENU_STATE_FAILED, // 保存菜单状态失败 - TEXT_SAVE_MENU_STATE, // 保存菜单状态 - - // 操作提示(0x0B00 ~ 0x0BFF) - TEXT_UP_ARROW = 0x0B00, // 上箭头 - TEXT_DOWN_ARROW, // 下箭头 - TEXT_LEFT_ARROW, // 左箭头 - TEXT_RIGHT_ARROW, // 右箭头 - - TEXT_MAX = 0x0FFF, // 所有文本ID最大值(用于边界检查) -} TextId_e; - -/** - * @brief 菜单节点ID枚举 - * @note 采用模块化命名,便于扩展和维护 - * 分级规则: - * - 一级菜单(0x1000~0x1FFF) - * - 二级菜单(0x2000~0x2FFF) - * - 三级菜单(0x3000~0x3FFF) - * - 四级菜单(0x4000~0x4FFF) - */ -typedef enum -{ - // 无效节点/根节点标记 - MENU_NODE_ID_NONE = 0x0000, - - // 一级菜单(0x1000 ~ 0x1FFF) - MENU_NODE_ID_MAIN = 0x1000, // 主菜单 - MENU_NODE_ID_MEASUREMENT, // 测量菜单 - MENU_NODE_ID_PROTECTION, // 保护菜单 - MENU_NODE_ID_CONTROL, // 控制菜单 - MENU_NODE_ID_SETTING, // 设置菜单 - MENU_NODE_ID_RECORD, // 记录菜单 - MENU_NODE_ID_HELP, // 帮助菜单 - MENU_NODE_ID_ABOUT, // 关于菜单 - - // 二级菜单:测量菜单子项(0x2000 ~ 0x20FF) - MENU_NODE_ID_MEASUREMENT_VOLTAGE = 0x2000, // 电压测量 - MENU_NODE_ID_MEASUREMENT_CURRENT, // 电流测量 - MENU_NODE_ID_MEASUREMENT_POWER, // 功率测量 - MENU_NODE_ID_MEASUREMENT_ENERGY, // 能量测量 - MENU_NODE_ID_MEASUREMENT_FREQUENCY, // 频率测量 - MENU_NODE_ID_MEASUREMENT_TEMPERATURE, // 温度测量 - - // 二级菜单:保护菜单子项(0x2100 ~ 0x21FF) - MENU_NODE_ID_PROTECTION_OVER_VOLTAGE = 0x2100, // 过电压保护 - MENU_NODE_ID_PROTECTION_UNDER_VOLTAGE, // 欠电压保护 - MENU_NODE_ID_PROTECTION_OVER_CURRENT, // 过电流保护 - MENU_NODE_ID_PROTECTION_SETTING, // 保护设置 - - // 二级菜单:控制菜单子项(0x2200 ~ 0x22FF) - MENU_NODE_ID_CONTROL_ON_OFF = 0x2200, // 开关控制 - MENU_NODE_ID_CONTROL_START_STOP, // 启停控制 - MENU_NODE_ID_CONTROL_AUTO_MANUAL, // 自动/手动切换 - - // 二级菜单:设置菜单子项(0x2300 ~ 0x23FF) - MENU_NODE_ID_SETTING_LANGUAGE = 0x2300, // 语言设置 - - // 二级菜单:记录菜单子项(0x2400 ~ 0x24FF) - MENU_NODE_ID_RECORD_EVENT = 0x2400, // 事件记录 - - // 二级菜单:帮助菜单子项(0x2500 ~ 0x25FF) - MENU_NODE_ID_HELP_GUIDE = 0x2500, // 指南 - - // 二级菜单:关于菜单子项(0x2600 ~ 0x26FF) - MENU_NODE_ID_ABOUT_VERSION = 0x2600, // 版本信息 - - MENU_NODE_ID_MAX = 0x4FFF, // 菜单节点ID最大值 -} MenuNodeId_e; - -/** - * @brief 菜单节点属性枚举 - * @note 使用位掩码方式,便于组合和扩展 - */ -typedef enum -{ - MENU_NODE_ATTR_NONE = 0x00, // 无属性 - MENU_NODE_ATTR_HAS_CHILDREN = 0x01, // 有子节点 - MENU_NODE_ATTR_OPERABLE = 0x02, // 可操作 - MENU_NODE_ATTR_VISIBLE = 0x04, // 可见 - MENU_NODE_ATTR_EDITABLE = 0x08, // 可编辑 -} MenuNodeAttr_e; - -/** - * @brief 菜单节点信息结构体 - * @note 用于建立菜单节点ID与文本ID、父子关系、属性等映射 - * 采用更紧凑的设计,便于扩展 - */ -typedef struct -{ - MenuNodeId_e node_id; // 当前菜单节点ID(唯一标识) - MenuNodeId_e parent_id; // 父节点ID(MENU_NODE_ID_NONE表示无父节点) - TextId_e text_id; // 对应显示的文本ID - uint8_t level; // 菜单层级(1=一级,2=二级,3=三级,4=四级) - uint8_t attributes; // 节点属性(使用MenuNodeAttr_e位掩码组合) -} MenuNodeInfo_t; - -/* 宏定义 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 菜单节点属性检查宏 - * @param attr 节点属性 - * @param flag 要检查的属性标志 - * @return 1表示属性存在,0表示属性不存在 - */ -#define MENU_NODE_HAS_ATTR(attr, flag) ((attr) & (flag)) - -/** - * @brief 菜单框架配置常量 - */ -#define MENU_CFG_MAX_DEPTH 4 // 最大菜单深度(一级~四级) -#define MENU_CFG_MAX_NODES 50 // 最大菜单节点数 -#define MENU_CFG_MAX_TEXT_LEN 50 // 最大文本长度(字符数) - -/* 全局变量声明 ---------------------------------------------------------------------------------------------------*/ - -/** - * @brief 全局菜单节点映射表 - * @note 所有菜单节点的关联关系集中在这里维护,修改时仅需调整此表 - * 按一级菜单、二级菜单的顺序排列,便于阅读和维护 - */ -extern const MenuNodeInfo_t menu_node_map[]; - -/** - * @brief 菜单节点映射表大小 - */ -extern const uint32_t menu_node_map_size; - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化语言模块 - * @return MenuErrCode 操作结果 - */ -MenuErrCode language_init(void); - -/** - * @brief 根据文本ID获取对应语言的文本字符串 - * @param text_id 文本ID - * @return const char* 对应语言的文本字符串,若ID无效返回NULL - */ -const char* get_text(TextId_e text_id); - -/** - * @brief 设置当前系统语言 - * @param lang 要设置的语言 - * @return MenuErrCode 操作结果 - */ -MenuErrCode set_language(SystemLang_e lang); - -/** - * @brief 获取当前系统语言 - * @return SystemLang_e 当前使用的语言 - */ -SystemLang_e get_current_language(void); - -/** - * @brief 根据菜单节点ID获取对应的文本ID - * @param node_id 菜单节点ID - * @return TextId_e 对应的文本ID,若节点不存在返回TEXT_MAX - */ -TextId_e get_menu_text_id(MenuNodeId_e node_id); - -/** - * @brief 根据菜单节点ID获取对应的父节点ID - * @param node_id 菜单节点ID - * @return MenuNodeId_e 对应的父节点ID,若节点不存在返回MENU_NODE_ID_NONE - */ -MenuNodeId_e get_menu_parent_id(MenuNodeId_e node_id); - -/** - * @brief 检查菜单节点是否有子节点 - * @param node_id 菜单节点ID - * @return uint8_t 1=有子节点,0=无子节点/节点不存在 - */ -uint8_t menu_node_has_children(MenuNodeId_e node_id); - -/** - * @brief 检查菜单节点是否可操作 - * @param node_id 菜单节点ID - * @return uint8_t 1=可操作,0=不可操作/节点不存在 - */ -uint8_t menu_node_is_operable(MenuNodeId_e node_id); - -/** - * @brief 获取菜单节点的显示文本 - * @param node_id 菜单节点ID - * @return const char* 对应语言的文本字符串,若节点无效返回NULL - */ -const char* get_menu_node_text(MenuNodeId_e node_id); - -#endif /* LANGUAGE_H */ \ No newline at end of file diff --git a/menu_persistence.dat b/menu_persistence.dat deleted file mode 100644 index b15631b..0000000 Binary files a/menu_persistence.dat and /dev/null differ diff --git a/port/menu_port.c b/port/menu_port.c deleted file mode 100644 index 961239b..0000000 --- a/port/menu_port.c +++ /dev/null @@ -1,319 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_port.c - * @brief 菜单组件硬件端口层实现 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_port.h" -#include -#include - -/* 全局变量 ---------------------------------------------------------------------------------------------------------*/ -static const MenuPortDriver* sg_menu_port_driver = NULL; - -/* 默认硬件驱动实现 -------------------------------------------------------------------------------------------------*/ - -/** - * @brief 默认打印函数 - * @param fmt 格式化字符串 - * @param args 可变参数列表 - */ -static void menu_port_default_printf(const char* fmt, va_list args) -{ - // 默认不实现打印功能 - (void)fmt; - (void)args; -} - -/** - * @brief 默认获取系统时间函数 - * @return 系统时间(ms) - */ -static uint32_t menu_port_default_get_tick(void) -{ - // 默认返回0,用户需要根据实际硬件实现 - return 0; -} - -/** - * @brief 默认延迟函数 - * @param ms 延迟时间(ms) - */ -static void menu_port_default_delay_ms(uint32_t ms) -{ - // 默认实现简单的延迟 - for (uint32_t i = 0; i < ms * 1000; i++) { - __asm__ volatile ("nop"); - } -} - -/** - * @brief 默认显示函数 - * @param menu_name 菜单名称 - * @param menu_id 菜单ID - */ -static void menu_port_default_display(const char* menu_name, uint16_t menu_id) -{ - // 默认不实现显示功能 - (void)menu_name; - (void)menu_id; -} - -/** - * @brief 默认按键扫描函数 - * @return 按键事件类型 - */ -static MenuEventType menu_port_default_key_scan(void) -{ - // 默认返回无事件 - return MENU_EVENT_NONE; -} - -/** - * @brief 默认中断管理函数 - * @param enable 是否启用中断 - */ -static void menu_port_default_irq_ctrl(bool enable) -{ - // 默认不实现中断管理 - (void)enable; -} - -/** - * @brief 默认错误处理函数 - * @param err_code 错误码 - */ -static void menu_port_default_error_handler(MenuErrCode err_code) -{ - // 默认不实现错误处理 - (void)err_code; -} - -/** - * @brief 默认Modbus发送函数 - * @param reg_type 寄存器类型 - * @param reg_addr 寄存器地址 - * @param reg_buf 寄存器数据 - * @param buf_len 数据长度 - * @return 错误码 - */ -static MenuErrCode menu_port_default_modbus_send(ModbusRegType reg_type, uint16_t reg_addr, const uint8_t* reg_buf, uint8_t buf_len) -{ - // 默认不实现Modbus发送 - (void)reg_type; - (void)reg_addr; - (void)reg_buf; - (void)buf_len; - return MENU_ERR_OPERATION_FAILED; -} - -/** - * @brief 默认Modbus接收函数 - * @param reg_type 寄存器类型 - * @param reg_addr 寄存器地址 - * @param reg_buf 寄存器数据 - * @param buf_len 数据长度 - * @return 错误码 - */ -static MenuErrCode menu_port_default_modbus_receive(ModbusRegType reg_type, uint16_t reg_addr, uint8_t* reg_buf, uint8_t buf_len) -{ - // 默认不实现Modbus接收 - (void)reg_type; - (void)reg_addr; - (void)reg_buf; - (void)buf_len; - return MENU_ERR_OPERATION_FAILED; -} - -/** - * @brief 默认持久化保存函数 - * @param data 要保存的数据 - * @param size 数据大小 - * @return 错误码 - */ -static MenuErrCode menu_port_default_persistence_save(const uint8_t* data, uint16_t size) -{ - // 默认不实现持久化保存功能 - (void)data; - (void)size; - return MENU_ERR_OPERATION_FAILED; -} - -/** - * @brief 默认持久化恢复函数 - * @param data 恢复数据缓冲区 - * @param size 数据大小 - * @return 错误码 - */ -static MenuErrCode menu_port_default_persistence_restore(uint8_t* data, uint16_t* size) -{ - // 默认不实现持久化恢复功能 - (void)data; - (void)size; - return MENU_ERR_OPERATION_FAILED; -} - -/** - * @brief 默认硬件驱动 - */ -static const MenuPortDriver sg_default_driver = { - .printf = menu_port_default_printf, - .get_tick = menu_port_default_get_tick, - .delay_ms = menu_port_default_delay_ms, - .display = menu_port_default_display, - .key_scan = menu_port_default_key_scan, - .irq_ctrl = menu_port_default_irq_ctrl, - .error_handler = menu_port_default_error_handler, - .modbus_send = menu_port_default_modbus_send, - .modbus_receive = menu_port_default_modbus_receive, - .persistence_save = menu_port_default_persistence_save, - .persistence_restore = menu_port_default_persistence_restore, -}; - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化硬件端口层 - * @param driver 硬件驱动结构体指针 - * @return 错误码 - */ -MenuErrCode menu_port_init(const MenuPortDriver* driver) -{ - if (driver != NULL) { - sg_menu_port_driver = driver; - } else { - sg_menu_port_driver = &sg_default_driver; - } - return MENU_ERR_OK; -} - -/** - * @brief 反初始化硬件端口层 - * @return 错误码 - */ -MenuErrCode menu_port_deinit(void) -{ - sg_menu_port_driver = NULL; - return MENU_ERR_OK; -} - -/** - * @brief 获取当前系统时间(ms) - * @return 系统时间(ms) - */ -uint32_t menu_port_get_tick(void) -{ - if (sg_menu_port_driver != NULL && sg_menu_port_driver->get_tick != NULL) { - return sg_menu_port_driver->get_tick(); - } - return menu_port_default_get_tick(); -} - -/** - * @brief 硬件延迟函数 - * @param ms 延迟时间(ms) - */ -void menu_port_delay_ms(uint32_t ms) -{ - if (sg_menu_port_driver != NULL && sg_menu_port_driver->delay_ms != NULL) { - sg_menu_port_driver->delay_ms(ms); - } else { - menu_port_default_delay_ms(ms); - } -} - -/** - * @brief 打印函数 - * @param fmt 格式化字符串 - * @param ... 可变参数 - */ -void menu_port_printf(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - - if (sg_menu_port_driver != NULL && sg_menu_port_driver->printf != NULL) { - sg_menu_port_driver->printf(fmt, args); - } else { - menu_port_default_printf(fmt, args); - } - - va_end(args); -} - -/** - * @brief 菜单显示函数 - * @param menu_name 菜单名称 - * @param menu_id 菜单ID - */ -void menu_port_display(const char* menu_name, uint16_t menu_id) -{ - if (sg_menu_port_driver != NULL && sg_menu_port_driver->display != NULL) { - sg_menu_port_driver->display(menu_name, menu_id); - } else { - menu_port_default_display(menu_name, menu_id); - } -} - -/** - * @brief 按键扫描函数 - * @return 按键事件类型 - */ -MenuEventType menu_port_key_scan(void) -{ - if (sg_menu_port_driver != NULL && sg_menu_port_driver->key_scan != NULL) { - return sg_menu_port_driver->key_scan(); - } - return menu_port_default_key_scan(); -} - -/** - * @brief 中断管理函数 - * @param enable 是否启用中断 - */ -void menu_port_irq_ctrl(bool enable) -{ - if (sg_menu_port_driver != NULL && sg_menu_port_driver->irq_ctrl != NULL) { - sg_menu_port_driver->irq_ctrl(enable); - } else { - menu_port_default_irq_ctrl(enable); - } -} - -/** - * @brief 错误处理函数 - * @param err_code 错误码 - */ -void menu_port_error_handler(MenuErrCode err_code) -{ - if (sg_menu_port_driver != NULL && sg_menu_port_driver->error_handler != NULL) { - sg_menu_port_driver->error_handler(err_code); - } else { - menu_port_default_error_handler(err_code); - } -} - -/** - * @brief 断言失败处理函数 - * @param expr 断言表达式 - * @param file 文件名 - * @param line 行号 - */ -void menu_assert_failed(const char* expr, const char* file, uint32_t line) -{ - // 打印断言失败信息 - char buf[128] = {0}; - snprintf(buf, sizeof(buf), "Assertion failed: %s, file %s, line %lu\n", expr, file, (unsigned long)line); - - // 直接使用printf输出,因为menu_port_printf需要va_list参数 - printf("%s", buf); - - // 进入死循环 - while (1) { - // 可以添加其他处理逻辑,如复位系统等 - } -} diff --git a/port/menu_port.h b/port/menu_port.h deleted file mode 100644 index 233af6a..0000000 --- a/port/menu_port.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_port.h - * @brief 菜单组件硬件端口层定义 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_PORT_H -#define MENU_PORT_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "../src/core/menu_config.h" -#include - -/* 类型定义 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief Modbus寄存器类型 - */ -typedef enum { - MODBUS_REG_TYPE_COIL, /*!< 线圈寄存器 */ - MODBUS_REG_TYPE_DISCRETE_INPUT, /*!< 离散输入寄存器 */ - MODBUS_REG_TYPE_HOLDING_REG, /*!< 保持寄存器 */ - MODBUS_REG_TYPE_INPUT_REG, /*!< 输入寄存器 */ -} ModbusRegType; - -/** - * @brief 持久化操作回调函数类型定义 - */ -typedef MenuErrCode (*MenuPersistenceSaveCallback)(const uint8_t* data, uint16_t size); ///< 保存持久化数据回调 -typedef MenuErrCode (*MenuPersistenceRestoreCallback)(uint8_t* data, uint16_t* size); ///< 恢复持久化数据回调 - -/** - * @brief 硬件驱动结构体 - */ -typedef struct { - void (*printf)(const char* fmt, va_list args); ///< 硬件打印接口 - uint32_t (*get_tick)(void); ///< 获取系统滴答时间 - void (*delay_ms)(uint32_t ms); ///< 硬件延迟函数 - void (*display)(const char* menu_name, uint16_t menu_id); ///< 菜单显示接口 - MenuEventType (*key_scan)(void); ///< 按键扫描接口(可选) - void (*irq_ctrl)(bool enable); ///< 中断管理接口(可选) - void (*error_handler)(MenuErrCode err_code); ///< 错误处理接口(可选) - MenuErrCode (*modbus_send)(ModbusRegType reg_type, uint16_t reg_addr, const uint8_t* reg_buf, uint8_t buf_len); ///< Modbus发送接口(可选) - MenuErrCode (*modbus_receive)(ModbusRegType reg_type, uint16_t reg_addr, uint8_t* reg_buf, uint8_t buf_len); ///< Modbus接收接口(可选) - MenuPersistenceSaveCallback persistence_save; ///< 持久化数据保存接口(可选) - MenuPersistenceRestoreCallback persistence_restore; ///< 持久化数据恢复接口(可选) -} MenuPortDriver; - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化硬件端口层 - * @param driver 硬件驱动结构体指针 - * @return 错误码 - */ -MenuErrCode menu_port_init(const MenuPortDriver* driver); - -/** - * @brief 反初始化硬件端口层 - * @return 错误码 - */ -MenuErrCode menu_port_deinit(void); - -/** - * @brief 获取当前系统时间(ms) - * @return 系统时间(ms) - */ -uint32_t menu_port_get_tick(void); - -/** - * @brief 硬件延迟函数 - * @param ms 延迟时间(ms) - */ -void menu_port_delay_ms(uint32_t ms); - -/** - * @brief 打印函数 - * @param fmt 格式化字符串 - * @param ... 可变参数 - */ -void menu_port_printf(const char* fmt, ...); - -/** - * @brief 菜单显示函数 - * @param menu_name 菜单名称 - * @param menu_id 菜单ID - */ -void menu_port_display(const char* menu_name, uint16_t menu_id); - -/** - * @brief 按键扫描函数 - * @return 按键事件类型 - */ -MenuEventType menu_port_key_scan(void); - -/** - * @brief 中断管理函数 - * @param enable 是否启用中断 - */ -void menu_port_irq_ctrl(bool enable); - -/** - * @brief 错误处理函数 - * @param err_code 错误码 - */ -void menu_port_error_handler(MenuErrCode err_code); - -#endif /* MENU_PORT_H */ diff --git a/src/core/menu_config.h b/src/core/menu_config.h deleted file mode 100644 index 5a2003a..0000000 --- a/src/core/menu_config.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_config.h - * @brief 菜单组件核心配置文件 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_CONFIG_H -#define MENU_CONFIG_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include -#include -#include - -/* 配置项 -----------------------------------------------------------------------------------------------------------*/ - -/* 菜单节点配置 */ -#define MENU_CONFIG_MAX_NODES 32U /* 最大菜单节点数 */ -#define MENU_CONFIG_HASH_TABLE_SIZE 31U /* 哈希表大小(必须为质数) */ -#define MENU_CONFIG_STACK_DEPTH 8U /* 菜单栈深度 */ -#define MENU_CONFIG_MAX_STATE_TRANSITIONS 16U /* 最大自定义状态转换规则数 */ - -/* 事件队列配置 */ -#define MENU_CONFIG_EVENT_QUEUE_LEN 16U /* 事件队列长度 */ -#define MENU_CONFIG_EVENT_MAX_PRIORITY 4U /* 事件最大优先级(0-3) */ - -/* 功能开关配置 */ -#define MENU_CONFIG_ENABLE_ASSERT 1U /* 是否启用断言 */ -#define MENU_CONFIG_ENABLE_DEBUG 1U /* 是否启用调试打印 */ -#define MENU_CONFIG_ENABLE_MEM_MONITOR 1U /* 是否启用内存监控 */ -#define MENU_CONFIG_ENABLE_PARAM 1U /* 是否启用参数管理 */ -#define MENU_CONFIG_ENABLE_LANG 1U /* 是否启用多语言支持 */ -#define MENU_CONFIG_ENABLE_MODBUS_MAP 1U /* 是否启用Modbus映射 */ -#define MENU_CONFIG_ENABLE_STATE_MACHINE_EXT 1U /* 是否启用状态机扩展 */ -#define MENU_CONFIG_ENABLE_PERMISSION 1U /* 是否启用权限管理 */ -#define MENU_CONFIG_ENABLE_PERSISTENCE 1U /* 是否启用状态持久化 */ - -/* 权限管理配置 */ -#define MENU_CONFIG_PERMISSION_MAX_ROLES 8U /* 最大支持的角色数量 */ -#define MENU_CONFIG_PERMISSION_MAX_LEVEL 16U /* 最大权限级别 */ - -/* 状态持久化配置 */ -#define MENU_CONFIG_PERSISTENCE_MAX_SIZE 256U /* 持久化数据的最大大小(字节) */ -#define MENU_CONFIG_PERSISTENCE_AUTO_SAVE_INTERVAL 5000U /* 自动保存间隔(ms) */ -#define MENU_CONFIG_PERSISTENCE_ENABLE_ENCRYPT 1U /* 是否启用持久化数据加密 */ - -/* 类型定义 ---------------------------------------------------------------------------------------------------------*/ -typedef uint16_t MenuNodeId; /* 菜单节点ID类型 */ -typedef uint8_t MenuState; /* 菜单状态类型 */ -typedef uint8_t MenuEventType; /* 事件类型 */ -typedef uint16_t MenuErrCode; /* 错误码类型 */ - -/* 状态定义 ---------------------------------------------------------------------------------------------------------*/ -#define MENU_STATE_INIT 0U /* 初始化状态 */ -#define MENU_STATE_NORMAL 1U /* 正常导航状态 */ -#define MENU_STATE_PARAM_EDIT 2U /* 参数编辑状态 */ -#define MENU_STATE_CONFIRM 3U /* 确认状态 */ -#define MENU_STATE_ERROR 4U /* 错误状态 */ - -/* 事件类型定义 -----------------------------------------------------------------------------------------------------*/ -#define MENU_EVENT_NONE 0U /* 无事件 */ -#define MENU_EVENT_KEY_UP 1U /* 上键事件 */ -#define MENU_EVENT_KEY_DOWN 2U /* 下键事件 */ -#define MENU_EVENT_KEY_ENTER 3U /* 确认键事件 */ -#define MENU_EVENT_KEY_ESC 4U /* 退出键事件 */ -#define MENU_EVENT_TIMEOUT 5U /* 超时事件 */ -#define MENU_EVENT_CUSTOM_BASE 10U /* 自定义事件基值 */ - -/* 错误码定义 -------------------------------------------------------------------------------------------------------*/ -#define MENU_ERR_OK 0U /* 成功 */ -#define MENU_ERR_INVALID_PARAM 1U /* 参数无效 */ -#define MENU_ERR_OUT_OF_MEMORY 2U /* 内存不足 */ -#define MENU_ERR_NODE_NOT_FOUND 3U /* 节点未找到 */ -#define MENU_ERR_QUEUE_FULL 4U /* 队列已满 */ -#define MENU_ERR_QUEUE_EMPTY 5U /* 队列为空 */ -#define MENU_ERR_INVALID_STATE 6U /* 无效状态 */ -#define MENU_ERR_OPERATION_FAILED 7U /* 操作失败 */ -#define MENU_ERR_NOT_INITIALIZED 8U /* 未初始化 */ -#define MENU_ERR_ALREADY_EXISTS 9U /* 已存在 */ -#define MENU_ERR_STACK_OVERFLOW 10U /* 栈溢出 */ -#define MENU_ERR_STACK_UNDERFLOW 11U /* 栈下溢 */ -#define MENU_ERR_STACK_EMPTY 12U /* 栈为空 */ -#define MENU_ERR_NAV_PATH_OVERFLOW 13U /* 导航路径溢出 */ -#define MENU_ERR_INVALID_CALLBACK 14U /* 无效回调函数 */ -#define MENU_ERR_INVALID_TRANSITION 15U /* 无效状态转换 */ -#define MENU_ERR_NOT_SUPPORTED 16U /* 不支持的操作 */ - -/* 断言定义 ---------------------------------------------------------------------------------------------------------*/ -#if MENU_CONFIG_ENABLE_ASSERT -extern void menu_assert_failed(const char* expr, const char* file, uint32_t line); -#define MENU_ASSERT(expr) ((expr) ? (void)0U : menu_assert_failed(#expr, __FILE__, __LINE__)) -#else -#define MENU_ASSERT(expr) ((void)0U) -#endif - -/* 调试打印定义 -----------------------------------------------------------------------------------------------------*/ -#if MENU_CONFIG_ENABLE_DEBUG -extern void menu_debug_print(const char* fmt, ...); -#define MENU_DEBUG(fmt, ...) menu_debug_print(fmt, ##__VA_ARGS__) -#else -#define MENU_DEBUG(fmt, ...) ((void)0U) -#endif - -#endif /* MENU_CONFIG_H */ diff --git a/src/core/menu_core.c b/src/core/menu_core.c deleted file mode 100644 index d305501..0000000 --- a/src/core/menu_core.c +++ /dev/null @@ -1,778 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_core.c - * @brief 菜单组件核心功能实现 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_types.h" -#include "menu_core.h" -#include "menu_hash.h" -#include "menu_event.h" -#include "menu_stack.h" - -#if MENU_CONFIG_ENABLE_PERMISSION -#include "menu_permission.h" -#endif - -#if MENU_CONFIG_ENABLE_PERSISTENCE -#include "menu_persistence.h" -#endif - -/* 私有函数原型 -----------------------------------------------------------------------------------------------------*/ -static MenuErrCode menu_core_init_nodes(MenuCoreCtx* core_ctx); -static MenuNode* menu_core_get_free_node(MenuCoreCtx* core_ctx); -static MenuErrCode menu_core_state_transition(MenuCoreCtx* core_ctx, MenuEventType event); -static MenuErrCode menu_core_navigate_enter(MenuCoreCtx* core_ctx, MenuNodeId node_id); -static MenuErrCode menu_core_navigate_back(MenuCoreCtx* core_ctx); -static MenuErrCode menu_core_navigate_up(MenuCoreCtx* core_ctx); -static MenuErrCode menu_core_navigate_down(MenuCoreCtx* core_ctx); - -/* 全局变量 ---------------------------------------------------------------------------------------------------------*/ -static MenuCoreCtx sg_menu_core_ctx; - -/* 状态转换规则定义 -------------------------------------------------------------------------------------------------*/ -#if MENU_CONFIG_ENABLE_STATE_MACHINE_EXT -static MenuStateTransition sg_default_transitions[] = { - // 初始状态转换 - {MENU_STATE_INIT, MENU_EVENT_KEY_ENTER, MENU_STATE_NORMAL, NULL, "Init to Normal"}, - {MENU_STATE_INIT, MENU_EVENT_TIMEOUT, MENU_STATE_ERROR, NULL, "Init timeout to Error"}, - - // 正常状态转换 - {MENU_STATE_NORMAL, MENU_EVENT_KEY_ENTER, MENU_STATE_PARAM_EDIT, NULL, "Normal to Param Edit"}, - {MENU_STATE_NORMAL, MENU_EVENT_KEY_ESC, MENU_STATE_NORMAL, NULL, "Normal to Normal"}, - {MENU_STATE_NORMAL, MENU_EVENT_KEY_UP, MENU_STATE_NORMAL, NULL, "Normal to Normal (Up)"}, - {MENU_STATE_NORMAL, MENU_EVENT_KEY_DOWN, MENU_STATE_NORMAL, NULL, "Normal to Normal (Down)"}, - - // 参数编辑状态转换 - {MENU_STATE_PARAM_EDIT, MENU_EVENT_KEY_ENTER, MENU_STATE_CONFIRM, NULL, "Param Edit to Confirm"}, - {MENU_STATE_PARAM_EDIT, MENU_EVENT_KEY_ESC, MENU_STATE_NORMAL, NULL, "Param Edit to Normal"}, - - // 确认状态转换 - {MENU_STATE_CONFIRM, MENU_EVENT_KEY_ENTER, MENU_STATE_NORMAL, NULL, "Confirm to Normal"}, - {MENU_STATE_CONFIRM, MENU_EVENT_KEY_ESC, MENU_STATE_PARAM_EDIT, NULL, "Confirm to Param Edit"}, - - // 错误状态转换 - {MENU_STATE_ERROR, MENU_EVENT_KEY_ESC, MENU_STATE_INIT, NULL, "Error to Init"}, -}; - -#define MENU_DEFAULT_TRANSITION_COUNT (sizeof(sg_default_transitions) / sizeof(MenuStateTransition)) -#endif - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化菜单核心 - * @return 错误码 - */ -MenuErrCode menu_core_init(void) -{ - MenuCoreCtx* core_ctx = &sg_menu_core_ctx; - - // 初始化核心上下文 - core_ctx->is_initialized = false; - core_ctx->current_node_id = 0; - core_ctx->current_state = MENU_STATE_INIT; - core_ctx->last_refresh_tick = 0; - core_ctx->error_code = MENU_ERR_OK; - core_ctx->error_msg = NULL; - core_ctx->node_count = 0; - core_ctx->free_node_count = MENU_CONFIG_MAX_NODES; - -#if MENU_CONFIG_ENABLE_STATE_MACHINE_EXT - core_ctx->custom_transition_count = 0; -#endif - - // 初始化各个组件 - menu_core_init_nodes(core_ctx); - menu_hash_init(core_ctx); - menu_stack_init(&core_ctx->stack, MENU_CONFIG_STACK_DEPTH); - menu_nav_path_init(&core_ctx->nav_path, MENU_CONFIG_STACK_DEPTH); - menu_event_queue_init(&core_ctx->event_queue); - - #if MENU_CONFIG_ENABLE_STATE_MACHINE_EXT - // 注册默认状态转换规则 - for (uint16_t i = 0; i < MENU_DEFAULT_TRANSITION_COUNT; i++) { - core_ctx->custom_transitions[i] = sg_default_transitions[i]; - } - core_ctx->custom_transition_count = MENU_DEFAULT_TRANSITION_COUNT; - #endif - - #if MENU_CONFIG_ENABLE_PERMISSION - // 初始化权限管理模块 - menu_permission_init(); - #endif - - #if MENU_CONFIG_ENABLE_PERSISTENCE - // 初始化状态持久化模块 - menu_persistence_init(); - #endif - - core_ctx->is_initialized = true; - return MENU_ERR_OK; -} - -/** - * @brief 反初始化菜单核心 - * @return 错误码 - */ -MenuErrCode menu_core_deinit(void) -{ - MenuCoreCtx* core_ctx = &sg_menu_core_ctx; - - if (!core_ctx->is_initialized) { - return MENU_ERR_INVALID_STATE; - } - - // 清空事件队列 - menu_event_queue_clear(&core_ctx->event_queue); - - // 清空栈和导航路径 - menu_stack_clear(&core_ctx->stack); - menu_nav_path_clear(&core_ctx->nav_path); - - // 重置哈希表 - menu_hash_init(core_ctx); - - // 重置所有节点 - menu_core_init_nodes(core_ctx); - - // 重置核心上下文 - core_ctx->is_initialized = false; - core_ctx->current_node_id = 0; - core_ctx->current_state = MENU_STATE_INIT; - core_ctx->last_refresh_tick = 0; - core_ctx->error_code = MENU_ERR_OK; - core_ctx->error_msg = NULL; - core_ctx->node_count = 0; - core_ctx->free_node_count = MENU_CONFIG_MAX_NODES; - -#if MENU_CONFIG_ENABLE_STATE_MACHINE_EXT - core_ctx->custom_transition_count = 0; -#endif - - #if MENU_CONFIG_ENABLE_PERMISSION - // 反初始化权限管理模块 - menu_permission_deinit(); - #endif - - #if MENU_CONFIG_ENABLE_PERSISTENCE - // 反初始化状态持久化模块 - menu_persistence_deinit(); - #endif - - return MENU_ERR_OK; -} - -/** - * @brief 初始化菜单节点池 - * @param core_ctx 菜单核心上下文 - * @return 错误码 - */ -static MenuErrCode menu_core_init_nodes(MenuCoreCtx* core_ctx) -{ - for (uint16_t i = 0; i < MENU_CONFIG_MAX_NODES; i++) { - MenuNode* node = &core_ctx->nodes[i]; - - node->id = i + 1; // 节点ID从1开始 - node->parent_id = 0; - node->name = NULL; - node->enter_cb = NULL; - node->exit_cb = NULL; - node->first_child_id = 0; - node->next_sibling_id = 0; - node->prev_sibling_id = 0; - node->hash_next_id = 0; - - node->flags.is_registered = false; - node->flags.is_selected = false; - node->flags.is_visible = true; // 默认可见 - node->flags.is_enabled = true; // 默认启用 - -#if MENU_CONFIG_ENABLE_PARAM - node->param_id = 0; -#endif - -#if MENU_CONFIG_ENABLE_PERMISSION - node->permission_level = 0; // 默认权限级别为0(最低权限) -#endif - } - - return MENU_ERR_OK; -} - -/** - * @brief 获取一个空闲节点 - * @param core_ctx 菜单核心上下文 - * @return 空闲节点指针,没有空闲节点返回NULL - */ -static MenuNode* menu_core_get_free_node(MenuCoreCtx* core_ctx) -{ - static uint16_t last_allocated_index = 0; // 记录上次分配的索引,实现循环分配 - - // 先从上次分配的位置开始查找,实现循环分配 - for (uint16_t i = 0; i < MENU_CONFIG_MAX_NODES; i++) { - uint16_t index = (last_allocated_index + i) % MENU_CONFIG_MAX_NODES; - MenuNode* node = &core_ctx->nodes[index]; - if (!node->flags.is_registered) { - last_allocated_index = index; - return node; - } - } - return NULL; -} - -/** - * @brief 注册菜单节点 - * @param node_id 节点ID(0表示自动分配) - * @param parent_id 父节点ID - * @param name 节点名称 - * @param enter_cb 进入回调 - * @param exit_cb 退出回调 - * @return 实际分配的节点ID - */ -MenuNodeId menu_core_register_node(MenuNodeId node_id, MenuNodeId parent_id, const char* name, MenuCallback enter_cb, MenuCallback exit_cb) -{ - MenuCoreCtx* core_ctx = &sg_menu_core_ctx; - - // 参数验证 - if (!core_ctx->is_initialized) { - return 0; - } - - // 检查父节点是否有效(如果不是根节点) - if (parent_id != 0) { - MenuNode* parent_node = menu_hash_find(core_ctx, parent_id); - if (parent_node == NULL || !parent_node->flags.is_registered) { - return 0; - } - } - - // 检查节点名称是否有效 - if (name == NULL) { - return 0; - } - - MenuNode* node = NULL; - - if (node_id == 0) { - // 自动分配节点ID - node = menu_core_get_free_node(core_ctx); - if (node == NULL) { - return 0; - } - } else { - // 使用指定节点ID - if (node_id > MENU_CONFIG_MAX_NODES || node_id < 1) { - return 0; - } - - node = &core_ctx->nodes[node_id - 1]; - if (node->flags.is_registered) { - return 0; - } - } - - // 初始化节点 - node->parent_id = parent_id; - node->name = name; - node->enter_cb = enter_cb; - node->exit_cb = exit_cb; - - // 添加到父节点的子节点列表 - if (parent_id != 0) { - MenuNode* parent_node = menu_hash_find(core_ctx, parent_id); - if (parent_node != NULL) { - if (parent_node->first_child_id == 0) { - // 父节点没有子节点,直接添加 - parent_node->first_child_id = node->id; - } else { - // 查找父节点的最后一个子节点 - MenuNode* last_child = menu_hash_find(core_ctx, parent_node->first_child_id); - while (last_child->next_sibling_id != 0) { - last_child = menu_hash_find(core_ctx, last_child->next_sibling_id); - } - - // 添加到最后一个子节点的后面 - last_child->next_sibling_id = node->id; - node->prev_sibling_id = last_child->id; - } - } - } - - // 添加到哈希表 - menu_hash_add(core_ctx, node); - - // 更新节点计数 - node->flags.is_registered = true; - core_ctx->node_count++; - core_ctx->free_node_count--; - - // 如果是第一个节点,设置为当前节点 - if (core_ctx->current_node_id == 0) { - core_ctx->current_node_id = node->id; - menu_nav_path_add(&core_ctx->nav_path, node->id); - // 初始化栈,将根节点压入栈中,确保栈和导航路径深度一致 - menu_stack_push(&core_ctx->stack, node->id); - } - - return node->id; -} - -/** - * @brief 注销菜单节点 - * @param node_id 节点ID - * @return 错误码 - */ -static MenuErrCode menu_core_unregister_node_recursive(MenuCoreCtx* core_ctx, MenuNodeId node_id); - -/** - * @brief 注销菜单节点 - * @param node_id 节点ID - * @return 错误码 - */ -MenuErrCode menu_core_unregister_node(MenuNodeId node_id) -{ - MenuCoreCtx* core_ctx = &sg_menu_core_ctx; - - // 参数验证 - if (!core_ctx->is_initialized) { - return MENU_ERR_INVALID_STATE; - } - - if (node_id == 0 || node_id > MENU_CONFIG_MAX_NODES) { - return MENU_ERR_INVALID_PARAM; - } - - // 递归注销所有子节点 - return menu_core_unregister_node_recursive(core_ctx, node_id); -} - -/** - * @brief 递归注销菜单节点及其所有子节点 - * @param core_ctx 菜单核心上下文 - * @param node_id 节点ID - * @return 错误码 - */ -static MenuErrCode menu_core_unregister_node_recursive(MenuCoreCtx* core_ctx, MenuNodeId node_id) -{ - MenuNode* node = menu_hash_find(core_ctx, node_id); - if (node == NULL || !node->flags.is_registered) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 递归注销所有子节点 - if (node->first_child_id != 0) { - MenuNode* child_node = menu_hash_find(core_ctx, node->first_child_id); - while (child_node != NULL) { - MenuNodeId next_child_id = child_node->next_sibling_id; - // 递归注销子节点 - menu_core_unregister_node_recursive(core_ctx, child_node->id); - child_node = menu_hash_find(core_ctx, next_child_id); - } - } - - // 从哈希表中移除 - menu_hash_remove(core_ctx, node); - - // 从父节点的子节点列表中移除 - if (node->parent_id != 0) { - MenuNode* parent_node = menu_hash_find(core_ctx, node->parent_id); - if (parent_node != NULL) { - if (parent_node->first_child_id == node_id) { - // 移除的是第一个子节点 - parent_node->first_child_id = node->next_sibling_id; - } else { - // 移除的是中间或最后一个子节点 - if (node->prev_sibling_id != 0) { - MenuNode* prev_sibling = menu_hash_find(core_ctx, node->prev_sibling_id); - if (prev_sibling != NULL) { - prev_sibling->next_sibling_id = node->next_sibling_id; - } - } - } - - if (node->next_sibling_id != 0) { - MenuNode* next_sibling = menu_hash_find(core_ctx, node->next_sibling_id); - if (next_sibling != NULL) { - next_sibling->prev_sibling_id = node->prev_sibling_id; - } - } - } - } - - // 重置节点状态 - node->flags.is_registered = false; - node->flags.is_selected = false; - node->parent_id = 0; - node->next_sibling_id = 0; - node->prev_sibling_id = 0; - node->first_child_id = 0; - - // 更新节点计数 - core_ctx->node_count--; - core_ctx->free_node_count++; - - return MENU_ERR_OK; -} - -/** - * @brief 状态转换处理 - * @param core_ctx 菜单核心上下文 - * @param event 事件类型 - * @return 错误码 - */ -static MenuErrCode menu_core_state_transition(MenuCoreCtx* core_ctx, MenuEventType event) -{ - MenuStateTransition default_transition = {0}; - MenuStateTransition* matched_transition = NULL; - - // 1. 查找匹配的自定义状态转换规则 -#if MENU_CONFIG_ENABLE_STATE_MACHINE_EXT - for (uint16_t i = 0; i < core_ctx->custom_transition_count; i++) { - MenuStateTransition* transition = &core_ctx->custom_transitions[i]; - - if (transition->current_state == core_ctx->current_state && transition->event == event) { - matched_transition = transition; - break; - } - } -#endif - - // 2. 如果没有找到匹配的自定义规则,使用默认状态转换 - if (matched_transition == NULL) { - // 默认状态转换规则:保持当前状态不变 - default_transition.current_state = core_ctx->current_state; - default_transition.event = event; - default_transition.next_state = core_ctx->current_state; // 默认不改变状态 - default_transition.action = NULL; - default_transition.desc = "默认状态转换"; - matched_transition = &default_transition; - } - - // 3. 先更新状态,再执行转换动作 - MenuState old_state = core_ctx->current_state; - core_ctx->current_state = matched_transition->next_state; - - // 4. 执行状态转换动作(如果有) - if (matched_transition->action != NULL) { - MenuErrCode err = matched_transition->action(core_ctx); - if (err != MENU_ERR_OK) { - // 动作执行失败,恢复原状态 - core_ctx->current_state = old_state; - return err; - } - } - - return MENU_ERR_OK; -} - -/** - * @brief 导航进入子菜单 - * @param core_ctx 菜单核心上下文 - * @param node_id 节点ID - * @return 错误码 - */ -static MenuErrCode menu_core_navigate_enter(MenuCoreCtx* core_ctx, MenuNodeId node_id) -{ - MenuNode* node = menu_hash_find(core_ctx, node_id); - if (node == NULL) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 如果当前节点没有子节点,直接返回 - if (node->first_child_id == 0) { - return MENU_ERR_OK; - } - - // 进入第一个子节点 - MenuNodeId target_node_id = node->first_child_id; - MenuNode* target_node = menu_hash_find(core_ctx, target_node_id); - if (target_node == NULL) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 执行当前节点的退出回调 - MenuNode* curr_node = menu_hash_find(core_ctx, core_ctx->current_node_id); - if (curr_node != NULL && curr_node->exit_cb != NULL) { - curr_node->exit_cb(core_ctx->current_node_id, core_ctx); - } - - // 压入当前节点到栈中 - MenuErrCode err = menu_stack_push(&core_ctx->stack, core_ctx->current_node_id); - if (err != MENU_ERR_OK) { - return err; - } - - // 更新当前节点 - core_ctx->current_node_id = target_node_id; - - // 添加到导航路径 - err = menu_nav_path_add(&core_ctx->nav_path, target_node_id); - if (err != MENU_ERR_OK) { - menu_stack_pop(&core_ctx->stack, &node_id); - core_ctx->current_node_id = node_id; - return err; - } - - // 执行新节点的进入回调 - if (target_node->enter_cb != NULL) { - target_node->enter_cb(target_node_id, core_ctx); - } - - return MENU_ERR_OK; -} - -/** - * @brief 导航返回上一级菜单 - * @param core_ctx 菜单核心上下文 - * @return 错误码 - */ -static MenuErrCode menu_core_navigate_back(MenuCoreCtx* core_ctx) -{ - // 执行当前节点的退出回调 - MenuNode* curr_node = menu_hash_find(core_ctx, core_ctx->current_node_id); - if (curr_node != NULL && curr_node->exit_cb != NULL) { - curr_node->exit_cb(core_ctx->current_node_id, core_ctx); - } - - MenuNodeId prev_node_id; - MenuErrCode err; - - // 如果栈不为空,弹出上一级节点ID - if (!menu_stack_is_empty(&core_ctx->stack)) { - err = menu_stack_pop(&core_ctx->stack, &prev_node_id); - if (err != MENU_ERR_OK) { - return err; - } - } else { - // 栈为空,返回到根节点 - // 查找根节点 - prev_node_id = 0; - for (uint16_t i = 0; i < MENU_CONFIG_MAX_NODES; i++) { - MenuNode* node = &core_ctx->nodes[i]; - if (node->flags.is_registered && node->parent_id == 0) { - prev_node_id = node->id; - break; - } - } - - // 如果没有找到根节点,返回错误 - if (prev_node_id == 0) { - return MENU_ERR_NODE_NOT_FOUND; - } - } - - // 从导航路径移除当前节点 - err = menu_nav_path_remove_last(&core_ctx->nav_path); - if (err != MENU_ERR_OK) { - // 如果导航路径移除失败,检查是否还有深度 - if (core_ctx->nav_path.depth > 0) { - // 导航路径还有深度,直接更新当前节点 - core_ctx->current_node_id = prev_node_id; - } else { - // 导航路径已为空,添加根节点 - menu_nav_path_add(&core_ctx->nav_path, prev_node_id); - } - } else { - // 导航路径移除成功,更新当前节点 - core_ctx->current_node_id = prev_node_id; - } - - // 执行上一级节点的进入回调 - MenuNode* prev_node = menu_hash_find(core_ctx, prev_node_id); - if (prev_node != NULL && prev_node->enter_cb != NULL) { - prev_node->enter_cb(prev_node_id, core_ctx); - } - - return MENU_ERR_OK; -} - -/** - * @brief 导航向上选择 - * @param core_ctx 菜单核心上下文 - * @return 错误码 - */ -static MenuErrCode menu_core_navigate_up(MenuCoreCtx* core_ctx) -{ - MenuNode* curr_node = menu_hash_find(core_ctx, core_ctx->current_node_id); - if (curr_node == NULL) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 查找当前节点的父节点 - MenuNode* parent_node = menu_hash_find(core_ctx, curr_node->parent_id); - - // 如果当前节点有父节点,在同级节点中向上切换 - if (parent_node != NULL) { - // 查找同级的上一个兄弟节点 - if (curr_node->prev_sibling_id != 0) { - core_ctx->current_node_id = curr_node->prev_sibling_id; - } else if (parent_node->first_child_id != 0) { - // 没有上一个兄弟节点,查找父节点的最后一个子节点(环形导航) - MenuNode* last_child = menu_hash_find(core_ctx, parent_node->first_child_id); - if (last_child != NULL) { - // 查找最后一个子节点 - while (last_child->next_sibling_id != 0) { - MenuNode* next_child = menu_hash_find(core_ctx, last_child->next_sibling_id); - if (next_child == NULL) { - break; // 防止无限循环,安全退出 - } - last_child = next_child; - } - - core_ctx->current_node_id = last_child->id; - } - } - } else { - // 如果当前节点是根节点,在其子节点中向上切换 - if (curr_node->first_child_id != 0) { - // 查找最后一个子节点 - MenuNode* last_child = menu_hash_find(core_ctx, curr_node->first_child_id); - if (last_child != NULL) { - while (last_child->next_sibling_id != 0) { - MenuNode* next_child = menu_hash_find(core_ctx, last_child->next_sibling_id); - if (next_child == NULL) { - break; // 防止无限循环,安全退出 - } - last_child = next_child; - } - - core_ctx->current_node_id = last_child->id; - } - } - } - - return MENU_ERR_OK; -} - -/** - * @brief 导航向下选择 - * @param core_ctx 菜单核心上下文 - * @return 错误码 - */ -static MenuErrCode menu_core_navigate_down(MenuCoreCtx* core_ctx) -{ - MenuNode* curr_node = menu_hash_find(core_ctx, core_ctx->current_node_id); - if (curr_node == NULL) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 查找当前节点的父节点 - MenuNode* parent_node = menu_hash_find(core_ctx, curr_node->parent_id); - - // 如果当前节点有父节点,在同级节点中向下切换 - if (parent_node != NULL) { - // 查找同级的下一个兄弟节点 - if (curr_node->next_sibling_id != 0) { - core_ctx->current_node_id = curr_node->next_sibling_id; - } else if (parent_node->first_child_id != 0) { - // 没有下一个兄弟节点,选择父节点的第一个子节点(环形导航) - core_ctx->current_node_id = parent_node->first_child_id; - } - } else { - // 如果当前节点是根节点,在其子节点中向下切换 - if (curr_node->first_child_id != 0) { - // 导航到第一个子节点 - MenuNode* first_child = menu_hash_find(core_ctx, curr_node->first_child_id); - if (first_child != NULL) { - core_ctx->current_node_id = first_child->id; - } - } - // 如果根节点没有子节点,保持当前节点不变 - } - - return MENU_ERR_OK; -} - -/** - * @brief 菜单主循环 - * @param tick 当前系统时间(ms) - * @return 错误码 - */ -MenuErrCode menu_core_main_loop(uint32_t tick) -{ - MenuCoreCtx* core_ctx = &sg_menu_core_ctx; - - if (!core_ctx->is_initialized) { - return MENU_ERR_INVALID_STATE; - } - - // 更新最后刷新时间 - core_ctx->last_refresh_tick = tick; - - // 处理事件队列 - while (!menu_event_queue_is_empty(&core_ctx->event_queue)) { - MenuEvent event; - MenuErrCode err = menu_event_queue_pop(&core_ctx->event_queue, &event); - if (err != MENU_ERR_OK) { - continue; - } - - // 处理事件 - switch (event.type) { - case MENU_EVENT_KEY_UP: - menu_core_navigate_up(core_ctx); - break; - case MENU_EVENT_KEY_DOWN: - menu_core_navigate_down(core_ctx); - break; - case MENU_EVENT_KEY_ENTER: - menu_core_navigate_enter(core_ctx, core_ctx->current_node_id); - break; - case MENU_EVENT_KEY_ESC: - menu_core_navigate_back(core_ctx); - break; - default: - // 其他事件通过状态机处理 - menu_core_state_transition(core_ctx, event.type); - break; - } - } - - // 处理自动保存 - #if MENU_CONFIG_ENABLE_PERSISTENCE - menu_persistence_process_auto_save(tick); - #endif - - return MENU_ERR_OK; -} - -/** - * @brief 获取菜单核心上下文 - * @return 菜单核心上下文指针 - */ -MenuCoreCtx* menu_get_core_ctx(void) -{ - return &sg_menu_core_ctx; -} - -/** - * @brief 获取当前选中的节点ID - * @return 当前节点ID - */ -MenuNodeId menu_get_current_node_id(void) -{ - return sg_menu_core_ctx.current_node_id; -} - -/** - * @brief 获取当前菜单状态 - * @return 当前菜单状态 - */ -MenuState menu_get_current_state(void) -{ - return sg_menu_core_ctx.current_state; -} - -/** - * @brief 获取导航深度 - * @return 导航深度 - */ -uint8_t menu_core_get_nav_depth(void) -{ - return sg_menu_core_ctx.nav_path.depth; -} diff --git a/src/core/menu_core.h b/src/core/menu_core.h deleted file mode 100644 index b777c1b..0000000 --- a/src/core/menu_core.h +++ /dev/null @@ -1,246 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_core.h - * @brief 菜单组件核心功能声明 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_CORE_H -#define MENU_CORE_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_types.h" - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化菜单核心 - * @return 错误码 - */ -MenuErrCode menu_core_init(void); - -/** - * @brief 反初始化菜单核心 - * @return 错误码 - */ -MenuErrCode menu_core_deinit(void); - -/** - * @brief 注册菜单节点 - * @param node_id 节点ID(0表示自动分配) - * @param parent_id 父节点ID - * @param name 节点名称 - * @param enter_cb 进入回调 - * @param exit_cb 退出回调 - * @return 实际分配的节点ID - */ -MenuNodeId menu_core_register_node(MenuNodeId node_id, MenuNodeId parent_id, const char* name, MenuCallback enter_cb, MenuCallback exit_cb); - -/** - * @brief 注销菜单节点 - * @param node_id 节点ID - * @return 错误码 - */ -MenuErrCode menu_core_unregister_node(MenuNodeId node_id); - -/** - * @brief 获取菜单核心上下文 - * @return 菜单核心上下文指针 - */ -struct MenuCoreCtx* menu_get_core_ctx(void); - -/** - * @brief 获取当前选中的节点ID - * @return 当前节点ID - */ -MenuNodeId menu_get_current_node_id(void); - -/** - * @brief 获取当前菜单状态 - * @return 当前菜单状态 - */ -MenuState menu_get_current_state(void); - -/** - * @brief 获取导航深度 - * @return 导航深度 - */ -uint8_t menu_core_get_nav_depth(void); - -/** - * @brief 菜单主循环 - * @param tick 当前系统时间(ms) - * @return 错误码 - */ -MenuErrCode menu_core_main_loop(uint32_t tick); - -/* 权限管理函数声明 -------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_PERMISSION - -/** - * @brief 初始化权限管理模块 - * @return 错误码 - */ -MenuErrCode menu_permission_init(void); - -/** - * @brief 反初始化权限管理模块 - * @return 错误码 - */ -MenuErrCode menu_permission_deinit(void); - -/** - * @brief 注册角色 - * @param role 角色结构体指针 - * @return 错误码 - */ -MenuErrCode menu_permission_register_role(const MenuRole* role); - -/** - * @brief 注销角色 - * @param role_id 角色ID - * @return 错误码 - */ -MenuErrCode menu_permission_unregister_role(MenuRoleId role_id); - -/** - * @brief 设置当前角色 - * @param role_id 角色ID - * @return 错误码 - */ -MenuErrCode menu_permission_set_current_role(MenuRoleId role_id); - -/** - * @brief 获取当前角色 - * @return 当前角色ID - */ -MenuRoleId menu_permission_get_current_role(void); - -/** - * @brief 检查节点是否可访问 - * @param node_id 节点ID - * @return true表示可访问,false表示不可访问 - */ -bool menu_permission_check_node_access(MenuNodeId node_id); - -/** - * @brief 更新节点权限级别 - * @param node_id 节点ID - * @param permission_level 权限级别 - * @return 错误码 - */ -MenuErrCode menu_permission_update_node_level(MenuNodeId node_id, MenuPermissionLevel permission_level); - -/** - * @brief 获取节点权限级别 - * @param node_id 节点ID - * @return 节点权限级别 - */ -MenuPermissionLevel menu_permission_get_node_level(MenuNodeId node_id); - -/** - * @brief 更新所有节点的可见性和可用性 - * @return 错误码 - */ -MenuErrCode menu_permission_update_all_nodes(void); - -/** - * @brief 获取角色信息 - * @param role_id 角色ID - * @return 角色结构体指针,NULL表示角色不存在 - */ -const MenuRole* menu_permission_get_role(MenuRoleId role_id); - -#endif /* MENU_CONFIG_ENABLE_PERMISSION */ - -/* 状态持久化函数声明 -------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_PERSISTENCE - -/** - * @brief 初始化状态持久化模块 - * @return 错误码 - */ -MenuErrCode menu_persistence_init(void); - -/** - * @brief 反初始化状态持久化模块 - * @return 错误码 - */ -MenuErrCode menu_persistence_deinit(void); - -/** - * @brief 注册持久化回调函数 - * @param save_cb 保存回调函数 - * @param restore_cb 恢复回调函数 - * @return 错误码 - */ -MenuErrCode menu_persistence_register_callback(MenuPersistenceCallback save_cb, MenuRestoreCallback restore_cb); - -/** - * @brief 启用或禁用自动保存 - * @param enable true表示启用,false表示禁用 - * @return 错误码 - */ -MenuErrCode menu_persistence_set_auto_save(bool enable); - -/** - * @brief 获取自动保存状态 - * @return true表示启用,false表示禁用 - */ -bool menu_persistence_get_auto_save(void); - -/** - * @brief 设置自动保存间隔 - * @param interval 自动保存间隔(ms) - * @return 错误码 - */ -MenuErrCode menu_persistence_set_auto_save_interval(uint32_t interval); - -/** - * @brief 获取自动保存间隔 - * @return 自动保存间隔(ms) - */ -uint32_t menu_persistence_get_auto_save_interval(void); - -/** - * @brief 手动保存菜单状态 - * @return 错误码 - */ -MenuErrCode menu_persistence_save(void); - -/** - * @brief 恢复菜单状态 - * @return 错误码 - */ -MenuErrCode menu_persistence_restore(void); - -/** - * @brief 检查持久化数据是否有效 - * @param data 持久化数据 - * @param size 数据大小 - * @return true表示有效,false表示无效 - */ -bool menu_persistence_check_data_valid(const uint8_t* data, uint16_t size); - -/** - * @brief 处理自动保存(由菜单主循环调用) - * @param tick 当前系统时间(ms) - * @return 错误码 - */ -MenuErrCode menu_persistence_process_auto_save(uint32_t tick); - -/** - * @brief 计算数据校验和 - * @param data 数据指针 - * @param size 数据大小 - * @return 校验和 - */ -uint8_t menu_persistence_calculate_checksum(const uint8_t* data, uint16_t size); - -#endif /* MENU_CONFIG_ENABLE_PERSISTENCE */ - -#endif /* MENU_CORE_H */ diff --git a/src/core/menu_event.c b/src/core/menu_event.c deleted file mode 100644 index 8fee3d4..0000000 --- a/src/core/menu_event.c +++ /dev/null @@ -1,186 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_event.c - * @brief 菜单组件事件队列实现 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_types.h" - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化事件队列 - * @param queue 事件队列指针 - */ -void menu_event_queue_init(MenuEventQueue* queue) -{ - MENU_ASSERT(queue != NULL); - - queue->head = 0; - queue->tail = 0; - queue->count = 0; - queue->reserved = 0; -} - -/** - * @brief 检查事件队列是否为空 - * @param queue 事件队列指针 - * @return true为空,false不为空 - */ -bool menu_event_queue_is_empty(const MenuEventQueue* queue) -{ - MENU_ASSERT(queue != NULL); - return (queue->count == 0); -} - -/** - * @brief 检查事件队列是否已满 - * @param queue 事件队列指针 - * @return true已满,false未满 - */ -bool menu_event_queue_is_full(const MenuEventQueue* queue) -{ - MENU_ASSERT(queue != NULL); - return (queue->count >= MENU_CONFIG_EVENT_QUEUE_LEN); -} - -/** - * @brief 获取事件队列中的元素数量 - * @param queue 事件队列指针 - * @return 元素数量 - */ -uint8_t menu_event_queue_get_count(const MenuEventQueue* queue) -{ - MENU_ASSERT(queue != NULL); - return queue->count; -} - -/** - * @brief 向事件队列添加事件 - * @param queue 事件队列指针 - * @param event 要添加的事件 - * @return 错误码 - */ -MenuErrCode menu_event_queue_push(MenuEventQueue* queue, const MenuEvent* event) -{ - MENU_ASSERT(queue != NULL); - MENU_ASSERT(event != NULL); - - // 检查事件优先级是否合法 - if (event->priority >= MENU_CONFIG_EVENT_MAX_PRIORITY) { - return MENU_ERR_INVALID_PARAM; - } - - if (menu_event_queue_is_full(queue)) { - // 队列已满,替换低优先级事件 - uint8_t lowest_prio = 0; - uint8_t lowest_idx = queue->head; - - // 找到最低优先级的事件 - for (uint8_t i = 0; i < MENU_CONFIG_EVENT_QUEUE_LEN; i++) { - uint8_t idx = (queue->head + i) % MENU_CONFIG_EVENT_QUEUE_LEN; - if (queue->buffer[idx].priority > lowest_prio) { - lowest_prio = queue->buffer[idx].priority; - lowest_idx = idx; - } - } - - // 替换最低优先级事件 - queue->buffer[lowest_idx] = *event; - return MENU_ERR_OK; - } - - // 队列未满,添加到队尾 - queue->buffer[queue->tail] = *event; - queue->tail = (queue->tail + 1) % MENU_CONFIG_EVENT_QUEUE_LEN; - queue->count++; - - return MENU_ERR_OK; -} - -/** - * @brief 从事件队列获取下一个事件 - * @param queue 事件队列指针 - * @param event 用于存储获取的事件 - * @return 错误码 - */ -MenuErrCode menu_event_queue_pop(MenuEventQueue* queue, MenuEvent* event) -{ - MENU_ASSERT(queue != NULL); - MENU_ASSERT(event != NULL); - - if (menu_event_queue_is_empty(queue)) { - return MENU_ERR_QUEUE_EMPTY; - } - - // 寻找最高优先级的事件 - uint8_t highest_prio = MENU_CONFIG_EVENT_MAX_PRIORITY; - uint8_t highest_idx = queue->head; - - for (uint8_t i = 0; i < queue->count; i++) { - uint8_t idx = (queue->head + i) % MENU_CONFIG_EVENT_QUEUE_LEN; - if (queue->buffer[idx].priority < highest_prio) { - highest_prio = queue->buffer[idx].priority; - highest_idx = idx; - } - } - - // 取出最高优先级事件 - *event = queue->buffer[highest_idx]; - - // 移除该事件,将后续事件前移 - for (uint8_t i = highest_idx; i != queue->tail; i = (i + 1) % MENU_CONFIG_EVENT_QUEUE_LEN) { - uint8_t next_idx = (i + 1) % MENU_CONFIG_EVENT_QUEUE_LEN; - if (next_idx == queue->tail) { - break; - } - queue->buffer[i] = queue->buffer[next_idx]; - } - - // 更新队列状态 - if (queue->tail > 0) { - queue->tail--; - } else { - queue->tail = MENU_CONFIG_EVENT_QUEUE_LEN - 1; - } - queue->count--; - - return MENU_ERR_OK; -} - -/** - * @brief 清空事件队列 - * @param queue 事件队列指针 - */ -void menu_event_queue_clear(MenuEventQueue* queue) -{ - MENU_ASSERT(queue != NULL); - - queue->head = 0; - queue->tail = 0; - queue->count = 0; -} - -/** - * @brief 向事件队列推送一个简单事件 - * @param core_ctx 菜单核心上下文 - * @param type 事件类型 - * @param priority 事件优先级 - * @return 错误码 - */ -MenuErrCode menu_core_post_event(struct MenuCoreCtx* core_ctx, MenuEventType type, uint8_t priority) -{ - MenuEvent event; - - event.type = type; - event.priority = priority; - event.target_node_id = core_ctx->current_node_id; - event.data = NULL; - event.timestamp = core_ctx->last_refresh_tick; - - return menu_event_queue_push(&core_ctx->event_queue, &event); -} diff --git a/src/core/menu_event.h b/src/core/menu_event.h deleted file mode 100644 index 10bd958..0000000 --- a/src/core/menu_event.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_event.h - * @brief 菜单组件事件队列功能声明 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_EVENT_H -#define MENU_EVENT_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_types.h" - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化事件队列 - * @param queue 事件队列指针 - */ -void menu_event_queue_init(MenuEventQueue* queue); - -/** - * @brief 检查事件队列是否为空 - * @param queue 事件队列指针 - * @return true为空,false不为空 - */ -bool menu_event_queue_is_empty(const MenuEventQueue* queue); - -/** - * @brief 检查事件队列是否已满 - * @param queue 事件队列指针 - * @return true已满,false未满 - */ -bool menu_event_queue_is_full(const MenuEventQueue* queue); - -/** - * @brief 获取事件队列中的元素数量 - * @param queue 事件队列指针 - * @return 元素数量 - */ -uint8_t menu_event_queue_get_count(const MenuEventQueue* queue); - -/** - * @brief 向事件队列添加事件 - * @param queue 事件队列指针 - * @param event 要添加的事件 - * @return 错误码 - */ -MenuErrCode menu_event_queue_push(MenuEventQueue* queue, const MenuEvent* event); - -/** - * @brief 从事件队列获取下一个事件 - * @param queue 事件队列指针 - * @param event 用于存储获取的事件 - * @return 错误码 - */ -MenuErrCode menu_event_queue_pop(MenuEventQueue* queue, MenuEvent* event); - -/** - * @brief 清空事件队列 - * @param queue 事件队列指针 - */ -void menu_event_queue_clear(MenuEventQueue* queue); - -/** - * @brief 向事件队列推送一个简单事件 - * @param core_ctx 菜单核心上下文 - * @param type 事件类型 - * @param priority 事件优先级 - * @return 错误码 - */ -MenuErrCode menu_core_post_event(struct MenuCoreCtx* core_ctx, MenuEventType type, uint8_t priority); - -#endif /* MENU_EVENT_H */ diff --git a/src/core/menu_hash.c b/src/core/menu_hash.c deleted file mode 100644 index 9b29b09..0000000 --- a/src/core/menu_hash.c +++ /dev/null @@ -1,141 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_hash.c - * @brief 菜单组件哈希表实现 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_types.h" - -/* 私有函数原型 -----------------------------------------------------------------------------------------------------*/ -static uint16_t menu_hash_func(MenuNodeId node_id); - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 优化的哈希函数,用于菜单节点ID - * @param node_id 节点ID - * @return 哈希值 - */ -static uint16_t menu_hash_func(MenuNodeId node_id) -{ - // 高性能哈希函数,针对连续节点ID优化,减少哈希冲突 - uint32_t hash = node_id; - - // 使用FNV-1a哈希算法,具有良好的分布性和低冲突率 - hash = (hash ^ 0x811C9DC5) * 0x01000193; - hash = (hash ^ (hash >> 16)) * 0x01000193; - hash = hash ^ (hash >> 16); - - return (uint16_t)(hash % MENU_CONFIG_HASH_TABLE_SIZE); -} - -/** - * @brief 初始化哈希表 - * @param core_ctx 菜单核心上下文 - */ -void menu_hash_init(struct MenuCoreCtx* core_ctx) -{ - MENU_ASSERT(core_ctx != NULL); - - // 初始化哈希表所有条目为0 - for (uint16_t i = 0; i < MENU_CONFIG_HASH_TABLE_SIZE; i++) { - core_ctx->hash_table[i] = 0; - } -} - -/** - * @brief 将节点添加到哈希表 - * @param core_ctx 菜单核心上下文 - * @param node 要添加的节点 - */ -void menu_hash_add(struct MenuCoreCtx* core_ctx, MenuNode* node) -{ - MENU_ASSERT(core_ctx != NULL); - MENU_ASSERT(node != NULL); - - // 计算哈希值 - uint16_t hash = menu_hash_func(node->id); - - // 将节点插入到哈希表对应位置的链表头部 - node->hash_next_id = core_ctx->hash_table[hash]; - core_ctx->hash_table[hash] = node->id; -} - -/** - * @brief 从哈希表中移除节点 - * @param core_ctx 菜单核心上下文 - * @param node 要移除的节点 - */ -void menu_hash_remove(struct MenuCoreCtx* core_ctx, MenuNode* node) -{ - MENU_ASSERT(core_ctx != NULL); - MENU_ASSERT(node != NULL); - - // 计算哈希值 - uint16_t hash = menu_hash_func(node->id); - - // 在链表中查找并移除节点 - MenuNodeId prev_id = 0; - MenuNodeId curr_id = core_ctx->hash_table[hash]; - MenuNode* curr_node = NULL; - - while (curr_id != 0) { - curr_node = &core_ctx->nodes[curr_id - 1]; - - if (curr_node->id == node->id) { - // 找到了节点,进行移除操作 - if (prev_id == 0) { - // 移除的是链表头 - core_ctx->hash_table[hash] = node->hash_next_id; - } else { - // 移除的是链表中间节点 - MenuNode* prev_node = &core_ctx->nodes[prev_id - 1]; - prev_node->hash_next_id = node->hash_next_id; - } - - // 清空节点的哈希表链接 - node->hash_next_id = 0; - break; - } - - // 继续遍历 - prev_id = curr_id; - curr_id = curr_node->hash_next_id; - } -} - -/** - * @brief 根据ID查找节点 - * @param core_ctx 菜单核心上下文 - * @param node_id 节点ID - * @return 找到的节点指针,未找到返回NULL - */ -MenuNode* menu_hash_find(struct MenuCoreCtx* core_ctx, MenuNodeId node_id) -{ - MENU_ASSERT(core_ctx != NULL); - - // 计算哈希值 - uint16_t hash = menu_hash_func(node_id); - - // 在链表中查找节点 - MenuNodeId curr_id = core_ctx->hash_table[hash]; - - while (curr_id != 0) { - MenuNode* curr_node = &core_ctx->nodes[curr_id - 1]; - - if (curr_node->id == node_id) { - // 找到了节点 - return curr_node; - } - - // 继续遍历 - curr_id = curr_node->hash_next_id; - } - - // 未找到节点 - return NULL; -} diff --git a/src/core/menu_hash.h b/src/core/menu_hash.h deleted file mode 100644 index 5f014b3..0000000 --- a/src/core/menu_hash.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_hash.h - * @brief 菜单组件哈希表功能声明 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_HASH_H -#define MENU_HASH_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_types.h" - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化哈希表 - * @param core_ctx 菜单核心上下文 - */ -void menu_hash_init(struct MenuCoreCtx* core_ctx); - -/** - * @brief 将节点添加到哈希表 - * @param core_ctx 菜单核心上下文 - * @param node 要添加的节点 - */ -void menu_hash_add(struct MenuCoreCtx* core_ctx, MenuNode* node); - -/** - * @brief 从哈希表中移除节点 - * @param core_ctx 菜单核心上下文 - * @param node 要移除的节点 - */ -void menu_hash_remove(struct MenuCoreCtx* core_ctx, MenuNode* node); - -/** - * @brief 根据ID查找节点 - * @param core_ctx 菜单核心上下文 - * @param node_id 节点ID - * @return 找到的节点指针,未找到返回NULL - */ -MenuNode* menu_hash_find(struct MenuCoreCtx* core_ctx, MenuNodeId node_id); - -#endif /* MENU_HASH_H */ diff --git a/src/core/menu_permission.c b/src/core/menu_permission.c deleted file mode 100644 index e3b44af..0000000 --- a/src/core/menu_permission.c +++ /dev/null @@ -1,350 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_permission.c - * @brief 菜单组件权限管理功能实现 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_permission.h" -#include "menu_hash.h" - -/* 私有函数原型 -----------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_PERMISSION - -/** - * @brief 获取角色在角色列表中的索引 - * @param core_ctx 菜单核心上下文 - * @param role_id 角色ID - * @return 角色索引,-1表示未找到 - */ -static int menu_permission_get_role_index(MenuCoreCtx* core_ctx, MenuRoleId role_id); - -/** - * @brief 更新单个节点的可见性和可用性 - * @param core_ctx 菜单核心上下文 - * @param node 节点指针 - * @return 错误码 - */ -static MenuErrCode menu_permission_update_node(MenuCoreCtx* core_ctx, MenuNode* node); - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化权限管理模块 - * @return 错误码 - */ -MenuErrCode menu_permission_init(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - // 初始化权限配置 - core_ctx->permission_config.current_role = 0; - core_ctx->permission_config.role_count = 0; - - // 注册默认角色(管理员角色,权限级别最高) - MenuRole default_role = { - .id = 0, - .name = "Admin", - .max_level = MENU_CONFIG_PERMISSION_MAX_LEVEL - 1 - }; - - return menu_permission_register_role(&default_role); -} - -/** - * @brief 反初始化权限管理模块 - * @return 错误码 - */ -MenuErrCode menu_permission_deinit(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - // 清空角色列表 - core_ctx->permission_config.role_count = 0; - core_ctx->permission_config.current_role = 0; - - return MENU_ERR_OK; -} - -/** - * @brief 注册角色 - * @param role 角色结构体指针 - * @return 错误码 - */ -MenuErrCode menu_permission_register_role(const MenuRole* role) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL || role == NULL) { - return MENU_ERR_INVALID_PARAM; - } - - if (core_ctx->permission_config.role_count >= MENU_CONFIG_PERMISSION_MAX_ROLES) { - return MENU_ERR_OUT_OF_MEMORY; - } - - // 检查角色ID是否已存在 - if (menu_permission_get_role_index(core_ctx, role->id) >= 0) { - return MENU_ERR_ALREADY_EXISTS; - } - - // 添加角色到列表 - core_ctx->permission_config.roles[core_ctx->permission_config.role_count] = *role; - core_ctx->permission_config.role_count++; - - // 更新所有节点的可见性和可用性 - return menu_permission_update_all_nodes(); -} - -/** - * @brief 注销角色 - * @param role_id 角色ID - * @return 错误码 - */ -MenuErrCode menu_permission_unregister_role(MenuRoleId role_id) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - int index = menu_permission_get_role_index(core_ctx, role_id); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - if (index < 0) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 如果当前角色被注销,切换到默认角色 - if (core_ctx->permission_config.current_role == role_id) { - core_ctx->permission_config.current_role = 0; - } - - // 移除角色(将后续角色前移) - for (uint8_t i = index; i < core_ctx->permission_config.role_count - 1; i++) { - core_ctx->permission_config.roles[i] = core_ctx->permission_config.roles[i + 1]; - } - core_ctx->permission_config.role_count--; - - // 更新所有节点的可见性和可用性 - return menu_permission_update_all_nodes(); -} - -/** - * @brief 设置当前角色 - * @param role_id 角色ID - * @return 错误码 - */ -MenuErrCode menu_permission_set_current_role(MenuRoleId role_id) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - // 检查角色是否存在 - if (menu_permission_get_role_index(core_ctx, role_id) < 0) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 设置当前角色 - core_ctx->permission_config.current_role = role_id; - - // 更新所有节点的可见性和可用性 - return menu_permission_update_all_nodes(); -} - -/** - * @brief 获取当前角色 - * @return 当前角色ID - */ -MenuRoleId menu_permission_get_current_role(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return 0; - } - - return core_ctx->permission_config.current_role; -} - -/** - * @brief 检查节点是否可访问 - * @param node_id 节点ID - * @return true表示可访问,false表示不可访问 - */ -bool menu_permission_check_node_access(MenuNodeId node_id) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - MenuNode* node = menu_hash_find(core_ctx, node_id); - int role_index; - - if (core_ctx == NULL || node == NULL || !node->flags.is_registered) { - return false; - } - - // 获取当前角色索引 - role_index = menu_permission_get_role_index(core_ctx, core_ctx->permission_config.current_role); - if (role_index < 0) { - return false; - } - - // 检查权限级别 - return (node->permission_level <= core_ctx->permission_config.roles[role_index].max_level); -} - -/** - * @brief 更新节点权限级别 - * @param node_id 节点ID - * @param permission_level 权限级别 - * @return 错误码 - */ -MenuErrCode menu_permission_update_node_level(MenuNodeId node_id, MenuPermissionLevel permission_level) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - MenuNode* node = menu_hash_find(core_ctx, node_id); - - if (core_ctx == NULL || node == NULL || !node->flags.is_registered) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 更新权限级别 - node->permission_level = permission_level; - - // 更新节点的可见性和可用性 - return menu_permission_update_node(core_ctx, node); -} - -/** - * @brief 获取节点权限级别 - * @param node_id 节点ID - * @return 节点权限级别 - */ -MenuPermissionLevel menu_permission_get_node_level(MenuNodeId node_id) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - MenuNode* node = menu_hash_find(core_ctx, node_id); - - if (core_ctx == NULL || node == NULL || !node->flags.is_registered) { - return MENU_CONFIG_PERMISSION_MAX_LEVEL; - } - - return node->permission_level; -} - -/** - * @brief 更新所有节点的可见性和可用性 - * @return 错误码 - */ -MenuErrCode menu_permission_update_all_nodes(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - // 遍历所有节点,更新可见性和可用性 - for (uint16_t i = 0; i < MENU_CONFIG_MAX_NODES; i++) { - if (core_ctx->nodes[i].flags.is_registered) { - menu_permission_update_node(core_ctx, &core_ctx->nodes[i]); - } - } - - return MENU_ERR_OK; -} - -/** - * @brief 获取角色信息 - * @param role_id 角色ID - * @return 角色结构体指针,NULL表示角色不存在 - */ -const MenuRole* menu_permission_get_role(MenuRoleId role_id) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - int index; - - if (core_ctx == NULL) { - return NULL; - } - - index = menu_permission_get_role_index(core_ctx, role_id); - if (index < 0) { - return NULL; - } - - return &core_ctx->permission_config.roles[index]; -} - -/* 私有函数实现 -----------------------------------------------------------------------------------------------------*/ - -/** - * @brief 获取角色在角色列表中的索引 - * @param core_ctx 菜单核心上下文 - * @param role_id 角色ID - * @return 角色索引,-1表示未找到 - */ -static int menu_permission_get_role_index(MenuCoreCtx* core_ctx, MenuRoleId role_id) -{ - if (core_ctx == NULL) { - return -1; - } - - // 遍历角色列表,查找匹配的角色ID - for (uint8_t i = 0; i < core_ctx->permission_config.role_count; i++) { - if (core_ctx->permission_config.roles[i].id == role_id) { - return i; - } - } - - return -1; -} - -/** - * @brief 更新单个节点的可见性和可用性 - * @param core_ctx 菜单核心上下文 - * @param node 节点指针 - * @return 错误码 - */ -static MenuErrCode menu_permission_update_node(MenuCoreCtx* core_ctx, MenuNode* node) -{ - int role_index; - bool is_accessible; - - if (core_ctx == NULL || node == NULL) { - return MENU_ERR_INVALID_PARAM; - } - - // 获取当前角色索引 - role_index = menu_permission_get_role_index(core_ctx, core_ctx->permission_config.current_role); - if (role_index < 0) { - // 角色不存在,禁用节点 - node->flags.is_visible = false; - node->flags.is_enabled = false; - return MENU_ERR_OK; - } - - // 检查节点是否可访问 - is_accessible = (node->permission_level <= core_ctx->permission_config.roles[role_index].max_level); - - // 更新节点的可见性和可用性 - node->flags.is_visible = is_accessible; - node->flags.is_enabled = is_accessible; - - return MENU_ERR_OK; -} - -#endif /* MENU_CONFIG_ENABLE_PERMISSION */ diff --git a/src/core/menu_permission.h b/src/core/menu_permission.h deleted file mode 100644 index 0fa7329..0000000 --- a/src/core/menu_permission.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_permission.h - * @brief 菜单组件权限管理功能声明 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_PERMISSION_H -#define MENU_PERMISSION_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_types.h" - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_PERMISSION - -/** - * @brief 初始化权限管理模块 - * @return 错误码 - */ -MenuErrCode menu_permission_init(void); - -/** - * @brief 反初始化权限管理模块 - * @return 错误码 - */ -MenuErrCode menu_permission_deinit(void); - -/** - * @brief 注册角色 - * @param role 角色结构体指针 - * @return 错误码 - */ -MenuErrCode menu_permission_register_role(const MenuRole* role); - -/** - * @brief 注销角色 - * @param role_id 角色ID - * @return 错误码 - */ -MenuErrCode menu_permission_unregister_role(MenuRoleId role_id); - -/** - * @brief 设置当前角色 - * @param role_id 角色ID - * @return 错误码 - */ -MenuErrCode menu_permission_set_current_role(MenuRoleId role_id); - -/** - * @brief 获取当前角色 - * @return 当前角色ID - */ -MenuRoleId menu_permission_get_current_role(void); - -/** - * @brief 检查节点是否可访问 - * @param node_id 节点ID - * @return true表示可访问,false表示不可访问 - */ -bool menu_permission_check_node_access(MenuNodeId node_id); - -/** - * @brief 更新节点权限级别 - * @param node_id 节点ID - * @param permission_level 权限级别 - * @return 错误码 - */ -MenuErrCode menu_permission_update_node_level(MenuNodeId node_id, MenuPermissionLevel permission_level); - -/** - * @brief 获取节点权限级别 - * @param node_id 节点ID - * @return 节点权限级别 - */ -MenuPermissionLevel menu_permission_get_node_level(MenuNodeId node_id); - -/** - * @brief 更新所有节点的可见性和可用性 - * @return 错误码 - */ -MenuErrCode menu_permission_update_all_nodes(void); - -/** - * @brief 获取角色信息 - * @param role_id 角色ID - * @return 角色结构体指针,NULL表示角色不存在 - */ -const MenuRole* menu_permission_get_role(MenuRoleId role_id); - -#endif /* MENU_CONFIG_ENABLE_PERMISSION */ - -#endif /* MENU_PERMISSION_H */ diff --git a/src/core/menu_persistence.c b/src/core/menu_persistence.c deleted file mode 100644 index f38fd8d..0000000 --- a/src/core/menu_persistence.c +++ /dev/null @@ -1,441 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_persistence.c - * @brief 菜单组件状态持久化功能实现 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_persistence.h" - -/* 私有函数原型 -----------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_PERSISTENCE - -/** - * @brief 构建持久化数据 - * @param core_ctx 菜单核心上下文 - * @param data 持久化数据指针 - * @return 错误码 - */ -static MenuErrCode menu_persistence_build_data(MenuCoreCtx* core_ctx, MenuPersistenceData* data); - -/** - * @brief 应用持久化数据 - * @param core_ctx 菜单核心上下文 - * @param data 持久化数据指针 - * @return 错误码 - */ -static MenuErrCode menu_persistence_apply_data(MenuCoreCtx* core_ctx, const MenuPersistenceData* data); - -/** - * @brief 加密持久化数据 - * @param data 要加密的数据 - * @param size 数据大小 - * @return 错误码 - */ -static MenuErrCode menu_persistence_encrypt(uint8_t* data, uint16_t size); - -/** - * @brief 解密持久化数据 - * @param data 要解密的数据 - * @param size 数据大小 - * @return 错误码 - */ -static MenuErrCode menu_persistence_decrypt(uint8_t* data, uint16_t size); - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化状态持久化模块 - * @return 错误码 - */ -MenuErrCode menu_persistence_init(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - // 初始化持久化配置 - core_ctx->persistence_config.auto_save_enabled = true; - core_ctx->persistence_config.auto_save_interval = MENU_CONFIG_PERSISTENCE_AUTO_SAVE_INTERVAL; - core_ctx->persistence_config.last_save_tick = 0; - core_ctx->persistence_config.encrypt_enabled = (MENU_CONFIG_PERSISTENCE_ENABLE_ENCRYPT == 1U); - core_ctx->persistence_config.save_cb = NULL; - core_ctx->persistence_config.restore_cb = NULL; - - return MENU_ERR_OK; -} - -/** - * @brief 反初始化状态持久化模块 - * @return 错误码 - */ -MenuErrCode menu_persistence_deinit(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - // 清空持久化配置 - core_ctx->persistence_config.save_cb = NULL; - core_ctx->persistence_config.restore_cb = NULL; - - return MENU_ERR_OK; -} - -/** - * @brief 注册持久化回调函数 - * @param save_cb 保存回调函数 - * @param restore_cb 恢复回调函数 - * @return 错误码 - */ -MenuErrCode menu_persistence_register_callback(MenuPersistenceCallback save_cb, MenuRestoreCallback restore_cb) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - // 注册回调函数 - core_ctx->persistence_config.save_cb = save_cb; - core_ctx->persistence_config.restore_cb = restore_cb; - - return MENU_ERR_OK; -} - -/** - * @brief 启用或禁用自动保存 - * @param enable true表示启用,false表示禁用 - * @return 错误码 - */ -MenuErrCode menu_persistence_set_auto_save(bool enable) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - core_ctx->persistence_config.auto_save_enabled = enable; - - return MENU_ERR_OK; -} - -/** - * @brief 获取自动保存状态 - * @return true表示启用,false表示禁用 - */ -bool menu_persistence_get_auto_save(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return false; - } - - return core_ctx->persistence_config.auto_save_enabled; -} - -/** - * @brief 设置自动保存间隔 - * @param interval 自动保存间隔(ms) - * @return 错误码 - */ -MenuErrCode menu_persistence_set_auto_save_interval(uint32_t interval) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - core_ctx->persistence_config.auto_save_interval = interval; - - return MENU_ERR_OK; -} - -/** - * @brief 获取自动保存间隔 - * @return 自动保存间隔(ms) - */ -uint32_t menu_persistence_get_auto_save_interval(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return 0; - } - - return core_ctx->persistence_config.auto_save_interval; -} - -/** - * @brief 手动保存菜单状态 - * @return 错误码 - */ -MenuErrCode menu_persistence_save(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - MenuPersistenceData data; - uint8_t* data_buf; - uint16_t data_size = sizeof(MenuPersistenceData); - MenuErrCode ret; - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - if (core_ctx->persistence_config.save_cb == NULL) { - return MENU_ERR_INVALID_CALLBACK; - } - - // 构建持久化数据 - ret = menu_persistence_build_data(core_ctx, &data); - if (ret != MENU_ERR_OK) { - return ret; - } - - // 转换为字节数组 - data_buf = (uint8_t*)&data; - - // 如果启用加密,加密数据 - if (core_ctx->persistence_config.encrypt_enabled) { - ret = menu_persistence_encrypt(data_buf, data_size); - if (ret != MENU_ERR_OK) { - return ret; - } - } - - // 调用保存回调函数 - ret = core_ctx->persistence_config.save_cb(data_buf, data_size); - if (ret == MENU_ERR_OK) { - // 更新上次保存时间 - core_ctx->persistence_config.last_save_tick = core_ctx->last_refresh_tick; - } - - return ret; -} - -/** - * @brief 恢复菜单状态 - * @return 错误码 - */ -MenuErrCode menu_persistence_restore(void) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - uint8_t data_buf[MENU_CONFIG_PERSISTENCE_MAX_SIZE]; - uint16_t data_size = sizeof(MenuPersistenceData); - MenuPersistenceData* data = (MenuPersistenceData*)data_buf; - MenuErrCode ret; - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - if (core_ctx->persistence_config.restore_cb == NULL) { - return MENU_ERR_INVALID_CALLBACK; - } - - // 调用恢复回调函数 - ret = core_ctx->persistence_config.restore_cb(data_buf, &data_size); - if (ret != MENU_ERR_OK) { - return ret; - } - - // 检查数据大小是否正确 - if (data_size != sizeof(MenuPersistenceData)) { - return MENU_ERR_INVALID_PARAM; - } - - // 如果启用加密,解密数据 - if (core_ctx->persistence_config.encrypt_enabled) { - ret = menu_persistence_decrypt(data_buf, data_size); - if (ret != MENU_ERR_OK) { - return ret; - } - } - - // 检查数据是否有效 - if (!menu_persistence_check_data_valid(data_buf, data_size)) { - return MENU_ERR_INVALID_PARAM; - } - - // 应用持久化数据 - return menu_persistence_apply_data(core_ctx, data); -} - -/** - * @brief 检查持久化数据是否有效 - * @param data 持久化数据 - * @param size 数据大小 - * @return true表示有效,false表示无效 - */ -bool menu_persistence_check_data_valid(const uint8_t* data, uint16_t size) -{ - const MenuPersistenceData* persistence_data; - uint8_t calculated_checksum; - - if (data == NULL || size != sizeof(MenuPersistenceData)) { - return false; - } - - persistence_data = (const MenuPersistenceData*)data; - - // 计算校验和 - calculated_checksum = menu_persistence_calculate_checksum(data, size - sizeof(uint8_t)); - - // 检查校验和 - return (calculated_checksum == persistence_data->checksum); -} - -/** - * @brief 处理自动保存(由菜单主循环调用) - * @param tick 当前系统时间(ms) - * @return 错误码 - */ -MenuErrCode menu_persistence_process_auto_save(uint32_t tick) -{ - MenuCoreCtx* core_ctx = menu_get_core_ctx(); - - if (core_ctx == NULL) { - return MENU_ERR_NOT_INITIALIZED; - } - - // 如果启用自动保存,检查是否需要保存 - if (core_ctx->persistence_config.auto_save_enabled) { - if ((tick - core_ctx->persistence_config.last_save_tick) >= core_ctx->persistence_config.auto_save_interval) { - return menu_persistence_save(); - } - } - - return MENU_ERR_OK; -} - -/** - * @brief 计算数据校验和 - * @param data 数据指针 - * @param size 数据大小 - * @return 校验和 - */ -uint8_t menu_persistence_calculate_checksum(const uint8_t* data, uint16_t size) -{ - uint8_t checksum = 0; - - if (data == NULL || size == 0) { - return checksum; - } - - // 计算简单的异或校验和 - for (uint16_t i = 0; i < size; i++) { - checksum ^= data[i]; - } - - return checksum; -} - -/* 私有函数实现 -----------------------------------------------------------------------------------------------------*/ - -/** - * @brief 构建持久化数据 - * @param core_ctx 菜单核心上下文 - * @param data 持久化数据指针 - * @return 错误码 - */ -static MenuErrCode menu_persistence_build_data(MenuCoreCtx* core_ctx, MenuPersistenceData* data) -{ - if (core_ctx == NULL || data == NULL) { - return MENU_ERR_INVALID_PARAM; - } - - // 填充持久化数据 - data->current_node_id = core_ctx->current_node_id; - data->current_state = core_ctx->current_state; - data->nav_path = core_ctx->nav_path; - data->stack = core_ctx->stack; - data->timestamp = core_ctx->last_refresh_tick; - - // 计算校验和(不包括校验和字段本身) - data->checksum = menu_persistence_calculate_checksum((uint8_t*)data, sizeof(MenuPersistenceData) - sizeof(uint8_t)); - - return MENU_ERR_OK; -} - -/** - * @brief 应用持久化数据 - * @param core_ctx 菜单核心上下文 - * @param data 持久化数据指针 - * @return 错误码 - */ -static MenuErrCode menu_persistence_apply_data(MenuCoreCtx* core_ctx, const MenuPersistenceData* data) -{ - if (core_ctx == NULL || data == NULL) { - return MENU_ERR_INVALID_PARAM; - } - - // 恢复菜单状态 - core_ctx->current_node_id = data->current_node_id; - core_ctx->current_state = data->current_state; - core_ctx->nav_path = data->nav_path; - core_ctx->stack = data->stack; - - return MENU_ERR_OK; -} - -/** - * @brief 加密持久化数据 - * @param data 要加密的数据 - * @param size 数据大小 - * @return 错误码 - */ -static MenuErrCode menu_persistence_encrypt(uint8_t* data, uint16_t size) -{ - // 简单的XOR加密实现 - // 实际应用中应使用更安全的加密算法 - uint8_t key = 0xA5; // 加密密钥 - - if (data == NULL || size == 0) { - return MENU_ERR_INVALID_PARAM; - } - - for (uint16_t i = 0; i < size; i++) { - data[i] ^= key; - key = (key + data[i]) % 256; // 动态更新密钥 - } - - return MENU_ERR_OK; -} - -/** - * @brief 解密持久化数据 - * @param data 要解密的数据 - * @param size 数据大小 - * @return 错误码 - */ -static MenuErrCode menu_persistence_decrypt(uint8_t* data, uint16_t size) -{ - // 简单的XOR解密实现(与加密算法对称) - uint8_t key = 0xA5; // 解密密钥 - uint8_t temp; - - if (data == NULL || size == 0) { - return MENU_ERR_INVALID_PARAM; - } - - for (uint16_t i = 0; i < size; i++) { - temp = data[i]; - data[i] ^= key; - key = (key + temp) % 256; // 动态更新密钥 - } - - return MENU_ERR_OK; -} - -#endif /* MENU_CONFIG_ENABLE_PERSISTENCE */ diff --git a/src/core/menu_persistence.h b/src/core/menu_persistence.h deleted file mode 100644 index 92d44d4..0000000 --- a/src/core/menu_persistence.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_persistence.h - * @brief 菜单组件状态持久化功能声明 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_PERSISTENCE_H -#define MENU_PERSISTENCE_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_types.h" - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_PERSISTENCE - -/** - * @brief 初始化状态持久化模块 - * @return 错误码 - */ -MenuErrCode menu_persistence_init(void); - -/** - * @brief 反初始化状态持久化模块 - * @return 错误码 - */ -MenuErrCode menu_persistence_deinit(void); - -/** - * @brief 注册持久化回调函数 - * @param save_cb 保存回调函数 - * @param restore_cb 恢复回调函数 - * @return 错误码 - */ -MenuErrCode menu_persistence_register_callback(MenuPersistenceCallback save_cb, MenuRestoreCallback restore_cb); - -/** - * @brief 启用或禁用自动保存 - * @param enable true表示启用,false表示禁用 - * @return 错误码 - */ -MenuErrCode menu_persistence_set_auto_save(bool enable); - -/** - * @brief 获取自动保存状态 - * @return true表示启用,false表示禁用 - */ -bool menu_persistence_get_auto_save(void); - -/** - * @brief 设置自动保存间隔 - * @param interval 自动保存间隔(ms) - * @return 错误码 - */ -MenuErrCode menu_persistence_set_auto_save_interval(uint32_t interval); - -/** - * @brief 获取自动保存间隔 - * @return 自动保存间隔(ms) - */ -uint32_t menu_persistence_get_auto_save_interval(void); - -/** - * @brief 手动保存菜单状态 - * @return 错误码 - */ -MenuErrCode menu_persistence_save(void); - -/** - * @brief 恢复菜单状态 - * @return 错误码 - */ -MenuErrCode menu_persistence_restore(void); - -/** - * @brief 检查持久化数据是否有效 - * @param data 持久化数据 - * @param size 数据大小 - * @return true表示有效,false表示无效 - */ -bool menu_persistence_check_data_valid(const uint8_t* data, uint16_t size); - -/** - * @brief 处理自动保存(由菜单主循环调用) - * @param tick 当前系统时间(ms) - * @return 错误码 - */ -MenuErrCode menu_persistence_process_auto_save(uint32_t tick); - -/** - * @brief 计算数据校验和 - * @param data 数据指针 - * @param size 数据大小 - * @return 校验和 - */ -uint8_t menu_persistence_calculate_checksum(const uint8_t* data, uint16_t size); - -#endif /* MENU_CONFIG_ENABLE_PERSISTENCE */ - -#endif /* MENU_PERSISTENCE_H */ diff --git a/src/core/menu_stack.c b/src/core/menu_stack.c deleted file mode 100644 index 01044a1..0000000 --- a/src/core/menu_stack.c +++ /dev/null @@ -1,215 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_stack.c - * @brief 菜单组件栈管理实现 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_types.h" - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化菜单栈 - * @param stack 栈指针 - * @param max_depth 最大深度 - */ -void menu_stack_init(MenuStack* stack, uint8_t max_depth) -{ - MENU_ASSERT(stack != NULL); - - stack->top = 0; - stack->max_depth = max_depth; - - // 初始化栈元素为0 - for (uint8_t i = 0; i < max_depth; i++) { - stack->items[i] = 0; - } -} - -/** - * @brief 检查栈是否为空 - * @param stack 栈指针 - * @return true为空,false不为空 - */ -bool menu_stack_is_empty(const MenuStack* stack) -{ - MENU_ASSERT(stack != NULL); - return (stack->top == 0); -} - -/** - * @brief 检查栈是否已满 - * @param stack 栈指针 - * @return true已满,false未满 - */ -bool menu_stack_is_full(const MenuStack* stack) -{ - MENU_ASSERT(stack != NULL); - return (stack->top >= stack->max_depth); -} - -/** - * @brief 获取栈的当前深度 - * @param stack 栈指针 - * @return 当前深度 - */ -uint8_t menu_stack_get_depth(const MenuStack* stack) -{ - MENU_ASSERT(stack != NULL); - return stack->top; -} - -/** - * @brief 向栈中压入元素 - * @param stack 栈指针 - * @param node_id 要压入的节点ID - * @return 错误码 - */ -MenuErrCode menu_stack_push(MenuStack* stack, MenuNodeId node_id) -{ - MENU_ASSERT(stack != NULL); - - if (menu_stack_is_full(stack)) { - return MENU_ERR_OUT_OF_MEMORY; - } - - stack->items[stack->top] = node_id; - stack->top++; - - return MENU_ERR_OK; -} - -/** - * @brief 从栈中弹出元素 - * @param stack 栈指针 - * @param node_id 用于存储弹出的节点ID - * @return 错误码 - */ -MenuErrCode menu_stack_pop(MenuStack* stack, MenuNodeId* node_id) -{ - MENU_ASSERT(stack != NULL); - MENU_ASSERT(node_id != NULL); - - if (menu_stack_is_empty(stack)) { - return MENU_ERR_QUEUE_EMPTY; - } - - stack->top--; - *node_id = stack->items[stack->top]; - stack->items[stack->top] = 0; - - return MENU_ERR_OK; -} - -/** - * @brief 获取栈顶元素 - * @param stack 栈指针 - * @param node_id 用于存储栈顶节点ID - * @return 错误码 - */ -MenuErrCode menu_stack_peek(const MenuStack* stack, MenuNodeId* node_id) -{ - MENU_ASSERT(stack != NULL); - MENU_ASSERT(node_id != NULL); - - if (menu_stack_is_empty(stack)) { - return MENU_ERR_QUEUE_EMPTY; - } - - *node_id = stack->items[stack->top - 1]; - - return MENU_ERR_OK; -} - -/** - * @brief 清空栈 - * @param stack 栈指针 - */ -void menu_stack_clear(MenuStack* stack) -{ - MENU_ASSERT(stack != NULL); - - stack->top = 0; - - // 清空栈元素 - for (uint8_t i = 0; i < stack->max_depth; i++) { - stack->items[i] = 0; - } -} - -/** - * @brief 初始化菜单导航路径 - * @param nav_path 导航路径指针 - * @param max_depth 最大深度 - */ -void menu_nav_path_init(MenuNavPath* nav_path, uint8_t max_depth) -{ - MENU_ASSERT(nav_path != NULL); - - nav_path->depth = 0; - nav_path->max_depth = max_depth; - - // 初始化路径为0 - for (uint8_t i = 0; i < max_depth; i++) { - nav_path->path[i] = 0; - } -} - -/** - * @brief 添加导航路径节点 - * @param nav_path 导航路径指针 - * @param node_id 要添加的节点ID - * @return 错误码 - */ -MenuErrCode menu_nav_path_add(MenuNavPath* nav_path, MenuNodeId node_id) -{ - MENU_ASSERT(nav_path != NULL); - - if (nav_path->depth >= nav_path->max_depth) { - return MENU_ERR_OUT_OF_MEMORY; - } - - nav_path->path[nav_path->depth] = node_id; - nav_path->depth++; - - return MENU_ERR_OK; -} - -/** - * @brief 移除导航路径最后一个节点 - * @param nav_path 导航路径指针 - * @return 错误码 - */ -MenuErrCode menu_nav_path_remove_last(MenuNavPath* nav_path) -{ - MENU_ASSERT(nav_path != NULL); - - if (nav_path->depth == 0) { - return MENU_ERR_QUEUE_EMPTY; - } - - nav_path->depth--; - nav_path->path[nav_path->depth] = 0; - - return MENU_ERR_OK; -} - -/** - * @brief 清空导航路径 - * @param nav_path 导航路径指针 - */ -void menu_nav_path_clear(MenuNavPath* nav_path) -{ - MENU_ASSERT(nav_path != NULL); - - nav_path->depth = 0; - - // 清空路径 - for (uint8_t i = 0; i < nav_path->max_depth; i++) { - nav_path->path[i] = 0; - } -} diff --git a/src/core/menu_stack.h b/src/core/menu_stack.h deleted file mode 100644 index 1c08f10..0000000 --- a/src/core/menu_stack.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_stack.h - * @brief 菜单组件栈管理功能声明 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_STACK_H -#define MENU_STACK_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_types.h" - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 初始化菜单栈 - * @param stack 栈指针 - * @param max_depth 最大深度 - */ -void menu_stack_init(MenuStack* stack, uint8_t max_depth); - -/** - * @brief 检查栈是否为空 - * @param stack 栈指针 - * @return true为空,false不为空 - */ -bool menu_stack_is_empty(const MenuStack* stack); - -/** - * @brief 检查栈是否已满 - * @param stack 栈指针 - * @return true已满,false未满 - */ -bool menu_stack_is_full(const MenuStack* stack); - -/** - * @brief 获取栈的当前深度 - * @param stack 栈指针 - * @return 当前深度 - */ -uint8_t menu_stack_get_depth(const MenuStack* stack); - -/** - * @brief 向栈中压入元素 - * @param stack 栈指针 - * @param node_id 要压入的节点ID - * @return 错误码 - */ -MenuErrCode menu_stack_push(MenuStack* stack, MenuNodeId node_id); - -/** - * @brief 从栈中弹出元素 - * @param stack 栈指针 - * @param node_id 用于存储弹出的节点ID - * @return 错误码 - */ -MenuErrCode menu_stack_pop(MenuStack* stack, MenuNodeId* node_id); - -/** - * @brief 获取栈顶元素 - * @param stack 栈指针 - * @param node_id 用于存储栈顶节点ID - * @return 错误码 - */ -MenuErrCode menu_stack_peek(const MenuStack* stack, MenuNodeId* node_id); - -/** - * @brief 清空栈 - * @param stack 栈指针 - */ -void menu_stack_clear(MenuStack* stack); - -/** - * @brief 初始化菜单导航路径 - * @param nav_path 导航路径指针 - * @param max_depth 最大深度 - */ -void menu_nav_path_init(MenuNavPath* nav_path, uint8_t max_depth); - -/** - * @brief 添加导航路径节点 - * @param nav_path 导航路径指针 - * @param node_id 要添加的节点ID - * @return 错误码 - */ -MenuErrCode menu_nav_path_add(MenuNavPath* nav_path, MenuNodeId node_id); - -/** - * @brief 移除导航路径最后一个节点 - * @param nav_path 导航路径指针 - * @return 错误码 - */ -MenuErrCode menu_nav_path_remove_last(MenuNavPath* nav_path); - -/** - * @brief 清空导航路径 - * @param nav_path 导航路径指针 - */ -void menu_nav_path_clear(MenuNavPath* nav_path); - -#endif /* MENU_STACK_H */ diff --git a/src/core/menu_types.h b/src/core/menu_types.h deleted file mode 100644 index 738432d..0000000 --- a/src/core/menu_types.h +++ /dev/null @@ -1,233 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_types.h - * @brief 菜单组件核心数据结构定义 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_TYPES_H -#define MENU_TYPES_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_config.h" - -/* 前置声明 ---------------------------------------------------------------------------------------------------------*/ -struct MenuNode; -struct MenuCoreCtx; -struct MenuEvent; -struct MenuStateTransition; - -/* 函数前向声明 -----------------------------------------------------------------------------------------------------*/ - -/** - * @brief 获取菜单核心上下文 - * @return 菜单核心上下文指针 - */ -struct MenuCoreCtx* menu_get_core_ctx(void); - -/* 回调函数类型定义 -------------------------------------------------------------------------------------------------*/ - -/** - * @brief 菜单进入回调函数类型 - * @param node_id 当前节点ID - * @param core_ctx 菜单核心上下文 - * @return 错误码 - */ -typedef MenuErrCode (*MenuCallback)(MenuNodeId node_id, struct MenuCoreCtx* core_ctx); - -/** - * @brief 状态转换动作函数类型 - * @param core_ctx 菜单核心上下文 - * @return 错误码 - */ -typedef MenuErrCode (*MenuStateAction)(struct MenuCoreCtx* core_ctx); - -/** - * @brief 持久化回调函数类型 - * @param data 要持久化的数据 - * @param size 数据大小 - * @return 错误码 - */ -typedef MenuErrCode (*MenuPersistenceCallback)(const uint8_t* data, uint16_t size); - -/** - * @brief 恢复回调函数类型 - * @param data 要恢复的数据 - * @param size 数据大小 - * @return 错误码 - */ -typedef MenuErrCode (*MenuRestoreCallback)(uint8_t* data, uint16_t* size); - -/* 权限管理相关定义 -------------------------------------------------------------------------------------------------*/ - -/** - * @brief 权限级别类型 - */ -typedef uint8_t MenuPermissionLevel; - -/** - * @brief 角色ID类型 - */ -typedef uint8_t MenuRoleId; - -/** - * @brief 角色结构体 - */ -typedef struct { - MenuRoleId id; ///< 角色ID - const char* name; ///< 角色名称 - MenuPermissionLevel max_level; ///< 该角色的最大权限级别 -} MenuRole; - -/** - * @brief 权限配置结构体 - */ -typedef struct { - MenuRoleId current_role; ///< 当前角色ID - MenuRole roles[MENU_CONFIG_PERMISSION_MAX_ROLES]; ///< 角色列表 - uint8_t role_count; ///< 角色数量 -} MenuPermissionConfig; - -/* 核心数据结构定义 -------------------------------------------------------------------------------------------------*/ - -/** - * @brief 菜单节点结构体 - */ -typedef struct MenuNode { - MenuNodeId id; ///< 节点ID(唯一) - MenuNodeId parent_id; ///< 父节点ID(根节点为0) - const char* name; ///< 菜单名称(或多语言索引) - MenuCallback enter_cb; ///< 进入回调 - MenuCallback exit_cb; ///< 退出回调 - MenuNodeId first_child_id; ///< 第一个子节点ID(替代指针) - MenuNodeId next_sibling_id; ///< 下一个兄弟节点ID(替代指针) - MenuNodeId prev_sibling_id; ///< 上一个兄弟节点ID(替代指针) - MenuNodeId hash_next_id; ///< 哈希表下一个节点ID(替代指针) - // 位域:减少内存占用 - struct { - bool is_registered : 1; ///< 是否已注册 - bool is_selected : 1; ///< 是否被选中 - bool is_visible : 1; ///< 是否可见 - bool is_enabled : 1; ///< 是否启用 - unsigned int reserved : 4; ///< 保留位 - } flags; -#if MENU_CONFIG_ENABLE_PARAM - uint16_t param_id; ///< 绑定的参数ID(启用参数时有效) -#endif -#if MENU_CONFIG_ENABLE_PERMISSION - MenuPermissionLevel permission_level; ///< 访问该菜单所需的权限级别 -#endif -} MenuNode; - -/** - * @brief 菜单事件结构体 - */ -typedef struct MenuEvent { - MenuEventType type; ///< 事件类型 - uint8_t priority; ///< 事件优先级(0-3,0最高) - MenuNodeId target_node_id; ///< 目标节点ID - void* data; ///< 事件数据 - uint32_t timestamp; ///< 事件时间戳 -} MenuEvent; - -/** - * @brief 菜单事件队列结构体 - */ -typedef struct MenuEventQueue { - MenuEvent buffer[MENU_CONFIG_EVENT_QUEUE_LEN]; ///< 队列缓冲区 - uint8_t head; ///< 入队指针 - uint8_t tail; ///< 出队指针 - uint8_t count; ///< 队列元素数量 - uint8_t reserved; ///< 保留字节,用于对齐 -} MenuEventQueue; - -/** - * @brief 菜单导航路径结构体 - */ -typedef struct MenuNavPath { - MenuNodeId path[MENU_CONFIG_STACK_DEPTH]; ///< 导航路径 - uint8_t depth; ///< 当前深度 - uint8_t max_depth; ///< 最大深度 -} MenuNavPath; - -/** - * @brief 菜单栈结构体 - */ -typedef struct MenuStack { - MenuNodeId items[MENU_CONFIG_STACK_DEPTH]; ///< 栈元素 - uint8_t top; ///< 栈顶指针 - uint8_t max_depth; ///< 最大深度 -} MenuStack; - -/* 状态持久化相关定义 -------------------------------------------------------------------------------------------------*/ - -/** - * @brief 持久化数据结构体 - */ -typedef struct { - MenuNodeId current_node_id; ///< 当前节点ID - MenuState current_state; ///< 当前菜单状态 - MenuNavPath nav_path; ///< 当前导航路径 - MenuStack stack; ///< 当前菜单栈 - uint32_t timestamp; ///< 持久化时间戳 - uint8_t checksum; ///< 数据校验和 -} MenuPersistenceData; - -/** - * @brief 持久化配置结构体 - */ -typedef struct { - bool auto_save_enabled; ///< 是否启用自动保存 - uint32_t auto_save_interval; ///< 自动保存间隔(ms) - uint32_t last_save_tick; ///< 上次保存时间 - bool encrypt_enabled; ///< 是否启用加密 - MenuPersistenceCallback save_cb; ///< 保存回调函数 - MenuRestoreCallback restore_cb; ///< 恢复回调函数 -} MenuPersistenceConfig; - -/** - * @brief 状态转换规则结构体 - */ -typedef struct MenuStateTransition { - MenuState current_state; ///< 当前状态 - MenuEventType event; ///< 触发事件 - MenuState next_state; ///< 下一个状态 - MenuStateAction action; ///< 状态转换动作 - const char* desc; ///< 状态转换描述(用于调试) -} MenuStateTransition; - -/** - * @brief 菜单核心上下文结构体 - */ -typedef struct MenuCoreCtx { - MenuNode nodes[MENU_CONFIG_MAX_NODES]; ///< 静态菜单节点池(无动态分配) - MenuNodeId hash_table[MENU_CONFIG_HASH_TABLE_SIZE]; ///< 哈希表,用于快速查找节点 - MenuStack stack; ///< 菜单导航栈 - MenuNavPath nav_path; ///< 菜单导航路径 - MenuEventQueue event_queue; ///< 事件队列 - MenuNodeId current_node_id; ///< 当前选中的节点ID - MenuState current_state; ///< 当前菜单状态 - uint32_t last_refresh_tick; ///< 上次刷新时间(ms) - bool is_initialized; ///< 是否已初始化 - MenuErrCode error_code; ///< 当前错误码 - const char* error_msg; ///< 当前错误信息 - uint16_t node_count; ///< 已注册节点数量 - uint16_t free_node_count; ///< 空闲节点数量 - // 状态机扩展 -#if MENU_CONFIG_ENABLE_STATE_MACHINE_EXT - MenuStateTransition custom_transitions[MENU_CONFIG_MAX_STATE_TRANSITIONS]; ///< 自定义状态转换规则 - uint16_t custom_transition_count; ///< 自定义状态转换规则数量 -#endif - // 权限管理 -#if MENU_CONFIG_ENABLE_PERMISSION - MenuPermissionConfig permission_config; ///< 权限配置 -#endif - // 状态持久化 -#if MENU_CONFIG_ENABLE_PERSISTENCE - MenuPersistenceConfig persistence_config; ///< 持久化配置 -#endif -} MenuCoreCtx; - -#endif /* MENU_TYPES_H */ diff --git a/src/lang/menu_lang.c b/src/lang/menu_lang.c deleted file mode 100644 index 09af110..0000000 --- a/src/lang/menu_lang.c +++ /dev/null @@ -1,228 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_lang.c - * @brief 菜单组件多语言支持模块实现 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_lang.h" - -/* 配置参数 ---------------------------------------------------------------------------------------------------------*/ -#define MENU_LANG_MAX_PACKS 8U /* 最大支持的语言包数量 */ - -/* 全局变量 ---------------------------------------------------------------------------------------------------------*/ -static const LangPack* sg_lang_packs[MENU_LANG_MAX_PACKS]; -static uint8_t sg_lang_pack_count = 0; -static LangId sg_current_lang_id = 0; - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_LANG - -/** - * @brief 初始化多语言支持模块 - * @return 错误码 - */ -MenuErrCode menu_lang_init(void) -{ - // 初始化语言包数组 - for (uint8_t i = 0; i < MENU_LANG_MAX_PACKS; i++) { - sg_lang_packs[i] = NULL; - } - - sg_lang_pack_count = 0; - sg_current_lang_id = 0; - return MENU_ERR_OK; -} - -/** - * @brief 反初始化多语言支持模块 - * @return 错误码 - */ -MenuErrCode menu_lang_deinit(void) -{ - sg_lang_pack_count = 0; - return MENU_ERR_OK; -} - -/** - * @brief 设置当前语言 - * @param lang_id 语言ID - * @return 错误码 - */ -MenuErrCode menu_lang_set_current(LangId lang_id) -{ - // 检查语言包是否已注册 - bool found = false; - for (uint8_t i = 0; i < sg_lang_pack_count; i++) { - if (sg_lang_packs[i]->id == lang_id) { - found = true; - break; - } - } - - if (!found) { - return MENU_ERR_INVALID_PARAM; - } - - sg_current_lang_id = lang_id; - return MENU_ERR_OK; -} - -/** - * @brief 获取当前语言ID - * @return 当前语言ID - */ -LangId menu_lang_get_current(void) -{ - return sg_current_lang_id; -} - -/** - * @brief 查找语言包 - * @param lang_id 语言ID - * @return 语言包指针,未找到返回NULL - */ -static const LangPack* menu_lang_find_pack_internal(LangId lang_id) -{ - for (uint8_t i = 0; i < sg_lang_pack_count; i++) { - if (sg_lang_packs[i]->id == lang_id) { - return sg_lang_packs[i]; - } - } - return NULL; -} - -/** - * @brief 注册语言包 - * @param pack 语言包指针 - * @return 错误码 - */ -MenuErrCode menu_lang_register_pack(const LangPack* pack) -{ - if (pack == NULL) { - return MENU_ERR_INVALID_PARAM; - } - - // 检查语言包是否已存在 - if (menu_lang_find_pack_internal(pack->id) != NULL) { - return MENU_ERR_OPERATION_FAILED; - } - - // 检查语言包数量是否超过最大值 - if (sg_lang_pack_count >= MENU_LANG_MAX_PACKS) { - return MENU_ERR_OUT_OF_MEMORY; - } - - // 注册语言包 - sg_lang_packs[sg_lang_pack_count] = pack; - sg_lang_pack_count++; - - return MENU_ERR_OK; -} - -/** - * @brief 注销语言包 - * @param lang_id 语言ID - * @return 错误码 - */ -MenuErrCode menu_lang_unregister_pack(LangId lang_id) -{ - // 查找语言包在数组中的位置 - uint8_t index = 0; - bool found = false; - - for (index = 0; index < sg_lang_pack_count; index++) { - if (sg_lang_packs[index]->id == lang_id) { - found = true; - break; - } - } - - if (!found) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 将后续语言包前移 - for (uint8_t i = index; i < sg_lang_pack_count - 1; i++) { - sg_lang_packs[i] = sg_lang_packs[i + 1]; - } - - sg_lang_pack_count--; - - // 如果当前语言被注销,切换到第一个语言包 - if (sg_current_lang_id == lang_id && sg_lang_pack_count > 0) { - sg_current_lang_id = sg_lang_packs[0]->id; - } - - return MENU_ERR_OK; -} - -/** - * @brief 根据字符串ID获取当前语言的字符串 - * @param str_id 字符串ID - * @return 字符串指针,未找到返回NULL - */ -const char* menu_lang_get_str(StrId str_id) -{ - // 获取当前语言包 - const LangPack* pack = menu_lang_find_pack_internal(sg_current_lang_id); - if (pack == NULL) { - return NULL; - } - - // 在当前语言包中查找字符串 - for (uint16_t i = 0; i < pack->string_count; i++) { - if (pack->strings[i].id == str_id) { - return pack->strings[i].str; - } - } - - // 如果在当前语言包中未找到,尝试在第一个语言包中查找 - if (sg_lang_pack_count > 0 && pack != sg_lang_packs[0]) { - pack = sg_lang_packs[0]; - for (uint16_t i = 0; i < pack->string_count; i++) { - if (pack->strings[i].id == str_id) { - return pack->strings[i].str; - } - } - } - - return NULL; -} - -/** - * @brief 加载语言包 - * @param pack 语言包指针 - * @return 错误码 - */ -MenuErrCode menu_lang_load_pack(const LangPack* pack) -{ - if (pack == NULL) { - return MENU_ERR_INVALID_PARAM; - } - - // 注册语言包 - MenuErrCode err = menu_lang_register_pack(pack); - if (err != MENU_ERR_OK) { - return err; - } - - // 设置为当前语言 - return menu_lang_set_current(pack->id); -} - -/** - * @brief 查找语言包 - * @param lang_id 语言ID - * @return 语言包指针,未找到返回NULL - */ -const LangPack* menu_lang_find_pack(LangId lang_id) -{ - return menu_lang_find_pack_internal(lang_id); -} - -#endif /* MENU_CONFIG_ENABLE_LANG */ diff --git a/src/lang/menu_lang.h b/src/lang/menu_lang.h deleted file mode 100644 index 606c8a2..0000000 --- a/src/lang/menu_lang.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_lang.h - * @brief 菜单组件多语言支持模块 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_LANG_H -#define MENU_LANG_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "../core/menu_config.h" - -/* 类型定义 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 语言ID类型 - */ -typedef uint8_t LangId; - -/** - * @brief 字符串ID类型 - */ -typedef uint16_t StrId; - -/** - * @brief 字符串项结构体 - */ -typedef struct { - StrId id; ///< 字符串ID - const char* str; ///< 字符串内容 -} LangStrItem; - -/** - * @brief 语言包结构体 - */ -typedef struct { - LangId id; ///< 语言ID - const char* name; ///< 语言名称(如"English"、"中文") - const LangStrItem* strings; ///< 字符串数组 - uint16_t string_count; ///< 字符串数量 -} LangPack; - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_LANG - -/** - * @brief 初始化多语言支持模块 - * @return 错误码 - */ -MenuErrCode menu_lang_init(void); - -/** - * @brief 反初始化多语言支持模块 - * @return 错误码 - */ -MenuErrCode menu_lang_deinit(void); - -/** - * @brief 设置当前语言 - * @param lang_id 语言ID - * @return 错误码 - */ -MenuErrCode menu_lang_set_current(LangId lang_id); - -/** - * @brief 获取当前语言ID - * @return 当前语言ID - */ -LangId menu_lang_get_current(void); - -/** - * @brief 注册语言包 - * @param pack 语言包指针 - * @return 错误码 - */ -MenuErrCode menu_lang_register_pack(const LangPack* pack); - -/** - * @brief 注销语言包 - * @param lang_id 语言ID - * @return 错误码 - */ -MenuErrCode menu_lang_unregister_pack(LangId lang_id); - -/** - * @brief 根据字符串ID获取当前语言的字符串 - * @param str_id 字符串ID - * @return 字符串指针,未找到返回NULL - */ -const char* menu_lang_get_str(StrId str_id); - -/** - * @brief 加载语言包 - * @param pack 语言包指针 - * @return 错误码 - */ -MenuErrCode menu_lang_load_pack(const LangPack* pack); - -/** - * @brief 查找语言包 - * @param lang_id 语言ID - * @return 语言包指针,未找到返回NULL - */ -const LangPack* menu_lang_find_pack(LangId lang_id); - -#else /* MENU_CONFIG_ENABLE_LANG */ - -/* 多语言功能未启用时的空实现 */ -#define menu_lang_init() MENU_ERR_OK -#define menu_lang_deinit() MENU_ERR_OK -#define menu_lang_set_current(...) MENU_ERR_OK -#define menu_lang_get_current() 0 -#define menu_lang_register_pack(...) MENU_ERR_OK -#define menu_lang_unregister_pack(...) MENU_ERR_OK -#define menu_lang_get_str(id) "" -#define menu_lang_load_pack(...) MENU_ERR_OK -#define menu_lang_find_pack(...) NULL - -#endif /* MENU_CONFIG_ENABLE_LANG */ - -#endif /* MENU_LANG_H */ diff --git a/src/param/menu_param.c b/src/param/menu_param.c deleted file mode 100644 index a483514..0000000 --- a/src/param/menu_param.c +++ /dev/null @@ -1,397 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_param.c - * @brief 菜单组件参数管理模块实现 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "menu_param.h" -#include "../core/menu_hash.h" - -/* 配置参数 ---------------------------------------------------------------------------------------------------------*/ -#define MENU_PARAM_MAX_NUM 32U /* 最大参数数量 */ - -/* 全局变量 ---------------------------------------------------------------------------------------------------------*/ -static MenuParam sg_menu_params[MENU_PARAM_MAX_NUM]; -static uint16_t sg_menu_param_count = 0; - -/* 函数实现 ---------------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_PARAM - -/** - * @brief 初始化参数管理模块 - * @return 错误码 - */ -MenuErrCode menu_param_init(void) -{ - // 初始化参数数组 - for (uint16_t i = 0; i < MENU_PARAM_MAX_NUM; i++) { - sg_menu_params[i].id = 0; - sg_menu_params[i].name = NULL; - sg_menu_params[i].type = PARAM_TYPE_UINT8; - sg_menu_params[i].value = NULL; - sg_menu_params[i].default_value = NULL; - sg_menu_params[i].min_value = NULL; - sg_menu_params[i].max_value = NULL; - sg_menu_params[i].is_read_only = false; - sg_menu_params[i].is_modified = false; - } - - sg_menu_param_count = 0; - return MENU_ERR_OK; -} - -/** - * @brief 反初始化参数管理模块 - * @return 错误码 - */ -MenuErrCode menu_param_deinit(void) -{ - sg_menu_param_count = 0; - return MENU_ERR_OK; -} - -/** - * @brief 查找参数 - * @param id 参数ID - * @return 参数指针,未找到返回NULL - */ -MenuParam* menu_param_find_internal(uint16_t id) -{ - for (uint16_t i = 0; i < sg_menu_param_count; i++) { - if (sg_menu_params[i].id == id) { - return &sg_menu_params[i]; - } - } - return NULL; -} - -/** - * @brief 注册参数 - * @param id 参数ID - * @param name 参数名称 - * @param type 参数类型 - * @param value 参数值指针 - * @param default_value 默认值指针 - * @param min_value 最小值指针 - * @param max_value 最大值指针 - * @param is_read_only 是否只读 - * @return 错误码 - */ -MenuErrCode menu_param_register(uint16_t id, const char* name, ParamType type, void* value, void* default_value, void* min_value, void* max_value, bool is_read_only) -{ - // 检查参数ID是否已存在 - if (menu_param_find_internal(id) != NULL) { - return MENU_ERR_OPERATION_FAILED; - } - - // 检查参数数量是否超过最大值 - if (sg_menu_param_count >= MENU_PARAM_MAX_NUM) { - return MENU_ERR_OUT_OF_MEMORY; - } - - // 检查参数值指针是否有效 - if (value == NULL) { - return MENU_ERR_INVALID_PARAM; - } - - // 注册参数 - MenuParam* param = &sg_menu_params[sg_menu_param_count]; - param->id = id; - param->name = name; - param->type = type; - param->value = value; - param->default_value = default_value; - param->min_value = min_value; - param->max_value = max_value; - param->is_read_only = is_read_only; - param->is_modified = false; - - sg_menu_param_count++; - return MENU_ERR_OK; -} - -/** - * @brief 注销参数 - * @param id 参数ID - * @return 错误码 - */ -MenuErrCode menu_param_unregister(uint16_t id) -{ - MenuParam* param = menu_param_find_internal(id); - if (param == NULL) { - return MENU_ERR_NODE_NOT_FOUND; - } - - // 查找参数在数组中的位置 - uint16_t index = 0; - for (index = 0; index < sg_menu_param_count; index++) { - if (sg_menu_params[index].id == id) { - break; - } - } - - // 将后续参数前移 - for (uint16_t i = index; i < sg_menu_param_count - 1; i++) { - sg_menu_params[i] = sg_menu_params[i + 1]; - } - - sg_menu_param_count--; - return MENU_ERR_OK; -} - -/** - * @brief 获取参数值 - * @param id 参数ID - * @param value 用于存储参数值的指针 - * @return 错误码 - */ -MenuErrCode menu_param_get_value(uint16_t id, void* value) -{ - MenuParam* param = menu_param_find_internal(id); - if (param == NULL) { - return MENU_ERR_NODE_NOT_FOUND; - } - - if (value == NULL) { - return MENU_ERR_INVALID_PARAM; - } - - // 根据参数类型获取值 - switch (param->type) { - case PARAM_TYPE_INT8: - *(int8_t*)value = *(int8_t*)param->value; - break; - case PARAM_TYPE_UINT8: - *(uint8_t*)value = *(uint8_t*)param->value; - break; - case PARAM_TYPE_INT16: - *(int16_t*)value = *(int16_t*)param->value; - break; - case PARAM_TYPE_UINT16: - *(uint16_t*)value = *(uint16_t*)param->value; - break; - case PARAM_TYPE_INT32: - *(int32_t*)value = *(int32_t*)param->value; - break; - case PARAM_TYPE_UINT32: - *(uint32_t*)value = *(uint32_t*)param->value; - break; - case PARAM_TYPE_FLOAT: - *(float*)value = *(float*)param->value; - break; - default: - return MENU_ERR_INVALID_STATE; - } - - return MENU_ERR_OK; -} - -/** - * @brief 检查参数值是否在允许范围内 - * @param param 参数指针 - * @param value 要检查的值 - * @return true为在范围内,false为超出范围 - */ -static bool menu_param_check_range(MenuParam* param, const void* value) -{ - if (param->min_value == NULL || param->max_value == NULL) { - return true; // 没有设置范围限制 - } - - switch (param->type) { - case PARAM_TYPE_INT8: - return (*(int8_t*)value >= *(int8_t*)param->min_value) && (*(int8_t*)value <= *(int8_t*)param->max_value); - case PARAM_TYPE_UINT8: - return (*(uint8_t*)value >= *(uint8_t*)param->min_value) && (*(uint8_t*)value <= *(uint8_t*)param->max_value); - case PARAM_TYPE_INT16: - return (*(int16_t*)value >= *(int16_t*)param->min_value) && (*(int16_t*)value <= *(int16_t*)param->max_value); - case PARAM_TYPE_UINT16: - return (*(uint16_t*)value >= *(uint16_t*)param->min_value) && (*(uint16_t*)value <= *(uint16_t*)param->max_value); - case PARAM_TYPE_INT32: - return (*(int32_t*)value >= *(int32_t*)param->min_value) && (*(int32_t*)value <= *(int32_t*)param->max_value); - case PARAM_TYPE_UINT32: - return (*(uint32_t*)value >= *(uint32_t*)param->min_value) && (*(uint32_t*)value <= *(uint32_t*)param->max_value); - case PARAM_TYPE_FLOAT: - return (*(float*)value >= *(float*)param->min_value) && (*(float*)value <= *(float*)param->max_value); - default: - return false; - } -} - -/** - * @brief 设置参数值 - * @param id 参数ID - * @param value 新的参数值 - * @return 错误码 - */ -MenuErrCode menu_param_set_value(uint16_t id, const void* value) -{ - MenuParam* param = menu_param_find_internal(id); - if (param == NULL) { - return MENU_ERR_NODE_NOT_FOUND; - } - - if (value == NULL) { - return MENU_ERR_INVALID_PARAM; - } - - // 检查参数是否只读 - if (param->is_read_only) { - return MENU_ERR_OPERATION_FAILED; - } - - // 检查参数值是否在允许范围内 - if (!menu_param_check_range(param, value)) { - return MENU_ERR_INVALID_PARAM; - } - - // 根据参数类型设置值 - switch (param->type) { - case PARAM_TYPE_INT8: - if (*(int8_t*)value != *(int8_t*)param->value) { - *(int8_t*)param->value = *(int8_t*)value; - param->is_modified = true; - } - break; - case PARAM_TYPE_UINT8: - if (*(uint8_t*)value != *(uint8_t*)param->value) { - *(uint8_t*)param->value = *(uint8_t*)value; - param->is_modified = true; - } - break; - case PARAM_TYPE_INT16: - if (*(int16_t*)value != *(int16_t*)param->value) { - *(int16_t*)param->value = *(int16_t*)value; - param->is_modified = true; - } - break; - case PARAM_TYPE_UINT16: - if (*(uint16_t*)value != *(uint16_t*)param->value) { - *(uint16_t*)param->value = *(uint16_t*)value; - param->is_modified = true; - } - break; - case PARAM_TYPE_INT32: - if (*(int32_t*)value != *(int32_t*)param->value) { - *(int32_t*)param->value = *(int32_t*)value; - param->is_modified = true; - } - break; - case PARAM_TYPE_UINT32: - if (*(uint32_t*)value != *(uint32_t*)param->value) { - *(uint32_t*)param->value = *(uint32_t*)value; - param->is_modified = true; - } - break; - case PARAM_TYPE_FLOAT: - if (*(float*)value != *(float*)param->value) { - *(float*)param->value = *(float*)value; - param->is_modified = true; - } - break; - default: - return MENU_ERR_INVALID_STATE; - } - - return MENU_ERR_OK; -} - -/** - * @brief 恢复参数默认值 - * @param id 参数ID - * @return 错误码 - */ -MenuErrCode menu_param_restore_default(uint16_t id) -{ - MenuParam* param = menu_param_find_internal(id); - if (param == NULL) { - return MENU_ERR_NODE_NOT_FOUND; - } - - if (param->default_value == NULL) { - return MENU_ERR_INVALID_PARAM; - } - - // 检查参数是否只读 - if (param->is_read_only) { - return MENU_ERR_OPERATION_FAILED; - } - - // 恢复默认值 - return menu_param_set_value(id, param->default_value); -} - -/** - * @brief 获取参数类型 - * @param id 参数ID - * @return 参数类型 - */ -ParamType menu_param_get_type(uint16_t id) -{ - MenuParam* param = menu_param_find_internal(id); - if (param != NULL) { - return param->type; - } - return PARAM_TYPE_UINT8; -} - -/** - * @brief 检查参数是否只读 - * @param id 参数ID - * @return true为只读,false为可写 - */ -bool menu_param_is_read_only(uint16_t id) -{ - MenuParam* param = menu_param_find_internal(id); - if (param != NULL) { - return param->is_read_only; - } - return false; -} - -/** - * @brief 检查参数是否已修改 - * @param id 参数ID - * @return true为已修改,false为未修改 - */ -bool menu_param_is_modified(uint16_t id) -{ - MenuParam* param = menu_param_find_internal(id); - if (param != NULL) { - return param->is_modified; - } - return false; -} - -/** - * @brief 清除参数修改标记 - * @param id 参数ID - * @return 错误码 - */ -MenuErrCode menu_param_clear_modified_flag(uint16_t id) -{ - MenuParam* param = menu_param_find_internal(id); - if (param == NULL) { - return MENU_ERR_NODE_NOT_FOUND; - } - - param->is_modified = false; - return MENU_ERR_OK; -} - -/** - * @brief 查找参数 - * @param id 参数ID - * @return 参数指针,未找到返回NULL - */ -const MenuParam* menu_param_find(uint16_t id) -{ - return menu_param_find_internal(id); -} - -#endif /* MENU_CONFIG_ENABLE_PARAM */ diff --git a/src/param/menu_param.h b/src/param/menu_param.h deleted file mode 100644 index 4c0ed46..0000000 --- a/src/param/menu_param.h +++ /dev/null @@ -1,159 +0,0 @@ -/** - ********************************************************************************************************************** - * @file menu_param.h - * @brief 菜单组件参数管理模块 - * @author menu_component - * @date 2025-12-19 - ********************************************************************************************************************** - */ - -#ifndef MENU_PARAM_H -#define MENU_PARAM_H - -/* Includes ----------------------------------------------------------------------------------------------------------*/ -#include "../core/menu_config.h" - -/* 类型定义 ---------------------------------------------------------------------------------------------------------*/ - -/** - * @brief 参数类型 - */ -typedef enum { - PARAM_TYPE_INT8, /*!< 8位有符号整数 */ - PARAM_TYPE_UINT8, /*!< 8位无符号整数 */ - PARAM_TYPE_INT16, /*!< 16位有符号整数 */ - PARAM_TYPE_UINT16, /*!< 16位无符号整数 */ - PARAM_TYPE_INT32, /*!< 32位有符号整数 */ - PARAM_TYPE_UINT32, /*!< 32位无符号整数 */ - PARAM_TYPE_FLOAT, /*!< 浮点数 */ -} ParamType; - -/** - * @brief 参数结构体 - */ -typedef struct { - uint16_t id; ///< 参数ID - const char* name; ///< 参数名称 - ParamType type; ///< 参数类型 - void* value; ///< 参数值指针 - void* default_value; ///< 默认值指针 - void* min_value; ///< 最小值指针 - void* max_value; ///< 最大值指针 - bool is_read_only; ///< 是否只读 - bool is_modified; ///< 是否已修改 -} MenuParam; - -/* 函数声明 ---------------------------------------------------------------------------------------------------------*/ - -#if MENU_CONFIG_ENABLE_PARAM - -/** - * @brief 初始化参数管理模块 - * @return 错误码 - */ -MenuErrCode menu_param_init(void); - -/** - * @brief 反初始化参数管理模块 - * @return 错误码 - */ -MenuErrCode menu_param_deinit(void); - -/** - * @brief 注册参数 - * @param id 参数ID - * @param name 参数名称 - * @param type 参数类型 - * @param value 参数值指针 - * @param default_value 默认值指针 - * @param min_value 最小值指针 - * @param max_value 最大值指针 - * @param is_read_only 是否只读 - * @return 错误码 - */ -MenuErrCode menu_param_register(uint16_t id, const char* name, ParamType type, void* value, void* default_value, void* min_value, void* max_value, bool is_read_only); - -/** - * @brief 注销参数 - * @param id 参数ID - * @return 错误码 - */ -MenuErrCode menu_param_unregister(uint16_t id); - -/** - * @brief 获取参数值 - * @param id 参数ID - * @param value 用于存储参数值的指针 - * @return 错误码 - */ -MenuErrCode menu_param_get_value(uint16_t id, void* value); - -/** - * @brief 设置参数值 - * @param id 参数ID - * @param value 新的参数值 - * @return 错误码 - */ -MenuErrCode menu_param_set_value(uint16_t id, const void* value); - -/** - * @brief 恢复参数默认值 - * @param id 参数ID - * @return 错误码 - */ -MenuErrCode menu_param_restore_default(uint16_t id); - -/** - * @brief 获取参数类型 - * @param id 参数ID - * @return 参数类型 - */ -ParamType menu_param_get_type(uint16_t id); - -/** - * @brief 检查参数是否只读 - * @param id 参数ID - * @return true为只读,false为可写 - */ -bool menu_param_is_read_only(uint16_t id); - -/** - * @brief 检查参数是否已修改 - * @param id 参数ID - * @return true为已修改,false为未修改 - */ -bool menu_param_is_modified(uint16_t id); - -/** - * @brief 清除参数修改标记 - * @param id 参数ID - * @return 错误码 - */ -MenuErrCode menu_param_clear_modified_flag(uint16_t id); - -/** - * @brief 查找参数 - * @param id 参数ID - * @return 参数指针,未找到返回NULL - */ -const MenuParam* menu_param_find(uint16_t id); - -#else /* MENU_CONFIG_ENABLE_PARAM */ - -/* 参数管理功能未启用时的空实现 */ -#define menu_param_init() MENU_ERR_OK -#define menu_param_deinit() MENU_ERR_OK -#define menu_param_register(...) MENU_ERR_OK -#define menu_param_unregister(...) MENU_ERR_OK -#define menu_param_get_value(...) MENU_ERR_OK -#define menu_param_set_value(...) MENU_ERR_OK -#define menu_param_restore_default(...) MENU_ERR_OK -#define menu_param_get_type(id) PARAM_TYPE_UINT8 -#define menu_param_is_read_only(id) false -#define menu_param_is_modified(id) false -#define menu_param_clear_modified_flag(...) MENU_ERR_OK -#define menu_param_find(id) NULL - -#endif /* MENU_CONFIG_ENABLE_PARAM */ - -#endif /* MENU_PARAM_H */ diff --git a/tools/menu_config.yaml b/tools/menu_config.yaml new file mode 100644 index 0000000..aa1c2ee --- /dev/null +++ b/tools/menu_config.yaml @@ -0,0 +1,1794 @@ +# 电磁启动器(电机保护型)菜单与参数配置文件(优化版) +# 适配场景:低压三相异步电机的启动、控制与综合保护 +# 核心特性:支持C代码自动生成、枚举复用、多语言、权限控制、硬件存储映射 +config: + # 多语言配置 + languages: + - code: en + name: English + alias: LANG_EN + - code: cn + name: Chinese + alias: LANG_CN + # 菜单全局属性 + default_language: cn # 默认中文 + menu_max_depth: 4 # 菜单最大嵌套深度 + default_permission_level: 0 # 0-操作员,1-管理员,2-厂家 + show_back_item: true # 显示返回项 + show_home_item: true # 显示主页项 + save_params_on_change: true # 参数修改后自动保存 + param_apply_delay: 1000 # 参数生效延时(ms) + # C代码自动生成配置(核心工程化配置) + c_code_gen: + enable: true + output_dir: ../output + header_prefix: menu_ + source_prefix: menu_ + type_mapping: + FLOAT: float + INT: int + ENUM: uint8_t + STRING: char + param_storage: + type: struct + struct_name: MenuParams + array_name: g_menu_params + eeprom_base_addr: 0 + function_naming: + prefix: menu_ + enter_suffix: _enter + exit_suffix: _exit + action_suffix: _action + display_suffix: _display + visible_suffix: _visible + constant_defs: + header_file: menu_constants.h + enum_prefix: ENUM_ + param_id_prefix: PARAM_ + menu_id_prefix: MENU_ + code_style: + indent: 4 + braces: k&r + line_length: 120 + comment_style: c99 + features: + generate_param_accessors: true + generate_menu_navigation: true + generate_action_functions: true + generate_display_functions: true + generate_enum_definitions: true + generate_constant_defines: true + generate_init_function: true + generate_save_load_functions: true + generate_visible_callbacks: true + +# 全局枚举模板(支持C代码生成,可复用) +enum_templates: + - template_id: SWITCH_TEMPLATE + name: + en: Switch + cn: 开关 + description: + en: Basic on/off switch template + cn: 基础开关模板 + enum_options: + 0: + alias: SWITCH_OFF + label: + en: 'Off' + cn: 关闭 + value: 0 + 1: + alias: SWITCH_ON + label: + en: 'On' + cn: 开启 + value: 1 + c_code: + typedef_name: SwitchType + enum_name: SwitchEnum + header_file: menu_enums.h + c_comment: 基础开关枚举类型(0=关闭,1=开启) + use_typedef: true + generate_constants: true + + - template_id: PROTECT_ENABLE_TEMPLATE + name: + en: Protection Enable + cn: 保护投退 + description: + en: Protection enable/disable template + cn: 保护功能投退模板 + enum_options: + 0: + alias: PROT_DISABLE + label: + en: Disable + cn: 退出 + value: 0 + 1: + alias: PROT_ENABLE + label: + en: Enable + cn: 投入 + value: 1 + c_code: + typedef_name: ProtectEnableType + enum_name: ProtectEnableEnum + header_file: menu_enums.h + c_comment: 保护功能投退枚举类型(0=退出,1=投入) + use_typedef: true + generate_constants: true + + - template_id: START_MODE_TEMPLATE + name: + en: Start Mode + cn: 启动方式 + description: + en: Motor start mode template + cn: 电机启动方式模板 + enum_options: + 0: + alias: START_DIRECT + label: + en: Direct Start + cn: 直接启动 + value: 0 + 1: + alias: START_STAR_DELTA + label: + en: Star-Delta Start + cn: 星三角启动 + value: 1 + 2: + alias: START_SOFT + label: + en: Soft Start + cn: 软启动 + value: 2 + c_code: + typedef_name: StartModeType + enum_name: StartModeEnum + header_file: menu_enums.h + c_comment: 电机启动方式枚举类型(0=直接启动,1=星三角启动,2=软启动) + use_typedef: true + generate_constants: true + + - template_id: OVERLOAD_CURVE_TEMPLATE + name: + en: Overload Curve + cn: 过载曲线 + description: + en: Motor overload protection curve template + cn: 电机过载保护曲线模板 + enum_options: + 0: + alias: CURVE_10A + label: + en: 10A Curve (General) + cn: 10A曲线(通用) + value: 0 + 1: + alias: CURVE_20A + label: + en: 20A Curve (Motor) + cn: 20A曲线(电机) + value: 1 + 2: + alias: CURVE_30A + label: + en: 30A Curve (Heavy Load) + cn: 30A曲线(重载) + value: 2 + c_code: + typedef_name: OverloadCurveType + enum_name: OverloadCurveEnum + header_file: menu_enums.h + c_comment: 电机过载保护曲线枚举类型(0=10A通用,1=20A电机,2=30A重载) + use_typedef: true + generate_constants: true + +# 核心参数项(电磁启动器实际参数,含完整C代码配置) +params: + # -------------------- 1. 电机基本参数 -------------------- + - id: 1001 + name: + en: "Motor Rated Voltage" + cn: "电机额定电压" + id_name: MOTOR_RATED_VOLT + type: FLOAT + variable_name: motor_rated_volt + default: 380.0 + min: 220.0 + max: 660.0 + step: 10.0 + unit: V + read_only: false + comm_addr: 4097 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 0 + accessor_name: motor_rated_volt + init_value: 380.0 + validation_func: validate_motor_rated_volt + validation_params: + min: 220.0 + max: 660.0 + format_string: '%.1f' + display_precision: 1 + display_unit: V + storage_type: RAM + eeprom_offset: 0 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 1002 + name: + en: "Motor Rated Current" + cn: "电机额定电流" + id_name: MOTOR_RATED_CURR + type: FLOAT + variable_name: motor_rated_curr + default: 10.0 + min: 0.1 + max: 100.0 + step: 0.1 + unit: A + read_only: false + comm_addr: 4098 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 1 + accessor_name: motor_rated_curr + init_value: 10.0 + validation_func: validate_motor_rated_curr + validation_params: + min: 0.1 + max: 100.0 + format_string: '%.1f' + display_precision: 1 + display_unit: A + storage_type: RAM + eeprom_offset: 4 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 1003 + name: + en: "Motor Rated Power" + cn: "电机额定功率" + id_name: MOTOR_RATED_POWER + type: FLOAT + variable_name: motor_rated_power + default: 5.5 + min: 0.1 + max: 55.0 + step: 0.1 + unit: kW + read_only: false + comm_addr: 4099 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 2 + accessor_name: motor_rated_power + init_value: 5.5 + validation_func: validate_motor_rated_power + validation_params: + min: 0.1 + max: 55.0 + format_string: '%.1f' + display_precision: 1 + display_unit: kW + storage_type: RAM + eeprom_offset: 8 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 1004 + name: + en: "Motor Pole Number" + cn: "电机极数" + id_name: MOTOR_POLE_NUM + type: INT + variable_name: motor_pole_num + default: 4 + min: 2 + max: 8 + step: 2 + unit: 极 + read_only: false + comm_addr: 4100 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 3 + accessor_name: motor_pole_num + init_value: 4 + validation_func: validate_motor_pole_num + validation_params: + min: 2 + max: 8 + format_string: '%d' + display_precision: 0 + display_unit: 极 + storage_type: RAM + eeprom_offset: 12 + bit_width: 16 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + # -------------------- 2. 保护功能参数 -------------------- + - id: 2001 + name: + en: "Overload Protection Enable" + cn: "过载保护投退" + id_name: PROT_OVERLOAD_ENABLE + type: ENUM + variable_name: prot_overload_enable + default: 1 + default_alias: PROT_ENABLE + enum_template: PROTECT_ENABLE_TEMPLATE + unit: '' + read_only: false + comm_addr: 8193 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 4 + accessor_name: prot_overload_enable + init_value: 1 + validation_func: validate_prot_overload_enable + validation_params: + min: 0 # 修正:匹配枚举实际范围(0=退出,1=投入) + max: 1 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 16 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2002 + name: + en: "Overload Current Threshold" + cn: "过载电流阈值" + id_name: PROT_OVERLOAD_THRESH + type: FLOAT + variable_name: prot_overload_thresh + default: 1.2 + min: 1.0 + max: 2.0 + step: 0.05 + unit: Ie + read_only: false + comm_addr: 8194 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 5 + accessor_name: prot_overload_thresh + init_value: 1.2 + validation_func: validate_prot_overload_thresh + validation_params: + min: 1.0 + max: 2.0 + format_string: '%.1f' + display_precision: 1 + display_unit: Ie + storage_type: RAM + eeprom_offset: 20 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2003 + name: + en: "Overload Curve Type" + cn: "过载保护曲线" + id_name: PROT_OVERLOAD_CURVE + type: ENUM + variable_name: prot_overload_curve + default: 1 + default_alias: CURVE_20A + enum_template: OVERLOAD_CURVE_TEMPLATE + unit: '' + read_only: false + comm_addr: 8195 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 6 + accessor_name: prot_overload_curve + init_value: 1 + validation_func: validate_prot_overload_curve + validation_params: + min: 0 # 修正:匹配枚举实际范围(0-2) + max: 2 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 24 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2004 + name: + en: "Phase Loss Protection Enable" + cn: "缺相保护投退" + id_name: PROT_PHASE_LOSS_ENABLE + type: ENUM + variable_name: prot_phase_loss_enable + default: 1 + default_alias: PROT_ENABLE + enum_template: PROTECT_ENABLE_TEMPLATE + unit: '' + read_only: false + comm_addr: 8196 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 7 + accessor_name: prot_phase_loss_enable + init_value: 1 + validation_func: validate_prot_phase_loss_enable + validation_params: + min: 0 # 修正:匹配枚举实际范围 + max: 1 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 28 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2005 + name: + en: "Phase Loss Delay Time" + cn: "缺相保护延时" + id_name: PROT_PHASE_LOSS_DELAY + type: FLOAT + variable_name: prot_phase_loss_delay + default: 0.5 + min: 0.0 + max: 5.0 + step: 0.1 + unit: s + read_only: false + comm_addr: 8197 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 8 + accessor_name: prot_phase_loss_delay + init_value: 0.5 + validation_func: validate_prot_phase_loss_delay + validation_params: + min: 0.0 + max: 5.0 + format_string: '%.1f' + display_precision: 1 + display_unit: s + storage_type: RAM + eeprom_offset: 32 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2006 + name: + en: "Lock Rotor Protection Enable" + cn: "堵转保护投退" + id_name: PROT_LOCK_ROTOR_ENABLE + type: ENUM + variable_name: prot_lock_rotor_enable + default: 1 + default_alias: PROT_ENABLE + enum_template: PROTECT_ENABLE_TEMPLATE + unit: '' + read_only: false + comm_addr: 8198 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 9 + accessor_name: prot_lock_rotor_enable + init_value: 1 + validation_func: validate_prot_lock_rotor_enable + validation_params: + min: 0 # 修正:匹配枚举实际范围 + max: 1 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 36 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2007 + name: + en: "Lock Rotor Current Threshold" + cn: "堵转电流阈值" + id_name: PROT_LOCK_ROTOR_THRESH + type: FLOAT + variable_name: prot_lock_rotor_thresh + default: 5.0 + min: 3.0 + max: 10.0 + step: 0.1 + unit: Ie + read_only: false + comm_addr: 8199 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 10 + accessor_name: prot_lock_rotor_thresh + init_value: 5.0 + validation_func: validate_prot_lock_rotor_thresh + validation_params: + min: 3.0 + max: 10.0 + format_string: '%.1f' + display_precision: 1 + display_unit: Ie + storage_type: RAM + eeprom_offset: 40 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2008 + name: + en: "Phase Unbalance Protection Enable" + cn: "相不平衡保护投退" + id_name: PROT_PHASE_UNBALANCE_ENABLE + type: ENUM + variable_name: prot_phase_unbalance_enable + default: 1 + default_alias: PROT_ENABLE + enum_template: PROTECT_ENABLE_TEMPLATE + unit: '' + read_only: false + comm_addr: 8200 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 11 + accessor_name: prot_phase_unbalance_enable + init_value: 1 + validation_func: validate_prot_phase_unbalance_enable + validation_params: + min: 0 # 修正:匹配枚举实际范围 + max: 1 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 44 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2009 + name: + en: "Phase Unbalance Threshold" + cn: "相不平衡阈值" + id_name: PROT_PHASE_UNBALANCE_THRESH + type: FLOAT + variable_name: prot_phase_unbalance_thresh + default: 20.0 + min: 5.0 + max: 50.0 + step: 1.0 + unit: '%' + read_only: false + comm_addr: 8201 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 12 + accessor_name: prot_phase_unbalance_thresh + init_value: 20.0 + validation_func: validate_prot_phase_unbalance_thresh + validation_params: + min: 5.0 + max: 50.0 + format_string: '%.1f' + display_precision: 1 + display_unit: '%' + storage_type: RAM + eeprom_offset: 48 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2010 + name: + en: "Under Voltage Protection Enable" + cn: "欠压保护投退" + id_name: PROT_UNDERVOLT_ENABLE + type: ENUM + variable_name: prot_undervolt_enable + default: 1 + default_alias: PROT_ENABLE + enum_template: PROTECT_ENABLE_TEMPLATE + unit: '' + read_only: false + comm_addr: 8208 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 13 + accessor_name: prot_undervolt_enable + init_value: 1 + validation_func: validate_prot_undervolt_enable + validation_params: + min: 0 # 修正:匹配枚举实际范围 + max: 1 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 52 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2011 + name: + en: "Under Voltage Threshold" + cn: "欠压保护阈值" + id_name: PROT_UNDERVOLT_THRESH + type: FLOAT + variable_name: prot_undervolt_thresh + default: 85.0 + min: 70.0 + max: 90.0 + step: 1.0 + unit: '%Ue' + read_only: false + comm_addr: 8209 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 14 + accessor_name: prot_undervolt_thresh + init_value: 85.0 + validation_func: validate_prot_undervolt_thresh + validation_params: + min: 70.0 + max: 90.0 + format_string: '%.1f' + display_precision: 1 + display_unit: '%Ue' + storage_type: RAM + eeprom_offset: 56 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2012 + name: + en: "Over Voltage Protection Enable" + cn: "过压保护投退" + id_name: PROT_OVERVOLT_ENABLE + type: ENUM + variable_name: prot_overvolt_enable + default: 1 + default_alias: PROT_ENABLE + enum_template: PROTECT_ENABLE_TEMPLATE + unit: '' + read_only: false + comm_addr: 8210 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 15 + accessor_name: prot_overvolt_enable + init_value: 1 + validation_func: validate_prot_overvolt_enable + validation_params: + min: 0 # 修正:匹配枚举实际范围 + max: 1 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 60 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 2013 + name: + en: "Over Voltage Threshold" + cn: "过压保护阈值" + id_name: PROT_OVERVOLT_THRESH + type: FLOAT + variable_name: prot_overvolt_thresh + default: 110.0 + min: 105.0 + max: 120.0 + step: 1.0 + unit: '%Ue' + read_only: false + comm_addr: 8211 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 16 + accessor_name: prot_overvolt_thresh + init_value: 110.0 + validation_func: validate_prot_overvolt_thresh + validation_params: + min: 105.0 + max: 120.0 + format_string: '%.1f' + display_precision: 1 + display_unit: '%Ue' + storage_type: RAM + eeprom_offset: 64 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + # -------------------- 3. 控制功能参数 -------------------- + - id: 3001 + name: + en: "Start Mode" + cn: "启动方式" + id_name: CONTROL_START_MODE + type: ENUM + variable_name: control_start_mode + default: 0 + default_alias: START_DIRECT + enum_template: START_MODE_TEMPLATE + unit: '' + read_only: false + comm_addr: 12289 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 17 + accessor_name: control_start_mode + init_value: 0 + validation_func: validate_control_start_mode + validation_params: + min: 0 # 修正:匹配枚举实际范围(0-2) + max: 2 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 68 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 3002 + name: + en: "Star-Delta Switch Delay" + cn: "星三角切换延时" + id_name: CONTROL_STAR_DELTA_DELAY + type: FLOAT + variable_name: control_star_delta_delay + default: 5.0 + min: 1.0 + max: 30.0 + step: 0.1 + unit: s + read_only: false + comm_addr: 12290 + comm_rw: 1 + permission_level: 1 + visible_cb: check_star_delta_mode + c_code: + struct_member: true + array_index: 18 + accessor_name: control_star_delta_delay + init_value: 5.0 + validation_func: validate_control_star_delta_delay + validation_params: + min: 1.0 + max: 30.0 + format_string: '%.1f' + display_precision: 1 + display_unit: s + storage_type: RAM + eeprom_offset: 72 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 3003 + name: + en: "Soft Start Time" + cn: "软启动时间" + id_name: CONTROL_SOFT_START_TIME + type: FLOAT + variable_name: control_soft_start_time + default: 10.0 + min: 1.0 + max: 60.0 + step: 1.0 + unit: s + read_only: false + comm_addr: 12291 + comm_rw: 1 + permission_level: 1 + visible_cb: check_soft_start_mode + c_code: + struct_member: true + array_index: 19 + accessor_name: control_soft_start_time + init_value: 10.0 + validation_func: validate_control_soft_start_time + validation_params: + min: 1.0 + max: 60.0 + format_string: '%.1f' + display_precision: 1 + display_unit: s + storage_type: RAM + eeprom_offset: 76 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 3004 + name: + en: "Stop Delay Time" + cn: "停止延时时间" + id_name: CONTROL_STOP_DELAY + type: FLOAT + variable_name: control_stop_delay + default: 0.0 + min: 0.0 + max: 60.0 + step: 0.1 + unit: s + read_only: false + comm_addr: 12292 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 20 + accessor_name: control_stop_delay + init_value: 0.0 + validation_func: validate_control_stop_delay + validation_params: + min: 0.0 + max: 60.0 + format_string: '%.1f' + display_precision: 1 + display_unit: s + storage_type: RAM + eeprom_offset: 80 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 3005 + name: + en: "Remote Control Enable" + cn: "远程控制投退" + id_name: CONTROL_REMOTE_ENABLE + type: ENUM + variable_name: control_remote_enable + default: 0 + default_alias: SWITCH_OFF + enum_template: SWITCH_TEMPLATE + unit: '' + read_only: false + comm_addr: 12293 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 21 + accessor_name: control_remote_enable + init_value: 0 + validation_func: validate_control_remote_enable + validation_params: + min: 0 # 修正:匹配枚举实际范围(0=关闭,1=开启) + max: 1 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 84 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + # -------------------- 4. 系统配置参数 -------------------- + - id: 4001 + name: + en: "Communication Address" + cn: "通讯地址" + id_name: SYS_COMM_ADDR + type: INT + variable_name: sys_comm_addr + default: 1 + min: 1 + max: 247 + step: 1 + unit: '' + read_only: false + comm_addr: 16385 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 22 + accessor_name: sys_comm_addr + init_value: 1 + validation_func: validate_sys_comm_addr + validation_params: + min: 1 + max: 247 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 88 + bit_width: 16 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 4002 + name: + en: "Baud Rate" + cn: "波特率" + id_name: SYS_BAUDRATE + type: ENUM + variable_name: sys_baudrate + default: 9600 + default_alias: BAUD_9600 + enum_options: + 2400: + alias: BAUD_2400 + label: + en: 2400 bps + cn: 2400 波特 + value: 2400 + 4800: + alias: BAUD_4800 + label: + en: 4800 bps + cn: 4800 波特 + value: 4800 + 9600: + alias: BAUD_9600 + label: + en: 9600 bps + cn: 9600 波特 + value: 9600 + 19200: + alias: BAUD_19200 + label: + en: 19200 bps + cn: 19200 波特 + value: 19200 + unit: bps + read_only: false + comm_addr: 16386 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 23 + accessor_name: sys_baudrate + init_value: 9600 + validation_func: validate_sys_baudrate + validation_params: + min: 2400 # 修正:匹配波特率实际范围 + max: 19200 + format_string: '%d' + display_precision: 0 + display_unit: bps + storage_type: RAM + eeprom_offset: 92 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + # 新增:波特率枚举C代码配置 + typedef_name: BaudRateType + enum_name: BaudRateEnum + header_file: menu_enums.h + c_comment: 通讯波特率枚举类型 + use_typedef: true + generate_constants: true + + - id: 4003 + name: + en: "Admin Password" + cn: "管理员密码" + id_name: SYS_ADMIN_PWD + type: INT + variable_name: sys_admin_pwd + default: 123456 + min: 0 + max: 999999 + step: 1 + unit: '' + read_only: false + comm_addr: 16387 + comm_rw: 1 + permission_level: 2 + c_code: + struct_member: true + array_index: 24 + accessor_name: sys_admin_pwd + init_value: 123456 + validation_func: validate_sys_admin_pwd + validation_params: + min: 0 + max: 999999 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 96 + bit_width: 16 + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + - id: 4004 + name: + en: "System Time" + cn: "系统时间" + id_name: SYS_TIME + type: STRING + variable_name: sys_time + default: '2025-01-01 00:00:00' + unit: '' + read_only: false + comm_addr: 16388 + comm_rw: 1 + permission_level: 1 + c_code: + struct_member: true + array_index: 25 + accessor_name: sys_time + init_value: '2025-01-01 00:00:00' + validation_func: validate_sys_time + validation_params: + min: 0 + max: 1000 + format_string: '%s' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 100 + bit_width: 8 + string_length: 20 # 新增:字符串长度(适配"YYYY-MM-DD HH:MM:SS"格式) + scaling_factor: 1.0 + generate_getter: true + generate_setter: true + generate_validator: true + + # -------------------- 5. 状态采集参数(只读) -------------------- + - id: 5001 + name: + en: "Phase Current A" + cn: "A相电流" + id_name: STATUS_CURR_A + type: FLOAT + variable_name: status_curr_a + unit: A + read_only: true + comm_addr: 20481 + comm_rw: 0 + c_code: + struct_member: true + array_index: 26 + accessor_name: status_curr_a + init_value: 0.0 + validation_func: validate_status_curr_a + validation_params: + min: 0.0 + max: 200.0 # 修正:合理的电流测量范围 + format_string: '%.1f' + display_precision: 1 + display_unit: A + storage_type: RAM + eeprom_offset: 104 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: false # 修正:只读参数不生成setter + generate_validator: true + + - id: 5002 + name: + en: "Phase Current B" + cn: "B相电流" + id_name: STATUS_CURR_B + type: FLOAT + variable_name: status_curr_b + unit: A + read_only: true + comm_addr: 20482 + comm_rw: 0 + c_code: + struct_member: true + array_index: 27 + accessor_name: status_curr_b + init_value: 0.0 + validation_func: validate_status_curr_b + validation_params: + min: 0.0 + max: 200.0 + format_string: '%.1f' + display_precision: 1 + display_unit: A + storage_type: RAM + eeprom_offset: 108 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: false # 修正:只读参数不生成setter + generate_validator: true + + - id: 5003 + name: + en: "Phase Current C" + cn: "C相电流" + id_name: STATUS_CURR_C + type: FLOAT + variable_name: status_curr_c + unit: A + read_only: true + comm_addr: 20483 + comm_rw: 0 + c_code: + struct_member: true + array_index: 28 + accessor_name: status_curr_c + init_value: 0.0 + validation_func: validate_status_curr_c + validation_params: + min: 0.0 + max: 200.0 + format_string: '%.1f' + display_precision: 1 + display_unit: A + storage_type: RAM + eeprom_offset: 112 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: false # 修正:只读参数不生成setter + generate_validator: true + + - id: 5004 + name: + en: "Line Voltage AB" + cn: "AB线电压" + id_name: STATUS_VOLT_AB + type: FLOAT + variable_name: status_volt_ab + unit: V + read_only: true + comm_addr: 20484 + comm_rw: 0 + c_code: + struct_member: true + array_index: 29 + accessor_name: status_volt_ab + init_value: 0.0 + validation_func: validate_status_volt_ab + validation_params: + min: 0.0 + max: 800.0 # 修正:合理的电压测量范围 + format_string: '%.1f' + display_precision: 1 + display_unit: V + storage_type: RAM + eeprom_offset: 116 + bit_width: 32 + scaling_factor: 1.0 + generate_getter: true + generate_setter: false # 修正:只读参数不生成setter + generate_validator: true + + - id: 5005 + name: + en: "Motor Running Status" + cn: "电机运行状态" + id_name: STATUS_MOTOR_RUN + type: ENUM + variable_name: status_motor_run + default: 0 + default_alias: STATUS_STOP + enum_options: + 0: + alias: STATUS_STOP + label: + en: Stop + cn: 停止 + value: 0 + 1: + alias: STATUS_RUN + label: + en: Run + cn: 运行 + value: 1 + 2: + alias: STATUS_FAULT + label: + en: Fault + cn: 故障 + value: 2 + unit: '' + read_only: true + comm_addr: 20485 + comm_rw: 0 + c_code: + struct_member: true + array_index: 30 + accessor_name: status_motor_run + init_value: 0 + validation_func: validate_status_motor_run + validation_params: + min: 0 # 修正:匹配枚举实际范围(0-2) + max: 2 + format_string: '%d' + display_precision: 0 + display_unit: '' + storage_type: RAM + eeprom_offset: 120 + bit_width: 8 + scaling_factor: 1.0 + generate_getter: true + generate_setter: false # 修正:只读参数不生成setter + generate_validator: true + # 新增:电机状态枚举C代码配置 + typedef_name: MotorStatusType + enum_name: MotorStatusEnum + header_file: menu_enums.h + c_comment: 电机运行状态枚举类型(0=停止,1=运行,2=故障) + use_typedef: true + generate_constants: true + +# 菜单层级结构(语义化类型,适配C代码生成) +nodes: + - id: 1 + parent_id: 0 + name: + en: "Main Menu" + cn: "主菜单" + id_name: MAIN_MENU + enter_cb: menu_enter_main + c_code: + struct_member: true + menu_item_type: MAIN_MENU # 语义化:主菜单 + function_name: menu_enter_main + header_file: menu_nodes.h + + # -------------------- 一级菜单:实时数据 -------------------- + - id: 10 + parent_id: 1 + name: + en: "Real-Time Data" + cn: "实时数据" + id_name: MENU_REAL_TIME_DATA + enter_cb: menu_enter_real_time_data + c_code: + struct_member: true + menu_item_type: SUB_MENU # 语义化:子菜单 + function_name: menu_enter_real_time_data + header_file: menu_nodes.h + + - id: 1001 + parent_id: 10 + name: + en: "Current Data" + cn: "电流数据" + id_name: MENU_CURRENT_DATA + display_cb: show_phase_current + c_code: + struct_member: true + menu_item_type: DISPLAY_ITEM # 语义化:显示项(无编辑) + function_name: show_phase_current + header_file: menu_nodes.h + + - id: 1002 + parent_id: 10 + name: + en: "Voltage Data" + cn: "电压数据" + id_name: MENU_VOLTAGE_DATA + display_cb: show_line_voltage + c_code: + struct_member: true + menu_item_type: DISPLAY_ITEM + function_name: show_line_voltage + header_file: menu_nodes.h + + - id: 1003 + parent_id: 10 + name: + en: "Motor Status" + cn: "电机状态" + id_name: MENU_MOTOR_STATUS + display_cb: show_motor_status + c_code: + struct_member: true + menu_item_type: DISPLAY_ITEM + function_name: show_motor_status + header_file: menu_nodes.h + + # -------------------- 一级菜单:参数设置 -------------------- + - id: 20 + parent_id: 1 + name: + en: "Parameter Settings" + cn: "参数设置" + id_name: MENU_PARAM_SETTINGS + enter_cb: menu_enter_param_settings + permission_level: 1 + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_param_settings + header_file: menu_nodes.h + + - id: 2001 + parent_id: 20 + name: + en: "Motor Basic Params" + cn: "电机基本参数" + id_name: MENU_MOTOR_BASIC_PARAMS + enter_cb: menu_enter_motor_basic_params + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_motor_basic_params + header_file: menu_nodes.h + + - id: 200101 + parent_id: 2001 + name: + en: "Motor Rated Voltage" + cn: "电机额定电压" + id_name: MENU_MOTOR_RATED_VOLT + bind_param_id: 1001 + enter_cb: menu_enter_param_edit + c_code: + struct_member: true + menu_item_type: PARAM_EDIT_ITEM # 语义化:参数编辑项 + function_name: menu_enter_param_edit + header_file: menu_nodes.h + + - id: 200102 + parent_id: 2001 + name: + en: "Motor Rated Current" + cn: "电机额定电流" + id_name: MENU_MOTOR_RATED_CURR + bind_param_id: 1002 + enter_cb: menu_enter_param_edit + c_code: + struct_member: true + menu_item_type: PARAM_EDIT_ITEM + function_name: menu_enter_param_edit + header_file: menu_nodes.h + + - id: 200103 + parent_id: 2001 + name: + en: "Motor Rated Power" + cn: "电机额定功率" + id_name: MENU_MOTOR_RATED_POWER + bind_param_id: 1003 + enter_cb: menu_enter_param_edit + c_code: + struct_member: true + menu_item_type: PARAM_EDIT_ITEM + function_name: menu_enter_param_edit + header_file: menu_nodes.h + + - id: 2002 + parent_id: 20 + name: + en: "Protection Params" + cn: "保护功能参数" + id_name: MENU_PROTECTION_PARAMS + enter_cb: menu_enter_protection_params + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_protection_params + header_file: menu_nodes.h + + - id: 200201 + parent_id: 2002 + name: + en: "Overload Protection" + cn: "过载保护" + id_name: MENU_OVERLOAD_PROT + enter_cb: menu_enter_overload_prot + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_overload_prot + header_file: menu_nodes.h + + - id: 20020101 + parent_id: 200201 + name: + en: "Overload Protect Enable" + cn: "过载保护投退" + id_name: MENU_OVERLOAD_PROT_ENABLE + bind_param_id: 2001 + enter_cb: menu_enter_param_edit + c_code: + struct_member: true + menu_item_type: PARAM_EDIT_ITEM + function_name: menu_enter_param_edit + header_file: menu_nodes.h + + - id: 20020102 + parent_id: 200201 + name: + en: "Overload Current Threshold" + cn: "过载电流阈值" + id_name: MENU_OVERLOAD_PROT_THRESH + bind_param_id: 2002 + enter_cb: menu_enter_param_edit + c_code: + struct_member: true + menu_item_type: PARAM_EDIT_ITEM + function_name: menu_enter_param_edit + header_file: menu_nodes.h + + - id: 200202 + parent_id: 2002 + name: + en: "Phase Loss Protection" + cn: "缺相保护" + id_name: MENU_PHASE_LOSS_PROT + enter_cb: menu_enter_phase_loss_prot + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_phase_loss_prot + header_file: menu_nodes.h + + - id: 2003 + parent_id: 20 + name: + en: "Control Function Params" + cn: "控制功能参数" + id_name: MENU_CONTROL_PARAMS + enter_cb: menu_enter_control_params + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_control_params + header_file: menu_nodes.h + + - id: 200301 + parent_id: 2003 + name: + en: "Start Mode" + cn: "启动方式" + id_name: MENU_START_MODE + bind_param_id: 3001 + enter_cb: menu_enter_param_edit + c_code: + struct_member: true + menu_item_type: PARAM_EDIT_ITEM + function_name: menu_enter_param_edit + header_file: menu_nodes.h + + - id: 200302 + parent_id: 2003 + name: + en: "Star-Delta Switch Delay" + cn: "星三角切换延时" + id_name: MENU_STAR_DELTA_DELAY + bind_param_id: 3002 + enter_cb: menu_enter_param_edit + visible_cb: check_star_delta_mode + c_code: + struct_member: true + menu_item_type: PARAM_EDIT_ITEM + function_name: menu_enter_param_edit + header_file: menu_nodes.h + + - id: 2004 + parent_id: 20 + name: + en: "System Config Params" + cn: "系统配置参数" + id_name: MENU_SYSTEM_PARAMS + enter_cb: menu_enter_system_params + permission_level: 1 + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_system_params + header_file: menu_nodes.h + + # -------------------- 一级菜单:保护投退 -------------------- + - id: 30 + parent_id: 1 + name: + en: "Protection Enable/Disable" + cn: "保护投退" + id_name: MENU_PROTECT_ENABLE + enter_cb: menu_enter_protect_enable + permission_level: 1 + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_protect_enable + header_file: menu_nodes.h + + - id: 3001 + parent_id: 30 + name: + en: "Overload Protect Enable" + cn: "过载保护投退" + id_name: MENU_OVERLOAD_PROT_ENABLE + bind_param_id: 2001 + enter_cb: menu_enter_param_edit + c_code: + struct_member: true + menu_item_type: PARAM_EDIT_ITEM + function_name: menu_enter_param_edit + header_file: menu_nodes.h + + - id: 3002 + parent_id: 30 + name: + en: "Phase Loss Protect Enable" + cn: "缺相保护投退" + id_name: MENU_PHASE_LOSS_PROT_ENABLE + bind_param_id: 2004 + enter_cb: menu_enter_param_edit + c_code: + struct_member: true + menu_item_type: PARAM_EDIT_ITEM + function_name: menu_enter_param_edit + header_file: menu_nodes.h + + # -------------------- 一级菜单:控制操作 -------------------- + - id: 40 + parent_id: 1 + name: + en: "Control Operation" + cn: "控制操作" + id_name: MENU_CONTROL_OP + enter_cb: menu_enter_control_op + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_control_op + header_file: menu_nodes.h + + - id: 4001 + parent_id: 40 + name: + en: "Motor Start" + cn: "电机启动" + id_name: MENU_MOTOR_START + action_cb: action_motor_start + confirm_required: true + visible_cb: check_motor_stop + c_code: + struct_member: true + menu_item_type: ACTION_ITEM # 语义化:操作项(执行动作) + function_name: action_motor_start + header_file: menu_nodes.h + + - id: 4002 + parent_id: 40 + name: + en: "Motor Stop" + cn: "电机停止" + id_name: MENU_MOTOR_STOP + action_cb: action_motor_stop + confirm_required: true + visible_cb: check_motor_run + c_code: + struct_member: true + menu_item_type: ACTION_ITEM + function_name: action_motor_stop + header_file: menu_nodes.h + + - id: 4003 + parent_id: 40 + name: + en: "Fault Reset" + cn: "故障复位" + id_name: MENU_FAULT_RESET + action_cb: action_fault_reset + confirm_required: true + visible_cb: check_motor_fault + c_code: + struct_member: true + menu_item_type: ACTION_ITEM + function_name: action_fault_reset + header_file: menu_nodes.h + + # -------------------- 一级菜单:故障记录 -------------------- + - id: 50 + parent_id: 1 + name: + en: "Fault Record" + cn: "故障记录" + id_name: MENU_FAULT_RECORD + enter_cb: menu_enter_fault_record + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_fault_record + header_file: menu_nodes.h + + - id: 5001 + parent_id: 50 + name: + en: "Current Fault" + cn: "当前故障" + id_name: MENU_CURRENT_FAULT + display_cb: show_current_fault + c_code: + struct_member: true + menu_item_type: DISPLAY_ITEM + function_name: show_current_fault + header_file: menu_nodes.h + + - id: 5002 + parent_id: 50 + name: + en: "History Fault" + cn: "历史故障" + id_name: MENU_HISTORY_FAULT + enter_cb: menu_enter_history_fault + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_history_fault + header_file: menu_nodes.h + + - id: 5003 + parent_id: 50 + name: + en: "Clear History Fault" + cn: "清除历史故障" + id_name: MENU_CLEAR_HISTORY_FAULT + action_cb: action_clear_history_fault + confirm_required: true + permission_level: 1 + c_code: + struct_member: true + menu_item_type: ACTION_ITEM + function_name: action_clear_history_fault + header_file: menu_nodes.h + + # -------------------- 一级菜单:系统信息 -------------------- + - id: 60 + parent_id: 1 + name: + en: "System Info" + cn: "系统信息" + id_name: MENU_SYSTEM_INFO + enter_cb: menu_enter_system_info + c_code: + struct_member: true + menu_item_type: SUB_MENU + function_name: menu_enter_system_info + header_file: menu_nodes.h + + - id: 6001 + parent_id: 60 + name: + en: "Device Version" + cn: "设备版本" + id_name: MENU_DEVICE_VERSION + display_cb: show_device_version + c_code: + struct_member: true + menu_item_type: DISPLAY_ITEM + function_name: show_device_version + header_file: menu_nodes.h + + - id: 6002 + parent_id: 60 + name: + en: "Run Time" + cn: "运行时间" + id_name: MENU_RUN_TIME + display_cb: show_run_time + c_code: + struct_member: true + menu_item_type: DISPLAY_ITEM + function_name: show_run_time + header_file: menu_nodes.h \ No newline at end of file