[ { "id": "rm_basic_tab", "type": "tab", "label": "RotatingMachine - Basic Manual Control", "disabled": false, "info": "Demonstrates basic manual control of a single rotatingMachine using inject nodes only. No dashboard dependencies." }, { "id": "rm_basic_comment_title", "type": "comment", "z": "rm_basic_tab", "name": "RotatingMachine - Basic Manual Control\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nDemonstrates startup/shutdown sequences, speed setpoint\ncontrol, and pressure simulation for a single pump.\n\nPrerequisites: EVOLV package installed.", "info": "", "x": 360, "y": 40, "wires": [] }, { "id": "rm_basic_comment_howto", "type": "comment", "z": "rm_basic_tab", "name": "HOW TO USE:\n1. Deploy flow\n2. Click 'Set virtualControl' to enable manual control\n3. Click 'Startup' to run the startup sequence\n4. Click 'Set 60%' to move to 60% speed\n5. Inject BOTH pressure values to see flow/power predictions\n6. Click 'Shutdown' when done\n\nNOTE: Output uses delta compression - only changed\nfields are sent each tick. The formatter merges\ndeltas into a running cache for display.\n\nIMPORTANT: Flow and power predictions require at least\none pressure value to be injected. Without pressure,\npredictions use fDimension=0 (unrealistic values).\nOutput keys use 4-segment format:\ntype.variant.position.childId (e.g. flow.predicted.downstream.default)", "info": "", "x": 360, "y": 100, "wires": [] }, { "id": "rm_basic_node", "type": "rotatingMachine", "z": "rm_basic_tab", "name": "Pump 1", "speed": "1", "startup": "3", "warmup": "2", "shutdown": "3", "cooldown": "2", "movementMode": "staticspeed", "machineCurve": "", "uuid": "example-pump-001", "supplier": "hidrostal", "category": "pump", "assetType": "pump-centrifugal", "model": "hidrostal-H05K-S03R", "unit": "m3/h", "curvePressureUnit": "mbar", "curveFlowUnit": "m3/h", "curvePowerUnit": "kW", "curveControlUnit": "%", "enableLog": true, "logLevel": "info", "positionVsParent": "atEquipment", "positionIcon": "", "hasDistance": false, "distance": "", "distanceUnit": "m", "distanceDescription": "", "x": 560, "y": 340, "wires": [ ["rm_basic_format_output"], ["rm_basic_debug_port1"], ["rm_basic_debug_port2"] ] }, { "id": "rm_basic_inject_mode", "type": "inject", "z": "rm_basic_tab", "name": "Set virtualControl", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "virtualControl", "vt": "str" } ], "topic": "setMode", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 190, "y": 200, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_auto", "type": "inject", "z": "rm_basic_tab", "name": "Set auto mode", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "auto", "vt": "str" } ], "topic": "setMode", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 180, "y": 240, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_startup", "type": "inject", "z": "rm_basic_tab", "name": "Startup", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "{\"source\":\"GUI\",\"action\":\"execSequence\",\"parameter\":\"startup\"}", "vt": "json" } ], "topic": "execSequence", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 170, "y": 300, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_shutdown", "type": "inject", "z": "rm_basic_tab", "name": "Shutdown", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "{\"source\":\"GUI\",\"action\":\"execSequence\",\"parameter\":\"shutdown\"}", "vt": "json" } ], "topic": "execSequence", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 170, "y": 340, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_emergency", "type": "inject", "z": "rm_basic_tab", "name": "Emergency Stop", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "{\"source\":\"GUI\",\"action\":\"emergencystop\"}", "vt": "json" } ], "topic": "emergencystop", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 190, "y": 380, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_setpoint60", "type": "inject", "z": "rm_basic_tab", "name": "Set 60%", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "{\"source\":\"GUI\",\"action\":\"execMovement\",\"setpoint\":60}", "vt": "json" } ], "topic": "execMovement", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 170, "y": 440, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_setpoint30", "type": "inject", "z": "rm_basic_tab", "name": "Set 30%", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "{\"source\":\"GUI\",\"action\":\"execMovement\",\"setpoint\":30}", "vt": "json" } ], "topic": "execMovement", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 170, "y": 480, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_setpoint100", "type": "inject", "z": "rm_basic_tab", "name": "Set 100%", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "{\"source\":\"GUI\",\"action\":\"execMovement\",\"setpoint\":100}", "vt": "json" } ], "topic": "execMovement", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 170, "y": 520, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_pressure_down", "type": "inject", "z": "rm_basic_tab", "name": "Sim downstream 1100 mbar", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "{\"type\":\"pressure\",\"position\":\"downstream\",\"value\":1100,\"unit\":\"mbar\"}", "vt": "json" } ], "topic": "simulateMeasurement", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 230, "y": 600, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_pressure_up", "type": "inject", "z": "rm_basic_tab", "name": "Sim upstream 200 mbar", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "{\"type\":\"pressure\",\"position\":\"upstream\",\"value\":200,\"unit\":\"mbar\"}", "vt": "json" } ], "topic": "simulateMeasurement", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 220, "y": 640, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_maintenance", "type": "inject", "z": "rm_basic_tab", "name": "Enter Maintenance", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "{\"source\":\"GUI\",\"action\":\"execSequence\",\"parameter\":\"entermaintenance\"}", "vt": "json" } ], "topic": "execSequence", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 200, "y": 700, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_inject_leavemaint", "type": "inject", "z": "rm_basic_tab", "name": "Leave Maintenance", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload", "v": "{\"source\":\"GUI\",\"action\":\"execSequence\",\"parameter\":\"leavemaintenance\"}", "vt": "json" } ], "topic": "execSequence", "repeat": "", "crontab": "", "once": false, "onceDelay": "", "x": 200, "y": 740, "wires": [["rm_basic_node"]] }, { "id": "rm_basic_format_output", "type": "function", "z": "rm_basic_tab", "name": "Merge deltas and format", "func": "const p = msg.payload || {};\nconst cache = context.get('c') || {};\nObject.assign(cache, p);\ncontext.set('c', cache);\nfunction find(prefix) {\n for (var k in cache) { if (k.indexOf(prefix) === 0) return cache[k]; }\n return null;\n}\nconst fl = find('flow.predicted.downstream.');\nconst pw = find('power.predicted.atequipment.');\nconst pD = find('pressure.measured.downstream.');\nconst pU = find('pressure.measured.upstream.');\nmsg.payload = {\n state: cache.state || 'idle',\n mode: cache.mode || 'auto',\n ctrl: cache.ctrl != null ? Number(cache.ctrl).toFixed(1) + '%' : 'n/a',\n flow: fl != null ? Number(fl).toFixed(2) + ' m3/h' : 'n/a',\n power: pw != null ? Number(pw).toFixed(2) + ' kW' : 'n/a',\n NCog: cache.NCog != null ? Number(cache.NCog).toFixed(1) + '%' : 'n/a',\n pDown: pD != null ? Number(pD).toFixed(0) + ' mbar' : 'n/a',\n pUp: pU != null ? Number(pU).toFixed(0) + ' mbar' : 'n/a',\n runtime: cache.runtime != null ? Number(cache.runtime).toFixed(3) + ' h' : '0'\n};\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 790, "y": 300, "wires": [["rm_basic_debug_port0"]] }, { "id": "rm_basic_debug_port0", "type": "debug", "z": "rm_basic_tab", "name": "Port 0: Process Data", "active": true, "tosidebar": true, "console": false, "tostatus": true, "complete": "payload", "targetType": "msg", "statusVal": "payload.state", "statusType": "auto", "x": 1020, "y": 300, "wires": [] }, { "id": "rm_basic_debug_port1", "type": "debug", "z": "rm_basic_tab", "name": "Port 1: InfluxDB Telemetry", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "x": 1040, "y": 360, "wires": [] }, { "id": "rm_basic_debug_port2", "type": "debug", "z": "rm_basic_tab", "name": "Port 2: Parent Registration", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "x": 1040, "y": 420, "wires": [] } ]