Node-RED Integration

Creating SCADA-like user interfaces for Node-RED with SCADAvis.io

Integration Guide

1. Add the UI-Builder Package

Add the UI-Builder package to enhance Node-RED with powerful UI capabilities:

  • Install "node-red-contrib-uibuilder" package
  • Add the uibuilder node to your flow

2. Configure UI-Builder

Edit the UI-Builder source files:

  1. Double click the node
  2. Click the "Edit Source Files" button
  3. Replace index.html with the code below
index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>SCADAvis.io Node-RED Example</title>
  <link rel="stylesheet" href="../uibuilder/vendor/normalize.css/normalize.css">
  <link rel="stylesheet" href="./index.css">
  <script src="https://scadavis.io/synoptic/synopticapi.js"></script>
</head>
<body>
  <div id="app">
    <h1>SCADAvis.io Node-RED Integration</h1>
    <div id="status">
      <p>UIBuilder Version: <span id="feVersion"></span></p>
      <p>Connection Status: <span id="socketConnectedState"></span></p>
      <p>Messages Received: <span id="msgsReceived"></span></p>
    </div>
  </div>

  <div id="scadavis_display1"></div>

  <script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
  <script src="../uibuilder/vendor/jquery/dist/jquery.min.js"></script>
  <script src="./uibuilderfe.min.js"></script>

  <script>
    var substationsynoptic = new scadavis({
      container: "scadavis_display1",
      iframeparams: 'frameborder="0" height="500" width="1000"',
      svgurl: "https://raw.githubusercontent.com/riclolsen/displayfiles/master/kor1.svg"
    });
    substationsynoptic.zoomTo(0.5);

    // Event handling
    substationsynoptic.on("click", function (event, tag) {
      var v = substationsynoptic.getValue(tag);
      
      if (event.currentTarget.id === "TAPUP")
        substationsynoptic.setValue(tag, v + 1, false, false);
      else if (event.currentTarget.id === "TAPDOWN")
        substationsynoptic.setValue(tag, v - 1, false, false);

      if (event.currentTarget.id === "XCBROPEN")
        substationsynoptic.setValue(tag, false, false, false);
      else if (event.currentTarget.id === "XCBRCLOSE")
        substationsynoptic.setValue(tag, true, false, false);

      if (v === true)
        substationsynoptic.setValue(tag, false, false, false);
      else if (v === false)
        substationsynoptic.setValue(tag, true, false, false);
    });

    // Data handling
    uibuilder.onChange('msg', function (newVal) {
      for (i = 0; i < newVal.payload.length; i++)
        substationsynoptic.storeValue(newVal.payload[i].tag, newVal.payload[i].value);
      substationsynoptic.updateValues();
    });

    uibuilder.start();
  </script>
</body>
</html>

3. Configure Dependencies

  • Remove or empty the original index.js file
  • Use "Manage front-end libraries" to add jQuery

4. Set Up Data Flow

Create a data pipeline in Node-RED:

  • Add an Inject node to your flow
  • Connect it to the UI Builder input
  • Configure the Inject to JSON payload
  • Add tagged data payload as in this example below.
