RTU/mimo/MEMORY.md

122 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 多通道、MQTTmosquitto、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` 防止同模块回调自循环。SBOSelect 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 连接拥有独立的信号资源 sessionper-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` 动态创建 IedModelLD/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`