feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
[
{
"id" : "77f00aef1c966167" ,
"type" : "tab" ,
"label" : "PumpingStation - Dashboard" ,
"disabled" : false ,
"info" : "Tier 2: single pumpingStation node driven by a FlowFuse dashboard. Same command surface as the Basic flow, plus live status rows, four trend charts, and a raw-output table."
} ,
{
"id" : "aa3381b896eb2cfb" ,
"type" : "group" ,
"z" : "77f00aef1c966167" ,
"name" : "Pumping Station (Process Cell)" ,
"style" : {
"label" : true ,
"stroke" : "#000000" ,
"fill" : "#0c99d9" ,
"fill-opacity" : "0.10"
} ,
"nodes" : [
"8e78b6607deb33a7"
] ,
"x" : 534 ,
"y" : 371.5 ,
"w" : 232 ,
"h" : 97
} ,
{
"id" : "4996420d47442fad" ,
"type" : "group" ,
"z" : "77f00aef1c966167" ,
"name" : "1. Control mode" ,
"style" : {
"stroke" : "#666666" ,
"fill" : "#ffdf7f" ,
"fill-opacity" : "0.15" ,
"label" : true ,
"color" : "#333333"
} ,
"nodes" : [
"ui_btn_mode_manual" ,
"ui_btn_mode_lvl"
] ,
"x" : 94 ,
"y" : 119 ,
"w" : 272 ,
"h" : 122
} ,
{
"id" : "a9f9b38b0e00c1d7" ,
"type" : "group" ,
"z" : "77f00aef1c966167" ,
"name" : "2. Flow signals (inflow / outflow)" ,
"style" : {
"stroke" : "#666666" ,
"fill" : "#ffdf7f" ,
"fill-opacity" : "0.15" ,
"label" : true ,
"color" : "#333333"
} ,
"nodes" : [
"ui_btn_inflow" ,
"ui_btn_outflow"
] ,
"x" : 94 ,
"y" : 279 ,
"w" : 272 ,
"h" : 122
} ,
{
"id" : "42bf82c87d05f498" ,
"type" : "group" ,
"z" : "77f00aef1c966167" ,
"name" : "3. Operator demand (manual mode only)" ,
"style" : {
"stroke" : "#666666" ,
"fill" : "#ffdf7f" ,
"fill-opacity" : "0.15" ,
"label" : true ,
"color" : "#333333"
} ,
"nodes" : [
"ui_btn_demand"
] ,
"x" : 94 ,
"y" : 459 ,
"w" : 261 ,
"h" : 82
} ,
{
"id" : "234bdce20170061a" ,
"type" : "group" ,
"z" : "77f00aef1c966167" ,
"name" : "4. Calibration" ,
"style" : {
"stroke" : "#666666" ,
"fill" : "#ffdf7f" ,
"fill-opacity" : "0.15" ,
"label" : true ,
"color" : "#333333"
} ,
"nodes" : [
"ui_btn_cal_vol" ,
"ui_btn_cal_lvl"
] ,
"x" : 94 ,
"y" : 579 ,
"w" : 272 ,
"h" : 122
} ,
{
"id" : "grp_status_panel" ,
"type" : "group" ,
"z" : "77f00aef1c966167" ,
"name" : "Live status, trends, raw output" ,
"style" : {
"stroke" : "#666666" ,
"fill" : "#bde0fe" ,
"fill-opacity" : "0.20" ,
"label" : true ,
"color" : "#333333"
} ,
"nodes" : [
"fn_status_split" ,
"ui_txt_mode" ,
"ui_txt_direction" ,
"ui_txt_level" ,
"ui_txt_volume" ,
"ui_txt_volpct" ,
"ui_txt_pct" ,
"ui_txt_demand" ,
"ui_chart_level" ,
"ui_chart_volume" ,
"ui_chart_volpct" ,
"ui_chart_flow" ,
"ui_tpl_raw"
] ,
"x" : 854 ,
"y" : 99 ,
"w" : 712 ,
"h" : 642
} ,
{
"id" : "f4ba4542514ed853" ,
"type" : "group" ,
"z" : "77f00aef1c966167" ,
"name" : "Debug outputs (sidebar)" ,
"style" : {
"stroke" : "#666666" ,
"fill" : "#d1d1d1" ,
"fill-opacity" : "0.2" ,
"label" : true ,
"color" : "#333333"
} ,
"nodes" : [
"b2450e5ee2eebfaa" ,
"386af1ad8aa8ed12" ,
"c27c2655f199b530"
] ,
"x" : 854 ,
"y" : 779 ,
"w" : 252 ,
"h" : 202
} ,
{
"id" : "b30af582f935bcb7" ,
"type" : "comment" ,
"z" : "77f00aef1c966167" ,
2026-05-26 17:31:44 +02:00
"name" : "PumpingStation \u2014 Dashboard (Tier 2)" ,
"info" : "Same command surface as the Basic example, driven by a FlowFuse dashboard.\n\nOpen /dashboard/pumpingstation-basic after deploy.\n\nCONTROLS panel\n- Mode buttons \u2192 set.mode (manual / levelbased)\n- Inflow / Outflow buttons \u2192 set.inflow / set.outflow (60 / 80 m\u00b3/h)\n- Demand button \u2192 set.demand (40 m\u00b3/h, manual mode only)\n- Calibrate buttons \u2192 cmd.calibrate.volume / cmd.calibrate.level\n\nSTATUS panel\n- 7 text rows: Mode, Direction, Level, Volume, Volume %, percControl, Manual demand\n\nTRENDS panel\n- 4 charts: Level (m), Volume (m\u00b3), Volume %, Flow (in/out/net m\u00b3/h)\n\nRAW OUTPUT panel\n- Full key/value dump of the latest Port 0 cache (sorted). Shows every field the node emits including basin geometry, safety thresholds, predicted overflow/underflow.\n\nThe fan-out function caches last-known values so delta-only Port 0 updates never blank a row." ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"x" : 660 ,
"y" : 320 ,
"wires" : [ ]
} ,
{
"id" : "ui_base_ps" ,
"type" : "ui-base" ,
"name" : "EVOLV Demo" ,
"path" : "/dashboard" ,
"appIcon" : "" ,
"includeClientData" : true ,
"acceptsClientConfig" : [
"ui-notification" ,
"ui-control"
] ,
"showPathInSidebar" : false ,
"headerContent" : "page" ,
"navigationStyle" : "default" ,
"titleBarStyle" : "default"
} ,
{
"id" : "ui_theme_ps" ,
"type" : "ui-theme" ,
"name" : "EVOLV Basic Theme" ,
"colors" : {
"surface" : "#ffffff" ,
"primary" : "#0c99d9" ,
"bgPage" : "#eeeeee" ,
"groupBg" : "#ffffff" ,
"groupOutline" : "#cccccc"
} ,
"sizes" : {
"density" : "default" ,
"pagePadding" : "14px" ,
"groupGap" : "14px" ,
"groupBorderRadius" : "6px" ,
"widgetGap" : "12px"
}
} ,
{
"id" : "ui_page_ps" ,
"type" : "ui-page" ,
"name" : "PumpingStation Basic" ,
"ui" : "ui_base_ps" ,
"path" : "/pumpingstation-basic" ,
"icon" : "water-pump" ,
"layout" : "grid" ,
"theme" : "ui_theme_ps" ,
"breakpoints" : [
{
"name" : "Default" ,
"px" : "0" ,
"cols" : "12"
}
] ,
"order" : 1 ,
"className" : ""
} ,
{
"id" : "ui_group_ctrl" ,
"type" : "ui-group" ,
"name" : "Controls" ,
"page" : "ui_page_ps" ,
"width" : "6" ,
"height" : "1" ,
"order" : 1 ,
"showTitle" : true ,
"className" : ""
} ,
{
"id" : "ui_group_status" ,
"type" : "ui-group" ,
"name" : "Status" ,
"page" : "ui_page_ps" ,
"width" : "6" ,
"height" : "1" ,
"order" : 2 ,
"showTitle" : true ,
"className" : ""
} ,
{
"id" : "ui_group_trends" ,
"type" : "ui-group" ,
"name" : "Trends" ,
"page" : "ui_page_ps" ,
"width" : "12" ,
"height" : "1" ,
"order" : 3 ,
"showTitle" : true ,
"className" : ""
} ,
{
"id" : "ui_group_raw" ,
"type" : "ui-group" ,
"name" : "Raw output (Port 0 cache)" ,
"page" : "ui_page_ps" ,
"width" : "12" ,
"height" : "1" ,
"order" : 4 ,
"showTitle" : true ,
"className" : ""
} ,
{
"id" : "ui_btn_mode_manual" ,
"type" : "ui-button" ,
"z" : "77f00aef1c966167" ,
"g" : "4996420d47442fad" ,
"group" : "ui_group_ctrl" ,
"name" : "Mode: Manual" ,
"label" : "Mode: Manual" ,
"order" : 1 ,
"width" : "3" ,
"height" : "1" ,
"emulateClick" : false ,
"tooltip" : "Switch control mode to manual (set.demand is honoured)" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "pan_tool" ,
"payload" : "manual" ,
"payloadType" : "str" ,
"topic" : "set.mode" ,
"topicType" : "str" ,
"x" : 230 ,
"y" : 160 ,
"wires" : [
[
"8e78b6607deb33a7"
]
]
} ,
{
"id" : "ui_btn_mode_lvl" ,
"type" : "ui-button" ,
"z" : "77f00aef1c966167" ,
"g" : "4996420d47442fad" ,
"group" : "ui_group_ctrl" ,
"name" : "Mode: Levelbased" ,
"label" : "Mode: Levelbased" ,
"order" : 2 ,
"width" : "3" ,
"height" : "1" ,
"emulateClick" : false ,
"tooltip" : "Switch control mode to levelbased (ramp drives demand from level)" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "stacked_line_chart" ,
"payload" : "levelbased" ,
"payloadType" : "str" ,
"topic" : "set.mode" ,
"topicType" : "str" ,
"x" : 240 ,
"y" : 200 ,
"wires" : [
[
"8e78b6607deb33a7"
]
]
} ,
{
"id" : "ui_btn_inflow" ,
"type" : "ui-button" ,
"z" : "77f00aef1c966167" ,
"g" : "a9f9b38b0e00c1d7" ,
"group" : "ui_group_ctrl" ,
2026-05-26 17:31:44 +02:00
"name" : "Inflow 60 m\u00b3/h" ,
"label" : "Inflow 60 m\u00b3/h" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"order" : 3 ,
"width" : "3" ,
"height" : "1" ,
"emulateClick" : false ,
2026-05-26 17:31:44 +02:00
"tooltip" : "Push a measured inflow of 60 m\u00b3/h into the basin balance" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"color" : "" ,
"bgcolor" : "" ,
"icon" : "south" ,
"payload" : "60" ,
"payloadType" : "num" ,
"topic" : "set.inflow" ,
"topicType" : "str" ,
"x" : 240 ,
"y" : 320 ,
"wires" : [
[
"8e78b6607deb33a7"
]
]
} ,
{
"id" : "ui_btn_outflow" ,
"type" : "ui-button" ,
"z" : "77f00aef1c966167" ,
"g" : "a9f9b38b0e00c1d7" ,
"group" : "ui_group_ctrl" ,
2026-05-26 17:31:44 +02:00
"name" : "Outflow 80 m\u00b3/h" ,
"label" : "Outflow 80 m\u00b3/h" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"order" : 4 ,
"width" : "3" ,
"height" : "1" ,
"emulateClick" : false ,
2026-05-26 17:31:44 +02:00
"tooltip" : "Push a measured outflow of 80 m\u00b3/h into the basin balance" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"color" : "" ,
"bgcolor" : "" ,
"icon" : "north" ,
"payload" : "80" ,
"payloadType" : "num" ,
"topic" : "set.outflow" ,
"topicType" : "str" ,
"x" : 240 ,
"y" : 360 ,
"wires" : [
[
"8e78b6607deb33a7"
]
]
} ,
{
"id" : "ui_btn_demand" ,
"type" : "ui-button" ,
"z" : "77f00aef1c966167" ,
"g" : "42bf82c87d05f498" ,
"group" : "ui_group_ctrl" ,
2026-05-26 17:31:44 +02:00
"name" : "Demand 40 m\u00b3/h" ,
"label" : "Demand 40 m\u00b3/h (manual)" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"order" : 5 ,
"width" : "6" ,
"height" : "1" ,
"emulateClick" : false ,
2026-05-26 17:31:44 +02:00
"tooltip" : "Operator outflow demand \u2014 only forwarded when mode = manual" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"color" : "" ,
"bgcolor" : "" ,
"icon" : "speed" ,
"payload" : "40" ,
"payloadType" : "num" ,
"topic" : "set.demand" ,
"topicType" : "str" ,
"x" : 240 ,
"y" : 500 ,
"wires" : [
[
"8e78b6607deb33a7"
]
]
} ,
{
"id" : "ui_btn_cal_vol" ,
"type" : "ui-button" ,
"z" : "77f00aef1c966167" ,
"g" : "234bdce20170061a" ,
"group" : "ui_group_ctrl" ,
2026-05-26 17:31:44 +02:00
"name" : "Calibrate V=25 m\u00b3" ,
"label" : "Calibrate V = 25 m\u00b3" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"order" : 6 ,
"width" : "3" ,
"height" : "1" ,
"emulateClick" : false ,
2026-05-26 17:31:44 +02:00
"tooltip" : "Snap the predicted-volume integrator to 25 m\u00b3" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"color" : "" ,
"bgcolor" : "" ,
"icon" : "tune" ,
"payload" : "25" ,
"payloadType" : "num" ,
"topic" : "cmd.calibrate.volume" ,
"topicType" : "str" ,
"x" : 240 ,
"y" : 620 ,
"wires" : [
[
"8e78b6607deb33a7"
]
]
} ,
{
"id" : "ui_btn_cal_lvl" ,
"type" : "ui-button" ,
"z" : "77f00aef1c966167" ,
"g" : "234bdce20170061a" ,
"group" : "ui_group_ctrl" ,
"name" : "Calibrate L=1.5 m" ,
"label" : "Calibrate L = 1.5 m" ,
"order" : 7 ,
"width" : "3" ,
"height" : "1" ,
"emulateClick" : false ,
"tooltip" : "Snap the predicted-volume integrator to a known level of 1.5 m" ,
"color" : "" ,
"bgcolor" : "" ,
"icon" : "tune" ,
"payload" : "1.5" ,
"payloadType" : "num" ,
"topic" : "cmd.calibrate.level" ,
"topicType" : "str" ,
"x" : 240 ,
"y" : 660 ,
"wires" : [
[
"8e78b6607deb33a7"
]
]
} ,
{
"id" : "fn_status_split" ,
"type" : "function" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"name" : "fan-out Port 0 (status + charts + raw)" ,
2026-05-26 17:31:44 +02:00
"func" : "// Port 0 emits delta-only \u2014 cache last-known so deltas never blank a row.\n// Keys with dots use the runtime childId (= node id), so we pattern-match\n// by prefix rather than hardcoding.\nconst cache = context.get('cache') || {};\nconst p = msg.payload || {};\nfor (const k in p) cache[k] = p[k];\ncontext.set('cache', cache);\n\nconst findByPrefix = (prefix) => {\n for (const k of Object.keys(cache)) if (k.startsWith(prefix)) return cache[k];\n return null;\n};\nconst num = (v, dp, unit) => {\n const n = +v;\n if (!Number.isFinite(n)) return '\u2014';\n return n.toFixed(dp) + (unit ? ' ' + unit : '');\n};\n\nconst level = findByPrefix('level.predicted.atequipment.');\nconst volume = findByPrefix('volume.predicted.atequipment.');\nconst volPct = findByPrefix('volumePercent.predicted.atequipment.');\nconst qInS = findByPrefix('flow.predicted.in.');\nconst qOutS = findByPrefix('flow.predicted.out.');\nconst qNetS = findByPrefix('netFlowRate.predicted.atequipment.');\nconst qInH = Number.isFinite(+qInS) ? +qInS * 3600 : null;\nconst qOutH = Number.isFinite(+qOutS) ? +qOutS * 3600 : null;\nconst qNetH = Number.isFinite(+qNetS) ? +qNetS * 3600 : null;\nconst pct = cache.percControl;\nconst dem = cache.manualDemand;\nconst mode = cache.mode || '\u2014';\nconst dir = cache.direction || '\u2014';\n\nconst chart = (topic, v) => Number.isFinite(+v) ? { topic, payload: +v } : null;\n\n// Raw view: every cached key, sorted, with values prettified for display.\nconst rawRows = Object.keys(cache).sort().map((k) => {\n const v = cache[k];\n let display;\n if (v === null || v === undefined) display = '\u2014';\n else if (typeof v === 'number') display = Number.isInteger(v) ? String(v) : v.toFixed(4);\n else display = String(v);\n return { key: k, value: display };\n});\n\nreturn [\n // 0\u20136: status text widgets\n { payload: mode },\n { payload: dir },\n { payload: num(level, 2, 'm') },\n { payload: num(volume, 2, 'm\u00b3') },\n { payload: num(volPct, 2, '%') },\n { payload: num(pct, 1, '%') },\n { payload: mode === 'manual'\n ? (Number.isFinite(+dem) ? num(dem, 1, 'm\u00b3/h') : 'not set')\n : '\u2014' },\n // 7\u20139: single-series charts\n chart('Level', level),\n chart('Volume', volume),\n chart('Volume %', volPct),\n // 10\u201312: flow chart (three series share the same chart node)\n chart('Inflow', qInH),\n chart('Outflow', qOutH),\n chart('Net', qNetH),\n // 13: raw key/value rows for the ui-template\n { payload: rawRows },\n // 14: percControl chart\n chart('percControl', pct),\n];\n" ,
"outputs" : 15 ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"timeout" : 0 ,
"noerr" : 0 ,
"initialize" : "" ,
"finalize" : "" ,
"libs" : [ ] ,
"x" : 980 ,
"y" : 140 ,
"wires" : [
[
"ui_txt_mode"
] ,
[
"ui_txt_direction"
] ,
[
"ui_txt_level"
] ,
[
"ui_txt_volume"
] ,
[
"ui_txt_volpct"
] ,
[
"ui_txt_pct"
] ,
[
"ui_txt_demand"
] ,
[
"ui_chart_level"
] ,
[
"ui_chart_volume"
] ,
[
"ui_chart_volpct"
] ,
[
"ui_chart_flow"
] ,
[
"ui_chart_flow"
] ,
[
"ui_chart_flow"
] ,
[
"ui_tpl_raw"
2026-05-26 17:31:44 +02:00
] ,
[
"ui_chart_pumping_perccontrol"
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
]
]
} ,
{
"id" : "ui_txt_mode" ,
"type" : "ui-text" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_status" ,
"order" : 1 ,
"width" : "6" ,
"height" : "1" ,
"name" : "Mode" ,
"label" : "Mode" ,
"format" : "{{msg.payload}}" ,
"layout" : "row-spread" ,
"style" : false ,
"font" : "" ,
"fontSize" : 14 ,
"color" : "#1F4E79" ,
"x" : 1240 ,
"y" : 100 ,
"wires" : [ ]
} ,
{
"id" : "ui_txt_direction" ,
"type" : "ui-text" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_status" ,
"order" : 2 ,
"width" : "6" ,
"height" : "1" ,
"name" : "Direction" ,
"label" : "Direction" ,
"format" : "{{msg.payload}}" ,
"layout" : "row-spread" ,
"style" : false ,
"font" : "" ,
"fontSize" : 14 ,
"color" : "#1F4E79" ,
"x" : 1250 ,
"y" : 140 ,
"wires" : [ ]
} ,
{
"id" : "ui_txt_level" ,
"type" : "ui-text" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_status" ,
"order" : 3 ,
"width" : "6" ,
"height" : "1" ,
"name" : "Level" ,
"label" : "Level" ,
"format" : "{{msg.payload}}" ,
"layout" : "row-spread" ,
"style" : false ,
"font" : "" ,
"fontSize" : 14 ,
"color" : "#1F4E79" ,
"x" : 1240 ,
"y" : 180 ,
"wires" : [ ]
} ,
{
"id" : "ui_txt_volume" ,
"type" : "ui-text" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_status" ,
"order" : 4 ,
"width" : "6" ,
"height" : "1" ,
"name" : "Volume" ,
"label" : "Volume" ,
"format" : "{{msg.payload}}" ,
"layout" : "row-spread" ,
"style" : false ,
"font" : "" ,
"fontSize" : 14 ,
"color" : "#1F4E79" ,
"x" : 1250 ,
"y" : 220 ,
"wires" : [ ]
} ,
{
"id" : "ui_txt_volpct" ,
"type" : "ui-text" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_status" ,
"order" : 5 ,
"width" : "6" ,
"height" : "1" ,
"name" : "Volume %" ,
"label" : "Volume %" ,
"format" : "{{msg.payload}}" ,
"layout" : "row-spread" ,
"style" : false ,
"font" : "" ,
"fontSize" : 14 ,
"color" : "#1F4E79" ,
"x" : 1250 ,
"y" : 260 ,
"wires" : [ ]
} ,
{
"id" : "ui_txt_pct" ,
"type" : "ui-text" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_status" ,
"order" : 6 ,
"width" : "6" ,
"height" : "1" ,
"name" : "percControl" ,
"label" : "percControl" ,
"format" : "{{msg.payload}}" ,
"layout" : "row-spread" ,
"style" : false ,
"font" : "" ,
"fontSize" : 14 ,
"color" : "#1F4E79" ,
"x" : 1260 ,
"y" : 300 ,
"wires" : [ ]
} ,
{
"id" : "ui_txt_demand" ,
"type" : "ui-text" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_status" ,
"order" : 7 ,
"width" : "6" ,
"height" : "1" ,
"name" : "Manual demand" ,
"label" : "Manual demand" ,
"format" : "{{msg.payload}}" ,
"layout" : "row-spread" ,
"style" : false ,
"font" : "" ,
"fontSize" : 14 ,
"color" : "#7D3C98" ,
"x" : 1270 ,
"y" : 340 ,
"wires" : [ ]
} ,
{
"id" : "ui_chart_level" ,
"type" : "ui-chart" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_trends" ,
"name" : "Level (m)" ,
"label" : "Level (m)" ,
"order" : 1 ,
"width" : 6 ,
"height" : 4 ,
"chartType" : "line" ,
"category" : "topic" ,
"categoryType" : "msg" ,
"xAxisLabel" : "time" ,
"xAxisType" : "time" ,
"xAxisProperty" : "" ,
"xAxisPropertyType" : "timestamp" ,
"xAxisFormat" : "" ,
"xAxisFormatType" : "auto" ,
"yAxisLabel" : "m" ,
"yAxisProperty" : "payload" ,
"yAxisPropertyType" : "msg" ,
"xmin" : "" ,
"xmax" : "" ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : "15" ,
"removeOlderUnit" : "60" ,
"removeOlderPoints" : "" ,
"bins" : 10 ,
"action" : "append" ,
"stackSeries" : false ,
"pointShape" : "circle" ,
"pointRadius" : 4 ,
"interpolation" : "linear" ,
"showLegend" : false ,
"className" : "" ,
"colors" : [
"#0095FF" ,
"#FF0000" ,
"#FF7F0E" ,
"#2CA02C" ,
"#A347E1" ,
"#D62728" ,
"#FF9896" ,
"#9467BD" ,
"#C5B0D5"
] ,
"textColor" : [
"#666666"
] ,
"textColorDefault" : true ,
"gridColor" : [
"#e5e5e5"
] ,
"gridColorDefault" : true ,
"x" : 1240 ,
"y" : 400 ,
"wires" : [ ]
} ,
{
"id" : "ui_chart_volume" ,
"type" : "ui-chart" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_trends" ,
2026-05-26 17:31:44 +02:00
"name" : "Volume (m\u00b3)" ,
"label" : "Volume (m\u00b3)" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"order" : 2 ,
"width" : 6 ,
"height" : 4 ,
"chartType" : "line" ,
"category" : "topic" ,
"categoryType" : "msg" ,
"xAxisLabel" : "time" ,
"xAxisType" : "time" ,
"xAxisProperty" : "" ,
"xAxisPropertyType" : "timestamp" ,
"xAxisFormat" : "" ,
"xAxisFormatType" : "auto" ,
2026-05-26 17:31:44 +02:00
"yAxisLabel" : "m\u00b3" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"yAxisProperty" : "payload" ,
"yAxisPropertyType" : "msg" ,
"xmin" : "" ,
"xmax" : "" ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : "15" ,
"removeOlderUnit" : "60" ,
"removeOlderPoints" : "" ,
"bins" : 10 ,
"action" : "append" ,
"stackSeries" : false ,
"pointShape" : "circle" ,
"pointRadius" : 4 ,
"interpolation" : "linear" ,
"showLegend" : false ,
"className" : "" ,
"colors" : [
"#2CA02C" ,
"#FF0000" ,
"#FF7F0E" ,
"#0095FF" ,
"#A347E1" ,
"#D62728" ,
"#FF9896" ,
"#9467BD" ,
"#C5B0D5"
] ,
"textColor" : [
"#666666"
] ,
"textColorDefault" : true ,
"gridColor" : [
"#e5e5e5"
] ,
"gridColorDefault" : true ,
"x" : 1250 ,
"y" : 440 ,
"wires" : [ ]
} ,
{
"id" : "ui_chart_volpct" ,
"type" : "ui-chart" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_trends" ,
"name" : "Volume %" ,
"label" : "Volume %" ,
"order" : 3 ,
"width" : 6 ,
"height" : 4 ,
"chartType" : "line" ,
"category" : "topic" ,
"categoryType" : "msg" ,
"xAxisLabel" : "time" ,
"xAxisType" : "time" ,
"xAxisProperty" : "" ,
"xAxisPropertyType" : "timestamp" ,
"xAxisFormat" : "" ,
"xAxisFormatType" : "auto" ,
"yAxisLabel" : "%" ,
"yAxisProperty" : "payload" ,
"yAxisPropertyType" : "msg" ,
"xmin" : "" ,
"xmax" : "" ,
"ymin" : "0" ,
"ymax" : "100" ,
"removeOlder" : "15" ,
"removeOlderUnit" : "60" ,
"removeOlderPoints" : "" ,
"bins" : 10 ,
"action" : "append" ,
"stackSeries" : false ,
"pointShape" : "circle" ,
"pointRadius" : 4 ,
"interpolation" : "linear" ,
"showLegend" : false ,
"className" : "" ,
"colors" : [
"#A347E1" ,
"#FF0000" ,
"#FF7F0E" ,
"#2CA02C" ,
"#0095FF" ,
"#D62728" ,
"#FF9896" ,
"#9467BD" ,
"#C5B0D5"
] ,
"textColor" : [
"#666666"
] ,
"textColorDefault" : true ,
"gridColor" : [
"#e5e5e5"
] ,
"gridColorDefault" : true ,
"x" : 1240 ,
"y" : 480 ,
"wires" : [ ]
} ,
{
"id" : "ui_chart_flow" ,
"type" : "ui-chart" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_trends" ,
2026-05-26 17:31:44 +02:00
"name" : "Flow (m\u00b3/h)" ,
"label" : "Flow (m\u00b3/h) \u2014 Inflow / Outflow / Net" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"order" : 4 ,
"width" : 6 ,
"height" : 4 ,
"chartType" : "line" ,
"category" : "topic" ,
"categoryType" : "msg" ,
"xAxisLabel" : "time" ,
"xAxisType" : "time" ,
"xAxisProperty" : "" ,
"xAxisPropertyType" : "timestamp" ,
"xAxisFormat" : "" ,
"xAxisFormatType" : "auto" ,
2026-05-26 17:31:44 +02:00
"yAxisLabel" : "m\u00b3/h" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"yAxisProperty" : "payload" ,
"yAxisPropertyType" : "msg" ,
"xmin" : "" ,
"xmax" : "" ,
"ymin" : "" ,
"ymax" : "" ,
"removeOlder" : "15" ,
"removeOlderUnit" : "60" ,
"removeOlderPoints" : "" ,
"bins" : 10 ,
"action" : "append" ,
"stackSeries" : false ,
"pointShape" : "circle" ,
"pointRadius" : 4 ,
"interpolation" : "linear" ,
"showLegend" : true ,
"className" : "" ,
"colors" : [
"#0095FF" ,
"#FF7F0E" ,
"#2CA02C" ,
"#FF0000" ,
"#A347E1" ,
"#D62728" ,
"#FF9896" ,
"#9467BD" ,
"#C5B0D5"
] ,
"textColor" : [
"#666666"
] ,
"textColorDefault" : true ,
"gridColor" : [
"#e5e5e5"
] ,
"gridColorDefault" : true ,
"x" : 1250 ,
"y" : 520 ,
"wires" : [ ]
} ,
{
"id" : "ui_tpl_raw" ,
"type" : "ui-template" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_raw" ,
"name" : "Raw output table" ,
"order" : 1 ,
"width" : "12" ,
"height" : "8" ,
"head" : "" ,
"format" : "<template>\n <div style=\"font-family:monospace;font-size:12px\">\n <table style=\"width:100%;border-collapse:collapse\">\n <tr v-for=\"row in rows\" :key=\"row.key\" style=\"border-bottom:1px solid #eee\">\n <td style=\"padding:2px 8px;color:#444;white-space:nowrap\">{{ row.key }}</td>\n <td style=\"padding:2px 8px;text-align:right;color:#0c4a72\">{{ row.value }}</td>\n </tr>\n </table>\n </div>\n</template>\n\n<script>\nexport default {\n data() { return { rows: [] }; },\n watch: {\n msg(m) {\n if (m && Array.isArray(m.payload)) this.rows = m.payload;\n }\n }\n}\n</script>\n" ,
"storeOutMessages" : true ,
"passthru" : true ,
"resendOnRefresh" : true ,
"templateScope" : "local" ,
"className" : "" ,
"x" : 1260 ,
"y" : 580 ,
"wires" : [
[ ]
]
} ,
{
"id" : "b2450e5ee2eebfaa" ,
"type" : "debug" ,
"z" : "77f00aef1c966167" ,
"g" : "f4ba4542514ed853" ,
"name" : "Port 0: Process" ,
"active" : true ,
"tosidebar" : true ,
"console" : false ,
"tostatus" : false ,
"complete" : "payload" ,
"targetType" : "msg" ,
"x" : 980 ,
"y" : 820 ,
"wires" : [ ]
} ,
{
"id" : "386af1ad8aa8ed12" ,
"type" : "debug" ,
"z" : "77f00aef1c966167" ,
"g" : "f4ba4542514ed853" ,
"name" : "Port 1: InfluxDB" ,
"active" : true ,
"tosidebar" : true ,
"console" : false ,
"tostatus" : false ,
"complete" : "true" ,
"targetType" : "full" ,
"x" : 980 ,
"y" : 880 ,
"wires" : [ ]
} ,
{
"id" : "c27c2655f199b530" ,
"type" : "debug" ,
"z" : "77f00aef1c966167" ,
"g" : "f4ba4542514ed853" ,
"name" : "Port 2: Parent reg" ,
"active" : true ,
"tosidebar" : true ,
"console" : false ,
"tostatus" : false ,
"complete" : "true" ,
"targetType" : "full" ,
"x" : 990 ,
"y" : 940 ,
"wires" : [ ]
} ,
{
"id" : "8e78b6607deb33a7" ,
"type" : "pumpingStation" ,
"z" : "77f00aef1c966167" ,
"g" : "aa3381b896eb2cfb" ,
"name" : "" ,
"simulator" : false ,
"basinVolume" : 50 ,
"basinHeight" : 4 ,
"inflowLevel" : 1.5 ,
"outflowLevel" : 0.2 ,
"overflowLevel" : 3.8 ,
"defaultFluid" : "wastewater" ,
"inletPipeDiameter" : 0.3 ,
"outletPipeDiameter" : 0.3 ,
"pipelineLength" : 80 ,
"maxDischargeHead" : 24 ,
"staticHead" : 12 ,
"maxInflowRate" : 200 ,
"temperatureReferenceDegC" : 15 ,
"timeleftToFullOrEmptyThresholdSeconds" : 0 ,
"enableDryRunProtection" : true ,
"enableHighVolumeSafety" : true ,
"enableOverfillProtection" : true ,
"dryRunThresholdPercent" : 2 ,
"highVolumeSafetyThresholdPercent" : 98 ,
"overfillThresholdPercent" : 98 ,
"minHeightBasedOn" : "outlet" ,
"processOutputFormat" : "process" ,
"dbaseOutputFormat" : "influxdb" ,
"refHeight" : "NAP" ,
"basinBottomRef" : 1 ,
"uuid" : "" ,
"supplier" : "" ,
"category" : "" ,
"assetType" : "" ,
"model" : "" ,
"unit" : "" ,
"enableLog" : false ,
"logLevel" : "error" ,
"positionVsParent" : "atEquipment" ,
2026-05-26 17:31:44 +02:00
"positionIcon" : "\u22a5" ,
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
"hasDistance" : false ,
"distance" : "" ,
"controlMode" : "levelbased" ,
"levelCurveType" : "linear" ,
"logCurveFactor" : 9 ,
"enableShiftedRamp" : false ,
"shiftLevel" : 0 ,
"shiftArmPercent" : 95 ,
"startLevel" : 1 ,
"stopLevel" : 0.5 ,
"minLevel" : 0.3 ,
"maxLevel" : 3.8 ,
"flowSetpoint" : null ,
"flowDeadband" : null ,
"x" : 650 ,
"y" : 420 ,
"wires" : [
[
"b2450e5ee2eebfaa" ,
"fn_status_split"
] ,
[
"386af1ad8aa8ed12"
] ,
[
"c27c2655f199b530"
]
]
} ,
{
"id" : "ef77c1819422a098" ,
"type" : "global-config" ,
"env" : [ ] ,
"modules" : {
"EVOLV" : "1.0.29"
}
2026-05-26 17:31:44 +02:00
} ,
{
"id" : "ui_chart_pumping_perccontrol" ,
"type" : "ui-chart" ,
"z" : "77f00aef1c966167" ,
"g" : "grp_status_panel" ,
"group" : "ui_group_trends" ,
"name" : "percControl" ,
"label" : "percControl (%) \u2014 pumping-station demand" ,
"order" : 5 ,
"width" : 6 ,
"height" : 4 ,
"chartType" : "line" ,
"category" : "topic" ,
"categoryType" : "msg" ,
"xAxisLabel" : "time" ,
"xAxisType" : "time" ,
"xAxisProperty" : "" ,
"xAxisPropertyType" : "timestamp" ,
"xAxisFormat" : "" ,
"xAxisFormatType" : "auto" ,
"yAxisLabel" : "%" ,
"yAxisProperty" : "payload" ,
"yAxisPropertyType" : "msg" ,
"xmin" : "" ,
"xmax" : "" ,
"ymin" : "0" ,
"ymax" : "100" ,
"removeOlder" : "15" ,
"removeOlderUnit" : "60" ,
"removeOlderPoints" : "" ,
"bins" : 10 ,
"action" : "append" ,
"stackSeries" : false ,
"pointShape" : "circle" ,
"pointRadius" : 4 ,
"interpolation" : "linear" ,
"showLegend" : false ,
"className" : "" ,
"colors" : [
"#A347E1" ,
"#FF0000" ,
"#FF7F0E" ,
"#2CA02C" ,
"#0095FF" ,
"#D62728" ,
"#FF9896" ,
"#9467BD" ,
"#C5B0D5"
] ,
"textColor" : [
"#666666"
] ,
"textColorDefault" : true ,
"gridColor" : [
"#e5e5e5"
] ,
"gridColorDefault" : true ,
"x" : 1240 ,
"y" : 560 ,
"wires" : [
[ ]
]
feat(pumpingStation): realistic defaults, ramp-foot visual fix, manual-mode visibility, dashboard example
Editor + schema defaults
- pumpingStation.html: drag-in defaults now reflect a realistic basin
(volume=50 m³, height=4 m, inflowLevel=1.5, outflowLevel=0.2,
overflowLevel=3.8, startLevel=1, stopLevel=0.5, minLevel=0.3,
maxLevel=3.8). Old defaults left every level field null.
Visual bug fix
- src/editor/mode-preview.js: the level-based ramp curve in the editor
was being drawn with foot=startLevel via buildPath(start, start, max).
The runtime in control/levelBased.js has always used inflowLevel as
the ramp foot. Pass buildPath(start, upFoot, max) where upFoot falls
back to start when inflowLevel is missing, matching the runtime.
Manual mode observability
- src/specificClass.js: store last forwarded demand on this._manualDemand;
surface as `mode` and `manualDemand` in getOutput(); call
notifyOutputChanged() on forwardDemandToChildren and on changeMode so
Port 0/1 emit even with no children registered. Status badge compacted
to `mode | dir% | net m³/h` + `Qd=X m³/h` in manual mode.
Examples cleanup
- Drop stale 02-Integration.json, 03-Dashboard.json, basic-dashboard.flow.json,
standalone-demo.js.
- 01-Basic.json: numbered driver groups (1. Control mode … 4. Calibration),
Debug-outputs group, fixed typos and HOW-TO-USE; Port 1 debug now active.
- New 02-Dashboard.json: FlowFuse Dashboard 2.0 with Controls (7 buttons),
Status (7 ui-text rows), Trends (4 ui-charts: level / volume / volume% /
flow in-out-net), Raw output (ui-template dumping every Port 0 field).
Fan-out function pattern-matches the 4-segment measurement keys by
prefix instead of hardcoding childId, converts flow m³/s → m³/h, and
caches last-known values so deltas never blank a row.
- examples/README.md realigned to the two-file set.
Wiki
- Home.md: 5 image placeholders replaced with the provided screenshots
(01-node-and-editor, 02-basic-flow, 03-wiring-standalone,
04-wiring-integrated) and the demo GIF (01-basic-demo).
- Reference-Examples.md: shipped-files table reduced to 01-Basic +
02-Dashboard, Example-01 section uses the screenshot + GIF, Example-02
rewritten as Dashboard (kept screenshot/GIF callouts open for those
captures), Example-03/Integration sections + their debug-recipes row
removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 14:52:00 +02:00
}
2026-05-26 17:31:44 +02:00
]