@codesys/mcp-toolkit 2.5.0 → 2.7.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 +50 -0
- package/README.md +13 -9
- package/README.zh-CN.md +11 -6
- package/dist/codesys/device-tools.d.ts +21 -0
- package/dist/codesys/device-tools.js +60 -0
- package/dist/codesys/device-tools.js.map +1 -1
- package/dist/codesys/devices.d.ts +6 -0
- package/dist/codesys/devices.js +24 -1
- package/dist/codesys/devices.js.map +1 -1
- package/dist/codesys/recipes.d.ts +45 -0
- package/dist/codesys/recipes.js +130 -0
- package/dist/codesys/recipes.js.map +1 -0
- package/dist/hmi/native.d.ts +14 -2
- package/dist/hmi/native.js +116 -5
- package/dist/hmi/native.js.map +1 -1
- package/dist/hmi/render.d.ts +4 -0
- package/dist/hmi/render.js +13 -1
- package/dist/hmi/render.js.map +1 -1
- package/dist/hmi/service.d.ts +3 -0
- package/dist/hmi/service.js +29 -2
- package/dist/hmi/service.js.map +1 -1
- package/dist/hmi/spec.d.ts +18 -0
- package/dist/hmi/spec.js +45 -0
- package/dist/hmi/spec.js.map +1 -1
- package/dist/hmi/tools.js +69 -15
- package/dist/hmi/tools.js.map +1 -1
- package/dist/hmi/value.js +3 -0
- package/dist/hmi/value.js.map +1 -1
- package/dist/panel/hmi.js +66 -61
- package/dist/panel.js +1 -1
- package/dist/panel.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +44 -4
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
- package/watcher/mcp_alarms.py +42 -0
- package/watcher/mcp_caps.py +66 -0
- package/watcher/mcp_devices.py +158 -0
- package/watcher/mcp_lang.py +13 -1
- package/watcher/mcp_visu.py +81 -1
- package/watcher/watcher.py +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.7.0] - 2026-11-14
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Recipes: `create_recipes` generates ST for setpoint recipes (a struct, the
|
|
14
|
+
recipes in a RETAIN array, a program that applies a recipe or stores the
|
|
15
|
+
current values in one, through pointers so program variables work) and adds
|
|
16
|
+
it to MainTask; an HMI `recipe` widget offers Apply and Save in the browser
|
|
17
|
+
and in CODESYS. Checked in the SP21 simulation: apply, save, apply again.
|
|
18
|
+
(CODESYS's own Recipe Manager can be created by script, but in the
|
|
19
|
+
simulation its runtime never found the recipes.)
|
|
20
|
+
- `get_signature` lists the parameters of library methods (for example
|
|
21
|
+
`RecipeManCommands.SetRecipeValues`).
|
|
22
|
+
- STRING values show without quotes on HMI screens.
|
|
23
|
+
- Languages: `hmi_translate` stores translations of the HMI's texts per
|
|
24
|
+
language and lists what is still untranslated; the browser HMI gets language
|
|
25
|
+
buttons in its header and switches live (checked on SP21); `hmi_screenshot`
|
|
26
|
+
takes `language`. The export puts the alarm messages' translations into
|
|
27
|
+
CODESYS's alarm text list. Native pages don't switch language yet.
|
|
28
|
+
- `codesys_status` reports which optional features this CODESYS offers
|
|
29
|
+
(visualization, signatures, cross-references, debugging, trace, alarms, user
|
|
30
|
+
groups, device repository, FloatingPointUtils) and what a missing one affects.
|
|
31
|
+
- A table of what was checked on CODESYS SP21, SP22 and Machine Expert
|
|
32
|
+
(docs/reference.md), and live tests for the features beyond plain ST.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
- `export_sources` rewrote graphical bodies on every export because of the
|
|
36
|
+
time stamp in their XML header; it now leaves them out, so only real
|
|
37
|
+
changes show in git.
|
|
38
|
+
|
|
39
|
+
## [2.6.0] - 2026-11-14
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
- `device_parameters` and `configure_device`: read and set a device's
|
|
43
|
+
parameters (IP addresses, ports, unit IDs, enumerations such as DHCP) and map
|
|
44
|
+
its I/O channels to variables, with automatic or fixed IEC addresses, through
|
|
45
|
+
CODESYS's documented device scripting. Checked on SP22: a Modbus TCP server
|
|
46
|
+
device's register and a single bit mapped, 0 build errors.
|
|
47
|
+
|
|
48
|
+
- Native gauges look like the browser HMI's arc gauge (pictures per 2.5 %
|
|
49
|
+
of the range, in the band colours) instead of a bar.
|
|
50
|
+
- Native alarm rows follow CODESYS's alarm manager: the time the alarm came,
|
|
51
|
+
its state, and an ACK button that acknowledges it in CODESYS; a cleared alarm
|
|
52
|
+
stays until acknowledged. Checked live on SP21.
|
|
53
|
+
- `show_in_codesys`: with `--show-window`, open an object (a visualization, a
|
|
54
|
+
POU, a device) in its editor in the CODESYS window.
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
- `get_io_list`, `get_devices` and `project_report` listed a mapped channel
|
|
58
|
+
once for every device above it; each now appears once, under its own device.
|
|
59
|
+
|
|
10
60
|
## [2.5.0] - 2026-11-14
|
|
11
61
|
|
|
12
62
|
### Added
|
package/README.md
CHANGED
|
@@ -117,15 +117,15 @@ operation. [The reference](docs/reference.md) describes each one.
|
|
|
117
117
|
| **Build** | `compile` |
|
|
118
118
|
| **Libraries** | `list_libraries` `add_library` `remove_library` `get_library_api` `get_signature` |
|
|
119
119
|
| **Navigate code** | `find_references` `rename_symbol` |
|
|
120
|
-
| **Tasks and I/O** | `list_tasks` `configure_task` `get_io_list` `get_devices` `find_device` `add_device` |
|
|
120
|
+
| **Tasks and I/O** | `list_tasks` `configure_task` `get_io_list` `get_devices` `find_device` `add_device` `device_parameters` `configure_device` |
|
|
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
124
|
| **Debug** | `breakpoint_set` `breakpoint_clear` `debug_status` `debug_step` `debug_continue` |
|
|
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` |
|
|
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` |
|
|
128
|
-
| **Helpers** | `batch` `wait` `help` `open_workspace` |
|
|
127
|
+
| **Handover** | `project_report` `export_sources` `create_recipes` |
|
|
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
|
|
131
131
|
calls.
|
|
@@ -258,11 +258,15 @@ and the symbol's on and fault variables choose which one CODESYS shows.
|
|
|
258
258
|
|
|
259
259
|

