Files
pumpingStation/pumpingStation.html

354 lines
17 KiB
HTML
Raw Normal View History

2025-10-14 13:51:32 +02:00
<!--
| S88-niveau | Primair (blokkleur) | Tekstkleur |
| ---------------------- | ------------------- | ---------- |
| **Area** | `#0f52a5` | wit |
| **Process Cell** | `#0c99d9` | wit |
| **Unit** | `#50a8d9` | zwart |
| **Equipment (Module)** | `#86bbdd` | zwart |
| **Control Module** | `#a9daee` | zwart |
-->
<script src="/pumpingStation/menu.js"></script> <!-- Load the menu script for dynamic dropdowns -->
<script src="/pumpingStation/configData.js"></script> <!-- Load the config script for node information -->
<script src="/pumpingStation/editor.js"></script> <!-- Load the basin-diagram editor logic -->
2025-10-07 18:05:54 +02:00
2025-10-13 11:50:54 +02:00
<script>//test
2025-10-14 08:36:45 +02:00
RED.nodes.registerType("pumpingStation", {
2025-10-07 18:05:54 +02:00
category: "EVOLV",
2025-10-14 13:51:32 +02:00
color: "#0c99d9", // color for the node based on the S88 schema
2025-10-07 18:05:54 +02:00
defaults: {
name: { value: "" },
2025-10-07 18:05:54 +02:00
2025-10-14 16:32:44 +02:00
// Define station-specific properties
simulator: { value: false },
basinVolume: { value: 1 }, // m³, total empty basin
basinHeight: { value: 1 }, // m, floor to top
inflowLevel: { value: 0.8 }, // m, centre of inlet pipe above floor
outflowLevel: { value: 0.2 }, // m, centre of outlet pipe above floor
overflowLevel: { value: 0.9 }, // m, overflow elevation
defaultFluid: { value: "wastewater" },
inletPipeDiameter: { value: 0.3 }, // m
outletPipeDiameter: { value: 0.3 }, // m
pipelineLength: { value: 80 }, // m
maxDischargeHead: { value: 24 }, // m
staticHead: { value: 12 }, // m
maxInflowRate: { value: 200 }, // m³/h
temperatureReferenceDegC: { value: 15 },
2025-11-25 14:57:39 +01:00
timeleftToFullOrEmptyThresholdSeconds:{value:0}, // time threshold to safeguard starting or stopping pumps in seconds
enableDryRunProtection: { value: true },
enableOverfillProtection: { value: true },
dryRunThresholdPercent: { value: 2 },
overfillThresholdPercent: { value: 98 },
2025-11-20 12:15:46 +01:00
minHeightBasedOn: { value: "outlet" }, // basis for minimum height check: inlet or outlet
processOutputFormat: { value: "process" },
dbaseOutputFormat: { value: "influxdb" },
2025-10-14 16:32:44 +02:00
// Advanced reference information
refHeight: { value: "NAP" }, // reference height
basinBottomRef: { value: 1 }, // absolute elevation of basin floor
2025-10-07 18:05:54 +02:00
//define asset properties
uuid: { value: "" },
supplier: { value: "" },
category: { value: "" },
assetType: { value: "" },
model: { value: "" },
unit: { value: "" },
//logger properties
enableLog: { value: false },
logLevel: { value: "error" },
//physicalAspect
positionVsParent: { value: "" },
positionIcon: { value: "" },
hasDistance: { value: false },
distance: { value: 0 },
distanceUnit: { value: "m" },
2025-11-27 17:46:24 +01:00
distanceDescription: { value: "" },
// control strategy
controlMode: { value: "none" },
startLevel: { value: null },
minLevel: { value: null },
maxLevel: { value: null },
2025-11-27 17:46:24 +01:00
flowSetpoint: { value: null },
flowDeadband: { value: null }
2025-10-07 18:05:54 +02:00
},
inputs: 1,
outputs: 3,
inputLabels: ["Input"],
outputLabels: ["process", "dbase", "parent"],
2025-10-14 13:51:32 +02:00
icon: "font-awesome/fa-tint",
2025-10-07 18:05:54 +02:00
label: function () {
2025-10-21 12:45:19 +02:00
return this.positionIcon + " PumpingStation";
2025-10-07 18:05:54 +02:00
},
oneditprepare: function () {
window.EVOLV?.nodes?.pumpingStation?.editor?.init(this);
2025-10-07 18:05:54 +02:00
},
oneditsave: function () {
const node = this;
2025-10-14 16:32:44 +02:00
window.EVOLV?.nodes?.pumpingStation?.loggerMenu?.saveEditor?.(node);
window.EVOLV?.nodes?.pumpingStation?.positionMenu?.saveEditor?.(node);
window.EVOLV?.nodes?.pumpingStation?.editor?.save(node);
2025-10-07 18:05:54 +02:00
},
2025-10-14 16:32:44 +02:00
2025-10-07 18:05:54 +02:00
});
</script>
<!-- Main UI -->
2025-10-14 13:51:32 +02:00
<script type="text/html" data-template-name="pumpingStation">
2025-10-07 18:05:54 +02:00
2025-11-27 17:46:24 +01:00
<h4>Simulation</h4>
2025-10-07 18:05:54 +02:00
<div class="form-row">
2025-10-14 16:32:44 +02:00
<label for="node-input-simulator"><i class="fa fa-play-circle"></i> Simulator</label>
<input type="checkbox" id="node-input-simulator" style="width:20px;vertical-align:baseline;" />
<span>Run station in simulated mode</span>
2025-10-07 18:05:54 +02:00
</div>
2025-10-14 16:32:44 +02:00
<hr>
2025-11-27 17:46:24 +01:00
Editor: interactive basin diagram — inputs placed at each threshold line Replaces the static parameters-diagram-above-form-rows layout with a single interactive SVG where every threshold input sits directly on the tank at its proportional y-position. Typing a value repositions the corresponding line + input + label live. What moved into the diagram (via <foreignObject> holding real <input> elements with their existing node-input-* IDs so Node-RED save/restore is untouched): basinHeight — top of tank (fixed at rim by definition) overflowLevel — weir crest (red, dashed) maxLevel — 100 % demand line (orange, dashed) startLevel — ramp-start line (green, dashed) minLevel — MGC-shutdown line (purple, dashed) inflowLevel — Inlet arrow + input on left outflowLevel — Outlet arrow + input on right dryRunLevel — read-only, computed from outflow × (1+dryRunPct/100) Also in the diagram: - Dead-volume band fills the area below outflowLevel dynamically - Warning ribbon appears below the tank if ordering invariants break (mirrors specificClass._validateThresholdOrdering) - All positions scale against the user's basinHeight; if empty, a default 5 m scale is used just to keep the diagram readable What stayed as regular form rows: - Basin Volume (m³) — not a height, can't be placed on a y-axis - minLevel / startLevel / maxLevel were in the Control Strategy > Level-based section; removed from there and moved into the diagram (the level-based subsection now contains a one-line pointer) - Safety % inputs (dryRun, overfill) stay in the Safety section with their derived-level readouts, now synced with the diagram No schema changes, no field additions, no behaviour changes in the runtime. Pure editor-UX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:28:18 +02:00
<h4>Basin parameters</h4>
<p style="font-size:12px;color:#777;margin:0 0 8px 0;">Heights are measured from the basin floor (0 m). Enter values next to each line — the diagram scales to whatever you enter.</p>
<style>
#ps-basin-diagram input[type=number] {
width: 100%; height: 20px; box-sizing: border-box;
font-size: 11px; padding: 1px 4px; margin: 0;
border: 1px solid #ccc; border-radius: 3px; background: #fff;
}
#ps-basin-diagram input[type=number]:focus { outline: 1px solid #0c99d9; border-color: #0c99d9; }
</style>
<svg id="ps-basin-diagram" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 430"
Editor: interactive basin diagram — inputs placed at each threshold line Replaces the static parameters-diagram-above-form-rows layout with a single interactive SVG where every threshold input sits directly on the tank at its proportional y-position. Typing a value repositions the corresponding line + input + label live. What moved into the diagram (via <foreignObject> holding real <input> elements with their existing node-input-* IDs so Node-RED save/restore is untouched): basinHeight — top of tank (fixed at rim by definition) overflowLevel — weir crest (red, dashed) maxLevel — 100 % demand line (orange, dashed) startLevel — ramp-start line (green, dashed) minLevel — MGC-shutdown line (purple, dashed) inflowLevel — Inlet arrow + input on left outflowLevel — Outlet arrow + input on right dryRunLevel — read-only, computed from outflow × (1+dryRunPct/100) Also in the diagram: - Dead-volume band fills the area below outflowLevel dynamically - Warning ribbon appears below the tank if ordering invariants break (mirrors specificClass._validateThresholdOrdering) - All positions scale against the user's basinHeight; if empty, a default 5 m scale is used just to keep the diagram readable What stayed as regular form rows: - Basin Volume (m³) — not a height, can't be placed on a y-axis - minLevel / startLevel / maxLevel were in the Control Strategy > Level-based section; removed from there and moved into the diagram (the level-based subsection now contains a one-line pointer) - Safety % inputs (dryRun, overfill) stay in the Safety section with their derived-level readouts, now synced with the diagram No schema changes, no field additions, no behaviour changes in the runtime. Pure editor-UX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:28:18 +02:00
style="display:block;width:100%;max-width:540px;margin:0 0 12px 0;background:#fff;border:1px solid #e5e5e5;border-radius:4px;"
font-family="Arial,sans-serif" font-size="11">
<defs>
<marker id="ps-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#1F4E79" />
</marker>
</defs>
<!-- Tank body -->
<rect x="200" y="40" width="120" height="340" fill="#F0F8FF" stroke="#333" stroke-width="1.5" />
Editor: interactive basin diagram — inputs placed at each threshold line Replaces the static parameters-diagram-above-form-rows layout with a single interactive SVG where every threshold input sits directly on the tank at its proportional y-position. Typing a value repositions the corresponding line + input + label live. What moved into the diagram (via <foreignObject> holding real <input> elements with their existing node-input-* IDs so Node-RED save/restore is untouched): basinHeight — top of tank (fixed at rim by definition) overflowLevel — weir crest (red, dashed) maxLevel — 100 % demand line (orange, dashed) startLevel — ramp-start line (green, dashed) minLevel — MGC-shutdown line (purple, dashed) inflowLevel — Inlet arrow + input on left outflowLevel — Outlet arrow + input on right dryRunLevel — read-only, computed from outflow × (1+dryRunPct/100) Also in the diagram: - Dead-volume band fills the area below outflowLevel dynamically - Warning ribbon appears below the tank if ordering invariants break (mirrors specificClass._validateThresholdOrdering) - All positions scale against the user's basinHeight; if empty, a default 5 m scale is used just to keep the diagram readable What stayed as regular form rows: - Basin Volume (m³) — not a height, can't be placed on a y-axis - minLevel / startLevel / maxLevel were in the Control Strategy > Level-based section; removed from there and moved into the diagram (the level-based subsection now contains a one-line pointer) - Safety % inputs (dryRun, overfill) stay in the Safety section with their derived-level readouts, now synced with the diagram No schema changes, no field additions, no behaviour changes in the runtime. Pure editor-UX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:28:18 +02:00
<!-- Dead-volume band (y + height updated dynamically below outflowLevel) -->
<rect id="ps-deadvol" x="201" width="118" fill="#AACCE0" />
<!-- basinVolume — pinned above the rim -->
<text id="ps-label-basinVolume" x="330" y="19" fill="#333" font-weight="600">basin volume</text>
<foreignObject id="ps-fo-basinVolume" x="425" y="4" width="70" height="22">
<input xmlns="http://www.w3.org/1999/xhtml" type="number" id="node-input-basinVolume" min="0" step="0.1" />
</foreignObject>
<text id="ps-unit-basinVolume" x="500" y="19" fill="#555"></text>
<!-- Zone labels (mid-tank italic, positioned dynamically at midpoint between adjacent thresholds) -->
<text id="ps-zone-spare" x="260" text-anchor="middle" fill="#B78200" font-size="10" font-style="italic" visibility="hidden">Spare volume before spilling</text>
<text id="ps-zone-sewage" x="260" text-anchor="middle" fill="#1F4E79" font-size="10" font-style="italic" visibility="hidden">Sewage + tank buffer</text>
<text id="ps-zone-buffer1" x="260" text-anchor="middle" fill="#1F4E79" font-size="10" font-style="italic" visibility="hidden">Tank buffer</text>
<text id="ps-zone-buffer2" x="260" text-anchor="middle" fill="#1F4E79" font-size="10" font-style="italic" visibility="hidden">Tank buffer</text>
<text id="ps-zone-dead" x="260" text-anchor="middle" fill="#444" font-size="10" font-style="italic" visibility="hidden">Dead volume</text>
Editor: interactive basin diagram — inputs placed at each threshold line Replaces the static parameters-diagram-above-form-rows layout with a single interactive SVG where every threshold input sits directly on the tank at its proportional y-position. Typing a value repositions the corresponding line + input + label live. What moved into the diagram (via <foreignObject> holding real <input> elements with their existing node-input-* IDs so Node-RED save/restore is untouched): basinHeight — top of tank (fixed at rim by definition) overflowLevel — weir crest (red, dashed) maxLevel — 100 % demand line (orange, dashed) startLevel — ramp-start line (green, dashed) minLevel — MGC-shutdown line (purple, dashed) inflowLevel — Inlet arrow + input on left outflowLevel — Outlet arrow + input on right dryRunLevel — read-only, computed from outflow × (1+dryRunPct/100) Also in the diagram: - Dead-volume band fills the area below outflowLevel dynamically - Warning ribbon appears below the tank if ordering invariants break (mirrors specificClass._validateThresholdOrdering) - All positions scale against the user's basinHeight; if empty, a default 5 m scale is used just to keep the diagram readable What stayed as regular form rows: - Basin Volume (m³) — not a height, can't be placed on a y-axis - minLevel / startLevel / maxLevel were in the Control Strategy > Level-based section; removed from there and moved into the diagram (the level-based subsection now contains a one-line pointer) - Safety % inputs (dryRun, overfill) stay in the Safety section with their derived-level readouts, now synced with the diagram No schema changes, no field additions, no behaviour changes in the runtime. Pure editor-UX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:28:18 +02:00
<!-- basinHeight — always at tank rim (y=40 in viewBox coords) -->
<line id="ps-line-basinHeight" x1="195" y1="40" x2="325" y2="40" stroke="#333" stroke-width="1.5" />
<text id="ps-label-basinHeight" x="330" y="44" fill="#333">basinHeight</text>
<foreignObject id="ps-fo-basinHeight" x="425" y="29" width="70" height="22">
<input xmlns="http://www.w3.org/1999/xhtml" type="number" id="node-input-basinHeight" min="0" step="0.1" />
</foreignObject>
<text id="ps-unit-basinHeight" x="500" y="44" fill="#555">m</text>
<!-- overflowLevel -->
<line id="ps-line-overflowLevel" x1="195" x2="325" stroke="#C0392B" stroke-dasharray="4 2" stroke-width="1.5" />
<text id="ps-label-overflowLevel" x="330" fill="#C0392B">overflowLevel</text>
<foreignObject id="ps-fo-overflowLevel" x="425" width="70" height="22">
<input xmlns="http://www.w3.org/1999/xhtml" type="number" id="node-input-overflowLevel" min="0" step="0.01" />
</foreignObject>
<text id="ps-unit-overflowLevel" x="500" fill="#555">m</text>
<!-- maxLevel -->
<line id="ps-line-maxLevel" x1="195" x2="325" stroke="#D68910" stroke-dasharray="4 2" stroke-width="1.5" />
<text id="ps-label-maxLevel" x="330" fill="#D68910">maxLevel</text>
<foreignObject id="ps-fo-maxLevel" x="425" width="70" height="22">
<input xmlns="http://www.w3.org/1999/xhtml" type="number" id="node-input-maxLevel" min="0" step="0.01" />
</foreignObject>
<text id="ps-unit-maxLevel" x="500" fill="#555">m</text>
<!-- startLevel -->
<line id="ps-line-startLevel" x1="195" x2="325" stroke="#1E8449" stroke-dasharray="4 2" stroke-width="1.5" />
<text id="ps-label-startLevel" x="330" fill="#1E8449">startLevel</text>
<foreignObject id="ps-fo-startLevel" x="425" width="70" height="22">
<input xmlns="http://www.w3.org/1999/xhtml" type="number" id="node-input-startLevel" min="0" step="0.01" />
</foreignObject>
<text id="ps-unit-startLevel" x="500" fill="#555">m</text>
<!-- Inlet — arrow + input on the left -->
<line id="ps-line-inflowLevel" x1="140" x2="200" stroke="#1F4E79" stroke-width="2" marker-end="url(#ps-arrow)" />
<text id="ps-label-inflowLevel" x="135" text-anchor="end" fill="#1F4E79" font-weight="bold">Inlet</text>
<text id="ps-sub-inflowLevel" x="135" text-anchor="end" fill="#777" font-size="9">bottom of pipe</text>
<foreignObject id="ps-fo-inflowLevel" x="5" width="70" height="22">
<input xmlns="http://www.w3.org/1999/xhtml" type="number" id="node-input-inflowLevel" min="0" step="0.01" />
</foreignObject>
<text id="ps-unit-inflowLevel" x="80" fill="#555">m</text>
<!-- minLevel -->
<line id="ps-line-minLevel" x1="195" x2="325" stroke="#6C3483" stroke-dasharray="4 2" stroke-width="1.5" />
<text id="ps-label-minLevel" x="330" fill="#6C3483">minLevel</text>
<foreignObject id="ps-fo-minLevel" x="425" width="70" height="22">
<input xmlns="http://www.w3.org/1999/xhtml" type="number" id="node-input-minLevel" min="0" step="0.01" />
</foreignObject>
<text id="ps-unit-minLevel" x="500" fill="#555">m</text>
<!-- dryRunLevel (derived, read-only) -->
<line id="ps-line-dryRunLevel" x1="195" x2="325" stroke="#C0392B" stroke-dasharray="1 2" stroke-width="1" opacity="0.6" />
<text id="ps-label-dryRunLevel" x="330" fill="#C0392B" font-size="10" font-style="italic">dryRunLevel ≈ — m (safety — from %)</text>
<!-- Outlet — arrow on right, input below the threshold column -->
<line id="ps-line-outflowLevel" x1="320" x2="360" stroke="#1F4E79" stroke-width="2" marker-end="url(#ps-arrow)" />
<text id="ps-label-outflowLevel" x="365" fill="#1F4E79" font-weight="bold">Outlet</text>
<text id="ps-sub-outflowLevel" x="365" fill="#777" font-size="9">top of pipe</text>
<foreignObject id="ps-fo-outflowLevel" x="425" width="70" height="22">
<input xmlns="http://www.w3.org/1999/xhtml" type="number" id="node-input-outflowLevel" min="0" step="0.01" />
</foreignObject>
<text id="ps-unit-outflowLevel" x="500" fill="#555">m</text>
<!-- Floor / datum -->
<line x1="195" y1="380" x2="325" y2="380" stroke="#000" stroke-width="2" />
<text x="330" y="384" fill="#000">0 m (datum)</text>
Editor: interactive basin diagram — inputs placed at each threshold line Replaces the static parameters-diagram-above-form-rows layout with a single interactive SVG where every threshold input sits directly on the tank at its proportional y-position. Typing a value repositions the corresponding line + input + label live. What moved into the diagram (via <foreignObject> holding real <input> elements with their existing node-input-* IDs so Node-RED save/restore is untouched): basinHeight — top of tank (fixed at rim by definition) overflowLevel — weir crest (red, dashed) maxLevel — 100 % demand line (orange, dashed) startLevel — ramp-start line (green, dashed) minLevel — MGC-shutdown line (purple, dashed) inflowLevel — Inlet arrow + input on left outflowLevel — Outlet arrow + input on right dryRunLevel — read-only, computed from outflow × (1+dryRunPct/100) Also in the diagram: - Dead-volume band fills the area below outflowLevel dynamically - Warning ribbon appears below the tank if ordering invariants break (mirrors specificClass._validateThresholdOrdering) - All positions scale against the user's basinHeight; if empty, a default 5 m scale is used just to keep the diagram readable What stayed as regular form rows: - Basin Volume (m³) — not a height, can't be placed on a y-axis - minLevel / startLevel / maxLevel were in the Control Strategy > Level-based section; removed from there and moved into the diagram (the level-based subsection now contains a one-line pointer) - Safety % inputs (dryRun, overfill) stay in the Safety section with their derived-level readouts, now synced with the diagram No schema changes, no field additions, no behaviour changes in the runtime. Pure editor-UX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:28:18 +02:00
<!-- Leader lines: shown when the input row had to be nudged off its threshold's ideal y -->
<line id="ps-leader-basinHeight" x1="0" y1="0" x2="0" y2="0" stroke="#bbb" stroke-width="0.6" stroke-dasharray="2 2" visibility="hidden" />
<line id="ps-leader-overflowLevel" x1="0" y1="0" x2="0" y2="0" stroke="#bbb" stroke-width="0.6" stroke-dasharray="2 2" visibility="hidden" />
<line id="ps-leader-maxLevel" x1="0" y1="0" x2="0" y2="0" stroke="#bbb" stroke-width="0.6" stroke-dasharray="2 2" visibility="hidden" />
<line id="ps-leader-startLevel" x1="0" y1="0" x2="0" y2="0" stroke="#bbb" stroke-width="0.6" stroke-dasharray="2 2" visibility="hidden" />
<line id="ps-leader-minLevel" x1="0" y1="0" x2="0" y2="0" stroke="#bbb" stroke-width="0.6" stroke-dasharray="2 2" visibility="hidden" />
<line id="ps-leader-dryRunLevel" x1="0" y1="0" x2="0" y2="0" stroke="#bbb" stroke-width="0.6" stroke-dasharray="2 2" visibility="hidden" />
<line id="ps-leader-outflowLevel" x1="0" y1="0" x2="0" y2="0" stroke="#bbb" stroke-width="0.6" stroke-dasharray="2 2" visibility="hidden" />
Editor: interactive basin diagram — inputs placed at each threshold line Replaces the static parameters-diagram-above-form-rows layout with a single interactive SVG where every threshold input sits directly on the tank at its proportional y-position. Typing a value repositions the corresponding line + input + label live. What moved into the diagram (via <foreignObject> holding real <input> elements with their existing node-input-* IDs so Node-RED save/restore is untouched): basinHeight — top of tank (fixed at rim by definition) overflowLevel — weir crest (red, dashed) maxLevel — 100 % demand line (orange, dashed) startLevel — ramp-start line (green, dashed) minLevel — MGC-shutdown line (purple, dashed) inflowLevel — Inlet arrow + input on left outflowLevel — Outlet arrow + input on right dryRunLevel — read-only, computed from outflow × (1+dryRunPct/100) Also in the diagram: - Dead-volume band fills the area below outflowLevel dynamically - Warning ribbon appears below the tank if ordering invariants break (mirrors specificClass._validateThresholdOrdering) - All positions scale against the user's basinHeight; if empty, a default 5 m scale is used just to keep the diagram readable What stayed as regular form rows: - Basin Volume (m³) — not a height, can't be placed on a y-axis - minLevel / startLevel / maxLevel were in the Control Strategy > Level-based section; removed from there and moved into the diagram (the level-based subsection now contains a one-line pointer) - Safety % inputs (dryRun, overfill) stay in the Safety section with their derived-level readouts, now synced with the diagram No schema changes, no field additions, no behaviour changes in the runtime. Pure editor-UX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:28:18 +02:00
<!-- Ordering-warning ribbon -->
<text id="ps-warning" x="260" y="410" text-anchor="middle" fill="#C0392B" font-size="10" font-style="italic" visibility="hidden"></text>
Editor: interactive basin diagram — inputs placed at each threshold line Replaces the static parameters-diagram-above-form-rows layout with a single interactive SVG where every threshold input sits directly on the tank at its proportional y-position. Typing a value repositions the corresponding line + input + label live. What moved into the diagram (via <foreignObject> holding real <input> elements with their existing node-input-* IDs so Node-RED save/restore is untouched): basinHeight — top of tank (fixed at rim by definition) overflowLevel — weir crest (red, dashed) maxLevel — 100 % demand line (orange, dashed) startLevel — ramp-start line (green, dashed) minLevel — MGC-shutdown line (purple, dashed) inflowLevel — Inlet arrow + input on left outflowLevel — Outlet arrow + input on right dryRunLevel — read-only, computed from outflow × (1+dryRunPct/100) Also in the diagram: - Dead-volume band fills the area below outflowLevel dynamically - Warning ribbon appears below the tank if ordering invariants break (mirrors specificClass._validateThresholdOrdering) - All positions scale against the user's basinHeight; if empty, a default 5 m scale is used just to keep the diagram readable What stayed as regular form rows: - Basin Volume (m³) — not a height, can't be placed on a y-axis - minLevel / startLevel / maxLevel were in the Control Strategy > Level-based section; removed from there and moved into the diagram (the level-based subsection now contains a one-line pointer) - Safety % inputs (dryRun, overfill) stay in the Safety section with their derived-level readouts, now synced with the diagram No schema changes, no field additions, no behaviour changes in the runtime. Pure editor-UX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:28:18 +02:00
</svg>
2025-10-14 16:32:44 +02:00
<hr>
2025-11-27 17:46:24 +01:00
<h4>Control Strategy</h4>
<div class="form-row">
<label for="node-input-controlMode"><i class="fa fa-sliders"></i> Control mode</label>
<select id="node-input-controlMode">
<option value="none">None / Manual</option>
<option value="levelbased">Level-based</option>
<option value="flowbased">Flow-based</option>
</select>
</div>
<div id="ps-mode-levelbased" class="ps-mode-section">
Editor: interactive basin diagram — inputs placed at each threshold line Replaces the static parameters-diagram-above-form-rows layout with a single interactive SVG where every threshold input sits directly on the tank at its proportional y-position. Typing a value repositions the corresponding line + input + label live. What moved into the diagram (via <foreignObject> holding real <input> elements with their existing node-input-* IDs so Node-RED save/restore is untouched): basinHeight — top of tank (fixed at rim by definition) overflowLevel — weir crest (red, dashed) maxLevel — 100 % demand line (orange, dashed) startLevel — ramp-start line (green, dashed) minLevel — MGC-shutdown line (purple, dashed) inflowLevel — Inlet arrow + input on left outflowLevel — Outlet arrow + input on right dryRunLevel — read-only, computed from outflow × (1+dryRunPct/100) Also in the diagram: - Dead-volume band fills the area below outflowLevel dynamically - Warning ribbon appears below the tank if ordering invariants break (mirrors specificClass._validateThresholdOrdering) - All positions scale against the user's basinHeight; if empty, a default 5 m scale is used just to keep the diagram readable What stayed as regular form rows: - Basin Volume (m³) — not a height, can't be placed on a y-axis - minLevel / startLevel / maxLevel were in the Control Strategy > Level-based section; removed from there and moved into the diagram (the level-based subsection now contains a one-line pointer) - Safety % inputs (dryRun, overfill) stay in the Safety section with their derived-level readouts, now synced with the diagram No schema changes, no field additions, no behaviour changes in the runtime. Pure editor-UX. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:28:18 +02:00
<p style="font-size:12px;color:#777;margin:0;">Level-based uses <code>minLevel</code> / <code>startLevel</code> / <code>maxLevel</code> from the diagram above.</p>
2025-11-27 17:46:24 +01:00
</div>
<div id="ps-mode-flowbased" class="ps-mode-section" style="display:none">
<div class="form-row">
<label for="node-input-flowSetpoint">Flow setpoint</label>
<input type="number" id="node-input-flowSetpoint" placeholder="m3/h" />
</div>
<div class="form-row">
<label for="node-input-flowDeadband">Deadband</label>
<input type="number" id="node-input-flowDeadband" placeholder="m3/h" />
</div>
</div>
<hr>
<h4>Reference</h4>
2025-10-14 16:32:44 +02:00
<!-- Reference data -->
2025-11-20 12:15:46 +01:00
<div class="form-row">
<label for="node-input-minHeightBasedOn"><i class="fa fa-arrows-v"></i> Minimum Height Based On</label>
<select id="node-input-minHeightBasedOn" style="width:60%;">
<option value="inlet">Inlet Elevation</option>
<option value="outlet">Outlet Elevation</option>
</select>
</div>
2025-10-07 18:05:54 +02:00
<div class="form-row">
2025-10-14 16:32:44 +02:00
<label for="node-input-refHeight"><i class="fa fa-map-marker"></i> Reference height</label>
<select id="node-input-refHeight" style="width:60%;">
<option value="NAP">NAP</option>
2025-10-07 18:05:54 +02:00
</select>
</div>
<div class="form-row">
<label for="node-input-basinBottomRef"><i class="fa fa-level-down"></i> Basin floor above datum (m)</label>
2025-10-14 16:32:44 +02:00
<input type="number" id="node-input-basinBottomRef" step="0.01" />
2025-10-07 18:05:54 +02:00
</div>
2025-11-25 14:57:39 +01:00
<hr>
2025-11-27 17:46:24 +01:00
<h4>Safety</h4>
2025-11-25 14:57:39 +01:00
<!-- Safety settings -->
<div class="form-row">
<label for="node-input-timeleftToFullOrEmptyThresholdSeconds"><i class="fa fa-clock-o"></i> Time To Empty/Full (s)</label>
<input type="number" id="node-input-timeleftToFullOrEmptyThresholdSeconds" min="0" step="1" />
</div>
<div class="form-row">
<label for="node-input-enableDryRunProtection">
<i class="fa fa-shield"></i> Dry-run Protection
</label>
<input type="checkbox" id="node-input-enableDryRunProtection" style="width:20px;vertical-align:baseline;" />
<span>Prevent pumps from running on low volume</span>
</div>
<div class="form-row">
<label for="node-input-dryRunThresholdPercent" style="padding-left:20px;">Low Volume Threshold (%)</label>
<input type="number" id="node-input-dryRunThresholdPercent" min="0" max="100" step="0.1" style="width:80px;" />
<span id="derived-dryRunLevel" style="margin-left:8px;color:#777;font-size:12px;">→ dryRunLevel ≈ — m</span>
2025-11-25 14:57:39 +01:00
</div>
<div class="form-row">
<label for="node-input-enableOverfillProtection">
<i class="fa fa-exclamation-triangle"></i> Overfill Protection
</label>
<input type="checkbox" id="node-input-enableOverfillProtection" style="width:20px;vertical-align:baseline;" />
<span>Stop filling when approaching overflow</span>
</div>
<div class="form-row">
<label for="node-input-overfillThresholdPercent" style="padding-left:20px;">High Volume Threshold (%)</label>
<input type="number" id="node-input-overfillThresholdPercent" min="0" max="100" step="0.1" style="width:80px;" />
<span id="derived-overfillLevel" style="margin-left:8px;color:#777;font-size:12px;">→ overfillLevel ≈ — m</span>
2025-11-25 14:57:39 +01:00
</div>
<hr>
<h3>Output Formats</h3>
<div class="form-row">
<label for="node-input-processOutputFormat"><i class="fa fa-random"></i> Process Output</label>
<select id="node-input-processOutputFormat" style="width:60%;">
<option value="process">process</option>
<option value="json">json</option>
<option value="csv">csv</option>
</select>
</div>
<div class="form-row">
<label for="node-input-dbaseOutputFormat"><i class="fa fa-database"></i> Database Output</label>
<select id="node-input-dbaseOutputFormat" style="width:60%;">
<option value="influxdb">influxdb</option>
<option value="json">json</option>
<option value="csv">csv</option>
</select>
</div>
2025-10-14 16:32:44 +02:00
<!-- Shared asset/logger/position menus -->
2025-10-07 18:05:54 +02:00
<div id="asset-fields-placeholder"></div>
<div id="logger-fields-placeholder"></div>
<div id="position-fields-placeholder"></div>
2025-10-14 16:32:44 +02:00
2025-10-07 18:05:54 +02:00
</script>
2025-10-14 13:51:32 +02:00
<script type="text/html" data-help-name="pumpingStation">
2025-10-07 18:05:54 +02:00
</script>