Files
pumpingStation/examples/02-Dashboard.json
znetsixe fe5fa3577b 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

1071 lines
30 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[
{
"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",
"name": "PumpingStation — 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 → set.mode (manual / levelbased)\n- Inflow / Outflow buttons → set.inflow / set.outflow (60 / 80 m³/h)\n- Demand button → set.demand (40 m³/h, manual mode only)\n- Calibrate buttons → 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³), Volume %, Flow (in/out/net m³/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.",
"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",
"name": "Inflow 60 m³/h",
"label": "Inflow 60 m³/h",
"order": 3,
"width": "3",
"height": "1",
"emulateClick": false,
"tooltip": "Push a measured inflow of 60 m³/h into the basin balance",
"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",
"name": "Outflow 80 m³/h",
"label": "Outflow 80 m³/h",
"order": 4,
"width": "3",
"height": "1",
"emulateClick": false,
"tooltip": "Push a measured outflow of 80 m³/h into the basin balance",
"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",
"name": "Demand 40 m³/h",
"label": "Demand 40 m³/h (manual)",
"order": 5,
"width": "6",
"height": "1",
"emulateClick": false,
"tooltip": "Operator outflow demand — only forwarded when mode = manual",
"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",
"name": "Calibrate V=25 m³",
"label": "Calibrate V = 25 m³",
"order": 6,
"width": "3",
"height": "1",
"emulateClick": false,
"tooltip": "Snap the predicted-volume integrator to 25 m³",
"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)",
"func": "// Port 0 emits delta-only — 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 '—';\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 || '—';\nconst dir = cache.direction || '—';\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 = '—';\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 // 06: status text widgets\n { payload: mode },\n { payload: dir },\n { payload: num(level, 2, 'm') },\n { payload: num(volume, 2, 'm³') },\n { payload: num(volPct, 2, '%') },\n { payload: num(pct, 1, '%') },\n { payload: mode === 'manual'\n ? (Number.isFinite(+dem) ? num(dem, 1, 'm³/h') : 'not set')\n : '—' },\n // 79: single-series charts\n chart('Level', level),\n chart('Volume', volume),\n chart('Volume %', volPct),\n // 1012: 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];\n",
"outputs": 14,
"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"
]
]
},
{
"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",
"name": "Volume (m³)",
"label": "Volume (m³)",
"order": 2,
"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": [
"#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",
"name": "Flow (m³/h)",
"label": "Flow (m³/h) — Inflow / Outflow / Net",
"order": 4,
"width": 6,
"height": 4,
"chartType": "line",
"category": "topic",
"categoryType": "msg",
"xAxisLabel": "time",
"xAxisType": "time",
"xAxisProperty": "",
"xAxisPropertyType": "timestamp",
"xAxisFormat": "",
"xAxisFormatType": "auto",
"yAxisLabel": "m³/h",
"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",
"positionIcon": "⊥",
"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"
}
}
]