@codesys/mcp-toolkit 1.5.8 → 2.0.0-alpha.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 +153 -189
- package/LICENSE +21 -21
- package/README.md +224 -107
- package/dist/actions.d.ts +28 -0
- package/dist/actions.js +98 -0
- package/dist/actions.js.map +1 -0
- package/dist/bridge/bridge.d.ts +105 -0
- package/dist/bridge/bridge.js +400 -0
- package/dist/bridge/bridge.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +196 -0
- package/dist/cli.js.map +1 -0
- package/dist/codesys/cache.d.ts +48 -0
- package/dist/codesys/cache.js +82 -0
- package/dist/codesys/cache.js.map +1 -0
- package/dist/codesys/changes.d.ts +57 -0
- package/dist/codesys/changes.js +133 -0
- package/dist/codesys/changes.js.map +1 -0
- package/dist/codesys/decl.d.ts +45 -0
- package/dist/codesys/decl.js +251 -0
- package/dist/codesys/decl.js.map +1 -0
- package/dist/codesys/devices.d.ts +34 -0
- package/dist/codesys/devices.js +82 -0
- package/dist/codesys/devices.js.map +1 -0
- package/dist/codesys/diff.d.ts +13 -0
- package/dist/codesys/diff.js +61 -0
- package/dist/codesys/diff.js.map +1 -0
- package/dist/codesys/install.d.ts +40 -0
- package/dist/codesys/install.js +144 -0
- package/dist/codesys/install.js.map +1 -0
- package/dist/codesys/library-browse.d.ts +19 -0
- package/dist/codesys/library-browse.js +57 -0
- package/dist/codesys/library-browse.js.map +1 -0
- package/dist/codesys/outline.d.ts +32 -0
- package/dist/codesys/outline.js +219 -0
- package/dist/codesys/outline.js.map +1 -0
- package/dist/codesys/simulation.d.ts +34 -0
- package/dist/codesys/simulation.js +57 -0
- package/dist/codesys/simulation.js.map +1 -0
- package/dist/codesys/st.d.ts +36 -0
- package/dist/codesys/st.js +69 -0
- package/dist/codesys/st.js.map +1 -0
- package/dist/daemon.d.ts +46 -0
- package/dist/daemon.js +173 -0
- package/dist/daemon.js.map +1 -0
- package/dist/driver.d.ts +25 -0
- package/dist/driver.js +33 -0
- package/dist/driver.js.map +1 -0
- package/dist/panel/sim-panel.html +357 -0
- package/dist/panel/viewer.html +126 -0
- package/dist/panel-types.d.ts +20 -0
- package/dist/panel-types.js +3 -0
- package/dist/panel-types.js.map +1 -0
- package/dist/panel.d.ts +27 -0
- package/dist/panel.js +208 -0
- package/dist/panel.js.map +1 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +33 -974
- package/dist/server.js.map +1 -0
- package/dist/tools.d.ts +103 -0
- package/dist/tools.js +793 -0
- package/dist/tools.js.map +1 -0
- package/dist/viewer.d.ts +14 -0
- package/dist/viewer.js +125 -0
- package/dist/viewer.js.map +1 -0
- package/package.json +37 -21
- package/watcher/mcp_compat.py +147 -0
- package/watcher/mcp_ops.py +1178 -0
- package/watcher/mcp_sim.py +246 -0
- package/watcher/watcher.py +255 -0
- package/.claude/settings.local.json +0 -29
- package/CLAUDE.md +0 -26
- package/CONTRIBUTING.md +0 -72
- package/README.md.enhanced +0 -155
- package/codesys-mcp-toolkit-1.2.0.tgz +0 -0
- package/codesys-mcp-toolkit-1.2.1.tgz +0 -0
- package/codesys-mcp-toolkit-1.5.7.tgz +0 -0
- package/codesys-mcp-toolkit-1.5.8.tgz +0 -0
- package/dist/bin.js +0 -75
- package/dist/check_session_paths.js +0 -149
- package/dist/codesys_interop.js +0 -435
- package/dist/direct_session_command.js +0 -293
- package/dist/scriptLoader.js +0 -165
- package/dist/scripts/check_status.py +0 -21
- package/dist/scripts/compile_project.py +0 -65
- package/dist/scripts/create_method.py +0 -80
- package/dist/scripts/create_pou.py +0 -102
- package/dist/scripts/create_project.py +0 -116
- package/dist/scripts/create_property.py +0 -78
- package/dist/scripts/ensure_project_open.py +0 -154
- package/dist/scripts/find_object_by_path.py +0 -111
- package/dist/scripts/get_pou_code.py +0 -91
- package/dist/scripts/get_project_structure.py +0 -72
- package/dist/scripts/open_project.py +0 -25
- package/dist/scripts/save_project.py +0 -29
- package/dist/scripts/session_status.py +0 -281
- package/dist/scripts/set_pou_code.py +0 -109
- package/dist/scripts/start_session.py +0 -809
- package/dist/scripts/stop_session.py +0 -324
- package/dist/sessionManager.js +0 -798
- package/docs/configuration.md +0 -141
- package/docs/index.md +0 -26
- package/docs/installation.md +0 -84
- package/docs/session_management.md +0 -110
- package/examples/README.md +0 -78
- package/examples/sample_config.json +0 -32
- package/replacements_session_status.txt +0 -16
- package/scriptDoc.txt +0 -8679
- package/scripts/build.js +0 -25
- package/scripts/fix_fstrings.py +0 -76
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { parseDeclaration, signature } from "./decl.js";
|
|
2
|
+
const TOP_KINDS = new Set(["pou", "dut", "gvl", "interface"]);
|
|
3
|
+
const SECTION_LABEL = {
|
|
4
|
+
VAR_INPUT: "in",
|
|
5
|
+
VAR_OUTPUT: "out",
|
|
6
|
+
VAR_IN_OUT: "in_out",
|
|
7
|
+
VAR: "var",
|
|
8
|
+
VAR_TEMP: "temp",
|
|
9
|
+
VAR_STAT: "stat",
|
|
10
|
+
VAR_INST: "inst",
|
|
11
|
+
VAR_GLOBAL: "global",
|
|
12
|
+
VAR_EXTERNAL: "external",
|
|
13
|
+
VAR_CONFIG: "config",
|
|
14
|
+
};
|
|
15
|
+
function intervalText(t) {
|
|
16
|
+
if (!t.interval)
|
|
17
|
+
return t.kind ?? "";
|
|
18
|
+
return `${t.interval}${t.interval_unit && !/[a-z]/i.test(t.interval) ? ` ${t.interval_unit}` : ""}`;
|
|
19
|
+
}
|
|
20
|
+
const varText = (v, withComment = true) => `${v.name}${v.at ? ` AT ${v.at}` : ""} : ${v.type}${v.init !== undefined ? ` := ${v.init}` : ""}${withComment && v.comment ? ` // ${v.comment}` : ""}`;
|
|
21
|
+
export function buildOutline(nodes, tasks, o = {}) {
|
|
22
|
+
const byPath = new Map(nodes.map((n) => [n.path.toLowerCase(), n]));
|
|
23
|
+
const parentOf = (p) => (p.includes("/") ? p.slice(0, p.lastIndexOf("/")) : "");
|
|
24
|
+
const kids = new Map();
|
|
25
|
+
for (const n of nodes) {
|
|
26
|
+
const p = parentOf(n.path).toLowerCase();
|
|
27
|
+
if (!kids.has(p))
|
|
28
|
+
kids.set(p, []);
|
|
29
|
+
kids.get(p).push(n);
|
|
30
|
+
}
|
|
31
|
+
const childrenOf = (n, ...kinds) => (kids.get(n.path.toLowerCase()) ?? []).filter((c) => !kinds.length || kinds.includes(c.kind));
|
|
32
|
+
const isContainer = (p) => p === "" || byPath.get(p.toLowerCase())?.kind === "folder";
|
|
33
|
+
const tops = nodes.filter((n) => TOP_KINDS.has(n.kind) && isContainer(parentOf(n.path)));
|
|
34
|
+
const parsed = new Map();
|
|
35
|
+
const parse = (n) => {
|
|
36
|
+
let p = parsed.get(n.path);
|
|
37
|
+
if (!p) {
|
|
38
|
+
p = parseDeclaration(n.declaration);
|
|
39
|
+
parsed.set(n.path, p);
|
|
40
|
+
}
|
|
41
|
+
return p;
|
|
42
|
+
};
|
|
43
|
+
const runBy = new Map();
|
|
44
|
+
for (const t of tasks)
|
|
45
|
+
for (const pou of t.pous) {
|
|
46
|
+
const k = pou.split(".").pop().toLowerCase();
|
|
47
|
+
runBy.set(k, [...(runBy.get(k) ?? []), `${t.name} ${intervalText(t)}`.trim()]);
|
|
48
|
+
}
|
|
49
|
+
const isTest = (n) => parse(n).header.attributes.some((a) => a.toLowerCase() === "test");
|
|
50
|
+
// ---- one object, in detail
|
|
51
|
+
const detail = (n) => {
|
|
52
|
+
const p = parse(n);
|
|
53
|
+
const h = p.header;
|
|
54
|
+
const out = [];
|
|
55
|
+
const head = [n.path, kindText(n, p)];
|
|
56
|
+
const run = runBy.get(n.name.toLowerCase());
|
|
57
|
+
if (run)
|
|
58
|
+
head.push(`run by ${run.join(", ")}`);
|
|
59
|
+
out.push(head.join(" "));
|
|
60
|
+
if (n.st === false)
|
|
61
|
+
out.push(" (graphical body: not ST)");
|
|
62
|
+
if (h.attributes.length)
|
|
63
|
+
out.push(` attributes: ${h.attributes.join(", ")}`);
|
|
64
|
+
if (p.dutKind === "enum")
|
|
65
|
+
out.push(` members: ${p.enumMembers.map((m) => (m.value !== undefined ? `${m.name} := ${m.value}` : m.name)).join(", ")}${p.baseType ? ` (base ${p.baseType})` : ""}`);
|
|
66
|
+
if (p.dutKind === "alias")
|
|
67
|
+
out.push(` = ${p.baseType}`);
|
|
68
|
+
for (const f of p.fields ?? [])
|
|
69
|
+
out.push(` ${varText(f)}`);
|
|
70
|
+
let section = "";
|
|
71
|
+
for (const v of p.vars) {
|
|
72
|
+
if (v.section !== section) {
|
|
73
|
+
section = v.section;
|
|
74
|
+
out.push(` ${SECTION_LABEL[v.section] ?? v.section}${v.constant ? " constant" : ""}${v.retain ? " retain" : ""}${v.persistent ? " persistent" : ""}:`);
|
|
75
|
+
}
|
|
76
|
+
out.push(` ${varText(v)}`);
|
|
77
|
+
}
|
|
78
|
+
for (const m of childrenOf(n, "method", "interface_method")) {
|
|
79
|
+
const mp = parse(m);
|
|
80
|
+
const locals = mp.vars.filter((v) => !["VAR_INPUT", "VAR_OUTPUT", "VAR_IN_OUT"].includes(v.section)).length;
|
|
81
|
+
out.push(` method ${[...mp.header.modifiers, ""].join(" ")}${signature(mp, m.name)}${locals ? ` (${locals} local${locals > 1 ? "s" : ""})` : ""}`);
|
|
82
|
+
}
|
|
83
|
+
for (const pr of childrenOf(n, "property")) {
|
|
84
|
+
const pp = parse(pr);
|
|
85
|
+
const acc = childrenOf(pr, "accessor").map((a) => a.name.toLowerCase());
|
|
86
|
+
out.push(` property ${[...pp.header.modifiers, ""].join(" ")}${pr.name} : ${pp.header.returnType ?? "?"} (${acc.join(", ") || "no accessors"})`);
|
|
87
|
+
}
|
|
88
|
+
for (const a of childrenOf(n, "action"))
|
|
89
|
+
out.push(` action ${a.name}${a.st === false ? " [non-ST]" : ""}`);
|
|
90
|
+
const lines = (n.implementation ?? "").replace(/\s+$/, "").split("\n").filter((l) => l.trim()).length;
|
|
91
|
+
if (n.kind === "pou")
|
|
92
|
+
out.push(` implementation: ${lines} line(s)`);
|
|
93
|
+
return out;
|
|
94
|
+
};
|
|
95
|
+
// ---- overview line(s) for one object
|
|
96
|
+
const brief = (n) => {
|
|
97
|
+
const p = parse(n);
|
|
98
|
+
const run = runBy.get(n.name.toLowerCase());
|
|
99
|
+
const tags = [kindText(n, p), run ? `[${run.join(", ")}]` : "", n.st === false ? "[non-ST]" : ""].filter(Boolean).join(" ");
|
|
100
|
+
const out = [`${n.path} ${tags}`];
|
|
101
|
+
if (n.kind === "pou" && !isTest(n)) {
|
|
102
|
+
const ins = p.vars.filter((v) => v.section === "VAR_INPUT" || v.section === "VAR_IN_OUT");
|
|
103
|
+
const outs = p.vars.filter((v) => v.section === "VAR_OUTPUT");
|
|
104
|
+
if (ins.length)
|
|
105
|
+
out.push(` in: ${ins.map((v) => varText(v, false)).join("; ")}`);
|
|
106
|
+
if (outs.length)
|
|
107
|
+
out.push(` out: ${outs.map((v) => varText(v, false)).join("; ")}`);
|
|
108
|
+
const ms = childrenOf(n, "method").map((m) => signature(parse(m), m.name));
|
|
109
|
+
if (ms.length)
|
|
110
|
+
out.push(` methods: ${ms.join("; ")}`);
|
|
111
|
+
const ps = childrenOf(n, "property").map((pr) => {
|
|
112
|
+
const acc = childrenOf(pr, "accessor").map((a) => a.name.toLowerCase());
|
|
113
|
+
return `${pr.name} : ${parse(pr).header.returnType ?? "?"}${acc.length === 1 ? ` (${acc[0]} only)` : ""}`;
|
|
114
|
+
});
|
|
115
|
+
if (ps.length)
|
|
116
|
+
out.push(` properties: ${ps.join("; ")}`);
|
|
117
|
+
const as = childrenOf(n, "action").map((a) => a.name);
|
|
118
|
+
if (as.length)
|
|
119
|
+
out.push(` actions: ${as.join(", ")}`);
|
|
120
|
+
}
|
|
121
|
+
else if (n.kind === "interface") {
|
|
122
|
+
const ms = childrenOf(n, "interface_method", "method").map((m) => signature(parse(m), m.name));
|
|
123
|
+
if (ms.length)
|
|
124
|
+
out.push(` methods: ${ms.join("; ")}`);
|
|
125
|
+
}
|
|
126
|
+
else if (n.kind === "dut" && p.fields?.length) {
|
|
127
|
+
out.push(` fields: ${p.fields.slice(0, 12).map((f) => `${f.name} : ${f.type}`).join("; ")}${p.fields.length > 12 ? `; ... (${p.fields.length})` : ""}`);
|
|
128
|
+
}
|
|
129
|
+
return out;
|
|
130
|
+
};
|
|
131
|
+
const max = o.maxLines ?? 400;
|
|
132
|
+
const clip = (lines, hint) => (lines.length > max ? [...lines.slice(0, max), `... ${lines.length - max} more line(s). ${hint}`] : lines);
|
|
133
|
+
if (o.path) {
|
|
134
|
+
const target = byPath.get(o.path.replace(/^\/+/, "").toLowerCase());
|
|
135
|
+
if (!target) {
|
|
136
|
+
const close = nodes.filter((n) => n.name.toLowerCase() === o.path.split("/").pop().toLowerCase()).map((n) => n.path);
|
|
137
|
+
return `No object '${o.path}'.${close.length ? ` Did you mean: ${close.join(", ")}?` : ""}`;
|
|
138
|
+
}
|
|
139
|
+
if (target.kind === "folder") {
|
|
140
|
+
const inside = tops.filter((t) => t.path.toLowerCase().startsWith(target.path.toLowerCase() + "/"));
|
|
141
|
+
return clip([`${target.path}/ (${inside.length} object(s))`, ...inside.flatMap(brief)], "Ask for one object for details.").join("\n");
|
|
142
|
+
}
|
|
143
|
+
const top = TOP_KINDS.has(target.kind) ? target : undefined;
|
|
144
|
+
if (top)
|
|
145
|
+
return clip(detail(top), "").join("\n");
|
|
146
|
+
// a method, property or action: its own declaration
|
|
147
|
+
const p = parse(target);
|
|
148
|
+
return clip([`${target.path} ${target.kind}`, ...p.vars.map((v) => ` ${SECTION_LABEL[v.section] ?? v.section}: ${varText(v)}`), ...(p.header.returnType ? [` returns ${p.header.returnType}`] : [])], "").join("\n");
|
|
149
|
+
}
|
|
150
|
+
const count = (pred) => tops.filter(pred).length;
|
|
151
|
+
const tests = tops.filter((n) => n.kind === "pou" && isTest(n));
|
|
152
|
+
const header = [
|
|
153
|
+
`Outline: ${count((n) => n.kind === "pou" && !isTest(n))} POU(s), ${count((n) => n.kind === "gvl")} GVL(s), ${count((n) => n.kind === "dut")} DUT(s), ${count((n) => n.kind === "interface")} interface(s)${tests.length ? `, ${tests.length} test(s)` : ""}.`,
|
|
154
|
+
`Tasks: ${tasks.length ? tasks.map((t) => `${t.name} (${intervalText(t)}${t.priority ? `, prio ${t.priority}` : ""}) -> ${t.pous.join(", ") || "nothing"}`).join("; ") : "none"}`,
|
|
155
|
+
];
|
|
156
|
+
const order = (n) => (isTest(n) ? 9 : n.kind === "pou" ? (n.sub === "program" ? 0 : n.sub === "function_block" ? 1 : 2) : n.kind === "interface" ? 3 : n.kind === "dut" ? 4 : 5);
|
|
157
|
+
const sorted = [...tops].sort((a, b) => order(a) - order(b) || a.path.localeCompare(b.path));
|
|
158
|
+
const body = sorted.filter((n) => !isTest(n)).flatMap(brief);
|
|
159
|
+
if (tests.length)
|
|
160
|
+
body.push(`tests: ${tests.map((t) => t.path).join(", ")}`);
|
|
161
|
+
return clip([...header, ...body], "Pass path (an object or folder) to narrow it.").join("\n");
|
|
162
|
+
}
|
|
163
|
+
function kindText(n, p) {
|
|
164
|
+
const h = p.header;
|
|
165
|
+
const mods = h.modifiers.length ? `${h.modifiers.join(" ")} ` : "";
|
|
166
|
+
if (n.kind === "pou") {
|
|
167
|
+
if (h.attributes.some((a) => a.toLowerCase() === "test"))
|
|
168
|
+
return "TEST";
|
|
169
|
+
const kw = h.keyword || (n.sub ?? "").toUpperCase();
|
|
170
|
+
let s = `${mods}${kw}`;
|
|
171
|
+
if (h.returnType)
|
|
172
|
+
s += ` : ${h.returnType}`;
|
|
173
|
+
if (h.extends?.length)
|
|
174
|
+
s += ` EXTENDS ${h.extends.join(", ")}`;
|
|
175
|
+
if (h.implements?.length)
|
|
176
|
+
s += ` IMPLEMENTS ${h.implements.join(", ")}`;
|
|
177
|
+
return s;
|
|
178
|
+
}
|
|
179
|
+
if (n.kind === "interface") {
|
|
180
|
+
const bases = (h.extends ?? []).filter((b) => !/^__System\.IQueryInterface$/i.test(b));
|
|
181
|
+
return `INTERFACE${bases.length ? ` EXTENDS ${bases.join(", ")}` : ""}`;
|
|
182
|
+
}
|
|
183
|
+
if (n.kind === "gvl") {
|
|
184
|
+
const q = h.attributes.some((a) => a.toLowerCase() === "qualified_only");
|
|
185
|
+
return `GVL (${p.vars.length} var${p.vars.length === 1 ? "" : "s"}${q ? ", qualified_only" : ""})`;
|
|
186
|
+
}
|
|
187
|
+
if (n.kind === "dut") {
|
|
188
|
+
if (p.dutKind === "enum")
|
|
189
|
+
return `ENUM (${p.enumMembers.map((m) => (m.value !== undefined ? `${m.name}=${m.value}` : m.name)).join(", ")})`;
|
|
190
|
+
if (p.dutKind === "alias")
|
|
191
|
+
return `ALIAS = ${p.baseType}`;
|
|
192
|
+
return `${(p.dutKind ?? "dut").toUpperCase()}${p.fields ? ` (${p.fields.length} field${p.fields.length === 1 ? "" : "s"})` : ""}`;
|
|
193
|
+
}
|
|
194
|
+
return n.kind;
|
|
195
|
+
}
|
|
196
|
+
/** Variables with AT addresses (including the %I* and %Q* placeholders), from GVLs and POUs. */
|
|
197
|
+
export function ioList(nodes) {
|
|
198
|
+
const out = [];
|
|
199
|
+
for (const n of nodes) {
|
|
200
|
+
if (!["gvl", "pou"].includes(n.kind))
|
|
201
|
+
continue;
|
|
202
|
+
for (const v of parseDeclaration(n.declaration).vars) {
|
|
203
|
+
if (!v.at)
|
|
204
|
+
continue;
|
|
205
|
+
const area = /^%([IQM])/i.exec(v.at)?.[1]?.toUpperCase();
|
|
206
|
+
out.push({
|
|
207
|
+
owner: n.path,
|
|
208
|
+
name: v.name,
|
|
209
|
+
at: v.at,
|
|
210
|
+
type: v.type,
|
|
211
|
+
direction: area === "I" ? "input" : area === "Q" ? "output" : "memory",
|
|
212
|
+
...(v.comment ? { comment: v.comment } : {}),
|
|
213
|
+
placeholder: /\*$/.test(v.at),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return out;
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=outline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outline.js","sourceRoot":"","sources":["../../src/codesys/outline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { RegisterAction } from "../actions.js";
|
|
2
|
+
import type { AppContext } from "../tools.js";
|
|
3
|
+
interface Status {
|
|
4
|
+
running: boolean;
|
|
5
|
+
state?: string;
|
|
6
|
+
operation?: string;
|
|
7
|
+
forced?: string[];
|
|
8
|
+
cycles?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface CodesysSimState {
|
|
11
|
+
state: string;
|
|
12
|
+
forced: string[];
|
|
13
|
+
cycles: number;
|
|
14
|
+
/** The bridge's restart count when this was recorded: a restart ends the simulation. */
|
|
15
|
+
restarts?: number;
|
|
16
|
+
}
|
|
17
|
+
type ToolResult = {
|
|
18
|
+
content: {
|
|
19
|
+
type: "text";
|
|
20
|
+
text: string;
|
|
21
|
+
}[];
|
|
22
|
+
isError?: boolean;
|
|
23
|
+
};
|
|
24
|
+
export interface SimToolDeps {
|
|
25
|
+
reg: RegisterAction;
|
|
26
|
+
run: (fn: () => Promise<string>) => Promise<ToolResult>;
|
|
27
|
+
/** Compile; the build report when it has errors, otherwise undefined. */
|
|
28
|
+
compileErrors: () => Promise<string | undefined>;
|
|
29
|
+
}
|
|
30
|
+
/** The simulation the panel should show; undefined when none runs. */
|
|
31
|
+
export declare function currentCodesysSim(ctx: AppContext): CodesysSimState | undefined;
|
|
32
|
+
export declare function describeSim(s: Status): string;
|
|
33
|
+
export declare function registerCodesysSim(ctx: AppContext, deps: SimToolDeps): void;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CODESYS's own simulation: runs the active application inside CODESYS, with no
|
|
3
|
+
* controller and nothing extra to install. It uses the real CODESYS compiler
|
|
4
|
+
* and libraries. It can run, read, write, force and take single cycles. It has
|
|
5
|
+
* no breakpoints: CODESYS's scripting offers none, and its breakpoint commands
|
|
6
|
+
* work at an editor cursor, which a session without a window doesn't have.
|
|
7
|
+
*/
|
|
8
|
+
import * as z from "zod/v4";
|
|
9
|
+
/** The simulation the panel should show; undefined when none runs. */
|
|
10
|
+
export function currentCodesysSim(ctx) {
|
|
11
|
+
const s = ctx.codesysSim;
|
|
12
|
+
return s && s.restarts === ctx.bridge.health().restarts ? s : undefined;
|
|
13
|
+
}
|
|
14
|
+
export function describeSim(s) {
|
|
15
|
+
if (!s.running)
|
|
16
|
+
return "CODESYS simulation: not running.";
|
|
17
|
+
return `CODESYS simulation: application ${s.state}.${s.forced?.length ? ` Forced: ${s.forced.join(", ")}.` : ""}`;
|
|
18
|
+
}
|
|
19
|
+
const names = z.array(z.string()).min(1).describe("Variables as CODESYS expressions relative to the application, e.g. 'PLC_PRG.nCount' or 'GVL_IO.xValve'");
|
|
20
|
+
const values = z.record(z.string(), z.string()).describe("Variable to value, with values as Structured Text: { 'PLC_PRG.xStart': 'TRUE', 'PLC_PRG.nSpeed': '5' }");
|
|
21
|
+
export function registerCodesysSim(ctx, deps) {
|
|
22
|
+
const b = ctx.bridge;
|
|
23
|
+
const { reg, run } = deps;
|
|
24
|
+
const NOTE = "CODESYS's own simulation: no controller is involved.";
|
|
25
|
+
const status = async (op, args = {}, timeoutMs = 60_000) => {
|
|
26
|
+
const s = await b.call(op, args, { timeoutMs });
|
|
27
|
+
ctx.codesysSim = s.running ? { state: s.state ?? "unknown", forced: s.forced ?? [], cycles: s.cycles ?? 0, restarts: b.health().restarts } : undefined;
|
|
28
|
+
return describeSim(s);
|
|
29
|
+
};
|
|
30
|
+
reg("codesys_sim_start", {
|
|
31
|
+
description: `Compile, then load the active application into ${NOTE} Uses the real CODESYS compiler and libraries, and needs nothing installed beyond CODESYS. The application is loaded and stopped unless run is true. While the simulation runs the project is locked: compile, write_object and the other changing tools are refused until codesys_sim_stop. It has no breakpoints, and time runs at real speed.`,
|
|
32
|
+
inputSchema: z.object({ run: z.boolean().optional().describe("Start the application straight away (default false)") }),
|
|
33
|
+
}, async ({ run: start }) => run(async () => {
|
|
34
|
+
const errors = await deps.compileErrors();
|
|
35
|
+
if (errors)
|
|
36
|
+
throw new Error(`Fix the compile errors before simulating.\n${errors}`);
|
|
37
|
+
return `${await status("sim.start", { run: !!start }, 300_000)} The project is locked until codesys_sim_stop.`;
|
|
38
|
+
}));
|
|
39
|
+
reg("codesys_sim_stop", { description: "Stop CODESYS's own simulation, release all forced values and unlock the project.", inputSchema: z.object({}) }, async () => run(() => status("sim.stop", {}, 120_000)));
|
|
40
|
+
reg("codesys_sim_status", { description: "Whether CODESYS's own simulation is running, the application's state and the forced variables.", inputSchema: z.object({}) }, async () => run(() => status("sim.status")));
|
|
41
|
+
reg("codesys_sim_control", {
|
|
42
|
+
description: "Run, stop or reset the application in CODESYS's own simulation. A reset also releases forced values.",
|
|
43
|
+
inputSchema: z.object({ action: z.enum(["run", "stop", "reset_warm", "reset_cold"]) }),
|
|
44
|
+
}, async ({ action }) => run(() => status("sim.control", { action })));
|
|
45
|
+
reg("codesys_sim_cycle", {
|
|
46
|
+
description: "Run exactly this many task cycles in CODESYS's own simulation, then stay stopped. Stops the application first if it is running. Each cycle takes about 0.1 s. Timers follow the clock, not the cycle count: to let a TON elapse, wait, then run another cycle.",
|
|
47
|
+
inputSchema: z.object({ count: z.number().int().min(1).max(1000).optional().describe("Cycles to run (default 1)") }),
|
|
48
|
+
}, async ({ count }) => run(() => status("sim.cycle", { count: count ?? 1 }, Math.max(60_000, (count ?? 1) * 1_000))));
|
|
49
|
+
reg("codesys_sim_read", { description: "Read current values from CODESYS's own simulation. A read takes about 0.4 s, so read everything you need in one call.", inputSchema: z.object({ names }) }, async ({ names: list }) => run(async () => {
|
|
50
|
+
const r = await b.call("sim.read", { names: list });
|
|
51
|
+
return list.map((n) => (n in r.values ? `${n} = ${r.values[n]}` : `${n}: ${r.errors[n] ?? "no value"}`)).join("\n");
|
|
52
|
+
}));
|
|
53
|
+
reg("codesys_sim_write", { description: "Write values once in CODESYS's own simulation. If the program assigns the variable, the next cycle overwrites it; use codesys_sim_force to hold a value.", inputSchema: z.object({ values }) }, async ({ values: v }) => run(() => status("sim.write", { values: v })));
|
|
54
|
+
reg("codesys_sim_force", { description: "Force values in CODESYS's own simulation, until codesys_sim_unforce or codesys_sim_stop. Right for inputs. CODESYS re-applies a force between scans, so if the program assigns the variable, code before that assignment sees the forced value and code after it, in the same scan, sees the program's own value.", inputSchema: z.object({ values }) }, async ({ values: v }) => run(() => status("sim.force", { values: v })));
|
|
55
|
+
reg("codesys_sim_unforce", { description: "Release forced values in CODESYS's own simulation: the named ones, or all of them.", inputSchema: z.object({ names: names.optional() }) }, async ({ names: list }) => run(() => status("sim.unforce", list ? { names: list } : {})));
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=simulation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simulation.js","sourceRoot":"","sources":["../../src/codesys/simulation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Structured Text helpers: object kinds and declaration-header checks. */
|
|
2
|
+
export type ObjectKind = "pou" | "method" | "property" | "accessor" | "action" | "dut" | "gvl" | "interface" | "interface_method" | "task_config" | "task" | "task_call" | "library_manager" | "application" | "folder" | "device" | "other";
|
|
3
|
+
export type CreateKind = "program" | "function_block" | "function" | "method" | "property" | "action" | "interface" | "dut" | "gvl" | "folder";
|
|
4
|
+
export interface TreeNode {
|
|
5
|
+
path: string;
|
|
6
|
+
name: string;
|
|
7
|
+
kind: ObjectKind;
|
|
8
|
+
sub?: string;
|
|
9
|
+
st?: boolean;
|
|
10
|
+
depth: number;
|
|
11
|
+
declaration?: string;
|
|
12
|
+
implementation?: string;
|
|
13
|
+
/** Build properties that are set (excluded from build also when a folder excludes it). */
|
|
14
|
+
build?: {
|
|
15
|
+
excluded?: boolean;
|
|
16
|
+
link_always?: boolean;
|
|
17
|
+
external?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/** PLCopenXML of a graphical body (st false), so a checkpoint can restore it. */
|
|
20
|
+
xml?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function stripLeading(text: string): string;
|
|
23
|
+
export declare function declarationHeader(decl: string): {
|
|
24
|
+
keyword: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
} | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Check that a new declaration keeps the object's kind and name (issue #5:
|
|
29
|
+
* replacing a POU declaration without its `PROGRAM X` header silently
|
|
30
|
+
* changed the POU). Returns an error message, or undefined when it's fine.
|
|
31
|
+
*/
|
|
32
|
+
export declare function checkDeclaration(kind: ObjectKind, sub: string | undefined, name: string, decl: string): string | undefined;
|
|
33
|
+
/** Normalise CODESYS text for display/comparison. */
|
|
34
|
+
export declare function normalizeText(text: string | undefined): string | undefined;
|
|
35
|
+
/** Human label for a node kind. */
|
|
36
|
+
export declare function kindLabel(n: Pick<TreeNode, "kind" | "sub">): string;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Structured Text helpers: object kinds and declaration-header checks. */
|
|
2
|
+
const LEAD = /^(?:\s|\{[^}]*\}|\/\/[^\n]*(?:\n|$)|\(\*[\s\S]*?\*\))*/;
|
|
3
|
+
const MODIFIERS = "(?:(?:PUBLIC|PRIVATE|PROTECTED|INTERNAL|ABSTRACT|FINAL)\\s+)*";
|
|
4
|
+
const HEADER = new RegExp(`^(PROGRAM|FUNCTION_BLOCK|FUNCTION|METHOD|PROPERTY|INTERFACE|TYPE|VAR_GLOBAL|VAR)\\b\\s*${MODIFIERS}([A-Za-z_][A-Za-z0-9_]*)?`, "i");
|
|
5
|
+
export function stripLeading(text) {
|
|
6
|
+
return text.replace(LEAD, "");
|
|
7
|
+
}
|
|
8
|
+
export function declarationHeader(decl) {
|
|
9
|
+
const m = HEADER.exec(stripLeading(decl));
|
|
10
|
+
if (!m)
|
|
11
|
+
return undefined;
|
|
12
|
+
const keyword = m[1].toUpperCase();
|
|
13
|
+
const name = keyword === "VAR" || keyword === "VAR_GLOBAL" ? undefined : m[2];
|
|
14
|
+
return { keyword, name };
|
|
15
|
+
}
|
|
16
|
+
const POU_KEYWORD = {
|
|
17
|
+
program: "PROGRAM",
|
|
18
|
+
function_block: "FUNCTION_BLOCK",
|
|
19
|
+
function: "FUNCTION",
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Check that a new declaration keeps the object's kind and name (issue #5:
|
|
23
|
+
* replacing a POU declaration without its `PROGRAM X` header silently
|
|
24
|
+
* changed the POU). Returns an error message, or undefined when it's fine.
|
|
25
|
+
*/
|
|
26
|
+
export function checkDeclaration(kind, sub, name, decl) {
|
|
27
|
+
const h = declarationHeader(decl);
|
|
28
|
+
const expect = (kw) => `The declaration of ${name} must start with '${kw} ${name}'` +
|
|
29
|
+
(h ? ` (found '${h.keyword}${h.name ? " " + h.name : ""}').` : " (found no header).");
|
|
30
|
+
const sameName = () => (h?.name ?? "").toLowerCase() === name.toLowerCase();
|
|
31
|
+
switch (kind) {
|
|
32
|
+
case "pou": {
|
|
33
|
+
const kw = sub ? POU_KEYWORD[sub] : undefined;
|
|
34
|
+
const allowed = kw ? [kw] : Object.values(POU_KEYWORD);
|
|
35
|
+
if (!h || !allowed.includes(h.keyword) || !sameName()) {
|
|
36
|
+
return expect(kw ?? "PROGRAM|FUNCTION_BLOCK|FUNCTION") + " To change a POU's type, create a new object.";
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
case "method":
|
|
41
|
+
case "interface_method":
|
|
42
|
+
return h?.keyword === "METHOD" && sameName() ? undefined : expect("METHOD");
|
|
43
|
+
case "property":
|
|
44
|
+
return h?.keyword === "PROPERTY" && sameName() ? undefined : expect("PROPERTY");
|
|
45
|
+
case "interface":
|
|
46
|
+
return h?.keyword === "INTERFACE" && sameName() ? undefined : expect("INTERFACE");
|
|
47
|
+
case "dut":
|
|
48
|
+
return h?.keyword === "TYPE" && sameName() ? undefined : expect("TYPE");
|
|
49
|
+
case "gvl":
|
|
50
|
+
return h?.keyword === "VAR_GLOBAL" ? undefined : `A GVL declaration must start with VAR_GLOBAL (found '${h?.keyword ?? "nothing"}').`;
|
|
51
|
+
case "accessor":
|
|
52
|
+
return !h || h.keyword === "VAR" ? undefined : `A property accessor declaration holds only VAR ... END_VAR (found '${h.keyword}').`;
|
|
53
|
+
default:
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Normalise CODESYS text for display/comparison. */
|
|
58
|
+
export function normalizeText(text) {
|
|
59
|
+
return text?.replace(/\r\n?/g, "\n");
|
|
60
|
+
}
|
|
61
|
+
/** Human label for a node kind. */
|
|
62
|
+
export function kindLabel(n) {
|
|
63
|
+
if (n.kind === "pou")
|
|
64
|
+
return n.sub ?? "pou";
|
|
65
|
+
if (n.kind === "dut")
|
|
66
|
+
return n.sub ? `dut:${n.sub}` : "dut";
|
|
67
|
+
return n.kind;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=st.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"st.js","sourceRoot":"","sources":["../../src/codesys/st.ts"],"names":[],"mappings":"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"}
|
package/dist/daemon.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import net from "node:net";
|
|
2
|
+
export interface DaemonInfo {
|
|
3
|
+
pid: number;
|
|
4
|
+
port: number;
|
|
5
|
+
token: string;
|
|
6
|
+
key: string;
|
|
7
|
+
started: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function sessionKey(parts: unknown): string;
|
|
10
|
+
export declare function daemonPaths(dir: string, key: string): {
|
|
11
|
+
info: string;
|
|
12
|
+
lock: string;
|
|
13
|
+
log: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Run the owner's listener. Each client that sends the token on its first line
|
|
17
|
+
* is handed to onConnection with the rest of its stream. onIdle runs once no
|
|
18
|
+
* client has been connected for idleMs.
|
|
19
|
+
*/
|
|
20
|
+
export declare function serveDaemon(o: {
|
|
21
|
+
dir: string;
|
|
22
|
+
key: string;
|
|
23
|
+
idleMs: number;
|
|
24
|
+
onConnection: (socket: net.Socket) => Promise<void>;
|
|
25
|
+
onIdle: () => void;
|
|
26
|
+
log: (m: string) => void;
|
|
27
|
+
}): Promise<{
|
|
28
|
+
info: DaemonInfo;
|
|
29
|
+
close: () => void;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Connect to the owner of this session, starting it if there is none.
|
|
33
|
+
* Several processes may start at the same moment; a lock file makes exactly
|
|
34
|
+
* one of them spawn the owner, and the rest wait for it.
|
|
35
|
+
*/
|
|
36
|
+
export declare function connectDaemon(o: {
|
|
37
|
+
dir: string;
|
|
38
|
+
key: string;
|
|
39
|
+
spawnDaemon: (logFile: string) => void;
|
|
40
|
+
waitMs?: number;
|
|
41
|
+
}): Promise<{
|
|
42
|
+
socket: net.Socket;
|
|
43
|
+
info: DaemonInfo;
|
|
44
|
+
spawned: boolean;
|
|
45
|
+
log: string;
|
|
46
|
+
}>;
|