[ { "id": "ps_int_proc", "type": "tab", "label": "Process Plant", "disabled": false, "info": "Tier 2: pumpingStation + measurement child + machineGroupControl parent with two rotatingMachine pumps. Demonstrates Phase-2 parent/child handshakes and the canonical set.mode/set.inflow/set.demand topics." }, { "id": "ps_int_setup", "type": "tab", "label": "Setup", "disabled": false, "info": "Deploy-time once-true injects that initialise control modes on the EVOLV nodes." }, { "id": "ps_int_title", "type": "comment", "z": "ps_int_proc", "name": "PumpingStation - Integration\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nL0 link-ins | L2 level sensor (CM) | L3 pumps (EM) | L4 MGC (UN) | L5 station (PC).\nPumps register with MGC via Port 2; MGC and the level sensor register with the station via Port 2.\nCross-tab channels: setup:* drive once-true initialisation from the Setup tab.", "info": "", "x": 600, "y": 40, "wires": [] }, { "id": "lin_setup_mode", "type": "link in", "z": "ps_int_proc", "name": "setup:to-ps-mode", "links": [], "x": 120, "y": 500, "wires": [ [ "ps_int_station" ] ] }, { "id": "lin_setup_inflow", "type": "link in", "z": "ps_int_proc", "name": "setup:to-ps-inflow", "links": [], "x": 120, "y": 560, "wires": [ [ "ps_int_station" ] ] }, { "id": "lin_setup_mgcmode", "type": "link in", "z": "ps_int_proc", "name": "setup:to-mgc-mode", "links": [], "x": 120, "y": 360, "wires": [ [ "ps_int_mgc" ] ] }, { "id": "meas_level", "type": "measurement", "z": "ps_int_proc", "name": "Basin level sensor", "mode": "analog", "channels": "[]", "scaling": false, "i_min": 0, "i_max": 0, "i_offset": 0, "o_min": 0, "o_max": 1, "simulator": true, "smooth_method": "mean", "count": 5, "processOutputFormat": "process", "dbaseOutputFormat": "influxdb", "uuid": "example-level-001", "supplier": "vega", "category": "sensor", "assetType": "level", "model": "VEGAPULS-31", "unit": "m", "assetTagNumber": "LT-001", "enableLog": false, "logLevel": "error", "positionVsParent": "atEquipment", "positionIcon": "", "hasDistance": false, "distance": 0, "distanceUnit": "m", "distanceDescription": "", "x": 600, "y": 700, "wires": [ [ "ps_int_dbg_level" ], [], [ "ps_int_station" ] ] }, { "id": "ps_int_inj_level", "type": "inject", "z": "ps_int_proc", "name": "sim level 1.6 m", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "1.6", "vt": "num" } ], "topic": "measurement", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 120, "y": 700, "wires": [ [ "meas_level" ] ] }, { "id": "pump_a", "type": "rotatingMachine", "z": "ps_int_proc", "name": "Pump A", "speed": "1", "startup": "2", "warmup": "1", "shutdown": "2", "cooldown": "1", "movementMode": "staticspeed", "machineCurve": "", "uuid": "example-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": "error", "positionVsParent": "atEquipment", "positionIcon": "", "hasDistance": false, "distance": "", "distanceUnit": "m", "distanceDescription": "", "x": 840, "y": 320, "wires": [ [ "ps_int_dbg_pa" ], [], [ "ps_int_mgc" ] ] }, { "id": "pump_b", "type": "rotatingMachine", "z": "ps_int_proc", "name": "Pump B", "speed": "1", "startup": "2", "warmup": "1", "shutdown": "2", "cooldown": "1", "movementMode": "staticspeed", "machineCurve": "", "uuid": "example-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": "error", "positionVsParent": "atEquipment", "positionIcon": "", "hasDistance": false, "distance": "", "distanceUnit": "m", "distanceDescription": "", "x": 840, "y": 400, "wires": [ [ "ps_int_dbg_pb" ], [], [ "ps_int_mgc" ] ] }, { "id": "ps_int_mgc", "type": "machineGroupControl", "z": "ps_int_proc", "name": "Pump Group", "enableLog": true, "logLevel": "info", "positionVsParent": "atEquipment", "positionIcon": "", "hasDistance": false, "distance": "", "distanceUnit": "m", "x": 1080, "y": 360, "wires": [ [ "ps_int_dbg_mgc" ], [], [ "ps_int_station" ] ] }, { "id": "ps_int_station", "type": "pumpingStation", "z": "ps_int_proc", "name": "Pumping Station", "simulator": false, "basinVolume": 50, "basinHeight": 3.5, "inflowLevel": 3, "outflowLevel": 0.2, "overflowLevel": 3.2, "defaultFluid": "wastewater", "inletPipeDiameter": 0.3, "outletPipeDiameter": 0.3, "pipelineLength": 80, "maxDischargeHead": 24, "staticHead": 12, "maxInflowRate": 200, "temperatureReferenceDegC": 15, "timeleftToFullOrEmptyThresholdSeconds": 0, "enableDryRunProtection": true, "enableOverfillProtection": true, "dryRunThresholdPercent": 2, "overfillThresholdPercent": 98, "minHeightBasedOn": "outlet", "processOutputFormat": "process", "dbaseOutputFormat": "influxdb", "refHeight": "NAP", "basinBottomRef": 1, "uuid": "example-ps-001", "supplier": "WBD-RD", "category": "station", "assetType": "pumpingstation", "model": "demo-50m3", "unit": "m3/h", "enableLog": true, "logLevel": "info", "positionVsParent": "atEquipment", "positionIcon": "", "hasDistance": false, "distance": "", "distanceUnit": "m", "distanceDescription": "", "controlMode": "levelbased", "startLevel": 1.2, "minLevel": 0.4, "maxLevel": 2.8, "flowSetpoint": null, "flowDeadband": null, "x": 1320, "y": 520, "wires": [ [ "ps_int_format" ], [ "ps_int_dbg_influx" ], [] ] }, { "id": "ps_int_format", "type": "function", "z": "ps_int_proc", "name": "Merge deltas + format", "func": "const p = (msg && msg.payload && typeof msg.payload === 'object') ? msg.payload : {};\nconst cache = context.get('c') || {}; Object.assign(cache, p); context.set('c', cache);\nfunction pick(prefix){ for (const k of Object.keys(cache)) if (k===prefix||k.indexOf(prefix+'.')===0){ const v=Number(cache[k]); if(Number.isFinite(v)) return v;} return null; }\nconst vol=pick('volume.predicted.atequipment'), lvl=pick('level.predicted.atequipment'), flIn=pick('flow.predicted.in'), flOut=pick('flow.predicted.out');\nmsg.payload = {\n state: cache.state || 'unknown',\n controlMode: cache.controlMode || cache.mode || 'n/a',\n direction: cache.direction || 'n/a',\n percControl: cache.percControl != null ? Number(cache.percControl).toFixed(1)+' %' : 'n/a',\n volume: vol != null ? vol.toFixed(2)+' m3' : 'n/a',\n volumePercent: cache.volumePercent != null ? Number(cache.volumePercent).toFixed(1)+' %' : 'n/a',\n level: lvl != null ? lvl.toFixed(3)+' m' : 'n/a',\n inflow: flIn != null ? (flIn*3600).toFixed(1)+' m3/h' : 'n/a',\n outflow: flOut != null ? (flOut*3600).toFixed(1)+' m3/h' : 'n/a',\n childCount: cache.childCount != null ? cache.childCount : 'n/a'\n};\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1560, "y": 520, "wires": [ [ "ps_int_dbg_process" ] ] }, { "id": "ps_int_dbg_process", "type": "debug", "z": "ps_int_proc", "name": "PS Port 0: Process", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 1800, "y": 480, "wires": [] }, { "id": "ps_int_dbg_influx", "type": "debug", "z": "ps_int_proc", "name": "PS Port 1: InfluxDB", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "x": 1800, "y": 540, "wires": [] }, { "id": "ps_int_dbg_mgc", "type": "debug", "z": "ps_int_proc", "name": "MGC Port 0", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 1800, "y": 360, "wires": [] }, { "id": "ps_int_dbg_pa", "type": "debug", "z": "ps_int_proc", "name": "Pump A Port 0", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 1800, "y": 320, "wires": [] }, { "id": "ps_int_dbg_pb", "type": "debug", "z": "ps_int_proc", "name": "Pump B Port 0", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 1800, "y": 400, "wires": [] }, { "id": "ps_int_dbg_level", "type": "debug", "z": "ps_int_proc", "name": "Level Port 0", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 1800, "y": 700, "wires": [] }, { "id": "grp_pumpa", "type": "group", "z": "ps_int_proc", "name": "Pump A (EM)", "style": { "label": true, "stroke": "#000000", "fill": "#86bbdd", "fill-opacity": "0.10" }, "nodes": [ "pump_a", "ps_int_dbg_pa" ], "x": 815, "y": 275, "w": 1210, "h": 110 }, { "id": "grp_pumpb", "type": "group", "z": "ps_int_proc", "name": "Pump B (EM)", "style": { "label": true, "stroke": "#000000", "fill": "#86bbdd", "fill-opacity": "0.10" }, "nodes": [ "pump_b", "ps_int_dbg_pb" ], "x": 815, "y": 355, "w": 1210, "h": 110 }, { "id": "grp_mgc", "type": "group", "z": "ps_int_proc", "name": "Pump Group MGC (UN)", "style": { "label": true, "stroke": "#000000", "fill": "#50a8d9", "fill-opacity": "0.10" }, "nodes": [ "ps_int_mgc", "ps_int_dbg_mgc", "lin_setup_mgcmode" ], "x": 95, "y": 315, "w": 1930, "h": 110 }, { "id": "grp_station", "type": "group", "z": "ps_int_proc", "name": "Pumping Station (PC)", "style": { "label": true, "stroke": "#000000", "fill": "#0c99d9", "fill-opacity": "0.10" }, "nodes": [ "ps_int_station", "ps_int_format", "ps_int_dbg_process", "ps_int_dbg_influx", "lin_setup_mode", "lin_setup_inflow" ], "x": 95, "y": 435, "w": 1930, "h": 190 }, { "id": "grp_level", "type": "group", "z": "ps_int_proc", "name": "Level Sensor (CM)", "style": { "label": true, "stroke": "#000000", "fill": "#a9daee", "fill-opacity": "0.10" }, "nodes": [ "meas_level", "ps_int_inj_level", "ps_int_dbg_level" ], "x": 95, "y": 655, "w": 1930, "h": 110 }, { "id": "setup_title", "type": "comment", "z": "ps_int_setup", "name": "Deploy-time setup\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nFires once after each deploy: pushes the canonical set.mode / set.inflow /\nset.demand topics across cross-tab channels into the Process Plant tab.", "info": "", "x": 600, "y": 40, "wires": [] }, { "id": "setup_inj_mode", "type": "inject", "z": "ps_int_setup", "name": "set.mode = levelbased", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "levelbased", "vt": "str" } ], "topic": "set.mode", "repeat": "", "crontab": "", "once": true, "onceDelay": "0.5", "x": 120, "y": 160, "wires": [ [ "lout_setup_mode" ] ] }, { "id": "setup_inj_mgcmode", "type": "inject", "z": "ps_int_setup", "name": "MGC set.mode = auto", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "auto", "vt": "str" } ], "topic": "set.mode", "repeat": "", "crontab": "", "once": true, "onceDelay": "0.5", "x": 120, "y": 220, "wires": [ [ "lout_setup_mgcmode" ] ] }, { "id": "setup_inj_inflow", "type": "inject", "z": "ps_int_setup", "name": "seed inflow 60 m3/h", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "60", "vt": "num" } ], "topic": "set.inflow", "repeat": "", "crontab": "", "once": true, "onceDelay": "1.0", "x": 120, "y": 280, "wires": [ [ "lout_setup_inflow" ] ] }, { "id": "lout_setup_mode", "type": "link out", "z": "ps_int_setup", "name": "setup:to-ps-mode", "mode": "link", "links": [ "lin_setup_mode" ], "x": 1800, "y": 160, "wires": [] }, { "id": "lout_setup_mgcmode", "type": "link out", "z": "ps_int_setup", "name": "setup:to-mgc-mode", "mode": "link", "links": [ "lin_setup_mgcmode" ], "x": 1800, "y": 220, "wires": [] }, { "id": "lout_setup_inflow", "type": "link out", "z": "ps_int_setup", "name": "setup:to-ps-inflow", "mode": "link", "links": [ "lin_setup_inflow" ], "x": 1800, "y": 280, "wires": [] }, { "id": "grp_setup", "type": "group", "z": "ps_int_setup", "name": "Deploy-time setup", "style": { "label": true, "stroke": "#000000", "fill": "#dddddd", "fill-opacity": "0.10" }, "nodes": [ "setup_inj_mode", "setup_inj_mgcmode", "setup_inj_inflow", "lout_setup_mode", "lout_setup_mgcmode", "lout_setup_inflow" ], "x": 95, "y": 115, "w": 1930, "h": 230 } ]