Editor (mgc.html)
- Drag-in defaults now expose mode (optimalControl) and scaling (normalized)
via dropdowns in the edit dialog. Was: no control fields in the UI at all,
so users had to send set.mode/set.scaling after deploy or live with the
hidden schema defaults.
Wire-up (src/nodeClass.js)
- buildDomainConfig now bridges the flat editor fields (mode, scaling) into
the nested schema shape (mode.current, scaling.current). Was: returned {}
so the editor's mode/scaling never reached the runtime.
Mode-case bug fix (src/specificClass.js)
- Schema enum values are camelCase (optimalControl, priorityControl) but the
runtime switch in _runDispatch matched lowercase only. With the default
config, dispatch silently fell through to the warning branch and nothing
ran. Normalise via String(this.mode).toLowerCase() so both forms work.
Status badge (src/io/output.js)
- Compacted from ~80 chars (mode | Ⓝ: 💨=Q/Qmax | ⚡=P | N machine(s)) to
~50 chars (mode | norm | Q=Q/Qmax m³/h | P=P kW | active/total x).
Drops emoji glyphs that rendered inconsistently across themes; uses the
same dot+fill convention as pumpingStation.
Output extension (src/io/output.js)
- getOutput() now also emits flowCapacityMin/Max, machineCount,
machineCountActive. Was: only group-level totals + dist-from-peak +
mode/scaling, so dashboards couldn't show capacity / active count
without subscribing to each rotatingMachine individually.
Examples
- Drop pre-refactor stubs (basic.flow.json, integration.flow.json,
edge.flow.json). They had a single MGC + inject + debug, no children,
and never dispatched anything.
- 01-Basic.json: 1 MGC + 3 rotatingMachine pumps + Setup once-fires
virtualControl + cmd.startup on all pumps via fan-out function. Numbered
driver groups for Control mode / Scaling / Operator demand. Pumps
register with MGC via Port 2 (child.register, automatic).
- 02-Dashboard.json: same plumbing + FlowFuse Dashboard 2.0 page with
Controls (mode + scaling buttons, demand slider 0–100, stop + init
buttons), Status (7 ui-text rows), Trends (3 charts: flow + capacity,
power, BEP rel %), and a raw-output ui-template dumping every Port 0
field. Fan-out function caches last-known values so deltas don't blank.
Wiki + README
- examples/README.md rewritten for the two-file set with canonical command
surface table and "what to try" recipes.
- wiki/Home.md §11 (Examples) updated; §14 #4 (TODO flow item) replaced
with the actual current limitation (no per-pump fan-out on Port 0).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1206 lines
33 KiB
JSON
1206 lines
33 KiB
JSON
[
|
||
{
|
||
"id": "tab_mgc_dash",
|
||
"type": "tab",
|
||
"label": "MGC - Dashboard",
|
||
"disabled": false,
|
||
"info": "Tier 2: one machineGroupControl coordinating three rotatingMachine pumps, driven by a FlowFuse dashboard. Mode + scaling buttons, demand slider, live status rows, three trend charts, and a raw-output table."
|
||
},
|
||
{
|
||
"id": "grp_mgc_unit",
|
||
"type": "group",
|
||
"z": "tab_mgc_dash",
|
||
"name": "Machine Group (Unit)",
|
||
"style": {
|
||
"label": true,
|
||
"stroke": "#000000",
|
||
"fill": "#50a8d9",
|
||
"fill-opacity": "0.10"
|
||
},
|
||
"nodes": [
|
||
"mgc_dash_node"
|
||
],
|
||
"x": 974,
|
||
"y": 379,
|
||
"w": 152,
|
||
"h": 122
|
||
},
|
||
{
|
||
"id": "grp_pump_a",
|
||
"type": "group",
|
||
"z": "tab_mgc_dash",
|
||
"name": "Pump A (Equipment)",
|
||
"style": {
|
||
"label": true,
|
||
"stroke": "#000000",
|
||
"fill": "#86bbdd",
|
||
"fill-opacity": "0.10"
|
||
},
|
||
"nodes": [
|
||
"rm_dash_pump_a"
|
||
],
|
||
"x": 694,
|
||
"y": 219,
|
||
"w": 142,
|
||
"h": 82
|
||
},
|
||
{
|
||
"id": "grp_pump_b",
|
||
"type": "group",
|
||
"z": "tab_mgc_dash",
|
||
"name": "Pump B (Equipment)",
|
||
"style": {
|
||
"label": true,
|
||
"stroke": "#000000",
|
||
"fill": "#86bbdd",
|
||
"fill-opacity": "0.10"
|
||
},
|
||
"nodes": [
|
||
"rm_dash_pump_b"
|
||
],
|
||
"x": 694,
|
||
"y": 399,
|
||
"w": 142,
|
||
"h": 82
|
||
},
|
||
{
|
||
"id": "grp_pump_c",
|
||
"type": "group",
|
||
"z": "tab_mgc_dash",
|
||
"name": "Pump C (Equipment)",
|
||
"style": {
|
||
"label": true,
|
||
"stroke": "#000000",
|
||
"fill": "#86bbdd",
|
||
"fill-opacity": "0.10"
|
||
},
|
||
"nodes": [
|
||
"rm_dash_pump_c"
|
||
],
|
||
"x": 694,
|
||
"y": 579,
|
||
"w": 142,
|
||
"h": 82
|
||
},
|
||
{
|
||
"id": "grp_drv_mode",
|
||
"type": "group",
|
||
"z": "tab_mgc_dash",
|
||
"name": "1. Control mode",
|
||
"style": {
|
||
"stroke": "#666666",
|
||
"fill": "#ffdf7f",
|
||
"fill-opacity": "0.15",
|
||
"label": true,
|
||
"color": "#333333"
|
||
},
|
||
"nodes": [
|
||
"ui_btn_mode_optimal",
|
||
"ui_btn_mode_priority"
|
||
],
|
||
"x": 94,
|
||
"y": 99,
|
||
"w": 312,
|
||
"h": 122
|
||
},
|
||
{
|
||
"id": "grp_drv_scaling",
|
||
"type": "group",
|
||
"z": "tab_mgc_dash",
|
||
"name": "2. Scaling",
|
||
"style": {
|
||
"stroke": "#666666",
|
||
"fill": "#ffdf7f",
|
||
"fill-opacity": "0.15",
|
||
"label": true,
|
||
"color": "#333333"
|
||
},
|
||
"nodes": [
|
||
"ui_btn_scaling_norm",
|
||
"ui_btn_scaling_abs"
|
||
],
|
||
"x": 94,
|
||
"y": 259,
|
||
"w": 312,
|
||
"h": 122
|
||
},
|
||
{
|
||
"id": "grp_drv_demand",
|
||
"type": "group",
|
||
"z": "tab_mgc_dash",
|
||
"name": "3. Operator demand",
|
||
"style": {
|
||
"stroke": "#666666",
|
||
"fill": "#ffdf7f",
|
||
"fill-opacity": "0.15",
|
||
"label": true,
|
||
"color": "#333333"
|
||
},
|
||
"nodes": [
|
||
"ui_slider_demand",
|
||
"ui_btn_demand_stop"
|
||
],
|
||
"x": 94,
|
||
"y": 419,
|
||
"w": 312,
|
||
"h": 122
|
||
},
|
||
{
|
||
"id": "grp_setup",
|
||
"type": "group",
|
||
"z": "tab_mgc_dash",
|
||
"name": "Setup — once on deploy + manual re-init",
|
||
"style": {
|
||
"stroke": "#666666",
|
||
"fill": "#dddddd",
|
||
"fill-opacity": "0.20",
|
||
"label": true,
|
||
"color": "#333333"
|
||
},
|
||
"nodes": [
|
||
"inj_setup_start",
|
||
"ui_btn_setup_init",
|
||
"fn_setup_fanout"
|
||
],
|
||
"x": 94,
|
||
"y": 579,
|
||
"w": 532,
|
||
"h": 122
|
||
},
|
||
{
|
||
"id": "grp_status_panel",
|
||
"type": "group",
|
||
"z": "tab_mgc_dash",
|
||
"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_scaling",
|
||
"ui_txt_flow",
|
||
"ui_txt_power",
|
||
"ui_txt_capacity",
|
||
"ui_txt_machines",
|
||
"ui_txt_bep",
|
||
"ui_chart_flow",
|
||
"ui_chart_power",
|
||
"ui_chart_bep",
|
||
"ui_tpl_raw"
|
||
],
|
||
"x": 1234,
|
||
"y": 79,
|
||
"w": 712,
|
||
"h": 642
|
||
},
|
||
{
|
||
"id": "grp_dbg",
|
||
"type": "group",
|
||
"z": "tab_mgc_dash",
|
||
"name": "Debug outputs (sidebar)",
|
||
"style": {
|
||
"stroke": "#666666",
|
||
"fill": "#d1d1d1",
|
||
"fill-opacity": "0.2",
|
||
"label": true,
|
||
"color": "#333333"
|
||
},
|
||
"nodes": [
|
||
"dbg_port0",
|
||
"dbg_port1",
|
||
"dbg_port2"
|
||
],
|
||
"x": 1234,
|
||
"y": 759,
|
||
"w": 252,
|
||
"h": 202
|
||
},
|
||
{
|
||
"id": "cmt_title",
|
||
"type": "comment",
|
||
"z": "tab_mgc_dash",
|
||
"name": "MGC — Dashboard (Tier 2)",
|
||
"info": "Same command surface as the Basic flow, driven by a FlowFuse dashboard.\n\nOpen /dashboard/mgc-basic after deploy.\n\nCONTROLS panel\n- Mode: optimalControl / priorityControl → set.mode\n- Scaling: normalized (0–100 %) / absolute (m³/h) → set.scaling\n- Demand slider 0–100 → set.demand (interpretation depends on scaling)\n- Stop button (set.demand = 0) and Initialize pumps button\n\nSTATUS panel\n- Mode / Scaling / Total flow / Total power / Capacity (Qmin–Qmax) / Active machines / BEP distance (rel %)\n\nTRENDS panel\n- Flow (m³/h) — predicted aggregate vs capacity\n- Power (kW)\n- BEP distance (rel %)\n\nRAW OUTPUT panel\n- Full key/value dump of the latest MGC Port 0 cache (sorted).\n\nPORTS (preserved for inspection)\n- Port 0: process output (changed fields only)\n- Port 1: InfluxDB-shaped {measurement, fields, tags, timestamp}\n- Port 2: parent registration (when wired into a pumpingStation)",
|
||
"x": 1100,
|
||
"y": 280,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_base_mgc",
|
||
"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_mgc",
|
||
"type": "ui-theme",
|
||
"name": "EVOLV Basic Theme",
|
||
"colors": {
|
||
"surface": "#ffffff",
|
||
"primary": "#50a8d9",
|
||
"bgPage": "#eeeeee",
|
||
"groupBg": "#ffffff",
|
||
"groupOutline": "#cccccc"
|
||
},
|
||
"sizes": {
|
||
"density": "default",
|
||
"pagePadding": "14px",
|
||
"groupGap": "14px",
|
||
"groupBorderRadius": "6px",
|
||
"widgetGap": "12px"
|
||
}
|
||
},
|
||
{
|
||
"id": "ui_page_mgc",
|
||
"type": "ui-page",
|
||
"name": "MGC Basic",
|
||
"ui": "ui_base_mgc",
|
||
"path": "/mgc-basic",
|
||
"icon": "settings-input-component",
|
||
"layout": "grid",
|
||
"theme": "ui_theme_mgc",
|
||
"breakpoints": [
|
||
{
|
||
"name": "Default",
|
||
"px": "0",
|
||
"cols": "12"
|
||
}
|
||
],
|
||
"order": 1,
|
||
"className": ""
|
||
},
|
||
{
|
||
"id": "ui_group_ctrl",
|
||
"type": "ui-group",
|
||
"name": "Controls",
|
||
"page": "ui_page_mgc",
|
||
"width": "6",
|
||
"height": "1",
|
||
"order": 1,
|
||
"showTitle": true,
|
||
"className": ""
|
||
},
|
||
{
|
||
"id": "ui_group_status",
|
||
"type": "ui-group",
|
||
"name": "Status",
|
||
"page": "ui_page_mgc",
|
||
"width": "6",
|
||
"height": "1",
|
||
"order": 2,
|
||
"showTitle": true,
|
||
"className": ""
|
||
},
|
||
{
|
||
"id": "ui_group_trends",
|
||
"type": "ui-group",
|
||
"name": "Trends",
|
||
"page": "ui_page_mgc",
|
||
"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_mgc",
|
||
"width": "12",
|
||
"height": "1",
|
||
"order": 4,
|
||
"showTitle": true,
|
||
"className": ""
|
||
},
|
||
{
|
||
"id": "ui_btn_mode_optimal",
|
||
"type": "ui-button",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_drv_mode",
|
||
"group": "ui_group_ctrl",
|
||
"name": "Mode: optimalControl",
|
||
"label": "Mode: optimalControl",
|
||
"order": 1,
|
||
"width": "3",
|
||
"height": "1",
|
||
"emulateClick": false,
|
||
"tooltip": "Best-combination optimiser (BEP-Gravitation / NCog)",
|
||
"color": "",
|
||
"bgcolor": "",
|
||
"icon": "auto_fix_high",
|
||
"payload": "optimalControl",
|
||
"payloadType": "str",
|
||
"topic": "set.mode",
|
||
"topicType": "str",
|
||
"x": 260,
|
||
"y": 140,
|
||
"wires": [
|
||
[
|
||
"mgc_dash_node"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "ui_btn_mode_priority",
|
||
"type": "ui-button",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_drv_mode",
|
||
"group": "ui_group_ctrl",
|
||
"name": "Mode: priorityControl",
|
||
"label": "Mode: priorityControl",
|
||
"order": 2,
|
||
"width": "3",
|
||
"height": "1",
|
||
"emulateClick": false,
|
||
"tooltip": "Sequential equal-flow control by priority list",
|
||
"color": "",
|
||
"bgcolor": "",
|
||
"icon": "format_list_numbered",
|
||
"payload": "priorityControl",
|
||
"payloadType": "str",
|
||
"topic": "set.mode",
|
||
"topicType": "str",
|
||
"x": 260,
|
||
"y": 180,
|
||
"wires": [
|
||
[
|
||
"mgc_dash_node"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "ui_btn_scaling_norm",
|
||
"type": "ui-button",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_drv_scaling",
|
||
"group": "ui_group_ctrl",
|
||
"name": "Scaling: normalized",
|
||
"label": "Scaling: normalized",
|
||
"order": 3,
|
||
"width": "3",
|
||
"height": "1",
|
||
"emulateClick": false,
|
||
"tooltip": "Interpret set.demand as 0–100 % of group capacity",
|
||
"color": "",
|
||
"bgcolor": "",
|
||
"icon": "percent",
|
||
"payload": "normalized",
|
||
"payloadType": "str",
|
||
"topic": "set.scaling",
|
||
"topicType": "str",
|
||
"x": 260,
|
||
"y": 300,
|
||
"wires": [
|
||
[
|
||
"mgc_dash_node"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "ui_btn_scaling_abs",
|
||
"type": "ui-button",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_drv_scaling",
|
||
"group": "ui_group_ctrl",
|
||
"name": "Scaling: absolute",
|
||
"label": "Scaling: absolute",
|
||
"order": 4,
|
||
"width": "3",
|
||
"height": "1",
|
||
"emulateClick": false,
|
||
"tooltip": "Interpret set.demand as m³/h (capped by group min/max)",
|
||
"color": "",
|
||
"bgcolor": "",
|
||
"icon": "exposure",
|
||
"payload": "absolute",
|
||
"payloadType": "str",
|
||
"topic": "set.scaling",
|
||
"topicType": "str",
|
||
"x": 260,
|
||
"y": 340,
|
||
"wires": [
|
||
[
|
||
"mgc_dash_node"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "ui_slider_demand",
|
||
"type": "ui-slider",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_drv_demand",
|
||
"group": "ui_group_ctrl",
|
||
"name": "Demand",
|
||
"label": "Demand",
|
||
"order": 5,
|
||
"width": "6",
|
||
"height": "1",
|
||
"topic": "set.demand",
|
||
"topicType": "str",
|
||
"icon": "speed",
|
||
"iconType": "fa",
|
||
"min": 0,
|
||
"max": 100,
|
||
"step": 1,
|
||
"thumbLabel": "always",
|
||
"tickLabel": "true",
|
||
"showTicks": false,
|
||
"passthru": true,
|
||
"outs": "all",
|
||
"className": "",
|
||
"x": 260,
|
||
"y": 460,
|
||
"wires": [
|
||
[
|
||
"mgc_dash_node"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "ui_btn_demand_stop",
|
||
"type": "ui-button",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_drv_demand",
|
||
"group": "ui_group_ctrl",
|
||
"name": "Demand = 0 (Stop)",
|
||
"label": "Stop (demand = 0)",
|
||
"order": 6,
|
||
"width": "6",
|
||
"height": "1",
|
||
"emulateClick": false,
|
||
"tooltip": "Send set.demand = 0 — MGC calls turnOffAllMachines",
|
||
"color": "#ffffff",
|
||
"bgcolor": "#cc6600",
|
||
"icon": "stop",
|
||
"payload": "0",
|
||
"payloadType": "num",
|
||
"topic": "set.demand",
|
||
"topicType": "str",
|
||
"x": 260,
|
||
"y": 500,
|
||
"wires": [
|
||
[
|
||
"mgc_dash_node"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "ui_btn_setup_init",
|
||
"type": "ui-button",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_setup",
|
||
"group": "ui_group_ctrl",
|
||
"name": "Initialize pumps",
|
||
"label": "Initialize pumps (virtualControl + startup)",
|
||
"order": 7,
|
||
"width": "12",
|
||
"height": "1",
|
||
"emulateClick": false,
|
||
"tooltip": "Re-runs the once-on-deploy setup: virtualControl mode + cmd.startup on all three pumps",
|
||
"color": "",
|
||
"bgcolor": "",
|
||
"icon": "play_arrow",
|
||
"payload": "go",
|
||
"payloadType": "str",
|
||
"topic": "",
|
||
"topicType": "str",
|
||
"x": 260,
|
||
"y": 620,
|
||
"wires": [
|
||
[
|
||
"fn_setup_fanout"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "inj_setup_start",
|
||
"type": "inject",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_setup",
|
||
"name": "Auto-start pumps",
|
||
"props": [
|
||
{ "p": "payload", "v": "go", "vt": "str" }
|
||
],
|
||
"repeat": "",
|
||
"crontab": "",
|
||
"once": true,
|
||
"onceDelay": "1.5",
|
||
"topic": "",
|
||
"x": 260,
|
||
"y": 660,
|
||
"wires": [
|
||
[
|
||
"fn_setup_fanout"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "fn_setup_fanout",
|
||
"type": "function",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_setup",
|
||
"name": "fan-out: virtualControl + startup → A/B/C",
|
||
"func": "// Fire two messages per pump: set.mode = virtualControl, then cmd.startup.\nconst setMode = { topic: 'set.mode', payload: 'virtualControl' };\nconst startup = { topic: 'cmd.startup', payload: {} };\nreturn [\n [setMode, startup], // → Pump A\n [setMode, startup], // → Pump B\n [setMode, startup], // → Pump C\n];\n",
|
||
"outputs": 3,
|
||
"timeout": 0,
|
||
"noerr": 0,
|
||
"initialize": "",
|
||
"finalize": "",
|
||
"libs": [],
|
||
"x": 500,
|
||
"y": 640,
|
||
"wires": [
|
||
[
|
||
"rm_dash_pump_a"
|
||
],
|
||
[
|
||
"rm_dash_pump_b"
|
||
],
|
||
[
|
||
"rm_dash_pump_c"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "fn_status_split",
|
||
"type": "function",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_status_panel",
|
||
"name": "fan-out Port 0 (status + charts + raw)",
|
||
"func": "// MGC Port 0 emits delta-only. Cache last-known so deltas never blank a\n// row, then fan out one msg per ui-text / ui-chart / ui-template slot.\nconst cache = context.get('cache') || {};\nconst p = msg.payload || {};\nfor (const k in p) cache[k] = p[k];\ncontext.set('cache', cache);\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 mode = cache.mode || '—';\nconst scaling = cache.scaling || '—';\nconst flow = cache['atEquipment_predicted_flow'];\nconst power = cache['atEquipment_predicted_power'];\nconst qMin = cache.flowCapacityMin;\nconst qMax = cache.flowCapacityMax;\nconst nAct = cache.machineCountActive;\nconst nTot = cache.machineCount;\nconst bepRel = cache.relDistFromPeak;\n\nconst chart = (topic, v) => Number.isFinite(+v) ? { topic, payload: +v } : null;\n\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 // 0–6: status text\n { payload: mode },\n { payload: scaling },\n { payload: num(flow, 1, 'm³/h') },\n { payload: num(power, 2, 'kW') },\n { payload: Number.isFinite(+qMax) ? `${num(qMin, 1)} – ${num(qMax, 1, 'm³/h')}` : '—' },\n { payload: Number.isFinite(+nAct) && Number.isFinite(+nTot) ? `${nAct} / ${nTot}` : '—' },\n { payload: num(bepRel, 1, '%') },\n // 7–9: charts (flow vs capacity / power / bep distance)\n chart('Flow', flow),\n chart('Capacity', qMax),\n chart('Power', power),\n chart('BEP rel%', bepRel),\n // 11: raw rows for the ui-template\n { payload: rawRows },\n];\n",
|
||
"outputs": 12,
|
||
"timeout": 0,
|
||
"noerr": 0,
|
||
"initialize": "",
|
||
"finalize": "",
|
||
"libs": [],
|
||
"x": 1300,
|
||
"y": 140,
|
||
"wires": [
|
||
[
|
||
"ui_txt_mode"
|
||
],
|
||
[
|
||
"ui_txt_scaling"
|
||
],
|
||
[
|
||
"ui_txt_flow"
|
||
],
|
||
[
|
||
"ui_txt_power"
|
||
],
|
||
[
|
||
"ui_txt_capacity"
|
||
],
|
||
[
|
||
"ui_txt_machines"
|
||
],
|
||
[
|
||
"ui_txt_bep"
|
||
],
|
||
[
|
||
"ui_chart_flow"
|
||
],
|
||
[
|
||
"ui_chart_flow"
|
||
],
|
||
[
|
||
"ui_chart_power"
|
||
],
|
||
[
|
||
"ui_chart_bep"
|
||
],
|
||
[
|
||
"ui_tpl_raw"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "ui_txt_mode",
|
||
"type": "ui-text",
|
||
"z": "tab_mgc_dash",
|
||
"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": 1560,
|
||
"y": 100,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_txt_scaling",
|
||
"type": "ui-text",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_status_panel",
|
||
"group": "ui_group_status",
|
||
"order": 2,
|
||
"width": "6",
|
||
"height": "1",
|
||
"name": "Scaling",
|
||
"label": "Scaling",
|
||
"format": "{{msg.payload}}",
|
||
"layout": "row-spread",
|
||
"style": false,
|
||
"font": "",
|
||
"fontSize": 14,
|
||
"color": "#1F4E79",
|
||
"x": 1560,
|
||
"y": 140,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_txt_flow",
|
||
"type": "ui-text",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_status_panel",
|
||
"group": "ui_group_status",
|
||
"order": 3,
|
||
"width": "6",
|
||
"height": "1",
|
||
"name": "Total flow",
|
||
"label": "Total flow",
|
||
"format": "{{msg.payload}}",
|
||
"layout": "row-spread",
|
||
"style": false,
|
||
"font": "",
|
||
"fontSize": 14,
|
||
"color": "#1F4E79",
|
||
"x": 1570,
|
||
"y": 180,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_txt_power",
|
||
"type": "ui-text",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_status_panel",
|
||
"group": "ui_group_status",
|
||
"order": 4,
|
||
"width": "6",
|
||
"height": "1",
|
||
"name": "Total power",
|
||
"label": "Total power",
|
||
"format": "{{msg.payload}}",
|
||
"layout": "row-spread",
|
||
"style": false,
|
||
"font": "",
|
||
"fontSize": 14,
|
||
"color": "#1F4E79",
|
||
"x": 1580,
|
||
"y": 220,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_txt_capacity",
|
||
"type": "ui-text",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_status_panel",
|
||
"group": "ui_group_status",
|
||
"order": 5,
|
||
"width": "6",
|
||
"height": "1",
|
||
"name": "Capacity (Qmin–Qmax)",
|
||
"label": "Capacity",
|
||
"format": "{{msg.payload}}",
|
||
"layout": "row-spread",
|
||
"style": false,
|
||
"font": "",
|
||
"fontSize": 14,
|
||
"color": "#1F4E79",
|
||
"x": 1620,
|
||
"y": 260,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_txt_machines",
|
||
"type": "ui-text",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_status_panel",
|
||
"group": "ui_group_status",
|
||
"order": 6,
|
||
"width": "6",
|
||
"height": "1",
|
||
"name": "Machines (active / total)",
|
||
"label": "Machines",
|
||
"format": "{{msg.payload}}",
|
||
"layout": "row-spread",
|
||
"style": false,
|
||
"font": "",
|
||
"fontSize": 14,
|
||
"color": "#1F4E79",
|
||
"x": 1630,
|
||
"y": 300,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_txt_bep",
|
||
"type": "ui-text",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_status_panel",
|
||
"group": "ui_group_status",
|
||
"order": 7,
|
||
"width": "6",
|
||
"height": "1",
|
||
"name": "BEP distance (rel)",
|
||
"label": "BEP distance",
|
||
"format": "{{msg.payload}}",
|
||
"layout": "row-spread",
|
||
"style": false,
|
||
"font": "",
|
||
"fontSize": 14,
|
||
"color": "#7D3C98",
|
||
"x": 1600,
|
||
"y": 340,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_chart_flow",
|
||
"type": "ui-chart",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_status_panel",
|
||
"group": "ui_group_trends",
|
||
"name": "Flow vs capacity",
|
||
"label": "Flow (m³/h) — predicted vs capacity",
|
||
"order": 1,
|
||
"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",
|
||
"#cccccc",
|
||
"#FF7F0E",
|
||
"#2CA02C",
|
||
"#A347E1",
|
||
"#D62728",
|
||
"#FF9896",
|
||
"#9467BD",
|
||
"#C5B0D5"
|
||
],
|
||
"textColor": [
|
||
"#666666"
|
||
],
|
||
"textColorDefault": true,
|
||
"gridColor": [
|
||
"#e5e5e5"
|
||
],
|
||
"gridColorDefault": true,
|
||
"x": 1600,
|
||
"y": 400,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_chart_power",
|
||
"type": "ui-chart",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_status_panel",
|
||
"group": "ui_group_trends",
|
||
"name": "Power",
|
||
"label": "Power (kW)",
|
||
"order": 2,
|
||
"width": 6,
|
||
"height": 4,
|
||
"chartType": "line",
|
||
"category": "topic",
|
||
"categoryType": "msg",
|
||
"xAxisLabel": "time",
|
||
"xAxisType": "time",
|
||
"xAxisProperty": "",
|
||
"xAxisPropertyType": "timestamp",
|
||
"xAxisFormat": "",
|
||
"xAxisFormatType": "auto",
|
||
"yAxisLabel": "kW",
|
||
"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": 1580,
|
||
"y": 440,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_chart_bep",
|
||
"type": "ui-chart",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_status_panel",
|
||
"group": "ui_group_trends",
|
||
"name": "BEP distance (rel %)",
|
||
"label": "BEP distance (rel %)",
|
||
"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": "",
|
||
"ymax": "",
|
||
"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": 1610,
|
||
"y": 480,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "ui_tpl_raw",
|
||
"type": "ui-template",
|
||
"z": "tab_mgc_dash",
|
||
"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": 1620,
|
||
"y": 520,
|
||
"wires": [
|
||
[]
|
||
]
|
||
},
|
||
{
|
||
"id": "rm_dash_pump_a",
|
||
"type": "rotatingMachine",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_pump_a",
|
||
"name": "Pump A",
|
||
"speed": "1",
|
||
"startup": "2",
|
||
"warmup": "1",
|
||
"shutdown": "2",
|
||
"cooldown": "1",
|
||
"movementMode": "staticspeed",
|
||
"machineCurve": "",
|
||
"uuid": "mgc-dash-pump-a",
|
||
"supplier": "hidrostal",
|
||
"category": "pump",
|
||
"assetType": "pump-centrifugal",
|
||
"model": "hidrostal-H05K-S03R",
|
||
"unit": "m3/h",
|
||
"curvePressureUnit": "mbar",
|
||
"curveFlowUnit": "m3/h",
|
||
"curvePowerUnit": "kW",
|
||
"curveControlUnit": "%",
|
||
"enableLog": false,
|
||
"logLevel": "info",
|
||
"positionVsParent": "atEquipment",
|
||
"positionIcon": "",
|
||
"hasDistance": false,
|
||
"distance": "",
|
||
"distanceUnit": "m",
|
||
"distanceDescription": "",
|
||
"x": 760,
|
||
"y": 260,
|
||
"wires": [
|
||
[],
|
||
[],
|
||
[
|
||
"mgc_dash_node"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "rm_dash_pump_b",
|
||
"type": "rotatingMachine",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_pump_b",
|
||
"name": "Pump B",
|
||
"speed": "1",
|
||
"startup": "2",
|
||
"warmup": "1",
|
||
"shutdown": "2",
|
||
"cooldown": "1",
|
||
"movementMode": "staticspeed",
|
||
"machineCurve": "",
|
||
"uuid": "mgc-dash-pump-b",
|
||
"supplier": "hidrostal",
|
||
"category": "pump",
|
||
"assetType": "pump-centrifugal",
|
||
"model": "hidrostal-H05K-S03R",
|
||
"unit": "m3/h",
|
||
"curvePressureUnit": "mbar",
|
||
"curveFlowUnit": "m3/h",
|
||
"curvePowerUnit": "kW",
|
||
"curveControlUnit": "%",
|
||
"enableLog": false,
|
||
"logLevel": "info",
|
||
"positionVsParent": "atEquipment",
|
||
"positionIcon": "",
|
||
"hasDistance": false,
|
||
"distance": "",
|
||
"distanceUnit": "m",
|
||
"distanceDescription": "",
|
||
"x": 760,
|
||
"y": 440,
|
||
"wires": [
|
||
[],
|
||
[],
|
||
[
|
||
"mgc_dash_node"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "rm_dash_pump_c",
|
||
"type": "rotatingMachine",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_pump_c",
|
||
"name": "Pump C",
|
||
"speed": "1",
|
||
"startup": "2",
|
||
"warmup": "1",
|
||
"shutdown": "2",
|
||
"cooldown": "1",
|
||
"movementMode": "staticspeed",
|
||
"machineCurve": "",
|
||
"uuid": "mgc-dash-pump-c",
|
||
"supplier": "hidrostal",
|
||
"category": "pump",
|
||
"assetType": "pump-centrifugal",
|
||
"model": "hidrostal-H05K-S03R",
|
||
"unit": "m3/h",
|
||
"curvePressureUnit": "mbar",
|
||
"curveFlowUnit": "m3/h",
|
||
"curvePowerUnit": "kW",
|
||
"curveControlUnit": "%",
|
||
"enableLog": false,
|
||
"logLevel": "info",
|
||
"positionVsParent": "atEquipment",
|
||
"positionIcon": "",
|
||
"hasDistance": false,
|
||
"distance": "",
|
||
"distanceUnit": "m",
|
||
"distanceDescription": "",
|
||
"x": 760,
|
||
"y": 620,
|
||
"wires": [
|
||
[],
|
||
[],
|
||
[
|
||
"mgc_dash_node"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "mgc_dash_node",
|
||
"type": "machineGroupControl",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_mgc_unit",
|
||
"name": "Machine Group",
|
||
"processOutputFormat": "process",
|
||
"dbaseOutputFormat": "influxdb",
|
||
"mode": "optimalControl",
|
||
"scaling": "normalized",
|
||
"uuid": "",
|
||
"supplier": "",
|
||
"category": "",
|
||
"assetType": "",
|
||
"model": "",
|
||
"unit": "",
|
||
"enableLog": false,
|
||
"logLevel": "info",
|
||
"positionVsParent": "atEquipment",
|
||
"positionIcon": "",
|
||
"hasDistance": false,
|
||
"distance": "",
|
||
"distanceUnit": "m",
|
||
"distanceDescription": "",
|
||
"x": 1050,
|
||
"y": 440,
|
||
"wires": [
|
||
[
|
||
"dbg_port0",
|
||
"fn_status_split"
|
||
],
|
||
[
|
||
"dbg_port1"
|
||
],
|
||
[
|
||
"dbg_port2"
|
||
]
|
||
]
|
||
},
|
||
{
|
||
"id": "dbg_port0",
|
||
"type": "debug",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_dbg",
|
||
"name": "Port 0: Process",
|
||
"active": true,
|
||
"tosidebar": true,
|
||
"console": false,
|
||
"tostatus": false,
|
||
"complete": "payload",
|
||
"targetType": "msg",
|
||
"x": 1340,
|
||
"y": 800,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "dbg_port1",
|
||
"type": "debug",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_dbg",
|
||
"name": "Port 1: InfluxDB",
|
||
"active": true,
|
||
"tosidebar": true,
|
||
"console": false,
|
||
"tostatus": false,
|
||
"complete": "true",
|
||
"targetType": "full",
|
||
"x": 1340,
|
||
"y": 860,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "dbg_port2",
|
||
"type": "debug",
|
||
"z": "tab_mgc_dash",
|
||
"g": "grp_dbg",
|
||
"name": "Port 2: Parent reg",
|
||
"active": true,
|
||
"tosidebar": true,
|
||
"console": false,
|
||
"tostatus": false,
|
||
"complete": "true",
|
||
"targetType": "full",
|
||
"x": 1350,
|
||
"y": 920,
|
||
"wires": []
|
||
},
|
||
{
|
||
"id": "mgc_global_cfg",
|
||
"type": "global-config",
|
||
"env": [],
|
||
"modules": {
|
||
"EVOLV": "1.0.29"
|
||
}
|
||
}
|
||
]
|