Example Payload

 [{  "tag": "KOR1TR1--YTAP",
        "value": 9
    },{ "tag": "KOR1XSWI1",
        "value": false
    },{ "tag": "KOR1XSWI2",
        "value": true
    },{ "tag": "KOR1XSWI4",
        "value": true
    },{ "tag": "KOR1XSWI6",
        "value": true
    },{ "tag": "KOR1XSWI8",
        "value": true
    },{ "tag": "KOR1XSWI10",
        "value": false
    },{ "tag": "KOR1XSWI12",
        "value": true
    },{ "tag": "KOR1XSWI14",
        "value": true
    },{ "tag": "KOR1XSWI16",
        "value": false
    },{ "tag": "KOR1XSWI18",
        "value": true
    },{ "tag": "KOR1XSWI20",
        "value": true
    },{ "tag": "KOR1XSWI22",
        "value": false
    },{ "tag": "KOR1XSWI48",
        "value": true
    },{ "tag": "KOR1XSWI50",
        "value": true
    },{ "tag": "KOR1XSWI46",
        "value": false
    },{ "tag": "KOR1XSWI24",
        "value": false
    },{ "tag": "KOR1XSWI26",
        "value": true
    },{ "tag": "KOR1XSWI28",
        "value": false
    },{ "tag": "KOR1XSWI30",
        "value": true
    },{ "tag": "KOR1XSWI32",
        "value": true
    },{ "tag": "KOR1XSWI34",
        "value": true
    },{ "tag": "KOR1XSWI36",
        "value": true
    },{ "tag": "KOR1XSWI38",
        "value": false
    },{ "tag": "KOR1XSWI40",
        "value": true
    },{ "tag": "KOR1XSWI42",
        "value": true
    },{ "tag": "KOR1XSWI44",
        "value": false
    },{ "tag": "KOR1TR1-2XCBR5201",
        "value": true
    },{ "tag": "KOR1XCBR2",
        "value": true
    },{ "tag": "KOR1XCBR3",
        "value": true
    },{ "tag": "KOR1XCBR4",
        "value": true
    },{ "tag": "KOR1XCBR8",
        "value": true
    },{ "tag": "KOR1XCBR5",
        "value": true
    },{ "tag": "KOR1XCBR2401",
        "value": false
    },{ "tag": "KOR1XCBR6",
        "value": true
    },{ "tag": "KOR1AL11TC",
        "value": false
    },{ "tag": "KOR1AL11RREC",
        "value": true
    },{ "tag": "KOR1AL11TC",
        "value": true
    },{ "tag": "KOR1AL11PSTI",
        "value": true
    },{ "tag": "KOR1AL12TC",
        "value": false
    },{ "tag": "KOR1AL12RREC",
        "value": true
    },{ "tag": "KOR1AL12TC",
        "value": true
    },{ "tag": "KOR1AL12PSTI",
        "value": true
    },{ "tag": "KOR1AL13TC",
        "value": false
    },{ "tag": "KOR1AL13RREC",
        "value": true
    },{ "tag": "KOR1AL13TC",
        "value": true
    },{ "tag": "KOR1AL13PSTI",
        "value": true
    },{ "tag": "KOR1AL14TC",
        "value": false
    },{ "tag": "KOR1AL14RREC",
        "value": true
    },{ "tag": "KOR1AL14TC",
        "value": true
    },{ "tag": "KOR1AL14PSTI",
        "value": true
    },{ "tag": "KOR1AL15TC",
        "value": false
    },{ "tag": "KOR1AL15RREC",
        "value": true
    },{ "tag": "KOR1AL15TC",
        "value": true
    },{ "tag": "KOR1AL15PSTI",
        "value": true
    },{ "tag": "KOR1AL16TC",
        "value": false
    },{ "tag": "KOR1AL16RREC",
        "value": true
    },{ "tag": "KOR1AL16PSTI",
        "value": true
    },{ "tag": "KOR1AL17TC",
        "value": true
    },{ "tag": "KOR1AL17PSTI",
        "value": true
    },{ "tag": "KOR1AL17RREC",
        "value": true
    },{ "tag": "KOR1ALTFTC",
        "value": true
    },{ "tag": "KOR1ALTFPSTI",
        "value": true
    },{ "tag": "KOR1ALTFRREC",
        "value": true
    },{ "tag": "KOR1AL11MW",
        "value": 5
    },{ "tag": "KOR1AL12MW",
        "value": 7
    },{ "tag": "KOR1AL13MW",
        "value": 8
    },{ "tag": "KOR1AL14MW",
        "value": 4
    },{ "tag": "KOR1AL15MW",
        "value": 5
    },{ "tag": "KOR1AL16MW",
        "value": 12
    },{ "tag": "KOR1AL17MW",
        "value": 10
    },{ "tag": "KOR1AL11MVAR",
        "value": 0.3
    },{ "tag": "KOR1AL12MVAR",
        "value": 0.4
    },{ "tag": "KOR1AL13MVAR",
        "value": 0.5
    },{ "tag": "KOR1AL14MVAR",
        "value": 0.2
    },{ "tag": "KOR1AL15MVAR",
        "value": 0.1
    },{ "tag": "KOR1AL16MVAR",
        "value": 0.2
    },{ "tag": "KOR1AL17MVAR",
        "value": 0.3
    },{ "tag": "KOR1TR1MW",
        "value": 50
    },{ "tag": "KOR1TR1MVAR",
        "value": 1.5
    },{ "tag": "KOR1KV230",
        "value": 231
    },{ "tag": "KOR1KV23",
        "value": 23.6
    }]                  

5. Deploy and Test

  1. Deploy your Node-RED flow
  2. Open UI-Builder page at http://localhost:1880/uibuilder
  3. Click the Inject button to send data to the visualization

6. Develop your own displays

Change the code and use the SCADAvis.io Synoptic Editor to create new displays.