@codesys/mcp-toolkit 2.1.2 → 2.3.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/README.md +190 -10
  3. package/README.zh-CN.md +254 -0
  4. package/dist/actions.d.ts +9 -4
  5. package/dist/actions.js +1 -1
  6. package/dist/actions.js.map +1 -1
  7. package/dist/bridge/bridge.d.ts +12 -1
  8. package/dist/bridge/bridge.js +77 -11
  9. package/dist/bridge/bridge.js.map +1 -1
  10. package/dist/cli.js +7 -1
  11. package/dist/cli.js.map +1 -1
  12. package/dist/codesys/debug.d.ts +5 -0
  13. package/dist/codesys/debug.js +89 -0
  14. package/dist/codesys/debug.js.map +1 -0
  15. package/dist/codesys/device-tools.d.ts +3 -0
  16. package/dist/codesys/device-tools.js +38 -0
  17. package/dist/codesys/device-tools.js.map +1 -0
  18. package/dist/codesys/graphical.d.ts +76 -0
  19. package/dist/codesys/graphical.js +226 -0
  20. package/dist/codesys/graphical.js.map +1 -0
  21. package/dist/codesys/lang.d.ts +39 -0
  22. package/dist/codesys/lang.js +177 -0
  23. package/dist/codesys/lang.js.map +1 -0
  24. package/dist/codesys/simtest.d.ts +48 -0
  25. package/dist/codesys/simtest.js +103 -0
  26. package/dist/codesys/simtest.js.map +1 -0
  27. package/dist/codesys/st.d.ts +1 -1
  28. package/dist/codesys/st.js.map +1 -1
  29. package/dist/codesys/trace.d.ts +19 -0
  30. package/dist/codesys/trace.js +139 -0
  31. package/dist/codesys/trace.js.map +1 -0
  32. package/dist/hmi/native.d.ts +89 -0
  33. package/dist/hmi/native.js +447 -0
  34. package/dist/hmi/native.js.map +1 -0
  35. package/dist/hmi/render.d.ts +90 -0
  36. package/dist/hmi/render.js +307 -0
  37. package/dist/hmi/render.js.map +1 -0
  38. package/dist/hmi/route.d.ts +32 -0
  39. package/dist/hmi/route.js +184 -0
  40. package/dist/hmi/route.js.map +1 -0
  41. package/dist/hmi/service.d.ts +45 -0
  42. package/dist/hmi/service.js +182 -0
  43. package/dist/hmi/service.js.map +1 -0
  44. package/dist/hmi/spec.d.ts +821 -0
  45. package/dist/hmi/spec.js +191 -0
  46. package/dist/hmi/spec.js.map +1 -0
  47. package/dist/hmi/templates.d.ts +11 -0
  48. package/dist/hmi/templates.js +92 -0
  49. package/dist/hmi/templates.js.map +1 -0
  50. package/dist/hmi/tools.d.ts +4 -0
  51. package/dist/hmi/tools.js +222 -0
  52. package/dist/hmi/tools.js.map +1 -0
  53. package/dist/hmi/value.d.ts +3 -0
  54. package/dist/hmi/value.js +26 -0
  55. package/dist/hmi/value.js.map +1 -0
  56. package/dist/panel/hmi.js +138 -0
  57. package/dist/panel.d.ts +3 -0
  58. package/dist/panel.js +17 -0
  59. package/dist/panel.js.map +1 -1
  60. package/dist/server.d.ts +1 -1
  61. package/dist/server.js +7 -2
  62. package/dist/server.js.map +1 -1
  63. package/dist/tools.d.ts +5 -1
  64. package/dist/tools.js +19 -3
  65. package/dist/tools.js.map +1 -1
  66. package/dist/viewer.d.ts +1 -1
  67. package/dist/viewer.js +13 -2
  68. package/dist/viewer.js.map +1 -1
  69. package/package.json +1 -1
  70. package/watcher/mcp_alarms.py +134 -0
  71. package/watcher/mcp_debug.py +161 -0
  72. package/watcher/mcp_devices.py +83 -0
  73. package/watcher/mcp_lang.py +179 -0
  74. package/watcher/mcp_ops.py +3 -1
  75. package/watcher/mcp_trace.py +90 -0
  76. package/watcher/mcp_ui.py +54 -0
  77. package/watcher/mcp_visu.py +422 -0
  78. package/watcher/watcher.py +52 -10
