# Project memory _Durable project-level knowledge. Persists across all sessions in this project. Edit only content under italic instructions._ ## Project context _What is this project? What's its goal? High-level identity._ **RTU (Remote Terminal Unit)** — 基于 IEC 61850 的智能通信网关,用于电力系统自动化。 - **核心协议**: IEC 61850 MMS(服务端/客户端)、IEC 101/104(通过 ICP67 协议) - **通信方式**: TCP/UART/UDP 多通道、MQTT(mosquitto)、WebSocket - **数据模型**: 信号数据中心(遥测/遥信/遥控/遥调/参数),支持 XXH128 哈希索引 - **技术栈**: C/C++(GCC/Linux ARM 交叉编译)、Mongoose 嵌入式 Web 服务器、linenoise CLI - **编译**: `./release/build.sh`(x86)或 `./release/build.sh arm`(ARM 交叉编译) - **运行**: `./test/RTU` ### 模块架构 ``` src/ ├── system/RTU/ # 主程序入口、CLI、自点表配置、应用系统调度 ├── system/libdatacenter/ # 数据中心(信号注册/变更检测/SBO控制/事件队列) ├── system/libcom_channel/ # 通信通道管理(TCP服务端/客户端、串口) ├── protocol/libmms_s/ # IEC 61850 MMS 服务端(ICD解析、模型创建、控制/定值/文件) ├── protocol/libmms_m/ # IEC 61850 MMS 客户端(总召/读写/报告订阅) ├── protocol/libicp67/ # ICP67 协议(IEC 101/104 帧编解码) ├── protocol/libmongoose/ # Mongoose HTTP/WebSocket 嵌入式服务器 ├── public/libmy_mosquitto/ # MQTT 客户端库(mosquitto 2.x) ├── public/libcJSON/ # JSON 解析 └── public/libcomm/ # 统一通信抽象层(TCP/UART/UDP) ``` 9 个应用线程: `app_sys`, `app_cmd`, `app_comm_channel`, `app_com_scan`, `app_iec`, `app_self_ptl`, `app_web_server`, `app_iec61850m`, `app_iec61850s` ## Rules _Hard constraints from user that every session must respect._ ### 工作流程规则 1. **对话语言**: 全程使用中文显示 2. **编译路径**: `./release/build.sh`(x86)或 `./release/build.sh arm`(ARM交叉编译) 3. **执行路径**: `./test/RTU` 4. **排查问题流程**: 先重新读取对应位置的源码,再对照问题或打印信息排查,不要依赖记忆中的旧代码 5. **问题记录**: 每次解决的问题都追加到 `claude/问题处理文档.md` 6. **文档目录**: - `claude/mid/` — 存放中间文档、plan 文档 - `claude/工程/` — 存放按模块记录的项目工程文档 7. **每次读取项目工程时**: 把读到的东西按模块生成文档记录到 `claude/工程/` 文件夹 8. **解决问题的 plan**: 每次制定并执行 plan 解决问题后,将 plan 内容整理为文档存入 `claude/mid/` 目录 9. **Claude→Mimo 记忆转换规则** (2026-06-12, plan 1781250239159-brave-harbor): - `.claude/memory/MEMORY.md` → Mimo `memory/projects/global/MEMORY.md` - `.claude/memory/code-style.md` + `project-rules.md` → MEMORY.md §Rules - `.claude/memory/user_language.md` → Mimo `memory/global/MEMORY.md` - `claude/mid/*.md` → 提取核心知识 → MEMORY.md §Discovered durable knowledge - `claude/工程/*.md` → 提取核心知识 → MEMORY.md §Architecture decisions - 原始 claude 文件保留不动,仅新增 Mimo 记忆文件 ### C/C++ 代码格式规范 - **缩进**: 使用 **Tab 字符**缩进(显示宽度 4),不使用空格缩进 - **括号风格**: Allman 风格 — 所有大括号独占一行(函数、if、for、while、struct),单条语句也保留大括号 - **空格**: - 关键字与括号之间不加空格: `if(`, `for(`, `while(`, `switch(` - 函数名与括号之间不加空格: `func(args)` - 指针声明: `type *name`(`*` 前有空格,后无空格) - 引用声明: `type &name` - **Yoda 条件**: 常量写在比较运算符左侧,`if(NULL == ptr)` 而非 `if(ptr == NULL)` - **空行**: 函数之间两行空行,逻辑块之间一行空行,`#include` 区块末尾一行空行 - **typedef struct**: 结构体成员无缩进额外层级(与 `{` 对齐) - **命名约定**: 局部静态变量用 `LOCAL` 宏(= `static`),全局变量用 `g_` 前缀,结构体用 `stru_` 前缀,枚举用 `enum_` 前缀/`ENUM_` 值前缀 ## Architecture decisions _Major design choices with rationale. The "why" matters more than the "what" for future sessions._ ### 1. 数据中心信号管理 `dc_signal.cpp` 使用 XXH128 哈希对信号快速索引(`signal_out`, `signal_in`, `signal_yk`, `signal_ao`, `signal_param` 五张表,每表独立互斥锁)。输出信号变更通过脏队列 + 去重 + 比对 + 回调实现增量推送(仅变更时发送),`last_caller_module` 防止同模块回调自循环。SBO(Select Before Operate)控制流程:SELECT 暂存值 → DIRECT 校验与 SELECT 值一致 → 写入信号。事件队列(扰动/SOE/故障)使用 swap 模式低锁竞争 pop。 ### 2. 参数配置双文件机制 `param.xml` 为参数模板(min/max/step/unit/default),不随运行修改。`self_param.xml` 由 datacenter 在运行时自动生成,存储当前信号值。初始化时值优先级:self_param.xml > param.xml value > param.xml default。`dc_param_cfg_check` 每 1000ms 检测变更标志,将 Ao/Param 信号值序列化写入 self_param.xml。 ### 3. WebSocket 多连接隔离 每个 WebSocket 连接拥有独立的信号资源 session(per-connection),连接建立时开辟、断开时释放。全局共享方案会导致一个客户端的 add/del 操作影响其他客户端。 ### 4. MMS 客户端事件驱动模型 `mms_m.cpp` 使用事件队列 + 状态机模式,定时器驱动周期性操作(T0=120s all-call, T1=60s GI, T2=30s CO, T3=20s param)。RCB 订阅支持可配置化编号过滤。 ### 5. IEC 61850 服务器模型 `mms_s_icd.cpp` 解析 SCL XML ICD 文件构建完整数据模型。`mms_s_model.cpp` 动态创建 IedModel(LD/LN/DO/SDO/DA 树)。定值组管理通过 SGCB + SG/SE 镜像 DA 实现编辑区/运行区隔离。 ### 6. 通信通道统一抽象 `com_channel.cpp` 管理所有通信通道配置。`libcomm` 提供统一连接/发送/接收/断开接口,按类型分发到 TCP/UART/UDP 实现。ICP66 帧转换为 ICP67 格式。 ### 7. MQTT 通信 使用自编译 mosquitto 2.x 客户端库(`libmy_mosquitto`),支持 MQTT v5 特性。 ## Discovered durable knowledge _Cross-task facts that survive across sessions. Promoted from session checkpoints' §7 when proven durable._ ### 已修复的关键问题 #### #1 RCB 订阅编号可配置化(2026-06-10) - **问题**: `mms_m_icd_report_init()` 硬编码只订阅编号 `"01"` 的 RCB - **修复**: 新增 `mms_m_out_set_rcb_numbers()` API,支持逗号分隔的多编号和通配符 `"*"` - **文件**: `myMms_m.h`, `mms_m.h`, `mms_m.cpp`, `iec61850m.cpp` #### #2 libweb_server 多连接支持(2026-06-10) - **问题**: 原 WebSocket 服务端仅支持单客户端,存在多线程竞态、悬空指针等 10 个缺陷 - **修复**: 改为多连接,每个连接独立信号资源 session,断开自动释放 - **文件**: `web_server.cpp`, `ws_method.h`, `ws_method.cpp` #### #3 app_cmd CPU 108% 问题(2026-06-12) - **根因**: `linenoiseEdit()` 中 `read()` 仅检查 `-1` 未处理 EOF(返回 0),非终端环境下形成死循环 - **修复**: 改为 `<= 0` 判断 + `enableRawMode()` 返回值检查 + `select()` 非阻塞方案 - **文件**: `my_cmd.cpp`, `app_cmd.cpp` #### #4 Tab 命令补全前缀丢失(2026-06-12) - **问题**: 子命令 Tab 补全时命令名前缀被覆盖(如 `datacenter param` 变 `param`) - **修复**: Tab 键处理改为找到最后一个空格,只替换空格之后的当前词 - **文件**: `my_cmd.cpp` #### #5 app_cmd 交互卡顿(2026-06-12) - **问题**: select 非阻塞 + 100ms 定时器导致回车后回显有卡顿感 - **修复**: 改为简单阻塞循环 `while(1) { cmd_recv(); }`,linenoise 自管理终端模式 - **文件**: `app_cmd.cpp`