@codesys/mcp-toolkit 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +10 -7
- package/README.zh-CN.md +6 -5
- package/dist/codesys/compare.d.ts +17 -0
- package/dist/codesys/compare.js +105 -0
- package/dist/codesys/compare.js.map +1 -0
- package/dist/codesys/debug.d.ts +2 -0
- package/dist/codesys/debug.js +96 -2
- package/dist/codesys/debug.js.map +1 -1
- package/dist/codesys/graphical-read.d.ts +7 -4
- package/dist/codesys/graphical-read.js +103 -3
- package/dist/codesys/graphical-read.js.map +1 -1
- package/dist/codesys/graphical.d.ts +51 -4
- package/dist/codesys/graphical.js +247 -44
- package/dist/codesys/graphical.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +2 -2
- package/dist/tools.js +66 -12
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
- package/watcher/mcp_debug.py +54 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.8.0] - 2026-11-14
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `breakpoint_on_change`: a data breakpoint that halts the simulation right
|
|
14
|
+
after a variable is written, optionally only when a condition holds.
|
|
15
|
+
- `watch`: a watch list of expressions, read together, with what changed since
|
|
16
|
+
the previous read, or sampled several times with min, max and changes.
|
|
17
|
+
- `debug_status` shows the call stack while halted (for example
|
|
18
|
+
`PLC_PRG.fbCount <- PLC_PRG`).
|
|
19
|
+
- Checked in the SP22 simulation: the call stack, step into, over and out, a
|
|
20
|
+
data breakpoint with and without a condition, and the watch list.
|
|
21
|
+
- SFC with branches: `create_graphical` takes `sfc.chart`, with alternative
|
|
22
|
+
and parallel branches and jumps; `read_objects` describes a branched SFC as
|
|
23
|
+
such a chart, so it can be edited and sent back. Checked in the SP22
|
|
24
|
+
simulation (both paths of an alternative, a parallel branch).
|
|
25
|
+
- CFC: `create_graphical` takes `cfc` (the same description as `fbd`), and
|
|
26
|
+
`read_objects` reads CFC bodies as that description. Checked in the SP22
|
|
27
|
+
simulation with operators, a function and a TON.
|
|
28
|
+
- `compare_sources`: the open project compared with an `export_sources` folder
|
|
29
|
+
or another `.project` file, with a line diff per changed object.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
- `debug_continue` no longer fails when the simulation is already running.
|
|
33
|
+
|
|
10
34
|
## [2.7.0] - 2026-11-14
|
|
11
35
|
|
|
12
36
|
### Added
|
package/README.md
CHANGED
|
@@ -121,10 +121,10 @@ operation. [The reference](docs/reference.md) describes each one.
|
|
|
121
121
|
| **Change tracking** | `checkpoint` `get_changes` `revert_object` |
|
|
122
122
|
| **Simulation** | `codesys_sim_start` `codesys_sim_stop` `codesys_sim_status` `codesys_sim_control` `codesys_sim_cycle` `codesys_sim_read` `codesys_sim_write` `codesys_sim_force` `codesys_sim_unforce` `codesys_sim_test` |
|
|
123
123
|
| **Trace** | `trace_setup` `trace_record` |
|
|
124
|
-
| **Debug** | `breakpoint_set` `breakpoint_clear` `debug_status` `debug_step` `debug_continue` |
|
|
124
|
+
| **Debug** | `breakpoint_set` `breakpoint_on_change` `breakpoint_clear` `debug_status` `debug_step` `debug_continue` `watch` |
|
|
125
125
|
| **HMI screens** | `hmi_save_screen` `hmi_template` `hmi_screenshot` `hmi_export_codesys` `hmi_list` `hmi_delete_screen` `open_hmi` `hmi_save_symbol` `hmi_symbols` `hmi_delete_symbol` `hmi_translate` |
|
|
126
126
|
| **Alarms** | `alarm_list` `alarm_status` `alarm_acknowledge` |
|
|
127
|
-
| **Handover** | `project_report` `export_sources` `create_recipes` |
|
|
127
|
+
| **Handover** | `project_report` `export_sources` `compare_sources` `create_recipes` |
|
|
128
128
|
| **Helpers** | `batch` `wait` `help` `open_workspace` `show_in_codesys` |
|
|
129
129
|
|
|
130
130
|
`batch` runs up to 50 actions in one call, which is much faster than separate
|
|
@@ -139,12 +139,12 @@ They are **experimental**: checked on CODESYS V3.5 SP21 and SP22 as noted in
|
|
|
139
139
|
the [changelog](CHANGELOG.md). On another version they may report that the
|
|
140
140
|
feature isn't available, or not work.
|
|
141
141
|
|
|
142
|
-
Claude writes Structured Text, and creates ladder (LD), FBD and SFC
|
|
143
|
-
and function blocks with `create_graphical` from a simple description
|
|
144
|
-
networks or steps; CODESYS draws them.
|
|
142
|
+
Claude writes Structured Text, and creates ladder (LD), FBD, CFC and SFC
|
|
143
|
+
programs and function blocks with `create_graphical` from a simple description
|
|
144
|
+
of rungs, networks or steps; CODESYS draws them. SFC charts can have alternative
|
|
145
|
+
and parallel branches and jumps. Reading an LD, FBD, CFC or SFC POU gives the
|
|
145
146
|
same description, so Claude can change existing graphical code too: it edits the
|
|
146
|
-
description and sends it back with `replace: true`.
|
|
147
|
-
stays read-only as PLCopenXML.
|
|
147
|
+
description and sends it back with `replace: true`.
|
|
148
148
|
|
|
149
149
|
## Live panel
|
|
150
150
|
|
|
@@ -289,6 +289,9 @@ project tree, ladder/FBD/SFC bodies as PLCopenXML, a `project.txt` with tasks,
|
|
|
289
289
|
libraries, devices and alarms, and the HMI screens. A `.project` file is
|
|
290
290
|
binary; this folder is what makes a change reviewable as a diff. Exporting
|
|
291
291
|
again rewrites only what changed and removes the files of deleted objects.
|
|
292
|
+
`compare_sources` compares the open project with such a folder or with another
|
|
293
|
+
`.project` file: the objects only in one of them, and a line diff of each
|
|
294
|
+
changed one.
|
|
292
295
|
|
|
293
296
|
## Other clients and models
|
|
294
297
|
|
package/README.zh-CN.md
CHANGED
|
@@ -226,7 +226,8 @@ V3.5 SP21 的仿真中验证。可视化需要 CODESYS 库存储库中有 `Float
|
|
|
226
226
|
`export_sources` 把项目导出为纯文本以便用 git 管理:每个 POU、方法、属性、动作、DUT、GVL 和接口一个
|
|
227
227
|
`.st` 文件,按项目树的结构放在文件夹中;梯形图、FBD 和 SFC 以 PLCopenXML 保存;`project.txt` 包含任务、
|
|
228
228
|
库、设备和报警;以及 HMI 画面。`.project` 文件是二进制的,这个文件夹让每次改动都能以差异的形式审阅。
|
|
229
|
-
|
|
229
|
+
再次导出时只重写有变化的文件,并删除已删除对象的文件。`compare_sources` 将当前打开的项目与这样的文件夹或另一个
|
|
230
|
+
`.project` 文件进行比较:列出只存在于其中一方的对象,并给出每个有变化对象的逐行差异。
|
|
230
231
|
|
|
231
232
|
## 可用操作
|
|
232
233
|
|
|
@@ -245,9 +246,9 @@ V3.5 SP21 的仿真中验证。可视化需要 CODESYS 库存储库中有 `Float
|
|
|
245
246
|
| **改动跟踪** | `checkpoint` `get_changes` `revert_object` |
|
|
246
247
|
| **仿真** | `codesys_sim_start` `codesys_sim_stop` `codesys_sim_status` `codesys_sim_control` `codesys_sim_cycle` `codesys_sim_read` `codesys_sim_write` `codesys_sim_force` `codesys_sim_unforce` `codesys_sim_test` |
|
|
247
248
|
| **跟踪(Trace)** | `trace_setup` `trace_record` |
|
|
248
|
-
| **调试** | `breakpoint_set` `breakpoint_clear` `debug_status` `debug_step` `debug_continue` |
|
|
249
|
+
| **调试** | `breakpoint_set` `breakpoint_on_change` `breakpoint_clear` `debug_status` `debug_step` `debug_continue` `watch` |
|
|
249
250
|
| **报警** | `alarm_list` `alarm_status` `alarm_acknowledge` |
|
|
250
|
-
| **交接** | `project_report` `export_sources` `create_recipes` |
|
|
251
|
+
| **交接** | `project_report` `export_sources` `compare_sources` `create_recipes` |
|
|
251
252
|
| **HMI 画面** | `hmi_save_screen` `hmi_template` `hmi_screenshot` `hmi_export_codesys` `hmi_list` `hmi_delete_screen` `open_hmi` `hmi_save_symbol` `hmi_symbols` `hmi_delete_symbol` `hmi_translate` |
|
|
252
253
|
| **辅助** | `batch` `wait` `help` `open_workspace` `show_in_codesys` |
|
|
253
254
|
|
|
@@ -259,8 +260,8 @@ V3.5 SP21 的仿真中验证。可视化需要 CODESYS 库存储库中有 `Float
|
|
|
259
260
|
验证(见[更新日志](CHANGELOG.md)),在其他版本上可能提示功能不可用,或无法正常工作。
|
|
260
261
|
|
|
261
262
|
Claude 编写结构化文本,并可用 `create_graphical` 根据梯级、网络或步骤的简单描述创建梯形图(LD)、
|
|
262
|
-
FBD 和 SFC 程序及功能块,由 CODESYS
|
|
263
|
-
也能修改已有的图形化代码:修改描述后用 `replace: true`
|
|
263
|
+
FBD、CFC 和 SFC 程序及功能块,由 CODESYS 绘制。SFC 可以包含选择分支、并行分支和跳转。读取 LD、FBD、CFC
|
|
264
|
+
或 SFC POU 时会得到同样的描述,因此 Claude 也能修改已有的图形化代码:修改描述后用 `replace: true` 发回即可。
|
|
264
265
|
|
|
265
266
|
## 安全
|
|
266
267
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** An export_sources folder as relative path -> text (the files its manifest lists, or every text file). */
|
|
2
|
+
export declare function readSourceDir(dir: string): Map<string, string>;
|
|
3
|
+
export interface Comparison {
|
|
4
|
+
added: string[];
|
|
5
|
+
removed: string[];
|
|
6
|
+
changed: {
|
|
7
|
+
file: string;
|
|
8
|
+
plus: number;
|
|
9
|
+
minus: number;
|
|
10
|
+
diff: string[];
|
|
11
|
+
}[];
|
|
12
|
+
same: number;
|
|
13
|
+
}
|
|
14
|
+
/** What `to` has that `from` hasn't, the other way round, and the changed files with their diffs. */
|
|
15
|
+
export declare function compareSources(from: Map<string, string>, to: Map<string, string>, only?: string): Comparison;
|
|
16
|
+
/** The comparison as text; diffs stop after maxLines lines in all. */
|
|
17
|
+
export declare function describeComparison(c: Comparison, fromName: string, toName: string, maxLines?: number): string;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Comparing two projects as the text files export_sources writes: what was
|
|
3
|
+
* added, removed and changed, with a line diff per changed file. Pure, apart
|
|
4
|
+
* from reading an export folder.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
7
|
+
import { join, relative } from "node:path";
|
|
8
|
+
import { countDiff, formatDiff, lineDiff } from "./diff.js";
|
|
9
|
+
const MANIFEST = ".codesys-export.json";
|
|
10
|
+
const TEXT = /\.(st|xml|txt|json)$/i;
|
|
11
|
+
/** An export_sources folder as relative path -> text (the files its manifest lists, or every text file). */
|
|
12
|
+
export function readSourceDir(dir) {
|
|
13
|
+
if (!existsSync(dir) || !statSync(dir).isDirectory())
|
|
14
|
+
throw new Error(`${dir} isn't a folder. Give a folder export_sources wrote, or a .project file.`);
|
|
15
|
+
const out = new Map();
|
|
16
|
+
const manifest = join(dir, MANIFEST);
|
|
17
|
+
let listed;
|
|
18
|
+
if (existsSync(manifest)) {
|
|
19
|
+
try {
|
|
20
|
+
listed = JSON.parse(readFileSync(manifest, "utf8")).files;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
listed = undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const norm = (s) => s.replace(/\r\n/g, "\n");
|
|
27
|
+
if (listed) {
|
|
28
|
+
for (const f of listed)
|
|
29
|
+
if (!f.includes("..") && existsSync(join(dir, f)))
|
|
30
|
+
out.set(f, norm(readFileSync(join(dir, f), "utf8")));
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
const walk = (d) => {
|
|
34
|
+
for (const e of readdirSync(d, { withFileTypes: true })) {
|
|
35
|
+
const p = join(d, e.name);
|
|
36
|
+
if (e.isDirectory()) {
|
|
37
|
+
if (!e.name.startsWith("."))
|
|
38
|
+
walk(p);
|
|
39
|
+
}
|
|
40
|
+
else if (TEXT.test(e.name) && e.name !== MANIFEST)
|
|
41
|
+
out.set(relative(dir, p).replace(/\\/g, "/"), norm(readFileSync(p, "utf8")));
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
walk(dir);
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/** What `to` has that `from` hasn't, the other way round, and the changed files with their diffs. */
|
|
48
|
+
export function compareSources(from, to, only) {
|
|
49
|
+
const want = (only ?? "").toLowerCase().replace(/^\/+|\/+$/g, "");
|
|
50
|
+
const keep = (f) => {
|
|
51
|
+
const l = f.toLowerCase();
|
|
52
|
+
return !want || l === want || l.startsWith(`${want}.`) || l.startsWith(`${want}/`);
|
|
53
|
+
};
|
|
54
|
+
const out = { added: [], removed: [], changed: [], same: 0 };
|
|
55
|
+
for (const [f, text] of to) {
|
|
56
|
+
if (!keep(f))
|
|
57
|
+
continue;
|
|
58
|
+
const before = from.get(f);
|
|
59
|
+
if (before === undefined)
|
|
60
|
+
out.added.push(f);
|
|
61
|
+
else if (before.trimEnd() === text.trimEnd())
|
|
62
|
+
out.same++;
|
|
63
|
+
else {
|
|
64
|
+
const ops = lineDiff(before.trimEnd(), text.trimEnd());
|
|
65
|
+
out.changed.push({ file: f, ...countDiff(ops), diff: formatDiff(ops) });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const f of from.keys())
|
|
69
|
+
if (keep(f) && !to.has(f))
|
|
70
|
+
out.removed.push(f);
|
|
71
|
+
out.added.sort();
|
|
72
|
+
out.removed.sort();
|
|
73
|
+
out.changed.sort((a, b) => a.file.localeCompare(b.file));
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
/** The comparison as text; diffs stop after maxLines lines in all. */
|
|
77
|
+
export function describeComparison(c, fromName, toName, maxLines = 400) {
|
|
78
|
+
const object = (f) => (/\.xml$/i.test(f) ? `${f.slice(0, -4)} (graphical body)` : f.replace(/\.st$/i, ""));
|
|
79
|
+
if (!c.added.length && !c.removed.length && !c.changed.length)
|
|
80
|
+
return `No differences between ${fromName} and ${toName} (${c.same} file(s) compared).`;
|
|
81
|
+
const lines = [
|
|
82
|
+
`${fromName} -> ${toName}: ${c.changed.length} changed, ${c.added.length} added, ${c.removed.length} removed, ${c.same} the same.`,
|
|
83
|
+
];
|
|
84
|
+
if (c.added.length)
|
|
85
|
+
lines.push("", `Only in ${toName}:`, ...c.added.map((f) => ` + ${object(f)}`));
|
|
86
|
+
if (c.removed.length)
|
|
87
|
+
lines.push("", `Only in ${fromName}:`, ...c.removed.map((f) => ` - ${object(f)}`));
|
|
88
|
+
if (c.changed.length) {
|
|
89
|
+
lines.push("", "Changed:", ...c.changed.map((x) => ` ~ ${object(x.file)} (+${x.plus} -${x.minus})`));
|
|
90
|
+
let budget = maxLines;
|
|
91
|
+
for (const x of c.changed) {
|
|
92
|
+
if (budget <= 0) {
|
|
93
|
+
lines.push("", `(More diffs left out: pass path to see one object, or a larger max_lines.)`);
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
const shown = x.diff.slice(0, budget);
|
|
97
|
+
lines.push("", `=== ${object(x.file)} ===`, ...shown);
|
|
98
|
+
if (shown.length < x.diff.length)
|
|
99
|
+
lines.push(` ... (${x.diff.length - shown.length} more lines: pass path to see this object, or a larger max_lines)`);
|
|
100
|
+
budget -= shown.length;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return lines.join("\n");
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=compare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/codesys/compare.ts"],"names":[],"mappings":"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"}
|
package/dist/codesys/debug.d.ts
CHANGED
|
@@ -2,4 +2,6 @@ import type { ActionResult, RegisterAction } from "../actions.js";
|
|
|
2
2
|
import type { AppContext } from "../tools.js";
|
|
3
3
|
/** Implementation line (1-based) -> CODESYS position, for every statement. */
|
|
4
4
|
export declare function lineMap(impl: string, positions: number[]): Map<number, number>;
|
|
5
|
+
/** Bytes of an elementary value as the simulation reads it ('REAL#52', 'TRUE', 'T#1s'). */
|
|
6
|
+
export declare function dataSize(value: string | undefined): number | undefined;
|
|
5
7
|
export declare function registerDebugActions(reg: RegisterAction, ctx: AppContext, run: (fn: () => Promise<string>) => Promise<ActionResult>): void;
|
package/dist/codesys/debug.js
CHANGED
|
@@ -26,6 +26,25 @@ export function lineMap(impl, positions) {
|
|
|
26
26
|
}
|
|
27
27
|
return out;
|
|
28
28
|
}
|
|
29
|
+
const SIZES = {
|
|
30
|
+
BOOL: 1, BYTE: 1, SINT: 1, USINT: 1,
|
|
31
|
+
WORD: 2, INT: 2, UINT: 2,
|
|
32
|
+
DWORD: 4, DINT: 4, UDINT: 4, REAL: 4, TIME: 4, TOD: 4, TIME_OF_DAY: 4, DATE: 4, DT: 4, DATE_AND_TIME: 4,
|
|
33
|
+
LWORD: 8, LINT: 8, ULINT: 8, LREAL: 8, LTIME: 8,
|
|
34
|
+
};
|
|
35
|
+
/** Bytes of an elementary value as the simulation reads it ('REAL#52', 'TRUE', 'T#1s'). */
|
|
36
|
+
export function dataSize(value) {
|
|
37
|
+
if (value === undefined)
|
|
38
|
+
return undefined;
|
|
39
|
+
const v = value.trim();
|
|
40
|
+
if (/^(TRUE|FALSE)$/i.test(v))
|
|
41
|
+
return 1;
|
|
42
|
+
const m = /^([A-Z_]+)#/i.exec(v);
|
|
43
|
+
if (!m)
|
|
44
|
+
return undefined;
|
|
45
|
+
const t = m[1].toUpperCase();
|
|
46
|
+
return SIZES[t] ?? (t === "T" ? 4 : t === "LT" ? 8 : t === "D" ? 4 : undefined);
|
|
47
|
+
}
|
|
29
48
|
export function registerDebugActions(reg, ctx, run) {
|
|
30
49
|
const b = ctx.bridge;
|
|
31
50
|
const needSim = () => {
|
|
@@ -36,14 +55,89 @@ export function registerDebugActions(reg, ctx, run) {
|
|
|
36
55
|
if (!/halt/i.test(s.state))
|
|
37
56
|
return `Simulation: ${s.state}.`;
|
|
38
57
|
const at = s.at;
|
|
58
|
+
const stack = (s.call_stack ?? []).filter((e) => e.pou || e.instance);
|
|
59
|
+
const stackText = stack.length > 1 ? `\nCall stack (innermost first): ${stack.map((e) => e.instance || e.pou).join(" <- ")}` : "";
|
|
39
60
|
if (!at?.path)
|
|
40
|
-
return `Simulation: ${s.state} (position unknown)
|
|
61
|
+
return `Simulation: ${s.state} (position unknown).${stackText}`;
|
|
41
62
|
const map = lineMap(at.implementation ?? "", at.positions ?? []);
|
|
42
63
|
const line = [...map].find(([, p]) => p === at.position)?.[0];
|
|
43
64
|
const code = line ? (at.implementation ?? "").split(/\r?\n/)[line - 1]?.trim() : undefined;
|
|
44
65
|
const end = low(at.position) === 0xffffffff ? " at its end (RETURN)" : "";
|
|
45
|
-
return `Halted in ${at.path}${line ? ` at line ${line}: ${code}` : end} (instance ${at.instance}). Read values with codesys_sim_read, then debug_step or debug_continue
|
|
66
|
+
return `Halted in ${at.path}${line ? ` at line ${line}: ${code}` : end} (instance ${at.instance}). Read values with codesys_sim_read, then debug_step or debug_continue.${stackText}`;
|
|
46
67
|
};
|
|
68
|
+
reg("breakpoint_on_change", {
|
|
69
|
+
description: "A data breakpoint in the running simulation: halt right after a statement writes a variable (optionally only when a condition holds, e.g. 'PLC_PRG.nCount > 10'; CODESYS checks the condition on every write, which slows the simulation down). debug_status then shows where it halted and the call stack. Elementary variables only (1-8 bytes).",
|
|
70
|
+
inputSchema: z.object({
|
|
71
|
+
variable: z.string().describe("e.g. 'PLC_PRG.rSetpoint'"),
|
|
72
|
+
condition: z.string().optional(),
|
|
73
|
+
size: z.number().int().min(1).max(8).optional().describe("Bytes to watch; found from the variable's type when left out"),
|
|
74
|
+
}),
|
|
75
|
+
}, async ({ variable, condition, size }) => run(async () => {
|
|
76
|
+
needSim();
|
|
77
|
+
let bytes = size;
|
|
78
|
+
if (!bytes) {
|
|
79
|
+
const r = await b.call("sim.read", { names: [variable] }, { timeoutMs: 10_000 });
|
|
80
|
+
if (r.errors?.[variable])
|
|
81
|
+
throw new Error(`${variable}: ${r.errors[variable]}`);
|
|
82
|
+
bytes = dataSize(r.values?.[variable]);
|
|
83
|
+
if (!bytes)
|
|
84
|
+
throw new Error(`Can't tell the size of ${variable} (${r.values?.[variable]}): a data breakpoint watches 1-8 bytes of an elementary variable. Give size, or pick a variable of an elementary type.`);
|
|
85
|
+
}
|
|
86
|
+
const r = await b.call("debug.set_data", { expression: variable, size: bytes, ...(condition ? { condition } : {}) });
|
|
87
|
+
if (r.enabled === false)
|
|
88
|
+
throw new Error(`CODESYS created the data breakpoint on ${variable} but didn't enable it: this target may not support data breakpoints.`);
|
|
89
|
+
return `Data breakpoint on ${variable}${condition ? ` when ${condition}` : ""}: the simulation halts right after the statement that writes it (debug_status shows where). breakpoint_clear removes it.`;
|
|
90
|
+
}));
|
|
91
|
+
// A watch list the model keeps: one read of every expression, with what changed since the last read.
|
|
92
|
+
const watched = [];
|
|
93
|
+
let last = {};
|
|
94
|
+
reg("watch", {
|
|
95
|
+
description: "A watch list in the running simulation: add or remove expressions, then read them all at once; each read marks what changed since the previous one. samples > 1 reads several times (every ms) and reports min, max and changes per expression, e.g. to see a value move over a second.",
|
|
96
|
+
inputSchema: z.object({
|
|
97
|
+
add: z.array(z.string()).optional(),
|
|
98
|
+
remove: z.array(z.string()).optional(),
|
|
99
|
+
clear: z.boolean().optional(),
|
|
100
|
+
samples: z.number().int().min(1).max(50).default(1),
|
|
101
|
+
every: z.number().int().min(20).max(5000).default(200).describe("ms between samples"),
|
|
102
|
+
}),
|
|
103
|
+
}, async ({ add, remove, clear, samples, every }) => run(async () => {
|
|
104
|
+
if (clear)
|
|
105
|
+
watched.splice(0), (last = {});
|
|
106
|
+
for (const a of add ?? [])
|
|
107
|
+
if (!watched.includes(a))
|
|
108
|
+
watched.push(a);
|
|
109
|
+
for (const r of remove ?? []) {
|
|
110
|
+
const i = watched.indexOf(r);
|
|
111
|
+
if (i >= 0)
|
|
112
|
+
watched.splice(i, 1);
|
|
113
|
+
}
|
|
114
|
+
if (!watched.length)
|
|
115
|
+
return "The watch list is empty: add expressions, e.g. {add: ['PLC_PRG.nCount']}.";
|
|
116
|
+
needSim();
|
|
117
|
+
const reads = [];
|
|
118
|
+
let errors = {};
|
|
119
|
+
for (let k = 0; k < samples; k++) {
|
|
120
|
+
if (k)
|
|
121
|
+
await new Promise((r) => setTimeout(r, every));
|
|
122
|
+
const r = await b.call("sim.read", { names: watched }, { timeoutMs: 10_000 });
|
|
123
|
+
reads.push(r.values ?? {});
|
|
124
|
+
errors = r.errors ?? {};
|
|
125
|
+
}
|
|
126
|
+
const now = reads[reads.length - 1];
|
|
127
|
+
const lines = watched.map((w) => {
|
|
128
|
+
if (errors[w])
|
|
129
|
+
return ` ${w}: ${errors[w]}`;
|
|
130
|
+
const series = reads.map((r) => r[w]);
|
|
131
|
+
const changed = last[w] !== undefined && last[w] !== now[w] ? ` (was ${last[w]})` : "";
|
|
132
|
+
if (samples === 1)
|
|
133
|
+
return ` ${w} = ${now[w]}${changed}`;
|
|
134
|
+
const nums = series.map((v) => Number(String(v).replace(/^[A-Z_]+#/i, ""))).filter((n) => Number.isFinite(n));
|
|
135
|
+
const changes = series.filter((v, i) => i && v !== series[i - 1]).length;
|
|
136
|
+
return ` ${w} = ${now[w]} [${nums.length === samples ? `min ${Math.min(...nums)}, max ${Math.max(...nums)}, ` : ""}${changes} change(s) in ${samples} reads]${changed}`;
|
|
137
|
+
});
|
|
138
|
+
last = { ...now };
|
|
139
|
+
return [`Watch (${watched.length}):`, ...lines].join("\n");
|
|
140
|
+
}));
|
|
47
141
|
reg("breakpoint_set", {
|
|
48
142
|
description: "Set a breakpoint in the running simulation at a line of a POU's implementation. The simulation halts there; debug_status shows where, codesys_sim_read reads values, debug_step steps, debug_continue goes on. For a function block give the instance, e.g. 'PLC_PRG.fbPump'.",
|
|
49
143
|
inputSchema: z.object({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/codesys/debug.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/codesys/debug.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
* LD: every coil's power flow is followed back to the rail: contacts in series
|
|
8
8
|
* become {and}, parallel paths {or}. FBD: each output variable (or output
|
|
9
9
|
* written straight on a block) is followed back through blocks to the inputs.
|
|
10
|
-
* SFC: steps, their actions and the transition to the next step
|
|
11
|
-
*
|
|
10
|
+
* SFC: steps, their actions and the transition to the next step; with branches,
|
|
11
|
+
* the chart (alternative and parallel paths, jumps). What has no place in the
|
|
12
|
+
* description (function boxes in LD) is reported.
|
|
12
13
|
*/
|
|
13
|
-
import type { Fbd, Logic } from "./graphical.js";
|
|
14
|
+
import type { Fbd, Logic, SfcElement } from "./graphical.js";
|
|
14
15
|
interface El {
|
|
15
16
|
name: string;
|
|
16
17
|
attrs: Record<string, string>;
|
|
@@ -32,7 +33,7 @@ export type GraphicalDescription = {
|
|
|
32
33
|
};
|
|
33
34
|
notes: string[];
|
|
34
35
|
} | {
|
|
35
|
-
kind: "fbd";
|
|
36
|
+
kind: "fbd" | "cfc";
|
|
36
37
|
spec: {
|
|
37
38
|
networks: {
|
|
38
39
|
expr: Fbd;
|
|
@@ -55,6 +56,8 @@ export type GraphicalDescription = {
|
|
|
55
56
|
next: string;
|
|
56
57
|
when: string;
|
|
57
58
|
}[];
|
|
59
|
+
} | {
|
|
60
|
+
chart: SfcElement[];
|
|
58
61
|
};
|
|
59
62
|
notes: string[];
|
|
60
63
|
};
|
|
@@ -50,8 +50,42 @@ export function describeGraphical(xml) {
|
|
|
50
50
|
const sfc = kid(body, "SFC");
|
|
51
51
|
if (sfc)
|
|
52
52
|
return readSfc(sfc, pou);
|
|
53
|
+
const cfc = find(body, "CFC");
|
|
54
|
+
if (cfc)
|
|
55
|
+
return { ...readFbd(cfcAsFbd(cfc)), kind: "cfc" };
|
|
53
56
|
return undefined;
|
|
54
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* CODESYS's CFC as the FBD the reader knows: every line runs through an unnamed
|
|
60
|
+
* connector, so a connection to a connector becomes the connector's own
|
|
61
|
+
* connection (an input variable's or a function's output has no parameter in
|
|
62
|
+
* FBD terms), and the elements are taken in execution order.
|
|
63
|
+
*/
|
|
64
|
+
function cfcAsFbd(cfc) {
|
|
65
|
+
const byId = new Map(cfc.children.filter((c) => c.attrs.localId !== undefined).map((c) => [c.attrs.localId, c]));
|
|
66
|
+
const through = (conn) => {
|
|
67
|
+
const seen = new Set();
|
|
68
|
+
let c = conn;
|
|
69
|
+
for (;;) {
|
|
70
|
+
const target = byId.get(c.attrs.refLocalId);
|
|
71
|
+
if (target?.name !== "connector" || seen.has(target.attrs.localId))
|
|
72
|
+
break;
|
|
73
|
+
seen.add(target.attrs.localId);
|
|
74
|
+
const next = kids(kid(target, "connectionPointIn"), "connection")[0];
|
|
75
|
+
if (!next)
|
|
76
|
+
return { ...c, attrs: { refLocalId: "missing" } };
|
|
77
|
+
c = next;
|
|
78
|
+
}
|
|
79
|
+
const src = byId.get(c.attrs.refLocalId);
|
|
80
|
+
const plain = src?.name === "inVariable" || (src?.name === "block" && !src.attrs.instanceName);
|
|
81
|
+
const { formalParameter, ...rest } = c.attrs;
|
|
82
|
+
return { ...c, attrs: plain || !formalParameter ? rest : { ...rest, formalParameter } };
|
|
83
|
+
};
|
|
84
|
+
const rewire = (e) => (e.name === "connection" ? through(e) : { ...e, children: e.children.map(rewire) });
|
|
85
|
+
const order = (e) => (e.attrs.executionOrderId === undefined ? -1 : Number(e.attrs.executionOrderId));
|
|
86
|
+
const children = cfc.children.filter((c) => c.name !== "connector").map(rewire);
|
|
87
|
+
return { ...cfc, name: "FBD", children: children.sort((a, b) => order(a) - order(b)) };
|
|
88
|
+
}
|
|
55
89
|
function readLadder(ld) {
|
|
56
90
|
const notes = new Set();
|
|
57
91
|
const byId = new Map(ld.children.filter((c) => c.attrs.localId !== undefined).map((c) => [c.attrs.localId, c]));
|
|
@@ -180,9 +214,8 @@ function readSfc(sfc, pou) {
|
|
|
180
214
|
const notes = new Set();
|
|
181
215
|
const byId = new Map(sfc.children.filter((c) => c.attrs.localId !== undefined).map((c) => [c.attrs.localId, c]));
|
|
182
216
|
const bodies = new Map(kids(kid(pou, "actions"), "action").map((a) => [a.attrs.name, allText(find(a, "xhtml") ?? find(a, "ST")).trim()]));
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
notes.add(`${e.name} (a branch): the description holds one sequence; read_objects shows the XML`);
|
|
217
|
+
if (sfc.children.some((e) => /Divergence/.test(e.name)))
|
|
218
|
+
return readSfcChart(sfc, byId, bodies);
|
|
186
219
|
const after = (ref) => sfc.children.filter((c) => inputsOf(c).some((i) => i.ref === ref));
|
|
187
220
|
const steps = sfc.children
|
|
188
221
|
.filter((c) => c.name === "step")
|
|
@@ -211,4 +244,71 @@ function readSfc(sfc, pou) {
|
|
|
211
244
|
});
|
|
212
245
|
return { kind: "sfc", spec: { steps }, notes: [...notes] };
|
|
213
246
|
}
|
|
247
|
+
/** An SFC with branches, as create_graphical's chart: walked from the initial step along the connections. */
|
|
248
|
+
function readSfcChart(sfc, byId, bodies) {
|
|
249
|
+
const notes = new Set();
|
|
250
|
+
// Every connectionPointIn counts: a convergence has one per path.
|
|
251
|
+
const ins = (e) => kids(e, "connectionPointIn").flatMap((p) => kids(p, "connection").map((c) => c.attrs.refLocalId));
|
|
252
|
+
const after = (id) => sfc.children.filter((c) => c.name !== "actionBlock" && c.name !== "inVariable" && ins(c).includes(id));
|
|
253
|
+
const actionsOf = (id) => sfc.children
|
|
254
|
+
.filter((c) => c.name === "actionBlock" && ins(c).includes(id))
|
|
255
|
+
.flatMap((b) => kids(b, "action").map((a) => {
|
|
256
|
+
const name = kid(a, "reference")?.attrs.name ?? "";
|
|
257
|
+
return { name, qualifier: (a.attrs.qualifier ?? "N"), st: bodies.get(name) ?? allText(find(a, "xhtml")).trim() };
|
|
258
|
+
}));
|
|
259
|
+
const condition = (tr) => {
|
|
260
|
+
const cond = kid(tr, "condition");
|
|
261
|
+
const src = inputsOf(cond)[0];
|
|
262
|
+
return src ? allText(kid(byId.get(src.ref), "expression")).trim() : allText(find(cond ?? tr, "xhtml")).trim() || (kid(cond, "reference")?.attrs.name ?? "");
|
|
263
|
+
};
|
|
264
|
+
const seen = new Set();
|
|
265
|
+
/** The sequence from node on, and the convergence it ends at (the end of a branch path). */
|
|
266
|
+
const walk = (start) => {
|
|
267
|
+
const seq = [];
|
|
268
|
+
let node = start;
|
|
269
|
+
while (node) {
|
|
270
|
+
const id = node.attrs.localId;
|
|
271
|
+
if (/Convergence$/.test(node.name))
|
|
272
|
+
return { seq, conv: node };
|
|
273
|
+
if (seen.has(id)) {
|
|
274
|
+
notes.add("a connection loops back without a jump");
|
|
275
|
+
return { seq };
|
|
276
|
+
}
|
|
277
|
+
seen.add(id);
|
|
278
|
+
if (node.name === "step") {
|
|
279
|
+
const acts = actionsOf(id);
|
|
280
|
+
seq.push({ step: node.attrs.name, ...(node.attrs.initialStep === "true" ? { initial: true } : {}), ...(acts.length ? { actions: acts } : {}) });
|
|
281
|
+
node = after(id)[0];
|
|
282
|
+
}
|
|
283
|
+
else if (node.name === "transition") {
|
|
284
|
+
seq.push({ when: condition(node) });
|
|
285
|
+
node = after(id)[0];
|
|
286
|
+
}
|
|
287
|
+
else if (node.name === "jumpStep") {
|
|
288
|
+
seq.push({ jump: node.attrs.targetName });
|
|
289
|
+
const conv = after(id).find((c) => /Convergence$/.test(c.name));
|
|
290
|
+
return conv ? { seq, conv } : { seq };
|
|
291
|
+
}
|
|
292
|
+
else if (/Divergence$/.test(node.name)) {
|
|
293
|
+
const paths = after(id).map(walk);
|
|
294
|
+
const conv = paths.find((p) => p.conv)?.conv;
|
|
295
|
+
seq.push(node.name === "selectionDivergence" ? { alternative: paths.map((p) => p.seq) } : { parallel: paths.map((p) => p.seq) });
|
|
296
|
+
if (!conv)
|
|
297
|
+
return { seq };
|
|
298
|
+
// Past the convergence (a path that ended in a jump leads nowhere further).
|
|
299
|
+
const allJump = node.name === "selectionDivergence" && paths.every((p) => p.seq.length && "jump" in p.seq[p.seq.length - 1]);
|
|
300
|
+
node = allJump ? undefined : after(conv.attrs.localId)[0];
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
notes.add(`${node.name} elements aren't part of the description; read_objects shows the XML`);
|
|
304
|
+
return { seq };
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return { seq };
|
|
308
|
+
};
|
|
309
|
+
const steps = sfc.children.filter((c) => c.name === "step");
|
|
310
|
+
const first = steps.find((s) => s.attrs.initialStep === "true") ?? steps.find((s) => !ins(s).length) ?? steps[0];
|
|
311
|
+
const chart = walk(first).seq;
|
|
312
|
+
return { kind: "sfc", spec: { chart }, notes: [...notes] };
|
|
313
|
+
}
|
|
214
314
|
//# sourceMappingURL=graphical-read.js.map
|