<修改> 1、调整claude的部分规则记忆文件;2、调整自定义命令部分缺陷,旧版本cpu使用率超高

This commit is contained in:
ypc 2026-06-12 15:24:58 +08:00
parent 6c9b8e90b1
commit 3bf70c5b6d
14 changed files with 456 additions and 28 deletions

3
.claude/memory/MEMORY.md Normal file
View File

@ -0,0 +1,3 @@
- [user-language](user_language.md) — 用户要求所有对话和思考过程使用中文显示
- [project-rules](project-rules.md) — 项目开发规范:编译/运行路径、排查流程、文档管理、plan归档到mid目录
- [code-style](code-style.md) — C/C++代码格式规范Tab缩进、Allman括号、Yoda条件、空行规则

View File

@ -0,0 +1,79 @@
---
name: code-style
description: 项目 C/C++ 代码格式规范 — 缩进、括号、空格、空行、条件写法
metadata:
type: feedback
---
## 缩进
使用 **Tab 字符**缩进(显示宽度 4不使用空格缩进。
## 括号风格Allman 风格)
所有大括号 **独占一行**包括函数、if、for、while、struct
```cpp
LOCAL void check_sg_zone_change()
{
if(g_sg_zone_saddr.empty())
{
return;
}
for(auto &setting : g_vec_setting)
{
if(strcmp(setting.base.saddr, zone_saddr) == 0)
{
break;
}
}
}
```
单条语句也保留大括号,不省略。
## 空格规则
- 关键字与括号之间 **不加空格**`if(`, `for(`, `while(`, `switch(`
- 函数名与括号之间 **不加空格**`func(args)`
- 指针声明:`type *name``*` 前有空格,后无空格)
- 引用声明:`type &name`
## Yoda 条件
常量写在比较运算符左侧:
```cpp
if(NULL == ptr) // ✓ 正确
if(0 != ret) // ✓ 正确
if(ptr == NULL) // ✗ 不符合项目风格
```
## 空行
- 函数之间:两行空行
- 逻辑块之间:一行空行
- `#include` 区块末尾:一行空行
## typedef struct
```cpp
typedef struct
{
uint32_t field1;
uint8_t field2;
}stru_type_name;
```
结构体成员无缩进额外层级(与 `{` 对齐)。
## 变量声明
- 局部静态变量用 `LOCAL` 宏(= `static`
- 全局变量用 `g_` 前缀
- 结构体用 `stru_` 前缀
- 枚举用 `enum_` 前缀,枚举值用 `ENUM_` 前缀
**Why:** 从项目中多个核心源文件iec61850s.cpp、self_ptl.cpp、ws_method.cpp、dc_signal.cpp提取的共识格式规范
**How to apply:** 新增代码和修改现有代码时必须遵守此格式。本次仅统一缩进/括号/空格/空行,命名问题暂不处理。

View File

@ -0,0 +1,24 @@
---
name: project-rules
description: 项目开发规范 — 编译/运行路径、排查流程、文档管理、plan归档要求
metadata:
node_type: memory
type: feedback
originSessionId: 5e65af11-b197-479e-a82f-c2e5b475a8c3
---
## 核心规则
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/` 目录
**Why:** 用户明确要求的项目开发规范和工作流程
**How to apply:** 每次操作前检查这些规则,特别是编译/运行路径和问题排查流程。问题解决后必须追加到问题处理文档,同时将 plan 归档到 mid 目录。

View File

@ -0,0 +1,10 @@
---
name: user-language
description: 用户要求所有对话、思考过程和中间输出均使用中文显示
metadata:
node_type: memory
type: user
originSessionId: 5e65af11-b197-479e-a82f-c2e5b475a8c3
---
用户要求所有对话内容、思考过程thinking、以及所有用户能看到的中间过程都使用中文显示。包括但不限于回复内容、代码注释、任务列表、提交信息等。代码本身变量名、函数名等保持英文不变。

View File

@ -0,0 +1,82 @@
# Tab 命令补全功能实现
## 日期
2026-06-12
## 概述
为 CLI 交互实现多级 Tab 命令补全:第一个词补全命令名,后续词根据命令上下文补全子功能。
## 实现内容
### 1. 数据结构扩展myCmd.h
`stru_cmd` 增加 `complete` 回调字段:
```c
typedef struct
{
const char *name;
void (*func)(int argc, char *argv[]);
const char *desc;
void (*complete)(const char *buf, char ***completions, int *ncomp);
}stru_cmd;
```
`CMD_REGISTER` 宏改为支持可变参数,`cmd_manager_add_command` 增加默认参数 `complete = NULL`
### 2. 上下文感知补全my_cmd.cpp
`cmd_complete` 逻辑:
- 无空格 → 命令名前缀匹配(原行为)
- 有空格 → 提取第一个词查找命令,调用其 `complete` 回调获取子补全
`cmd_sub_complete` 辅助函数:给定子命令列表和前缀,返回匹配项。
### 3. 前缀保留修复my_cmd.cpp
`linenoiseEdit` 中 Tab 键处理原本用补全结果**覆盖整行**,导致子命令补全时命令名前缀丢失。改为找到最后一个空格,只替换空格之后的当前词:
```c
// 修复前strncpy(buf, completions[0], ...); // 整行覆盖
// 修复后:
char *last_space = strrchr_manual(buf, pos);
if (NULL != last_space)
strncpy(last_space + 1, completions[0], ...); // 只替换当前词
else
strncpy(buf, completions[0], ...); // 第一个词仍覆盖整行
```
### 4. 各模块子补全注册
| 命令 | 子命令 |
|------|--------|
| `datacenter` | `out`, `in`, `yk`, `ao`, `param`, `all` |
| `iec` | `run_cnt` |
| `iec61850m` | `info`, `yk`, `set` |
| `self_ptl` | `1`, `3`, `5`, `6`, `9`, `11` |
### 5. 构建系统修复
[release/src/system/makefile](release/src/system/makefile) 中 8 个子模块 SUBDIRS 被注释导致增量编译失效,已取消注释。
## 影响文件
| 文件 | 改动 |
|------|------|
| [myCmd.h](release/inc/myCmd.h) | stru_cmd 增加 complete 字段CMD_REGISTER 可变参数cmd_sub_complete 声明 |
| [my_cmd.cpp](src/public/libcmd/src/my_cmd.cpp) | cmd_complete 上下文感知cmd_sub_completeTab 替换前缀保留 |
| [dc_signal.cpp](src/system/libdatacenter/src/dc_signal.cpp) | datacenter 子补全 |
| [iec.cpp](src/system/libiec/src/iec.cpp) | iec 子补全 |
| [iec61850m.cpp](src/system/libiec61850m/src/iec61850m.cpp) | iec61850m 子补全 |
| [method.cpp](src/system/libself_ptl/src/method.cpp) | self_ptl 子补全 |
| [release/src/system/makefile](release/src/system/makefile) | 取消 SUBDIRS 注释 |
## 使用效果
```
cmd > d + Tab → datacenter
cmd > datacenter + p + Tab → datacenter param
cmd > iec + r + Tab → iec run_cnt
```

View File

@ -0,0 +1,60 @@
# app_cmd 线程 CPU 108% 问题修复
## 日期
2026-06-12
## 背景
`app_cmd` 线程是 CLI 命令行处理线程,属于 9 个应用线程之一。其主循环采用定时器驱动的事件模型EV_TIMER1=10ms、EV_TIMER2=100ms、EV_TIMER3=1000ms。原本 `cmd_recv()` 在 EV_TIMER1 中每次被调用,但该调用已被注释掉,原因是启用后 CPU 占用飙升至 108%。
## 根因
### 直接原因:`read()` 返回 EOF 未处理
`linenoiseEdit()`[my_cmd.cpp:107](src/public/libcmd/src/my_cmd.cpp#L107))中读取 stdin 的代码:
```c
if (read(STDIN_FILENO, &c, 1) == -1) return -1;
```
只检查了 `-1`(错误),未处理返回 `0`EOF。当进程无真正控制终端时RTU 嵌入式部署环境常见stdin 处于 EOF 状态,`read()` 立即返回 0。代码不匹配 `-1`,继续执行,`c` 为未定义值,后落入 `buf[len++] = c` 分支,循环回 `read()` — 死循环CPU 100%+。
### 架构层面问题
| 问题 | 说明 |
|------|------|
| 阻塞 I/O 在定时器线程中 | `linenoise()` 是同步阻塞调用,放在 10ms 定时器中导致线程被阻塞 |
| 无 stdin 就绪检查 | 没有用 `select()`/`poll()` 先检查 stdin 是否有数据 |
| 终端模式反复切换 | 每次 `linenoise()` 调用都 `tcgetattr`+`tcsetattr`,频率过高 |
| `tcsetattr` 返回值未检查 | `linenoise()` 中调用 `enableRawMode()` 未检查返回值 |
### 定时器机制
定时器使用 POSIX `timer_create(CLOCK_REALTIME, SIGEV_THREAD, ...)`,每次超时内核创建新线程执行回调 → `task_event_send``pthread_cond_signal` 唤醒 app 线程。
## 修复内容
### 1. my_cmd.cpp — 修复 EOF 处理和返回值检查
- `read()` 返回值判断从 `== -1` 改为 `<= 0`,覆盖 EOF 场景
- `linenoise()` 中检查 `enableRawMode()` 返回值,失败直接返回 NULL避免在有问题的终端上执行读取循环
### 2. app_cmd.cpp — 重构为非阻塞模式
- 新增 `isatty(STDIN_FILENO)` 前置检查,非终端环境直接跳过
- 用 `select()` 零超时检测 stdin 可读性,仅在数据就绪时才调用 `linenoise()`
- 从 EV_TIMER110ms移至 EV_TIMER2100ms降低终端模式切换频率
## 验证
- 编译:零错误零警告
- 测试:`./test/RTU < /dev/null` 运行 3 秒CPU 占用 0.0%(修复前为 108%
## 影响文件
| 文件 | 改动 |
|------|------|
| [my_cmd.cpp](src/public/libcmd/src/my_cmd.cpp) | `read()` EOF 处理;`enableRawMode()` 返回值检查 |
| [app_cmd.cpp](src/system/RTU/src/app_cmd.cpp) | 非阻塞 `cmd_recv_nonblock()``isatty` + `select`;移至 EV_TIMER2 |
| [CLAUDE.md](CLAUDE.md) | 全文翻译为中文 |

View File

@ -2,6 +2,49 @@
--- ---
## 2026-06-12
### #6 Tab 补全子命令前缀丢失
**问题**:输入 `datacenter ` + `p` + Tab 后,`datacenter ` 前缀被 `param` 覆盖,整行只剩 `param`
**根因**`linenoiseEdit` 中 Tab 键处理用 `strncpy(buf, completions[0])` 整行覆盖。
**修复**:改为找到最后一个空格,只替换空格之后的当前词,保留前缀。
---
### #5 app_cmd 交互卡顿与 Tab 补全失效
**问题**:上一轮将 `cmd_recv` 改为 select 非阻塞 + EV_TIMER2(100ms) 后:
1. 回车后 `cmd>` 回显不及时,有明显卡顿感
2. 输入 `d` 后按 Tab不会弹出命令补全
**根因**`select()` 方案与 `linenoise()` 交互式行编辑器根本性不兼容——select 时终端处于规范模式行缓冲Tab 不是行终止符不会触发 select100ms 定时器引入最多 100ms 延迟。
**修复**:将 `app_cmd` 线程从定时器事件驱动改为简单阻塞循环 `while(1) { cmd_recv(); }`。`linenoise()` 自管理终端模式切换和 Tab 补全,线程阻塞在 stdin 上零延迟响应。
**验证**:编译通过。
---
### #4 app_cmd 线程启用后 CPU 飙升至 108%
**问题**`app_cmd` 线程中 `cmd_recv()` 启用后CPU 占用 108%,导致该入口被暂时屏蔽([app_cmd.cpp:117](src/system/RTU/src/app_cmd.cpp#L117) 被注释)。
**根因**
1. **死循环层面**`linenoiseEdit()`[my_cmd.cpp:107](src/public/libcmd/src/my_cmd.cpp#L107))中 `read()` 只检查了返回 `-1`,未处理返回 `0`EOF。当进程无真正控制终端时RTU 嵌入式环境常见),`read()` 立即返回 0 形成死循环。
2. **架构层面**`linenoise()` 是同步阻塞调用,却被放在 10ms 定时器 EVI_TIMER1 中执行,与其他定时器事件循环模型不兼容。
**修复内容**
1. `my_cmd.cpp``read()` 返回值判断改为 `<= 0`(含 EOF 处理);`enableRawMode()` 返回值在 `linenoise()` 中检查,失败直接返回 NULL
2. `app_cmd.cpp`:重构 `cmd_recv``cmd_recv_nonblock()`,用 `select()` 实现非阻塞 stdin 检查 + `isatty()` 过滤非终端环境,移至 EV_TIMER2100ms调用
3. `CLAUDE.md`:全文翻译为中文
**验证**:编译通过(零错误零警告),`./test/RTU < /dev/null` 运行 3 秒 CPU 占用 0.0%。
---
## 2026-06-10 ## 2026-06-10
### #1 libmms_m RCB 订阅编号硬编码 ### #1 libmms_m RCB 订阅编号硬编码

View File

@ -7,15 +7,16 @@ typedef struct
const char *name; const char *name;
void (*func)(int argc, char *argv[]); void (*func)(int argc, char *argv[]);
const char *desc; const char *desc;
void (*complete)(const char *buf, char ***completions, int *ncomp);
}stru_cmd; }stru_cmd;
#define CMD_REGISTER(cmd_name, func_ptr, cmd_desc) \ #define CMD_REGISTER(cmd_name, func_ptr, cmd_desc, ...) \
__attribute__((constructor)) static void register_##func_ptr(void) { \ __attribute__((constructor)) static void register_##func_ptr(void) { \
cmd_manager_add_command(cmd_name, func_ptr, cmd_desc); \ cmd_manager_add_command(cmd_name, func_ptr, cmd_desc, ##__VA_ARGS__); \
} }
void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv[]), const char *desc); void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv[]), const char *desc, void (*complete)(const char *, char ***, int *) = NULL);
stru_cmd *cmd_manager_get_commands(unsigned int *out_count); stru_cmd *cmd_manager_get_commands(unsigned int *out_count);
@ -23,6 +24,7 @@ stru_cmd *cmd_manager_get_commands(unsigned int *out_count);
void cmd_help(int argc, char *argv[]); void cmd_help(int argc, char *argv[]);
stru_cmd *cmd_find(const char *name); stru_cmd *cmd_find(const char *name);
void cmd_complete(const char *buf, char ***completions, int *ncomp); void cmd_complete(const char *buf, char ***completions, int *ncomp);
void cmd_sub_complete(const char *buf, char ***completions, int *ncomp, const char **subs, int sub_count);
char *linenoise(const char *prompt); char *linenoise(const char *prompt);

View File

@ -22,7 +22,7 @@ static std::vector<stru_cmd>& get_cmd_list()
return s_cmd_list; return s_cmd_list;
} }
void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv[]), const char *desc) void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv[]), const char *desc, void (*complete)(const char *, char ***, int *))
{ {
if(NULL == name || NULL == func || NULL == desc) if(NULL == name || NULL == func || NULL == desc)
{ {
@ -34,6 +34,7 @@ void cmd_manager_add_command(const char *name, void (*func)(int argc, char *argv
.name = name, .name = name,
.func = func, .func = func,
.desc = desc, .desc = desc,
.complete = complete,
}); });
} }
@ -104,7 +105,8 @@ static int linenoiseEdit(char *buf, int bufsize, const char *prompt) {
int history_idx = linenoiseHistoryLen; int history_idx = linenoiseHistoryLen;
while (1) { while (1) {
if (read(STDIN_FILENO, &c, 1) == -1) return -1; ssize_t n = read(STDIN_FILENO, &c, 1);
if (n <= 0) return -1;
if (c == '\n' || c == '\r') { if (c == '\n' || c == '\r') {
buf[len] = 0; buf[len] = 0;
@ -164,7 +166,28 @@ static int linenoiseEdit(char *buf, int bufsize, const char *prompt) {
if (completionCallback) { if (completionCallback) {
completionCallback(buf, &completions, &ncomp); completionCallback(buf, &completions, &ncomp);
if (ncomp > 0) { if (ncomp > 0) {
/* 找到最后一个空格,只替换当前词,保留前缀 */
char *last_space = NULL;
for (int i = pos - 1; i >= 0; i--)
{
if (' ' == buf[i])
{
last_space = &buf[i];
break;
}
}
if (NULL != last_space)
{
int keep_len = last_space - buf + 1;
strncpy(last_space + 1, completions[0], bufsize - keep_len - 1);
buf[bufsize - 1] = '\0';
}
else
{
strncpy(buf, completions[0], bufsize - 1); strncpy(buf, completions[0], bufsize - 1);
}
len = pos = strlen(buf); len = pos = strlen(buf);
SAFE_WRITE(STDOUT_FILENO, "\r\033[K", 4); SAFE_WRITE(STDOUT_FILENO, "\r\033[K", 4);
SAFE_WRITE(STDOUT_FILENO, prompt, strlen(prompt)); SAFE_WRITE(STDOUT_FILENO, prompt, strlen(prompt));
@ -189,7 +212,7 @@ static int linenoiseEdit(char *buf, int bufsize, const char *prompt) {
char *linenoise(const char *prompt) { char *linenoise(const char *prompt) {
char buf[1024]; char buf[1024];
enableRawMode(); if (enableRawMode() != 0) return NULL;
int n = linenoiseEdit(buf, sizeof(buf), prompt); int n = linenoiseEdit(buf, sizeof(buf), prompt);
disableRawMode(); disableRawMode();
if (n <= 0) return NULL; if (n <= 0) return NULL;
@ -236,9 +259,35 @@ stru_cmd *cmd_find(const char *name)
void cmd_complete(const char *buf, char ***completions, int *ncomp) void cmd_complete(const char *buf, char ***completions, int *ncomp)
{ {
auto& s_cmd_list = get_cmd_list();
/* 判断是否有空格 —— 有空格则进入子命令补全 */
const char *space = strchr(buf, ' ');
if(NULL != space)
{
size_t cmd_len = space - buf;
for(auto &cmd : s_cmd_list)
{
if(0 == strncmp(cmd.name, buf, cmd_len) && '\0' == cmd.name[cmd_len])
{
if(NULL != cmd.complete)
{
cmd.complete(buf, completions, ncomp);
return;
}
break;
}
}
*ncomp = 0;
*completions = NULL;
return;
}
/* 无空格:命令名前缀匹配(原有逻辑) */
int cnt = 0; int cnt = 0;
char **c = NULL; char **c = NULL;
auto& s_cmd_list = get_cmd_list();
for(auto &cmd : s_cmd_list) for(auto &cmd : s_cmd_list)
{ {
@ -266,6 +315,38 @@ void cmd_complete(const char *buf, char ***completions, int *ncomp)
} }
} }
void cmd_sub_complete(const char *buf, char ***completions, int *ncomp, const char **subs, int sub_count)
{
const char *prefix = strrchr(buf, ' ');
if(NULL == prefix)
{
*ncomp = 0;
*completions = NULL;
return;
}
prefix++;
int cnt = 0;
char **c = NULL;
size_t prefix_len = strlen(prefix);
for(int i = 0; i < sub_count; i++)
{
if(0 == strncmp(subs[i], prefix, prefix_len))
{
if(NULL == c)
{
c = (char **)malloc(sizeof(char *) * (sub_count + 1));
}
c[cnt] = strdup(subs[i]);
cnt++;
}
}
*completions = c;
*ncomp = cnt;
}
void cmd_help(int argc, char *argv[]) void cmd_help(int argc, char *argv[])
{ {
auto& s_cmd_list = get_cmd_list(); auto& s_cmd_list = get_cmd_list();

View File

@ -12,13 +12,18 @@
LOCAL void cmd_recv() LOCAL void cmd_recv()
{ {
char *line = linenoise("cmd > "); if(!isatty(STDIN_FILENO))
if(line == NULL)
{ {
return; return;
} }
if(strlen(line) == 0) char *line = linenoise("cmd > ");
if(NULL == line)
{
return;
}
if(0 == strlen(line))
{ {
free(line); free(line);
return; return;
@ -28,7 +33,7 @@ LOCAL void cmd_recv()
char *orig_line = strdup(line); char *orig_line = strdup(line);
if(orig_line == NULL) if(NULL == orig_line)
{ {
free(line); free(line);
return; return;
@ -37,13 +42,13 @@ LOCAL void cmd_recv()
char *argv[MAX_ARGC]; char *argv[MAX_ARGC];
int argc = 0; int argc = 0;
char *p = strtok(line, " \t"); char *p = strtok(line, " \t");
while(p != NULL && argc < MAX_ARGC) while(NULL != p && argc < MAX_ARGC)
{ {
argv[argc++] = p; argv[argc++] = p;
p = strtok(NULL, " \t"); p = strtok(NULL, " \t");
} }
if(argc == 0) if(0 == argc)
{ {
free(orig_line); free(orig_line);
free(line); free(line);
@ -53,10 +58,10 @@ LOCAL void cmd_recv()
stru_cmd *p_cmd = cmd_find(argv[0]); stru_cmd *p_cmd = cmd_find(argv[0]);
if(NULL == p_cmd) if(NULL == p_cmd)
{ {
if(strcmp(argv[0], "cd") == 0) if(0 == strcmp(argv[0], "cd"))
{ {
const char *path = (argc >= 2) ? argv[1] : getenv("HOME"); const char *path = (argc >= 2) ? argv[1] : getenv("HOME");
if(path == NULL || chdir(path) != 0) if(NULL == path || 0 != chdir(path))
{ {
LOG_E("cd failed: %s", path ? path : "(null)"); LOG_E("cd failed: %s", path ? path : "(null)");
} }
@ -65,8 +70,7 @@ LOCAL void cmd_recv()
return; return;
} }
// 如果不是内部命令,则尝试执行 Linux shell 命令 if(0 != system(orig_line))
if(system(orig_line) != 0)
{ {
LOG_E("shell command failed: %s", orig_line); LOG_E("shell command failed: %s", orig_line);
} }
@ -82,7 +86,7 @@ LOCAL void cmd_recv()
int app_cmd_init1(void *arg) int app_cmd_init1(void *arg)
{ {
// lineniseSetCompletionCallback(cmd_complete); lineniseSetCompletionCallback(cmd_complete);
return 0; return 0;
} }
@ -114,7 +118,7 @@ void *app_cmd(void *arg)
if(event & EV_TIMER1) if(event & EV_TIMER1)
{ {
// cmd_recv(); cmd_recv();
} }
if(event & EV_TIMER2) if(event & EV_TIMER2)

View File

@ -2432,6 +2432,12 @@ LOCAL void cmd_dc(int argc, char *argv[])
} }
} }
CMD_REGISTER("datacenter", cmd_dc, "数据中心的控制命令"); LOCAL void cmd_dc_complete(const char *buf, char ***completions, int *ncomp)
{
static const char *subs[] = {"out", "in", "yk", "ao", "param", "all"};
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs)/sizeof(subs[0]));
}
CMD_REGISTER("datacenter", cmd_dc, "数据中心的控制命令", cmd_dc_complete);

View File

@ -514,4 +514,27 @@ LOCAL void cmd_iec(int argc, char *argv[])
} }
} }
CMD_REGISTER("iec", cmd_iec, "iec线程的控制命令"); LOCAL void cmd_iec_complete(const char *buf, char ***completions, int *ncomp)
{
int spaces = 0;
for(const char *p = buf; *p; p++)
{
if(' ' == *p)
{
spaces++;
}
}
if(1 == spaces)
{
static const char *subs[] = {"run_cnt"};
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs)/sizeof(subs[0]));
}
else if(2 == spaces)
{
static const char *subs[] = {"get", "reset"};
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs)/sizeof(subs[0]));
}
}
CMD_REGISTER("iec", cmd_iec, "iec线程的控制命令", cmd_iec_complete);

View File

@ -875,4 +875,10 @@ LOCAL void cmd_iec61850m(int argc, char *argv[])
} }
} }
CMD_REGISTER(MODULE_IEC61850M, cmd_iec61850m, "iec61850客户端线程的控制命令"); LOCAL void cmd_iec61850m_complete(const char *buf, char ***completions, int *ncomp)
{
static const char *subs[] = {"info", "yk", "set"};
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs)/sizeof(subs[0]));
}
CMD_REGISTER(MODULE_IEC61850M, cmd_iec61850m, "iec61850客户端线程的控制命令", cmd_iec61850m_complete);

View File

@ -1207,8 +1207,13 @@ LOCAL void cmd_self_ptl(int argc, char *argv[])
} }
LOCAL void cmd_self_ptl_complete(const char *buf, char ***completions, int *ncomp)
{
static const char *subs[] = {"1", "3", "5", "6", "9", "11"};
cmd_sub_complete(buf, completions, ncomp, subs, sizeof(subs)/sizeof(subs[0]));
}
CMD_REGISTER("self_ptl", cmd_self_ptl, "私有规约的控制命令"); CMD_REGISTER("self_ptl", cmd_self_ptl, "私有规约的控制命令", cmd_self_ptl_complete);