@@ -0,0 +1,307 @@
1
+ /**
2
+ * Renders an HMI screen to HTML + SVG on a fixed 1280x720 canvas (scaled to the
3
+ * window by the page). Pure: no DOM, so the server can build screenshot pages
4
+ * and the browser can mount live ones. Values are not rendered here: elements
5
+ * carry `data-b` (an index into `bindings`), and the live client (live.ts)
6
+ * applies values through CSS variables and classes, so animations keep running.
7
+ */
8
+ import { routed } from "./route.js";
9
+ export const CANVAS = { w: 1280, h: 720, header: 76, pad: 20, gap: 14 };
10
+ /** The canvas of a screen's panel size. */
11
+ export function canvasOf(screen) {
12
+ const [w, h] = (screen.size ?? "1280x720").split("x").map(Number);
13
+ if (h <= 480)
14
+ return { w, h, header: 54, pad: 12, gap: 9 };
15
+ if (h >= 1080)
16
+ return { w, h, header: 96, pad: 28, gap: 18 };
17
+ return { w, h, header: 76, pad: 20, gap: 14 };
18
+ }
19
+ const esc = (s) => s.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
20
+ const r1 = (n) => Math.round(n * 10) / 10;
21
+ export const SERIES_COLORS = ["#38bdf8", "#a78bfa", "#fbbf24", "#34d399", "#f472b6", "#60a5fa"];
22
+ /** The pixel box of a tile on the canvas. */
23
+ export function tileBox(screen, at) {
24
+ const [cols, rows] = screen.grid;
25
+ const { w, h, header, pad, gap } = canvasOf(screen);
26
+ const cw = (w - 2 * pad - (cols - 1) * gap) / cols;
27
+ const ch = (h - header - pad - (rows - 1) * gap) / rows;
28
+ const [c, r, wd, ht] = at;
29
+ return { x: pad + (c - 1) * (cw + gap), y: header + (r - 1) * (ch + gap), w: wd * cw + (wd - 1) * gap, h: ht * ch + (ht - 1) * gap };
30
+ }
31
+ export function renderScreen(screen, page = {}) {
32
+ const bindings = [];
33
+ const bind = (b) => `data-b="${bindings.push(b) - 1}"`;
34
+ let uid = 0;
35
+ const id = (p) => `${p}${++uid}`;
36
+ const faces = [];
37
+ const face = (title, f, extra) => {
38
+ const k = `fp-${faces.length + 1}`;
39
+ faces.push(faceplateHtml(k, title, f, extra, bind));
40
+ return `data-open="${k}"`;
41
+ };
42
+ const cv = canvasOf(screen);
43
+ const tiles = screen.widgets.map((wg) => {
44
+ const box = tileBox(screen, wg.at);
45
+ const inner = widget(wg, box, bind, id, face);
46
+ const title = wg.title ? `<div class="t-title">${esc(wg.title)}</div>` : "";
47
+ return `<section class="tile t-${wg.type}${wg.title ? "" : " untitled"}${box.h < 110 ? " compact" : ""}" style="left:${r1(box.x)}px;top:${r1(box.y)}px;width:${r1(box.w)}px;height:${r1(box.h)}px">${title}<div class="t-body">${inner}</div></section>`;
48
+ });
49
+ const nav = (page.pages?.length ?? 0) > 1 ? `<nav class="h-nav">${page.pages.map((p) => `<button class="h-page${p.name === screen.name ? " cur" : ""}" data-nav="${esc(p.name)}">${esc(p.title)}</button>`).join("")}</nav>` : "";
50
+ const alarmVars = (page.alarms ?? []).map((a) => a.active);
51
+ const badge = alarmVars.length ? `<div class="h-alarm" ${bind({ kind: "count", vars: alarmVars })}><span class="dot"></span><span class="n">0</span><span class="lbl">alarms</span></div>` : "";
52
+ const html = `<div class="hmi theme-${screen.theme}${cv.h <= 480 ? " small" : cv.h >= 1080 ? " large" : ""}" style="width:${cv.w}px;height:${cv.h}px;--hdr:${cv.header}px">
53
+ <div class="glow"></div>
54
+ <svg width="0" height="0" style="position:absolute" aria-hidden="true">${DEFS}</svg>
55
+ <header class="h-bar"><div class="h-titles"><div class="h-title">${esc(screen.title)}</div>${screen.subtitle ? `<div class="h-sub">${esc(screen.subtitle)}</div>` : ""}</div>
56
+ ${nav}<div class="h-right">${badge}<div class="h-sim" data-sim><span class="dot"></span><span class="lbl">Offline</span></div><div class="h-clock" data-clock>--:--:--</div></div></header>
57
+ ${tiles.join("\n")}
58
+ ${faces.join("\n")}
59
+ </div>`;
60
+ return { html, bindings, css: HMI_CSS };
61
+ }
62
+ function faceplateHtml(k, title, f, extra, bind) {
63
+ const status = [
64
+ extra.running ? `<span class="led tone-ok" ${bind({ kind: "on", v: extra.running })}><span class="led-dot"></span>Running</span>` : "",
65
+ extra.open ? `<span class="led tone-ok" ${bind({ kind: "on", v: extra.open })}><span class="led-dot"></span>Open</span>` : "",
66
+ extra.fault ? `<span class="led tone-alarm" ${bind({ kind: "on", v: extra.fault })}><span class="led-dot"></span>Fault</span>` : "",
67
+ ].join("");
68
+ const mode = f.auto ? `<label class="sw" data-act="toggle" data-var="${esc(f.auto)}" ${bind({ kind: "on", v: f.auto })}><span class="sw-track"><span class="sw-knob"></span></span><span class="sw-lbl">Automatic</span><span class="sw-state"><span class="s-on">AUTO</span><span class="s-off">MANUAL</span></span></label>` : "";
69
+ const btn = (label, v, tone) => (v ? `<button class="btn tone-${tone}" data-act="tap" data-var="${esc(v)}" ${bind({ kind: "on", v })}>${label}</button>` : "");
70
+ const buttons = [btn("Start", f.start, "ok"), btn("Stop", f.stop, "alarm"), btn("Open", f.open, "ok"), btn("Close", f.close, "alarm"), btn("Reset", f.reset, "warn")].join("");
71
+ const values = (f.values ?? []).map((x) => `<div class="fp-row"><span>${esc(x.label)}</span><b ${bind({ kind: "text", v: x.value, decimals: x.decimals, unit: x.unit })}>–</b></div>`).join("");
72
+ const sp = f.setpoint;
73
+ const setpoint = sp
74
+ ? `<div class="fp-sp"><div class="fp-row"><span>${esc(sp.label ?? "Setpoint")}</span></div><div class="sp" data-var="${esc(sp.variable)}" data-min="${sp.min}" data-max="${sp.max}" data-step="${sp.step ?? 1}" ${bind({ kind: "setpoint", v: sp.variable, decimals: 1 })}><div class="sp-row"><button class="sp-btn" data-step="-1">−</button><div class="sp-val"><span class="sp-num" ${bind({ kind: "text", v: sp.variable, decimals: 1 })}>–</span><span class="sp-unit">${esc(sp.unit ?? "")}</span></div><button class="sp-btn" data-step="1">+</button></div><input class="sp-range" type="range" min="${sp.min}" max="${sp.max}" step="${sp.step ?? 1}"></div></div>`
75
+ : "";
76
+ return `<div class="fp" id="${k}" hidden><div class="fp-card"><div class="fp-head"><div class="fp-title">${esc(f.title ?? title)}</div><button class="fp-x" data-close>×</button></div>${status ? `<div class="fp-status">${status}</div>` : ""}${mode}${buttons ? `<div class="btns fp-btns">${buttons}</div>` : ""}${values}${setpoint}</div></div>`;
77
+ }
78
+ function toneOf(t) {
79
+ return t ?? "accent";
80
+ }
81
+ function widget(w, box, bind, id, face) {
82
+ const bodyH = box.h - (w.title ? 44 : 20);
83
+ switch (w.type) {
84
+ case "value": {
85
+ const size = Math.max(22, Math.min(64, bodyH * (w.trend ? 0.36 : 0.55), box.w / 6));
86
+ const spark = w.trend ? `<svg class="spark" viewBox="0 0 200 40" preserveAspectRatio="none" ${bind({ kind: "spark", v: w.value })}><path class="spark-fill"/><path class="spark-line"/></svg>` : "";
87
+ return `<div class="v-wrap"><div class="v-num" style="font-size:${r1(size)}px" ${bind({ kind: "text", v: w.value, decimals: w.decimals, bands: w.bands })}>–</div>${w.unit ? `<div class="v-unit">${esc(w.unit)}</div>` : ""}</div>${spark}`;
88
+ }
89
+ case "gauge": {
90
+ const s = Math.min(box.w - 24, bodyH * 1.25);
91
+ const R = 80;
92
+ const arc = describeArc(100, 100, R, -120, 120);
93
+ const len = r1((240 / 360) * 2 * Math.PI * R);
94
+ const ticks = Array.from({ length: 11 }, (_, i) => {
95
+ const a = ((-120 + i * 24) * Math.PI) / 180;
96
+ const r0 = i % 5 === 0 ? 62 : 66;
97
+ return `<line x1="${r1(100 + r0 * Math.sin(a))}" y1="${r1(100 - r0 * Math.cos(a))}" x2="${r1(100 + 70 * Math.sin(a))}" y2="${r1(100 - 70 * Math.cos(a))}"/>`;
98
+ }).join("");
99
+ return `<svg class="gauge" style="width:${r1(s)}px;height:${r1(s * 0.86)}px;--len:${len}" viewBox="0 0 200 172" ${bind({ kind: "level", v: w.value, min: w.min, max: w.max, bands: w.bands })}>
100
+ <path class="g-track" d="${arc}"/><path class="g-val" d="${arc}" style="stroke-dasharray:${len};"/><g class="g-ticks">${ticks}</g>
101
+ <text x="100" y="104" class="g-num" ${bind({ kind: "text", v: w.value, decimals: w.decimals, bands: w.bands })}>–</text>
102
+ <text x="100" y="128" class="g-unit">${esc(w.unit ?? "")}</text>
103
+ <text x="${r1(100 - R * Math.sin((120 * Math.PI) / 180))}" y="166" class="g-lim">${w.min}</text><text x="${r1(100 + R * Math.sin((120 * Math.PI) / 180))}" y="166" class="g-lim">${w.max}</text></svg>`;
104
+ }
105
+ case "bar": {
106
+ const lvl = bind({ kind: "level", v: w.value, min: w.min, max: w.max, bands: w.bands });
107
+ return `<div class="bar-wrap${w.vertical ? " vert" : ""}"><div class="bar" ${lvl}><div class="bar-fill"></div></div><div class="bar-read"><span class="bar-num" ${bind({ kind: "text", v: w.value, decimals: 1, bands: w.bands })}>–</span> <span class="bar-unit">${esc(w.unit ?? "")}</span><span class="bar-lim">${w.min} – ${w.max}</span></div></div>`;
108
+ }
109
+ case "status":
110
+ return `<ul class="status">${w.items.map((i) => `<li class="led tone-${toneOf(i.tone ?? "ok")}" ${bind({ kind: "on", v: i.on, invert: i.invert })}><span class="led-dot"></span><span>${esc(i.label)}</span></li>`).join("")}</ul>`;
111
+ case "buttons":
112
+ return `<div class="btns${w.items.length > 2 && box.w < 360 ? " col" : ""}">${w.items
113
+ .map((i) => `<button class="btn tone-${toneOf(i.tone ?? (/stop|reset|off/i.test(i.label) ? "alarm" : "accent"))}" data-act="${i.action}" data-var="${esc(i.variable)}" ${i.action === "tap" || i.action === "toggle" ? bind({ kind: "on", v: i.variable }) : ""}>${esc(i.label)}</button>`)
114
+ .join("")}</div>`;
115
+ case "switch":
116
+ return `<label class="sw" data-act="toggle" data-var="${esc(w.variable)}" ${bind({ kind: "on", v: w.variable })}><span class="sw-track"><span class="sw-knob"></span></span><span class="sw-lbl">${esc(w.label ?? "")}</span><span class="sw-state"><span class="s-on">ON</span><span class="s-off">OFF</span></span></label>`;
117
+ case "setpoint": {
118
+ const dec = w.step !== undefined && !Number.isInteger(w.step) ? String(w.step).split(".")[1].length : 0;
119
+ return `<div class="sp" data-var="${esc(w.variable)}" data-min="${w.min}" data-max="${w.max}" data-step="${w.step ?? 1}" ${bind({ kind: "setpoint", v: w.variable, decimals: dec })}>
120
+ <div class="sp-row"><button class="sp-btn" data-step="-1">−</button><div class="sp-val"><span class="sp-num" ${bind({ kind: "text", v: w.variable, decimals: dec })}>–</span><span class="sp-unit">${esc(w.unit ?? "")}</span></div><button class="sp-btn" data-step="1">+</button></div>
121
+ <input class="sp-range" type="range" min="${w.min}" max="${w.max}" step="${w.step ?? 1}"><div class="sp-lim"><span>${w.min}</span><span>${w.max}</span></div></div>`;
122
+ }
123
+ case "trend": {
124
+ const lines = w.series.map((s, i) => `<path class="tr-line" style="stroke:${SERIES_COLORS[i % SERIES_COLORS.length]}"/>`).join("");
125
+ const legend = w.series.map((s, i) => `<span><i style="background:${SERIES_COLORS[i % SERIES_COLORS.length]}"></i>${esc(s.label ?? s.value.split(".").pop())}</span>`).join("");
126
+ const grid = [0.25, 0.5, 0.75].map((f) => `<line x1="0" x2="600" y1="${200 * f}" y2="${200 * f}"/>`).join("");
127
+ return `<div class="tr-legend">${legend}</div><svg class="trend" viewBox="0 0 600 200" preserveAspectRatio="none" ${bind({ kind: "trend", series: w.series.map((s) => s.value), min: w.min, max: w.max, seconds: w.seconds })}><g class="tr-grid">${grid}</g>${lines}</svg><div class="tr-axis"><span>−${w.seconds} s</span><span class="tr-range"><span class="tr-min"></span> – <span class="tr-max"></span></span><span>now</span></div>`;
128
+ }
129
+ case "alarms":
130
+ return `<ul class="alarms">${w.items.map((i) => `<li class="al sev-${i.severity}" ${bind({ kind: "alarm", v: i.active })}><span class="al-badge">${i.severity === "info" ? "INFO" : i.severity === "warning" ? "WARN" : "ALARM"}</span><span class="al-text">${esc(i.text)}</span></li>`).join("")}<li class="al-none">No active alarms</li></ul>`;
131
+ case "text":
132
+ return `<div class="txt">${esc(w.text).replace(/\n/g, "<br>")}</div>`;
133
+ case "process": {
134
+ const vw = 100;
135
+ const vh = r1((100 * Math.max(60, bodyH)) / Math.max(60, box.w - 24));
136
+ const sy = vh / 100;
137
+ const items = routed(w.items, sy).sort((a, b) => (a.type === "pipe" ? -1 : 0) - (b.type === "pipe" ? -1 : 0));
138
+ return `<svg class="proc" viewBox="0 0 ${vw} ${vh}" preserveAspectRatio="xMidYMid meet">${items.map((p) => processSvg(p, sy, bind, id, face)).join("")}</svg>`;
139
+ }
140
+ }
141
+ }
142
+ function describeArc(cx, cy, r, a0, a1) {
143
+ const p = (a) => [cx + r * Math.sin((a * Math.PI) / 180), cy - r * Math.cos((a * Math.PI) / 180)].map(r1);
144
+ const [x0, y0] = p(a0);
145
+ const [x1, y1] = p(a1);
146
+ return `M${x0} ${y0} A${r} ${r} 0 ${a1 - a0 > 180 ? 1 : 0} 1 ${x1} ${y1}`;
147
+ }
148
+ const DEFS = `<defs>
149
+ <linearGradient id="gShell" x1="0" x2="1"><stop offset="0" stop-color="var(--shell-a)"/><stop offset=".5" stop-color="var(--shell-b)"/><stop offset="1" stop-color="var(--shell-a)"/></linearGradient>
150
+ <linearGradient id="gLiquid" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="var(--liq-a)"/><stop offset="1" stop-color="var(--liq-b)"/></linearGradient>
151
+ <radialGradient id="gHub" cx=".35" cy=".35" r=".8"><stop offset="0" stop-color="var(--hub-a)"/><stop offset="1" stop-color="var(--hub-b)"/></radialGradient>
152
+ <filter id="fGlow" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="1.2" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
153
+ </defs>`;
154
+ function processSvg(p, sy, bind, id, face) {
155
+ const Y = (y) => r1(y * sy);
156
+ const label = (x, y, t) => (t ? `<text class="p-label" x="${r1(x)}" y="${Y(y)}">${esc(t)}</text>` : "");
157
+ switch (p.type) {
158
+ case "pipe": {
159
+ const d = (p.points ?? []).map(([x, y], i) => `${i ? "L" : "M"}${r1(x)} ${Y(y)}`).join(" ");
160
+ return `<g class="pipe" ${p.flow ? bind({ kind: "on", v: p.flow }) : ""}><path class="pipe-outer" d="${d}"/><path class="pipe-inner" d="${d}"/><path class="pipe-flow" d="${d}"/></g>`;
161
+ }
162
+ case "tank": {
163
+ const x = r1(p.x), y = Y(p.y), w = r1(p.w), h = Y(p.h);
164
+ const clip = id("tk");
165
+ const ticks = [0.25, 0.5, 0.75].map((f) => `<line x1="${r1(x + w - 2.2)}" x2="${r1(x + w - 0.8)}" y1="${r1(y + h * (1 - f))}" y2="${r1(y + h * (1 - f))}"/>`).join("");
166
+ return `<g class="tank" ${bind({ kind: "level", v: p.level, min: 0, max: p.max, bands: p.bands })}>
167
+ <clipPath id="${clip}"><rect x="${x}" y="${y}" width="${w}" height="${h}" rx="${r1(Math.min(w, h) * 0.12)}"/></clipPath>
168
+ <rect class="tank-shell" x="${x}" y="${y}" width="${w}" height="${h}" rx="${r1(Math.min(w, h) * 0.12)}"/>
169
+ <g clip-path="url(#${clip})"><g class="tank-liq" style="transform-origin:${x}px ${r1(y + h)}px"><rect x="${x}" y="${y}" width="${w}" height="${h}" fill="url(#gLiquid)"/><path class="tank-wave" d="M${x} ${r1(y + 1)} q ${r1(w / 8)} -1.2 ${r1(w / 4)} 0 t ${r1(w / 4)} 0 t ${r1(w / 4)} 0 t ${r1(w / 4)} 0 t ${r1(w / 4)} 0 V ${r1(y + 3)} H ${x} Z"/></g></g>
170
+ <rect class="tank-gloss" x="${r1(x + w * 0.1)}" y="${r1(y + h * 0.05)}" width="${r1(w * 0.12)}" height="${r1(h * 0.9)}" rx="${r1(w * 0.06)}"/>
171
+ <g class="tank-ticks">${ticks}</g>
172
+ <text class="tank-num" x="${r1(x + w / 2)}" y="${r1(y + h / 2 + 1.5)}" ${bind({ kind: "text", v: p.level, decimals: 0, unit: p.unit })}>–</text>
173
+ ${label(x + w / 2, p.y + p.h + 2.8 / sy, p.label)}</g>`;
174
+ }
175
+ case "pump": {
176
+ const s = p.size, cx = r1(p.x), cy = Y(p.y), r = r1(s / 2);
177
+ const blades = [0, 60, 120, 180, 240, 300].map((a) => `<path d="M0 0 Q ${r1(r * 0.3)} ${r1(-r * 0.25)} ${r1(r * 0.12)} ${r1(-r * 0.62)}" transform="rotate(${a})"/>`).join("");
178
+ return `<g ${p.fault ? bind({ kind: "fault", v: p.fault }) : ""} ${p.faceplate ? `class="clickable" ${face(p.label ?? "Pump", p.faceplate, { running: p.running, fault: p.fault })}` : ""}><g class="pump" ${bind({ kind: "on", v: p.running })}>
179
+ <circle class="pump-ring" cx="${cx}" cy="${cy}" r="${r}"/><circle class="pump-body" cx="${cx}" cy="${cy}" r="${r1(r * 0.86)}" fill="url(#gHub)"/>
180
+ <g transform="translate(${cx} ${cy})"><g class="pump-imp">${blades}<circle r="${r1(r * 0.14)}" class="pump-hub"/></g></g>
181
+ ${label(p.x, p.y + (s / 2 + 2.6) / sy, p.label)}</g></g>`;
182
+ }
183
+ case "fan": {
184
+ const s = p.size, cx = r1(p.x), cy = Y(p.y), r = r1(s / 2);
185
+ const blades = [0, 120, 240].map((a) => `<path d="M0 0 C ${r1(r * 0.5)} ${r1(-r * 0.2)} ${r1(r * 0.55)} ${r1(-r * 0.8)} 0 ${r1(-r * 0.86)} C ${r1(-r * 0.2)} ${r1(-r * 0.6)} ${r1(-r * 0.1)} ${r1(-r * 0.2)} 0 0Z" transform="rotate(${a})"/>`).join("");
186
+ return `<g class="pump fan${p.faceplate ? " clickable" : ""}" ${bind({ kind: "on", v: p.running })} ${p.faceplate ? face(p.label ?? "Fan", p.faceplate, { running: p.running }) : ""}><circle class="pump-ring" cx="${cx}" cy="${cy}" r="${r}"/><circle class="pump-body" cx="${cx}" cy="${cy}" r="${r1(r * 0.9)}" fill="url(#gHub)"/><g transform="translate(${cx} ${cy})"><g class="pump-imp">${blades}<circle r="${r1(r * 0.12)}" class="pump-hub"/></g></g>${label(p.x, p.y + (s / 2 + 2.6) / sy, p.label)}</g>`;
187
+ }
188
+ case "valve": {
189
+ const s = p.size, cx = r1(p.x), cy = Y(p.y), h = r1(s / 2);
190
+ const body = `<path class="valve-body" d="M${r1(-h)} ${r1(-h * 0.7)} L${h} ${r1(h * 0.7)} L${h} ${r1(-h * 0.7)} L${r1(-h)} ${r1(h * 0.7)} Z"/><line class="valve-stem" x1="0" y1="0" x2="0" y2="${r1(-h * 1.1)}"/><rect class="valve-act" x="${r1(-h * 0.5)}" y="${r1(-h * 1.5)}" width="${h}" height="${r1(h * 0.45)}" rx="${r1(h * 0.1)}"/>`;
191
+ return `<g class="valve${p.faceplate ? " clickable" : ""}" ${bind({ kind: "on", v: p.open })} ${p.faceplate ? face(p.label ?? "Valve", p.faceplate, { open: p.open }) : ""}><g transform="translate(${cx} ${cy})${p.vertical ? " rotate(90)" : ""}">${body}</g>${p.label ? (p.vertical ? `<text class="p-label left" x="${r1(p.x + s * 0.75)}" y="${r1(cy + 0.6)}">${esc(p.label)}</text>` : label(p.x, p.y + (s / 2 + 2.6) / sy, p.label)) : ""}</g>`;
192
+ }
193
+ case "sensor": {
194
+ const cx = r1(p.x), cy = Y(p.y);
195
+ return `<g class="sensor"><rect class="sen-box" x="${r1(cx - 6.5)}" y="${r1(cy - 2.1)}" width="13" height="4.2" rx="2.1"/><text class="sen-num" x="${cx}" y="${r1(cy + 0.75)}" ${bind({ kind: "text", v: p.value, decimals: p.decimals ?? 1, unit: p.unit })}>–</text>${p.label ? `<text class="sen-tag" x="${cx}" y="${r1(cy - 3)}">${esc(p.label)}</text>` : ""}</g>`;
196
+ }
197
+ case "lamp": {
198
+ const cx = r1(p.x), cy = Y(p.y);
199
+ return `<g class="plamp tone-${toneOf(p.tone ?? "ok")}" ${bind({ kind: "on", v: p.on })}><circle class="pl-halo" cx="${cx}" cy="${cy}" r="2.2"/><circle class="pl-dot" cx="${cx}" cy="${cy}" r="1.3"/>${p.label ? `<text class="p-label left" x="${r1(cx + 3)}" y="${r1(cy + 0.65)}">${esc(p.label)}</text>` : ""}</g>`;
200
+ }
201
+ case "junction":
202
+ return `<circle class="junction" cx="${r1(p.x)}" cy="${Y(p.y)}" r="1.1"/>`;
203
+ case "label":
204
+ return `<text class="p-text" x="${r1(p.x)}" y="${Y(p.y)}">${esc(p.text)}</text>`;
205
+ }
206
+ }
207
+ export const HMI_CSS = String.raw `
208
+ .hmi{position:relative;overflow:hidden;font-family:"Segoe UI Variable Display","Segoe UI",Inter,system-ui,sans-serif;color:var(--fg);background:var(--bg);border-radius:18px;box-sizing:border-box;-webkit-font-smoothing:antialiased}
209
+ .hmi *{box-sizing:border-box}
210
+ .theme-dark{--bg:radial-gradient(1200px 600px at 15% -10%,#13284a 0%,transparent 60%),radial-gradient(900px 500px at 110% 110%,#1c1640 0%,transparent 55%),#070d1a;--fg:#e6edf7;--muted:#8193ad;--tile:linear-gradient(160deg,rgba(30,41,64,.72),rgba(14,21,37,.78));--tile-bd:rgba(148,163,184,.13);--tile-sh:0 10px 30px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.05);--track:rgba(148,163,184,.16);--accent:#38bdf8;--ok:#22c55e;--warn:#f59e0b;--alarm:#ef4444;--neutral:#64748b;--shell-a:#1e293b;--shell-b:#334155;--liq-a:#38bdf8;--liq-b:#0369a1;--hub-a:#475569;--hub-b:#0f172a;--pipe:#334155;--pipe-in:#1e293b;--btn:rgba(148,163,184,.1)}
211
+ .theme-light{--bg:radial-gradient(1000px 500px at 10% -10%,#dbeafe 0%,transparent 60%),#eef2f7;--fg:#0f172a;--muted:#64748b;--tile:linear-gradient(160deg,#ffffff,#f8fafc);--tile-bd:#e2e8f0;--tile-sh:0 6px 20px rgba(15,23,42,.06);--track:#e2e8f0;--accent:#0284c7;--ok:#16a34a;--warn:#d97706;--alarm:#dc2626;--neutral:#94a3b8;--shell-a:#cbd5e1;--shell-b:#f1f5f9;--liq-a:#38bdf8;--liq-b:#0284c7;--hub-a:#e2e8f0;--hub-b:#94a3b8;--pipe:#94a3b8;--pipe-in:#cbd5e1;--btn:#f1f5f9}
212
+ .glow{position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(56,189,248,.06),transparent 30%)}
213
+ .h-bar{position:absolute;left:20px;right:20px;top:0;height:var(--hdr,76px);display:flex;align-items:center;justify-content:space-between}
214
+ .h-title{font-size:24px;font-weight:650;letter-spacing:-.01em}
215
+ .h-sub{font-size:13px;color:var(--muted);margin-top:2px}
216
+ .h-right{display:flex;gap:12px;align-items:center}
217
+ .h-sim{display:flex;align-items:center;gap:8px;padding:7px 13px;border-radius:999px;border:1px solid var(--tile-bd);background:var(--tile);font-size:12px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
218
+ .h-sim .dot{width:8px;height:8px;border-radius:50%;background:var(--neutral)}
219
+ .h-sim.run{color:var(--ok)}.h-sim.run .dot{background:var(--ok);box-shadow:0 0 0 4px color-mix(in srgb,var(--ok) 25%,transparent);animation:pulse 1.6s infinite}
220
+ .h-sim.stop{color:var(--warn)}.h-sim.stop .dot{background:var(--warn)}
221
+ .h-nav{position:absolute;left:50%;transform:translateX(-50%);display:flex;gap:4px;padding:4px;border-radius:12px;background:var(--tile);border:1px solid var(--tile-bd)}
222
+ .h-page{border:0;border-radius:9px;padding:8px 16px;background:transparent;color:var(--muted);font:600 13px/1 inherit;cursor:pointer;letter-spacing:.02em}
223
+ .h-page:hover{color:var(--fg)}.h-page.cur{background:var(--accent);color:#04121f}
224
+ .h-alarm{display:flex;align-items:center;gap:7px;padding:7px 12px;border-radius:999px;border:1px solid var(--tile-bd);background:var(--tile);font-size:12px;font-weight:700;color:var(--muted)}
225
+ .h-alarm .dot{width:8px;height:8px;border-radius:50%;background:var(--ok)}.h-alarm.on{color:#fff;background:color-mix(in srgb,var(--alarm) 75%,transparent);border-color:var(--alarm);animation:blink 1.2s infinite}.h-alarm.on .dot{background:#fff}
226
+ .clickable{cursor:pointer}.clickable:hover .pump-ring,.clickable:hover .valve-body{filter:drop-shadow(0 0 1.5px var(--accent))}
227
+ .fp{position:absolute;inset:0;background:rgba(2,6,23,.55);backdrop-filter:blur(3px);display:flex;align-items:center;justify-content:center;z-index:20}.fp[hidden]{display:none}
228
+ .fp-card{width:380px;border-radius:18px;background:var(--tile);background-color:#111a2e;border:1px solid var(--tile-bd);box-shadow:0 30px 80px rgba(0,0,0,.55);padding:18px 20px;display:flex;flex-direction:column;gap:14px}
229
+ .theme-light .fp-card{background-color:#fff}
230
+ .fp-head{display:flex;align-items:center;justify-content:space-between}.fp-title{font-size:18px;font-weight:650}
231
+ .fp-x{border:0;background:var(--btn);color:var(--fg);width:32px;height:32px;border-radius:10px;font-size:18px;cursor:pointer}
232
+ .fp-status{display:flex;gap:16px}.fp-btns{height:auto}.fp-btns .btn{min-height:46px}
233
+ .fp-row{display:flex;justify-content:space-between;font-size:14px;color:var(--muted)}.fp-row b{color:var(--fg);font-variant-numeric:tabular-nums}
234
+ .h-clock{font-variant-numeric:tabular-nums;font-size:15px;color:var(--muted);min-width:76px;text-align:right}
235
+ .tile{position:absolute;border-radius:16px;background:var(--tile);border:1px solid var(--tile-bd);box-shadow:var(--tile-sh);backdrop-filter:blur(8px);display:flex;flex-direction:column;padding:14px 16px 12px}
236
+ .tile.compact{padding:8px 16px}.tile.compact .t-title{height:15px;font-size:10.5px}
237
+ .t-title{font-size:11.5px;font-weight:650;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);height:20px;flex:none}
238
+ .t-body{flex:1;min-height:0;display:flex;flex-direction:column;justify-content:center;position:relative}
239
+ .tone-accent{--c:var(--accent)}.tone-ok{--c:var(--ok)}.tone-warn{--c:var(--warn)}.tone-alarm{--c:var(--alarm)}.tone-neutral{--c:var(--neutral)}
240
+ [data-tone=accent]{--c:var(--accent)}[data-tone=ok]{--c:var(--ok)}[data-tone=warn]{--c:var(--warn)}[data-tone=alarm]{--c:var(--alarm)}[data-tone=neutral]{--c:var(--neutral)}
241
+ .v-wrap{display:flex;align-items:baseline;gap:8px}
242
+ .v-num{font-weight:650;letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1;color:var(--c,var(--fg));transition:color .3s}
243
+ .v-unit{font-size:15px;color:var(--muted);font-weight:500}
244
+ .spark{width:100%;height:34%;margin-top:8px}.spark-line{fill:none;stroke:var(--accent);stroke-width:2;vector-effect:non-scaling-stroke}.spark-fill{fill:color-mix(in srgb,var(--accent) 16%,transparent)}
245
+ .gauge{display:block;margin:0 auto;--p:0}.g-track,.g-val{fill:none;stroke-width:14;stroke-linecap:round}.g-track{stroke:var(--track)}
246
+ .g-val{stroke:var(--c,var(--accent));stroke-dashoffset:calc(var(--len) * (1 - var(--p)));transition:stroke-dashoffset .5s cubic-bezier(.2,.8,.2,1),stroke .3s;filter:drop-shadow(0 0 6px color-mix(in srgb,var(--c,var(--accent)) 55%,transparent))}
247
+ .g-ticks line{stroke:var(--muted);stroke-width:1.5;opacity:.5}
248
+ .g-num{font-size:34px;font-weight:650;text-anchor:middle;fill:var(--fg);font-variant-numeric:tabular-nums}.g-unit{font-size:13px;text-anchor:middle;fill:var(--muted)}.g-lim{font-size:11px;fill:var(--muted);text-anchor:middle}
249
+ .bar-wrap{display:flex;flex-direction:column;gap:10px;--p:0}.bar{height:16px;border-radius:999px;background:var(--track);overflow:hidden;--p:0}
250
+ .bar-fill{height:100%;width:calc(var(--p) * 100%);border-radius:999px;background:linear-gradient(90deg,color-mix(in srgb,var(--c,var(--accent)) 70%,transparent),var(--c,var(--accent)));box-shadow:0 0 14px color-mix(in srgb,var(--c,var(--accent)) 45%,transparent);transition:width .5s cubic-bezier(.2,.8,.2,1)}
251
+ .bar-wrap.vert{flex-direction:row;height:100%;align-items:stretch}.bar-wrap.vert .bar{width:22px;height:auto;display:flex;align-items:flex-end}.bar-wrap.vert .bar-fill{width:100%;height:calc(var(--p) * 100%);transition:height .5s}
252
+ .bar-read{display:flex;align-items:baseline;gap:4px}.bar-num{font-size:26px;font-weight:650;font-variant-numeric:tabular-nums;color:var(--c,var(--fg))}.bar-unit{color:var(--muted);font-size:13px}.bar-lim{margin-left:auto;color:var(--muted);font-size:11px}
253
+ .status{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:9px}
254
+ .led{display:flex;align-items:center;gap:11px;font-size:14px;color:var(--muted);transition:color .3s}
255
+ .led-dot{width:12px;height:12px;border-radius:50%;background:var(--track);box-shadow:inset 0 1px 2px rgba(0,0,0,.4);transition:all .3s;flex:none}
256
+ .led.on{color:var(--fg)}.led.on .led-dot{background:radial-gradient(circle at 35% 35%,#fff 0,var(--c) 45%);box-shadow:0 0 0 3px color-mix(in srgb,var(--c) 22%,transparent),0 0 14px var(--c)}
257
+ .btns{display:flex;gap:10px;height:100%;align-items:center}.btns.col{flex-direction:column;align-items:stretch}
258
+ .btn{flex:1;min-height:52px;border-radius:12px;border:1px solid color-mix(in srgb,var(--c) 40%,var(--tile-bd));background:linear-gradient(180deg,color-mix(in srgb,var(--c) 22%,var(--btn)),color-mix(in srgb,var(--c) 10%,var(--btn)));color:var(--fg);font:650 16px/1 inherit;letter-spacing:.03em;cursor:pointer;transition:all .15s;box-shadow:0 4px 14px color-mix(in srgb,var(--c) 18%,transparent),inset 0 1px 0 rgba(255,255,255,.08)}
259
+ .btn:hover{filter:brightness(1.15)}.btn:active,.btn.on{transform:translateY(1px);background:color-mix(in srgb,var(--c) 45%,var(--btn));box-shadow:0 0 18px color-mix(in srgb,var(--c) 45%,transparent)}
260
+ .sw{display:flex;align-items:center;gap:14px;cursor:pointer;user-select:none}
261
+ .sw-track{width:58px;height:32px;border-radius:999px;background:var(--track);position:relative;transition:background .25s;flex:none}
262
+ .sw-knob{position:absolute;top:3px;left:3px;width:26px;height:26px;border-radius:50%;background:#fff;box-shadow:0 2px 6px rgba(0,0,0,.35);transition:transform .25s cubic-bezier(.2,.8,.2,1)}
263
+ .sw.on .sw-track{background:var(--ok);box-shadow:0 0 16px color-mix(in srgb,var(--ok) 45%,transparent)}.sw.on .sw-knob{transform:translateX(26px)}
264
+ .sw-lbl{font-size:15px;flex:1}.sw-state{font-size:12px;font-weight:700;letter-spacing:.08em;color:var(--muted)}.sw .s-on{display:none}.sw.on .s-on{display:inline;color:var(--ok)}.sw.on .s-off{display:none}
265
+ .sp{display:flex;flex-direction:column;gap:10px}.sp-row{display:flex;align-items:center;gap:10px}
266
+ .sp-btn{width:40px;height:40px;border-radius:12px;border:1px solid var(--tile-bd);background:var(--btn);color:var(--fg);font-size:22px;cursor:pointer}.sp-btn:hover{border-color:var(--accent)}
267
+ .sp-val{flex:1;text-align:center}.sp-num{font-size:30px;font-weight:650;font-variant-numeric:tabular-nums}.sp-unit{margin-left:6px;color:var(--muted);font-size:13px}
268
+ .sp-range{width:100%;accent-color:var(--accent)}.sp-lim{display:flex;justify-content:space-between;color:var(--muted);font-size:11px}
269
+ .tr-legend{display:flex;gap:14px;font-size:12px;color:var(--muted);margin-bottom:6px;flex-wrap:wrap}.tr-legend i{display:inline-block;width:10px;height:3px;border-radius:2px;margin-right:6px;vertical-align:middle}
270
+ .trend{flex:1;width:100%;min-height:0}.tr-grid line{stroke:var(--track);stroke-width:1;vector-effect:non-scaling-stroke}
271
+ .tr-line{fill:none;stroke-width:2.2;vector-effect:non-scaling-stroke;stroke-linejoin:round;filter:drop-shadow(0 0 4px rgba(56,189,248,.35))}
272
+ .tr-axis{display:flex;justify-content:space-between;font-size:10.5px;color:var(--muted);margin-top:4px}
273
+ .t-alarms .t-body,.t-status .t-body{justify-content:flex-start}
274
+ .alarms{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px;overflow:hidden}
275
+ .al{display:none;align-items:center;gap:9px;padding:8px 10px;border-radius:10px;font-size:12.5px;line-height:1.25;background:color-mix(in srgb,var(--c) 12%,transparent);border:1px solid color-mix(in srgb,var(--c) 35%,transparent)}
276
+ .al.active{display:flex}.sev-alarm{--c:var(--alarm)}.sev-warning{--c:var(--warn)}.sev-info{--c:var(--accent)}
277
+ .sev-alarm.active{animation:blink 1.2s infinite}
278
+ .al-badge{font-size:10px;font-weight:800;letter-spacing:.08em;padding:3px 7px;border-radius:6px;background:var(--c);color:#fff}
279
+ .al-none{display:flex;align-items:center;gap:9px;color:var(--ok);font-size:14px}.al-none::before{content:"";width:10px;height:10px;border-radius:50%;background:var(--ok);box-shadow:0 0 10px var(--ok)}
280
+ .alarms.has .al-none{display:none}
281
+ .txt{font-size:14px;line-height:1.5;color:var(--muted)}
282
+ .proc{width:100%;height:100%;overflow:visible}
283
+ .p-label{font-size:1.75px;fill:var(--muted);text-anchor:middle;font-weight:600;letter-spacing:.05em}.p-label.left{text-anchor:start}.p-text{font-size:2px;fill:var(--fg);font-weight:600}
284
+ .junction{fill:var(--pipe)}
285
+ .pipe-outer{fill:none;stroke:var(--pipe);stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}.pipe-inner{fill:none;stroke:var(--pipe-in);stroke-width:1;stroke-linecap:round;stroke-linejoin:round}
286
+ .pipe-flow{fill:none;stroke:var(--accent);stroke-width:.55;stroke-dasharray:1.1 1.9;stroke-linecap:round;opacity:0;transition:opacity .4s}.pipe.on .pipe-flow{opacity:1;animation:flow .8s linear infinite;filter:drop-shadow(0 0 1px var(--accent))}
287
+ .tank{--p:0}.tank-shell{fill:url(#gShell);stroke:var(--tile-bd);stroke-width:.4}.tank-liq{transform:scaleY(var(--p));transition:transform .8s cubic-bezier(.2,.8,.2,1)}
288
+ .tank-liq rect{fill:url(#gLiquid);opacity:.92}.tank[data-tone=warn] .tank-liq rect{fill:var(--warn)}.tank[data-tone=alarm] .tank-liq rect{fill:var(--alarm)}
289
+ .tank-wave{fill:rgba(255,255,255,.22);animation:wave 3s ease-in-out infinite alternate}
290
+ .tank-gloss{fill:rgba(255,255,255,.08)}.tank-ticks line{stroke:var(--muted);stroke-width:.3}
291
+ .tank-num{font-size:3.4px;font-weight:700;fill:#fff;text-anchor:middle;paint-order:stroke;stroke:rgba(2,6,23,.45);stroke-width:.6px;font-variant-numeric:tabular-nums}
292
+ .pump-ring{fill:none;stroke:var(--neutral);stroke-width:.9;transition:all .3s}.pump-body{stroke:var(--tile-bd);stroke-width:.3}.pump-out{fill:var(--shell-b);stroke:var(--tile-bd);stroke-width:.3}
293
+ .pump-imp path{fill:none;stroke:var(--muted);stroke-width:.9;stroke-linecap:round}.fan .pump-imp path{fill:var(--muted);stroke:none;opacity:.85}.pump-hub{fill:var(--muted)}
294
+ .pump.on .pump-ring{stroke:var(--ok);filter:url(#fGlow)}.pump.on .pump-imp{animation:spin 1s linear infinite}.pump.on .pump-imp path{stroke:var(--ok)}.fan.on .pump-imp path{fill:var(--ok)}.pump.on .pump-hub{fill:var(--ok)}
295
+ .fault .pump-ring{stroke:var(--alarm);animation:blink .8s infinite}
296
+ .valve-body{fill:var(--neutral);stroke:var(--tile-bd);stroke-width:.3;transition:fill .3s}.valve-stem{stroke:var(--muted);stroke-width:.6}.valve-act{fill:var(--shell-b);stroke:var(--tile-bd);stroke-width:.3}
297
+ .valve.on .valve-body{fill:var(--ok);filter:url(#fGlow)}
298
+ .sen-box{fill:rgba(2,6,23,.6);stroke:color-mix(in srgb,var(--accent) 70%,transparent);stroke-width:.22}.theme-light .sen-box{fill:#fff}
299
+ .sen-num{font-size:2px;font-weight:700;fill:var(--fg);text-anchor:middle;font-variant-numeric:tabular-nums}.sen-tag{font-size:1.5px;fill:var(--muted);text-anchor:middle;font-weight:600;letter-spacing:.06em}
300
+ .plamp .pl-dot{fill:var(--track);transition:all .3s}.plamp .pl-halo{fill:none}.plamp.on .pl-dot{fill:var(--c)}.plamp.on .pl-halo{fill:color-mix(in srgb,var(--c) 30%,transparent);filter:url(#fGlow)}
301
+ @keyframes spin{to{transform:rotate(360deg)}}@keyframes flow{to{stroke-dashoffset:-3}}@keyframes pulse{50%{opacity:.55}}@keyframes blink{50%{opacity:.45}}
302
+ @keyframes wave{from{transform:translateX(-6%)}to{transform:translateX(0)}}
303
+ .small .h-title{font-size:18px}.small .h-sub{display:none}.small .h-page{padding:6px 10px;font-size:11px}.small .t-title{font-size:10px}.small .tile{padding:9px 11px}
304
+ .large .h-title{font-size:32px}.large .h-page{font-size:16px;padding:10px 20px}.large .t-title{font-size:14px}
305
+ @media (prefers-reduced-motion:reduce){.hmi *{animation:none!important;transition:none!important}}
306
+ `;
307
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/hmi/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Ports and pipe routing for process diagrams. Symbols have named ports at
3
+ * their edges; a pipe from 'T-101.right' to 'P-101.in' is routed with right
4
+ * angles from port to port, so it always meets the symbols exactly, in the
5
+ * browser and in the CODESYS visualization alike.
6
+ *
7
+ * Coordinates: x across the diagram in 0..100, y down in 0..100 of its height.
8
+ * Symbol sizes are in x units, so a round symbol's height in y units is
9
+ * size / aspect, where aspect = height / width of the diagram on screen.
10
+ */
11
+ import type { ProcessItem } from "./spec.js";
12
+ type Pt = [number, number];
13
+ type Dir = "l" | "r" | "u" | "d";
14
+ export interface Port {
15
+ at: Pt;
16
+ dir: Dir;
17
+ }
18
+ /** The ports of a symbol (keyed by name), for a diagram of the given aspect. */
19
+ export declare function portsOf(p: ProcessItem, aspect: number): Record<string, Port>;
20
+ /** Port names per symbol type, for messages and the tool description. */
21
+ export declare const PORT_NAMES: Record<string, string[]>;
22
+ /** Problems with pipe ends: unknown symbols or ports. */
23
+ export declare function routeProblems(items: ProcessItem[]): string[];
24
+ /** The points of a pipe: right angles from port to port (or along raw points). */
25
+ export declare function routePipe(p: Extract<ProcessItem, {
26
+ type: "pipe";
27
+ }>, items: ProcessItem[], aspect: number): Pt[];
28
+ /** The diagram with every pipe's points resolved. */
29
+ export declare function routed(items: ProcessItem[], aspect: number): ProcessItem[];
30
+ /** Symbols that overlap each other or leave the diagram, as warnings (the screen still saves). */
31
+ export declare function overlapWarnings(items: ProcessItem[], aspect: number): string[];
32
+ export {};
@@ -0,0 +1,184 @@
1
+ const keyOf = (p) => ("id" in p && p.id) || ("label" in p && p.label) || undefined;
2
+ /** The ports of a symbol (keyed by name), for a diagram of the given aspect. */
3
+ export function portsOf(p, aspect) {
4
+ switch (p.type) {
5
+ case "tank": {
6
+ const { x, y, w, h } = p;
7
+ const cx = x + w / 2;
8
+ return {
9
+ top: { at: [cx, y], dir: "u" },
10
+ bottom: { at: [cx, y + h], dir: "d" },
11
+ left: { at: [x, y + h * 0.85], dir: "l" },
12
+ right: { at: [x + w, y + h * 0.85], dir: "r" },
13
+ "left-high": { at: [x, y + h * 0.15], dir: "l" },
14
+ "right-high": { at: [x + w, y + h * 0.15], dir: "r" },
15
+ };
16
+ }
17
+ case "pump":
18
+ case "fan": {
19
+ const r = p.size / 2;
20
+ const ry = r / aspect;
21
+ return {
22
+ in: { at: [p.x - r, p.y], dir: "l" },
23
+ out: { at: [p.x + r, p.y], dir: "r" },
24
+ top: { at: [p.x, p.y - ry], dir: "u" },
25
+ bottom: { at: [p.x, p.y + ry], dir: "d" },
26
+ };
27
+ }
28
+ case "valve": {
29
+ const r = p.size / 2;
30
+ return p.vertical
31
+ ? { in: { at: [p.x, p.y + r / aspect], dir: "d" }, out: { at: [p.x, p.y - r / aspect], dir: "u" } }
32
+ : { in: { at: [p.x - r, p.y], dir: "l" }, out: { at: [p.x + r, p.y], dir: "r" } };
33
+ }
34
+ case "junction":
35
+ return { c: { at: [p.x, p.y], dir: "r" } };
36
+ default:
37
+ return {};
38
+ }
39
+ }
40
+ /** Port names per symbol type, for messages and the tool description. */
41
+ export const PORT_NAMES = {
42
+ tank: ["top", "bottom", "left", "right", "left-high", "right-high"],
43
+ pump: ["in", "out", "top", "bottom"],
44
+ fan: ["in", "out", "top", "bottom"],
45
+ valve: ["in", "out"],
46
+ junction: ["c"],
47
+ };
48
+ /** Problems with pipe ends: unknown symbols or ports. */
49
+ export function routeProblems(items) {
50
+ const syms = new Map(items.flatMap((p) => (keyOf(p) && p.type in PORT_NAMES ? [[keyOf(p).toLowerCase(), p]] : [])));
51
+ const out = [];
52
+ items.forEach((p, i) => {
53
+ if (p.type !== "pipe")
54
+ return;
55
+ for (const e of [p.from, p.to]) {
56
+ if (typeof e !== "string")
57
+ continue;
58
+ const [name, port] = e.split(".");
59
+ const s = syms.get(name.toLowerCase());
60
+ if (!s)
61
+ out.push(`pipe ${i + 1}: no symbol named '${name}' (symbols: ${[...syms.keys()].join(", ") || "none"}).`);
62
+ else if (!PORT_NAMES[s.type].includes(port) || (s.type === "valve" && !["in", "out"].includes(port)))
63
+ out.push(`pipe ${i + 1}: ${s.type} '${name}' has no port '${port}' (ports: ${PORT_NAMES[s.type].join(", ")}).`);
64
+ }
65
+ });
66
+ return out;
67
+ }
68
+ const STEP = { l: [-1, 0], r: [1, 0], u: [0, -1], d: [0, 1] };
69
+ const horiz = (d) => d === "l" || d === "r";
70
+ /** The points of a pipe: right angles from port to port (or along raw points). */
71
+ export function routePipe(p, items, aspect) {
72
+ if (!p.from || !p.to)
73
+ return p.points ?? [];
74
+ const syms = new Map(items.flatMap((s) => (keyOf(s) && s.type in PORT_NAMES ? [[keyOf(s).toLowerCase(), s]] : [])));
75
+ const resolve = (e, other) => {
76
+ if (typeof e !== "string") {
77
+ // A free end at the diagram's edge leaves through that edge.
78
+ if (e[0] <= 5)
79
+ return { at: e, dir: "l" };
80
+ if (e[0] >= 95)
81
+ return { at: e, dir: "r" };
82
+ if (e[1] <= 5)
83
+ return { at: e, dir: "u" };
84
+ if (e[1] >= 95)
85
+ return { at: e, dir: "d" };
86
+ // Otherwise it leaves towards the other end along the longer axis.
87
+ const o = other ?? [50, 50];
88
+ const dx = o[0] - e[0], dy = (o[1] - e[1]) / aspect;
89
+ return { at: e, dir: Math.abs(dx) >= Math.abs(dy) ? (dx >= 0 ? "r" : "l") : dy >= 0 ? "d" : "u" };
90
+ }
91
+ const [name, port] = e.split(".");
92
+ const s = syms.get(name.toLowerCase());
93
+ const ports = s ? portsOf(s, aspect) : {};
94
+ return ports[port] ?? { at: [50, 50], dir: "r" };
95
+ };
96
+ const a0 = typeof p.from === "string" ? resolve(p.from) : undefined;
97
+ const b0 = typeof p.to === "string" ? resolve(p.to) : undefined;
98
+ const a = a0 ?? resolve(p.from, b0?.at ?? (Array.isArray(p.to) ? p.to : undefined));
99
+ const b = b0 ?? resolve(p.to, a.at);
100
+ // A junction takes the side facing the other end.
101
+ const face = (port, toward) => {
102
+ if (!(typeof p.from === "string" && port === a && p.from.endsWith(".c")) && !(typeof p.to === "string" && port === b && p.to.endsWith(".c")))
103
+ return port;
104
+ const dx = toward[0] - port.at[0], dy = (toward[1] - port.at[1]) / aspect;
105
+ return { at: port.at, dir: Math.abs(dx) >= Math.abs(dy) ? (dx >= 0 ? "r" : "l") : dy >= 0 ? "d" : "u" };
106
+ };
107
+ const A = face(a, b.at);
108
+ const B = face(b, a.at);
109
+ const pts = [A.at];
110
+ const targets = [...(p.via ?? []), B.at];
111
+ let cur = A.at;
112
+ let dir = A.dir;
113
+ targets.forEach((t, k) => {
114
+ const last = k === targets.length - 1;
115
+ const endDir = last ? B.dir : undefined;
116
+ for (const q of orthogonal(cur, dir, t, endDir))
117
+ pts.push(q);
118
+ const prev = pts[pts.length - 2] ?? cur;
119
+ dir = prev[0] === t[0] ? (t[1] >= prev[1] ? "d" : "u") : t[0] >= prev[0] ? "r" : "l";
120
+ cur = t;
121
+ });
122
+ return dedupe(pts);
123
+ }
124
+ /** Right-angle path from `a` (leaving in `dir`) to `b` (entered against `endDir`), without `a` itself. */
125
+ function orthogonal(a, dir, b, endDir) {
126
+ const eq = (x, y) => Math.abs(x - y) < 1e-6;
127
+ if (eq(a[0], b[0]) || eq(a[1], b[1]))
128
+ return [b];
129
+ const inH = endDir ? horiz(endDir) : !horiz(dir);
130
+ if (horiz(dir) && inH) {
131
+ const mx = (a[0] + b[0]) / 2;
132
+ return [[mx, a[1]], [mx, b[1]], b];
133
+ }
134
+ if (!horiz(dir) && !inH) {
135
+ const my = (a[1] + b[1]) / 2;
136
+ return [[a[0], my], [b[0], my], b];
137
+ }
138
+ return horiz(dir) ? [[b[0], a[1]], b] : [[a[0], b[1]], b];
139
+ }
140
+ function dedupe(pts) {
141
+ const out = [];
142
+ for (const p of pts) {
143
+ const q = out[out.length - 1];
144
+ if (q && Math.abs(q[0] - p[0]) < 1e-6 && Math.abs(q[1] - p[1]) < 1e-6)
145
+ continue;
146
+ // drop a middle point on a straight line
147
+ const r = out[out.length - 2];
148
+ if (q && r && ((Math.abs(r[0] - q[0]) < 1e-6 && Math.abs(q[0] - p[0]) < 1e-6) || (Math.abs(r[1] - q[1]) < 1e-6 && Math.abs(q[1] - p[1]) < 1e-6)))
149
+ out.pop();
150
+ out.push(p);
151
+ }
152
+ return out;
153
+ }
154
+ /** The diagram with every pipe's points resolved. */
155
+ export function routed(items, aspect) {
156
+ return items.map((p) => (p.type === "pipe" ? { ...p, points: routePipe(p, items, aspect), from: undefined, to: undefined, via: undefined } : p));
157
+ }
158
+ /** Symbols that overlap each other or leave the diagram, as warnings (the screen still saves). */
159
+ export function overlapWarnings(items, aspect) {
160
+ const boxes = [];
161
+ items.forEach((p, i) => {
162
+ const name = `${p.type} ${keyOf(p) ?? i + 1}`;
163
+ if (p.type === "tank")
164
+ boxes.push({ name, x0: p.x, y0: p.y, x1: p.x + p.w, y1: p.y + p.h });
165
+ else if (p.type === "pump" || p.type === "fan" || p.type === "valve") {
166
+ const r = p.size / 2;
167
+ boxes.push({ name, x0: p.x - r, y0: p.y - r / aspect, x1: p.x + r, y1: p.y + r / aspect });
168
+ }
169
+ else if (p.type === "sensor")
170
+ boxes.push({ name, x0: p.x - 7, y0: p.y - 2.2 / aspect, x1: p.x + 7, y1: p.y + 2.2 / aspect });
171
+ });
172
+ const out = [];
173
+ for (const b of boxes)
174
+ if (b.x0 < 0 || b.y0 < 0 || b.x1 > 100 || b.y1 > 100)
175
+ out.push(`${b.name} reaches outside the diagram (0..100).`);
176
+ for (let i = 0; i < boxes.length; i++)
177
+ for (let j = i + 1; j < boxes.length; j++) {
178
+ const a = boxes[i], b = boxes[j];
179
+ if (a.x0 < b.x1 && b.x0 < a.x1 && a.y0 < b.y1 && b.y0 < a.y1)
180
+ out.push(`${a.name} overlaps ${b.name}.`);
181
+ }
182
+ return out;
183
+ }
184
+ //# sourceMappingURL=route.js.map