|
|
260
260
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
261
|
+
Gauges are the same arc gauge as in the browser (pictures in the image pool,
|
|
262
|
+
one per 2.5 % of the range, in the band's colour), not CODESYS's chrome meter.
|
|
263
|
+
The alarm rows follow CODESYS's alarm manager: a row stays until the alarm is
|
|
264
|
+
acknowledged, with the time it came, its state and an ACK button that
|
|
265
|
+
acknowledges it in CODESYS, instead of CODESYS's grey alarm table. Trends show
|
|
266
|
+
their current values: a CODESYS trend needs a trend recording that scripting
|
|
267
|
+
can't create yet. Checked on CODESYS V3.5 SP21 in the simulation.
|
|
268
|
+
|
|
269
|
+
 A visualization needs the `FloatingPointUtils` library in CODESYS's
|
|
266
270
|
library repository; if it's missing, the export says so before it builds
|
|
267
271
|
anything. A long export reports its progress (each page, the alarms, the
|
|
268
272
|
compile) to clients that show MCP progress.
|
package/README.zh-CN.md
CHANGED
|
@@ -205,8 +205,13 @@ Claude 可以在仿真中测试这些报警:`alarm_status` 从 CODESYS 报警
|
|
|
205
205
|
|
|
206
206
|

|
|
207
207
|
|
|
208
|
-
CODESYS
|
|
209
|
-
|
|
208
|
+
仪表与浏览器中的弧形仪表相同(图片池中的图片,每 2.5% 一张,按色带着色),而不是 CODESYS 的金属仪表。
|
|
209
|
+
报警行跟随 CODESYS 报警管理器:报警被确认之前一直显示,带有报警出现的时间、状态和 ACK 按钮(在 CODESYS
|
|
210
|
+
中确认报警),而不是 CODESYS 的灰色报警表。趋势显示当前值:CODESYS 趋势需要脚本目前无法创建的趋势记录。
|
|
211
|
+
|
|
212
|
+

|
|
213
|
+
|
|
214
|
+
已在 CODESYS
|
|
210
215
|
V3.5 SP21 的仿真中验证。可视化需要 CODESYS 库存储库中有 `FloatingPointUtils` 库;如果缺少,导出会在
|
|
211
216
|
开始构建之前提示。
|
|
212
217
|
|
|
@@ -236,15 +241,15 @@ V3.5 SP21 的仿真中验证。可视化需要 CODESYS 库存储库中有 `Float
|
|
|
236
241
|
| **编译** | `compile` |
|
|
237
242
|
| **库** | `list_libraries` `add_library` `remove_library` `get_library_api` `get_signature` |
|
|
238
243
|
| **代码导航** | `find_references` `rename_symbol` |
|
|
239
|
-
| **任务与 I/O** | `list_tasks` `configure_task` `get_io_list` `get_devices` `find_device` `add_device` |
|
|
244
|
+
| **任务与 I/O** | `list_tasks` `configure_task` `get_io_list` `get_devices` `find_device` `add_device` `device_parameters` `configure_device` |
|
|
240
245
|
| **改动跟踪** | `checkpoint` `get_changes` `revert_object` |
|
|
241
246
|
| **仿真** | `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` |
|
|
242
247
|
| **跟踪(Trace)** | `trace_setup` `trace_record` |
|
|
243
248
|
| **调试** | `breakpoint_set` `breakpoint_clear` `debug_status` `debug_step` `debug_continue` |
|
|
244
249
|
| **报警** | `alarm_list` `alarm_status` `alarm_acknowledge` |
|
|
245
|
-
| **交接** | `project_report` `export_sources` |
|
|
246
|
-
| **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` |
|
|
247
|
-
| **辅助** | `batch` `wait` `help` `open_workspace` |
|
|
250
|
+
| **交接** | `project_report` `export_sources` `create_recipes` |
|
|
251
|
+
| **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
|
+
| **辅助** | `batch` `wait` `help` `open_workspace` `show_in_codesys` |
|
|
248
253
|
|
|
249
254
|
`batch` 可以在一次调用中执行最多 50 个操作,比逐个调用快得多。
|
|
250
255
|
|
|
@@ -1,3 +1,24 @@
|
|
|
1
1
|
import type { ActionResult, RegisterAction } from "../actions.js";
|
|
2
2
|
import type { AppContext } from "../tools.js";
|
|
3
|
+
export interface DeviceParam {
|
|
4
|
+
key: string;
|
|
5
|
+
name: string;
|
|
6
|
+
depth: number;
|
|
7
|
+
description?: string;
|
|
8
|
+
unit?: string;
|
|
9
|
+
section?: string;
|
|
10
|
+
type?: string;
|
|
11
|
+
access?: string;
|
|
12
|
+
channel?: string;
|
|
13
|
+
value?: string;
|
|
14
|
+
default?: string;
|
|
15
|
+
choices?: string[];
|
|
16
|
+
mapping?: {
|
|
17
|
+
variable: string;
|
|
18
|
+
address: string;
|
|
19
|
+
automatic_address: boolean;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** One parameter or channel as a line: key, name, value (and choices), mapping. */
|
|
23
|
+
export declare function describeParam(p: DeviceParam): string;
|
|
3
24
|
export declare function registerDeviceActions(reg: RegisterAction, ctx: AppContext, run: (fn: () => Promise<string>) => Promise<ActionResult>): void;
|
|
@@ -4,8 +4,68 @@
|
|
|
4
4
|
* (watcher/mcp_devices.py). Offline: nothing goes online.
|
|
5
5
|
*/
|
|
6
6
|
import * as z from "zod/v4";
|
|
7
|
+
/** One parameter or channel as a line: key, name, value (and choices), mapping. */
|
|
8
|
+
export function describeParam(p) {
|
|
9
|
+
const pad = " ".repeat(p.depth);
|
|
10
|
+
const val = p.value !== undefined ? ` = ${p.value}${p.unit ? ` ${p.unit}` : ""}` : "";
|
|
11
|
+
const choices = p.choices?.length ? ` (one of ${p.choices.slice(0, 12).join(", ")}${p.choices.length > 12 ? ", ..." : ""})` : "";
|
|
12
|
+
const map = p.mapping ? ` -> ${p.mapping.variable || "(not mapped)"}${p.mapping.address ? ` at ${p.mapping.address}${p.mapping.automatic_address ? "" : " (fixed)"}` : ""}` : "";
|
|
13
|
+
const ch = p.channel ? ` [${p.channel.toLowerCase()} channel${p.type ? ` ${p.type}` : ""}]` : p.type && p.depth === 0 ? ` [${p.type}]` : "";
|
|
14
|
+
const ro = p.access && /^read$|readonly|none/i.test(p.access) ? " (read-only)" : "";
|
|
15
|
+
return `${pad}${p.key} ${p.name}${ch}${val}${choices}${map}${ro}`;
|
|
16
|
+
}
|
|
7
17
|
export function registerDeviceActions(reg, ctx, run) {
|
|
8
18
|
const b = ctx.bridge;
|
|
19
|
+
reg("device_parameters", {
|
|
20
|
+
description: "A device's parameters and I/O channels from its device description (the device and its connectors' parameters, nested elements indented): key, name, value with unit and allowed choices, and for each I/O channel the variable it is mapped to. Use the keys with configure_device. Offline; nothing goes online.",
|
|
21
|
+
inputSchema: z.object({
|
|
22
|
+
device: z.string().describe("Device path from get_devices, e.g. '/PLCWinNT/Ethernet/Modbus_TCP_Server'"),
|
|
23
|
+
filter: z.string().optional().describe("Only parameters whose key, name or section contains this text"),
|
|
24
|
+
channels: z.boolean().optional().describe("Only I/O channels"),
|
|
25
|
+
depth: z.number().int().min(0).max(8).optional().describe("Nesting shown: 0 = parameters only, 1 (default) = also their elements (e.g. each register), 2 = also bits"),
|
|
26
|
+
}),
|
|
27
|
+
}, async ({ device, filter, channels, depth }) => run(async () => {
|
|
28
|
+
const r = await b.call("devices.params", { path: device, limit: 3000 }, { timeoutMs: 120_000 });
|
|
29
|
+
let ps = r.parameters;
|
|
30
|
+
if (channels)
|
|
31
|
+
ps = ps.filter((p) => p.mapping);
|
|
32
|
+
const max = depth ?? (filter ? 8 : 1);
|
|
33
|
+
const hidden = ps.filter((p) => p.depth > max).length;
|
|
34
|
+
ps = ps.filter((p) => p.depth <= max);
|
|
35
|
+
if (filter) {
|
|
36
|
+
const f = filter.toLowerCase();
|
|
37
|
+
ps = ps.filter((p) => `${p.key} ${p.name} ${p.section ?? ""}`.toLowerCase().includes(f));
|
|
38
|
+
}
|
|
39
|
+
if (!ps.length)
|
|
40
|
+
return `${r.path}: no ${channels ? "I/O channels" : "parameters"}${filter ? ` matching '${filter}'` : ""}.`;
|
|
41
|
+
const nChan = ps.filter((p) => p.mapping).length;
|
|
42
|
+
return [
|
|
43
|
+
`${r.path}: ${ps.length} parameter element(s)${nChan ? `, ${nChan} I/O channel(s)` : ""}${r.truncated ? " (the first 3000)" : ""}:`,
|
|
44
|
+
...ps.map(describeParam),
|
|
45
|
+
...(hidden ? [`(${hidden} nested element(s) deeper than ${max} not shown: pass depth or filter)`] : []),
|
|
46
|
+
].join("\n");
|
|
47
|
+
}));
|
|
48
|
+
reg("configure_device", {
|
|
49
|
+
description: "Set a device's parameters and map its I/O channels to variables (keys from device_parameters). values: {key: value} (an enumeration takes its identifier or name). mappings: [{channel: key, variable, address?}]: variable is an existing variable as 'Application.GVL_IO.xValve', or a plain name to let CODESYS create one; '' unmaps; address fixes the IEC address (e.g. '%IX10.0'), null makes it automatic. Offline; compile afterwards.",
|
|
50
|
+
inputSchema: z.object({
|
|
51
|
+
device: z.string(),
|
|
52
|
+
values: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
|
|
53
|
+
mappings: z.array(z.object({ channel: z.string(), variable: z.string(), address: z.string().nullable().optional() })).optional(),
|
|
54
|
+
}),
|
|
55
|
+
}, async ({ device, values, mappings }) => run(async () => {
|
|
56
|
+
const r = await b.call("devices.configure", {
|
|
57
|
+
path: device,
|
|
58
|
+
values: Object.entries(values ?? {}).map(([key, value]) => ({ key, value: String(value) })),
|
|
59
|
+
mappings: (mappings ?? []).map((m) => ({ key: m.channel, variable: m.variable, ...(m.address !== undefined ? { address: m.address } : {}) })),
|
|
60
|
+
save: ctx.autosave,
|
|
61
|
+
}, { timeoutMs: 120_000 });
|
|
62
|
+
return [
|
|
63
|
+
`${r.path}: ${r.done.length} change(s)${r.errors.length ? `, ${r.errors.length} failed` : ""}.`,
|
|
64
|
+
...r.done.map((d) => (d.variable !== undefined ? ` ${d.key} -> ${d.variable || "(not mapped)"}${d.address ? ` at ${d.address}` : ""}` : ` ${d.key} = ${d.value}`)),
|
|
65
|
+
...r.errors.map((e) => ` FAILED ${e.key}: ${e.error}`),
|
|
66
|
+
r.done.length ? "Compile to check." : "",
|
|
67
|
+
].filter(Boolean).join("\n");
|
|
68
|
+
}));
|
|
9
69
|
reg("find_device", {
|
|
10
70
|
description: "Search the device descriptions installed in CODESYS (fieldbus masters and slaves such as Modbus TCP, EtherCAT, CANopen, PROFINET; I/O modules; drives) by name. Returns type, id and version to pass to add_device.",
|
|
11
71
|
inputSchema: z.object({ text: z.string().describe("Part of the device name, e.g. 'Modbus TCP', 'EtherCAT Master', 'CANopen'"), limit: z.number().int().min(1).max(100).default(30) }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-tools.js","sourceRoot":"","sources":["../../src/codesys/device-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"device-tools.js","sourceRoot":"","sources":["../../src/codesys/device-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,4 +33,10 @@ export interface IoChannel {
|
|
|
33
33
|
export declare function parseIoMappingCsv(text: string): IoChannel[];
|
|
34
34
|
/** "Application.GVL_IO.xValve" -> "GVL_IO.xValve" (the toolkit's paths are relative to the application). */
|
|
35
35
|
export declare const shortVariable: (v: string) => string;
|
|
36
|
+
/**
|
|
37
|
+
* The channels mapped to variables across the device tree, each once: a device's
|
|
38
|
+
* export of its I/O mapping also contains its children's, so the same channel
|
|
39
|
+
* shows up under every device above it.
|
|
40
|
+
*/
|
|
41
|
+
export declare function mappedChannels(devices: DeviceInfo[]): IoChannel[];
|
|
36
42
|
export declare function describeDevices(devices: DeviceInfo[]): string;
|
package/dist/codesys/devices.js
CHANGED
|
@@ -64,6 +64,26 @@ export function parseIoMappingCsv(text) {
|
|
|
64
64
|
}
|
|
65
65
|
/** "Application.GVL_IO.xValve" -> "GVL_IO.xValve" (the toolkit's paths are relative to the application). */
|
|
66
66
|
export const shortVariable = (v) => v.replace(/^[A-Za-z_][A-Za-z0-9_]*\.(?=[A-Za-z_][A-Za-z0-9_]*\.)/, "");
|
|
67
|
+
/**
|
|
68
|
+
* The channels mapped to variables across the device tree, each once: a device's
|
|
69
|
+
* export of its I/O mapping also contains its children's, so the same channel
|
|
70
|
+
* shows up under every device above it.
|
|
71
|
+
*/
|
|
72
|
+
export function mappedChannels(devices) {
|
|
73
|
+
const seen = new Set();
|
|
74
|
+
const out = [];
|
|
75
|
+
for (const d of devices)
|
|
76
|
+
for (const c of d.io_csv ? parseIoMappingCsv(d.io_csv) : []) {
|
|
77
|
+
if (!c.variable)
|
|
78
|
+
continue;
|
|
79
|
+
const k = `${c.device}|${c.parameter}|${c.address}|${c.variable}`;
|
|
80
|
+
if (seen.has(k))
|
|
81
|
+
continue;
|
|
82
|
+
seen.add(k);
|
|
83
|
+
out.push(c);
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
67
87
|
export function describeDevices(devices) {
|
|
68
88
|
if (!devices.length)
|
|
69
89
|
return "No devices in the project.";
|
|
@@ -74,7 +94,10 @@ export function describeDevices(devices) {
|
|
|
74
94
|
: d.id
|
|
75
95
|
? ` (type ${d.type ?? "?"}, id ${d.id}, version ${d.version ?? "?"})`
|
|
76
96
|
: "";
|
|
77
|
-
|
|
97
|
+
// A device's export also lists its children's channels: keep its own (the export names the device of each).
|
|
98
|
+
const all = d.io_csv ? parseIoMappingCsv(d.io_csv) : [];
|
|
99
|
+
const own = all.filter((c) => !c.device || c.device === d.name);
|
|
100
|
+
const channels = own.length || !all.length ? own : all.filter((c) => !devices.some((o) => o !== d && o.name === c.device));
|
|
78
101
|
const mapped = channels.filter((c) => c.variable).length;
|
|
79
102
|
lines.push(`${" ".repeat(d.depth)}${d.name}${ident}${d.enabled === false ? " [disabled]" : ""}${channels.length ? `: ${channels.length} channel(s), ${mapped} mapped` : ""}${d.io_error ? ` (I/O mapping not readable: ${d.io_error})` : ""}`);
|
|
80
103
|
for (const c of channels) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devices.js","sourceRoot":"","sources":["../../src/codesys/devices.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"devices.js","sourceRoot":"","sources":["../../src/codesys/devices.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recipes as plain ST: a struct with one field per recipe variable, the recipes in a
|
|
3
|
+
* RETAIN array (so values saved from the HMI survive a power cycle), their names, and a
|
|
4
|
+
* program that applies a recipe to the live variables or stores the live values in one.
|
|
5
|
+
* Generated code works on any controller and needs no library. (CODESYS's own Recipe
|
|
6
|
+
* Manager can be created by script, but in the simulation its runtime never found the
|
|
7
|
+
* recipes; checked on SP21.)
|
|
8
|
+
*/
|
|
9
|
+
import * as z from "zod/v4";
|
|
10
|
+
import type { ActionResult, RegisterAction } from "../actions.js";
|
|
11
|
+
import type { AppContext } from "../tools.js";
|
|
12
|
+
import type { TreeNode } from "./st.js";
|
|
13
|
+
export declare const recipeSchema: z.ZodObject<{
|
|
14
|
+
name: z.ZodString;
|
|
15
|
+
variables: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
16
|
+
path: z.ZodString;
|
|
17
|
+
type: z.ZodOptional<z.ZodString>;
|
|
18
|
+
}, z.core.$strip>]>>;
|
|
19
|
+
recipes: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
export type RecipeSpec = z.infer<typeof recipeSchema>;
|
|
22
|
+
export interface RecipeCode {
|
|
23
|
+
dut: {
|
|
24
|
+
name: string;
|
|
25
|
+
declaration: string;
|
|
26
|
+
};
|
|
27
|
+
gvl: {
|
|
28
|
+
name: string;
|
|
29
|
+
declaration: string;
|
|
30
|
+
};
|
|
31
|
+
program: {
|
|
32
|
+
name: string;
|
|
33
|
+
declaration: string;
|
|
34
|
+
implementation: string;
|
|
35
|
+
};
|
|
36
|
+
fields: {
|
|
37
|
+
path: string;
|
|
38
|
+
field: string;
|
|
39
|
+
type: string;
|
|
40
|
+
}[];
|
|
41
|
+
}
|
|
42
|
+
export declare function recipeCode(spec: RecipeSpec, types: Record<string, string>): RecipeCode;
|
|
43
|
+
/** Types of 'OWNER.name' variables from the exported declarations (only direct members). */
|
|
44
|
+
export declare function variableTypes(nodes: TreeNode[], paths: string[]): Record<string, string>;
|
|
45
|
+
export declare function registerRecipeAction(reg: RegisterAction, ctx: AppContext, run: (fn: () => Promise<string>) => Promise<ActionResult>): void;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recipes as plain ST: a struct with one field per recipe variable, the recipes in a
|
|
3
|
+
* RETAIN array (so values saved from the HMI survive a power cycle), their names, and a
|
|
4
|
+
* program that applies a recipe to the live variables or stores the live values in one.
|
|
5
|
+
* Generated code works on any controller and needs no library. (CODESYS's own Recipe
|
|
6
|
+
* Manager can be created by script, but in the simulation its runtime never found the
|
|
7
|
+
* recipes; checked on SP21.)
|
|
8
|
+
*/
|
|
9
|
+
import * as z from "zod/v4";
|
|
10
|
+
import { parseDeclaration } from "./decl.js";
|
|
11
|
+
export const recipeSchema = z.object({
|
|
12
|
+
name: z.string().regex(/^[A-Za-z][A-Za-z0-9_]*$/).describe("e.g. 'Pump': makes ST_Recipe_Pump, GVL_Recipe_Pump and PRG_Recipe_Pump"),
|
|
13
|
+
variables: z
|
|
14
|
+
.array(z.union([z.string(), z.object({ path: z.string(), type: z.string().optional() })]))
|
|
15
|
+
.min(1)
|
|
16
|
+
.describe("The variables a recipe sets, e.g. ['PLC_PRG.rSetpoint', {path: 'GVL.rSpeed', type: 'REAL'}]; the type is looked up when left out"),
|
|
17
|
+
recipes: z.record(z.string().regex(/^[^'"$]{1,32}$/), z.record(z.string(), z.union([z.string(), z.number(), z.boolean()]))).describe("Recipe name -> { variable: value }, e.g. { Normal: { 'PLC_PRG.rSetpoint': 75 } }"),
|
|
18
|
+
});
|
|
19
|
+
/** An ST literal for a value of a type. */
|
|
20
|
+
function literal(v, type) {
|
|
21
|
+
if (typeof v === "boolean")
|
|
22
|
+
return v ? "TRUE" : "FALSE";
|
|
23
|
+
if (typeof v === "number")
|
|
24
|
+
return /REAL/i.test(type) && Number.isInteger(v) ? `${v}.0` : String(v);
|
|
25
|
+
if (/^W?STRING/i.test(type) && !/^'.*'$/.test(v))
|
|
26
|
+
return `'${v.replace(/'/g, "$$'")}'`;
|
|
27
|
+
return v;
|
|
28
|
+
}
|
|
29
|
+
export function recipeCode(spec, types) {
|
|
30
|
+
const n = spec.name;
|
|
31
|
+
const used = new Set();
|
|
32
|
+
const fields = spec.variables.map((v) => {
|
|
33
|
+
const path = typeof v === "string" ? v : v.path;
|
|
34
|
+
const type = (typeof v === "string" ? undefined : v.type) ?? types[path];
|
|
35
|
+
if (!type)
|
|
36
|
+
throw new Error(`No type for ${path}: give it as {path: '${path}', type: 'REAL'}.`);
|
|
37
|
+
let field = path.split(".").pop().replace(/\W/g, "_");
|
|
38
|
+
for (let k = 2; used.has(field.toLowerCase()); k++)
|
|
39
|
+
field = `${path.split(".").pop().replace(/\W/g, "_")}_${k}`;
|
|
40
|
+
used.add(field.toLowerCase());
|
|
41
|
+
return { path, field, type };
|
|
42
|
+
});
|
|
43
|
+
const names = Object.keys(spec.recipes);
|
|
44
|
+
const count = names.length;
|
|
45
|
+
for (const r of names)
|
|
46
|
+
for (const p of Object.keys(spec.recipes[r]))
|
|
47
|
+
if (!fields.some((f) => f.path === p))
|
|
48
|
+
throw new Error(`Recipe '${r}' sets ${p}, which isn't one of the variables.`);
|
|
49
|
+
const init = names.map((r) => `(${fields.filter((f) => spec.recipes[r][f.path] !== undefined).map((f) => `${f.field} := ${literal(spec.recipes[r][f.path], f.type)}`).join(", ")})`);
|
|
50
|
+
const dut = `ST_Recipe_${n}`, gvl = `GVL_Recipe_${n}`, prg = `PRG_Recipe_${n}`;
|
|
51
|
+
return {
|
|
52
|
+
fields,
|
|
53
|
+
dut: { name: dut, declaration: `TYPE ${dut} :\nSTRUCT\n${fields.map((f) => ` ${f.field} : ${f.type}; // ${f.path}`).join("\n")}\nEND_STRUCT\nEND_TYPE` },
|
|
54
|
+
gvl: {
|
|
55
|
+
name: gvl,
|
|
56
|
+
declaration: `// Recipes '${n}', generated by codesys-mcp-toolkit (create_recipes). RETAIN: values saved from the HMI survive a power cycle.\nVAR_GLOBAL RETAIN\n aRecipes : ARRAY[0..${count - 1}] OF ${dut} := [${init.join(", ")}];\nEND_VAR\nVAR_GLOBAL CONSTANT\n asNames : ARRAY[0..${count - 1}] OF STRING(32) := [${names.map((x) => `'${x}'`).join(", ")}];\n iCount : INT := ${count};\nEND_VAR`,
|
|
57
|
+
},
|
|
58
|
+
program: {
|
|
59
|
+
name: prg,
|
|
60
|
+
// Through pointers: another POU may not write a program's local variables directly.
|
|
61
|
+
declaration: `PROGRAM ${prg}\n// Set iApply to a recipe's index to write it to the variables; set iSave to store the variables in it.\nVAR\n iApply : INT := -1;\n iSave : INT := -1;\n iActive : INT := -1; // the recipe applied last\n sActive : STRING(32);\n${fields.map((f, k) => ` p${k} : POINTER TO ${f.type}; // ${f.path}`).join("\n")}\nEND_VAR`,
|
|
62
|
+
implementation: [
|
|
63
|
+
...fields.map((f, k) => `p${k} := ADR(${f.path});`),
|
|
64
|
+
`IF iApply >= 0 AND iApply < ${count} THEN`,
|
|
65
|
+
...fields.map((f, k) => ` p${k}^ := ${gvl}.aRecipes[iApply].${f.field};`),
|
|
66
|
+
` iActive := iApply;`,
|
|
67
|
+
` sActive := ${gvl}.asNames[iApply];`,
|
|
68
|
+
`END_IF`,
|
|
69
|
+
`iApply := -1;`,
|
|
70
|
+
`IF iSave >= 0 AND iSave < ${count} THEN`,
|
|
71
|
+
...fields.map((f, k) => ` ${gvl}.aRecipes[iSave].${f.field} := p${k}^;`),
|
|
72
|
+
`END_IF`,
|
|
73
|
+
`iSave := -1;`,
|
|
74
|
+
].join("\n"),
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** Types of 'OWNER.name' variables from the exported declarations (only direct members). */
|
|
79
|
+
export function variableTypes(nodes, paths) {
|
|
80
|
+
const out = {};
|
|
81
|
+
for (const p of paths) {
|
|
82
|
+
const [owner, name, ...rest] = p.split(".");
|
|
83
|
+
if (!owner || !name || rest.length)
|
|
84
|
+
continue;
|
|
85
|
+
const node = nodes.find((x) => x.name.toLowerCase() === owner.toLowerCase() && (x.kind === "pou" || x.kind === "gvl"));
|
|
86
|
+
const v = node ? parseDeclaration(node.declaration).vars.find((x) => x.name.toLowerCase() === name.toLowerCase()) : undefined;
|
|
87
|
+
if (v)
|
|
88
|
+
out[p] = v.type;
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
export function registerRecipeAction(reg, ctx, run) {
|
|
93
|
+
const b = ctx.bridge;
|
|
94
|
+
reg("create_recipes", {
|
|
95
|
+
description: "Recipes for the machine's setpoints as generated ST: ST_Recipe_<name> (a field per variable), GVL_Recipe_<name> (the recipes in a RETAIN array, so values saved from the HMI survive a power cycle, and their names) and PRG_Recipe_<name>, added to MainTask: set iApply to a recipe's index to write it to the variables, iSave to store the current values in it; iActive and sActive tell which recipe was applied last. On an HMI screen, a widget {type: 'recipe', recipe: '<name>', recipes: [names]} shows them with Apply and Save buttons. Recreating replaces the generated objects.",
|
|
96
|
+
inputSchema: recipeSchema,
|
|
97
|
+
}, async (spec) => run(async () => {
|
|
98
|
+
const paths = spec.variables.map((v) => (typeof v === "string" ? v : v.path));
|
|
99
|
+
const nodes = (await b.call("export", {}, { timeoutMs: 120_000 })).nodes;
|
|
100
|
+
const code = recipeCode(spec, variableTypes(nodes, paths));
|
|
101
|
+
const exists = (name) => nodes.some((x) => x.name.toLowerCase() === name.toLowerCase());
|
|
102
|
+
const put = async (kind, o) => {
|
|
103
|
+
if (exists(o.name))
|
|
104
|
+
await b.call("object.write", { path: o.name, declaration: o.declaration, ...(o.implementation ? { implementation: o.implementation } : {}) });
|
|
105
|
+
else
|
|
106
|
+
await b.call("object.create", { kind, name: o.name, declaration: o.declaration, ...(o.implementation ? { implementation: o.implementation } : {}) });
|
|
107
|
+
};
|
|
108
|
+
await put("dut", code.dut);
|
|
109
|
+
await put("gvl", code.gvl);
|
|
110
|
+
await put("program", code.program);
|
|
111
|
+
let task = "";
|
|
112
|
+
for (const t of ["MainTask", "Task"]) {
|
|
113
|
+
try {
|
|
114
|
+
await b.call("task.configure", { name: t, add_calls: [code.program.name], save: ctx.autosave });
|
|
115
|
+
task = t;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
/* try the next */
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const names = Object.keys(spec.recipes);
|
|
123
|
+
return [
|
|
124
|
+
`Created recipes '${spec.name}': ${names.map((x, i) => `${i} ${x}`).join(", ")} over ${code.fields.map((f) => `${f.path} : ${f.type}`).join(", ")}.`,
|
|
125
|
+
`${code.dut.name}, ${code.gvl.name} (RETAIN) and ${code.program.name}${task ? `, called from ${task}` : " (add it to a task with configure_task)"}.`,
|
|
126
|
+
`Apply one: ${code.program.name}.iApply := <index>; store the current values: ${code.program.name}.iSave := <index>. HMI: {type: 'recipe', recipe: '${spec.name}', recipes: ${JSON.stringify(names)}}. Compile to check.`,
|
|
127
|
+
].join("\n");
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=recipes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipes.js","sourceRoot":"","sources":["../../src/codesys/recipes.ts"],"names":[],"mappings":"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"}
|
package/dist/hmi/native.d.ts
CHANGED
|
@@ -2,7 +2,13 @@ import type { Screen, Tone } from "./spec.js";
|
|
|
2
2
|
import { type SymbolLib } from "./symbols.js";
|
|
3
3
|
type Argb = number;
|
|
4
4
|
export interface NativeElement {
|
|
5
|
-
kind: "rect" | "round" | "circle" | "switcher" | "image";
|
|
5
|
+
kind: "rect" | "round" | "circle" | "switcher" | "image" | "complex";
|
|
6
|
+
/** complex: CODESYS's element type, e.g. VisuFbElemMeter180 (made through the visual editor, so only with CODESYS's window). */
|
|
7
|
+
type_name?: string;
|
|
8
|
+
/** complex: properties in the order to set them. */
|
|
9
|
+
pairs?: [string, string | number | boolean][];
|
|
10
|
+
/** complex: what to draw instead when CODESYS has no window. */
|
|
11
|
+
fallback?: NativeElement[];
|
|
6
12
|
name?: string;
|
|
7
13
|
x: number;
|
|
8
14
|
y: number;
|
|
@@ -83,8 +89,14 @@ export declare function symbols(p: Palette): {
|
|
|
83
89
|
id: string;
|
|
84
90
|
svg: string;
|
|
85
91
|
}[];
|
|
92
|
+
/**
|
|
93
|
+
* alarmIndex: each HMI alarm's position in the CODESYS alarm group AG_HMI (when the export put
|
|
94
|
+
* them there); those rows then follow CODESYS's alarm states and can be acknowledged.
|
|
95
|
+
*/
|
|
86
96
|
export declare function nativePlan(screen: Screen, pages?: {
|
|
87
97
|
name: string;
|
|
88
98
|
title: string;
|
|
89
|
-
}[], custom?: SymbolLib): NativePlan;
|
|
99
|
+
}[], custom?: SymbolLib, alarmIndex?: Record<string, number>, languages?: string[]): NativePlan;
|
|
100
|
+
/** Pictures per gauge: one every 2.5 % of the range. */
|
|
101
|
+
export declare const GAUGE_STEPS = 40;
|
|
90
102
|
export {};
|