Configuring IOT2040 Node-RED as OPC UA Server: Flow Guide

David Krause11 min read
OPC / OPC UASiemensTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview

The Siemens SIMATIC IOT2040 is an industrial IoT gateway designed for DIN-rail mounting inside control cabinets. Based on an Intel Quark X1020 (x86, single-core, 400 MHz) platform with 1 GB DDR3 RAM and 4 GB on-board eMMC flash, the IOT2040 runs a hardened Yocto-based Linux distribution (Siemens Industrial OS, formerly "Example Industrial OS Image") that supports the Node-RED low-code environment out of the box.

Because Node-RED is delivered as a system service on the IOT2040 firmware image, the device can be turned into a fully functional OPC UA Server with a few flow edits and a single npm install. The reference architecture described here uses the Siemens-maintained node-red-contrib-iiot-opcua package and exposes the following capability set to any OPC UA client on the plant network:

  • OPC UA server endpoint with configurable user authentication
  • Browseable address space, including the ability to add and delete folders at runtime
  • Add/remove variables under those folders at runtime
  • Read, subscribe, and write values from a Node-RED Dashboard UI
  • Remote restart of the OPC UA server from the Dashboard

The flow described was authored in the Siemens Italy RC-IT DF FA AS IPC department and is fully compatible with Node-RED > 0.17.5. This article generalises the flow, hardens it for production use, and adds the diagnostics steps the original forum thread did not cover.

Successor product: The IOT2040 was superseded by the SIMATIC IOT2050 (Article No. 6ES7647-0BA00-0YA2) and the IOT2050 Advanced. New deployments should evaluate the IOT2050 line; however, the Node-RED + OPC UA pattern is portable between the two families.

Hardware Prerequisites

The minimum hardware configuration is the IOT2040 with a bootable SD card and at least one Ethernet network attached to the plant or office LAN. Confirm the following before installing software:

Item Specification Notes
Article number (IOT2040) 6ES7647-0KA01-0AX2 Standard model with SD card slot
CPU Intel Quark X1020 (x86), 400 MHz Single core, 32-bit
RAM 1 GB DDR3 Non-expandable
Storage 4 GB eMMC + SD card slot Industrial SD card recommended
Network 2 × 10/100 Mbps Ethernet X1, X2 connectors; X1 = LAN
Serial 1 × RS-232, 1 × RS-485 Not used by Node-RED flow
USB 2 × USB 2.0 For keyboard during commissioning
Power supply 24 V DC ± 20% Terminal block on bottom
Operating temperature 0 °C to 50 °C Vertical mounting required
Protection class IP20 Indoor cabinet installation

Refer to the SIMATIC IOT2040 operating instructions (Siemens Support entry ID 109741654) for mechanical and electrical installation details.

Software Prerequisites

Component Tested Version Recommended Minimum
Siemens Industrial OS V2.x (Yocto Linux) V2.4.0
Node.js 0.10.x (legacy) 14 LTS or 16 LTS for new installs
Node-RED > 0.17.5 3.1.0
node-red-contrib-iiot-opcua 4.x (legacy) 5.x (last "iiot" release)
node-red-dashboard 2.x 3.x
Package naming change: The original Siemens package node-red-contrib-iiot-opcua is no longer the actively maintained branch. New deployments on current Node.js should use the successor package node-red-contrib-opcua v0.2.x (same authors, same JSON I/O, renamed namespace to opcua-). The flow topology below is identical for both packages.

Install Node-RED, the OPC UA package, and the dashboard package:

  1. Connect to the IOT2040 over SSH (default user root, no password on factory image) or via the USB-to-UART debug port.
  2. Update the package index: opkg update
  3. Install Node-RED and its dependencies: opkg install nodejs node-red
  4. Install the OPC UA nodes globally:
    npm install -g node-red-contrib-iiot-opcua
    (alternatively npm install -g node-red-contrib-opcua for the current branch)
  5. Install the dashboard nodes: npm install -g node-red-dashboard
  6. Restart Node-RED: /etc/init.d/node-red restart

After restart, confirm the OPC UA nodes are loaded by browsing to http://<iot2040-ip>:1880 and confirming that the opcua section appears in the node palette on the left.

Network Topology

The IOT2040 sits at the boundary between the field/PLC network and the office network. OPC UA clients on either side can connect, but the typical deployment keeps the IOT2040 on the same subnet as the SCADA server.

S7-1500 / S7-1200 PLC (DB tags) ProfiNet / S7 SIMATIC IOT2040 Node-RED 3.1.0 node-red-contrib-opcua OPC UA Server :4840 SCADA / WinCC OPC UA Client TIA / WinCC V18 Operator Panel Node-RED Dashboard :1880/ui Read / Write / Browse S7 / ProfiNet OPC UA TCP HTTP Dashboard

Step 1 - Configure the OPC UA Server Endpoint

From the Node-RED editor, double-click any opcua server node to open its configuration panel. Create a new OPCUA Server Endpoint with the parameters below.

Parameter Value Comment
Endpoint opc.tcp://0.0.0.0:4840 Bind on all interfaces
Endpoint name IIoT_OPCUA_Server Shown to clients on Browse
Security mode NONE / SIGN / SIGNANDENCRYPT Use NONE only for lab
Security policy NONE / Basic128Rsa15 / Basic256Sha256 Basic256Sha256 for production
Authentication Username / Password Stored in flow credentials
User opcuauser Change before deployment
Password Type a strong password > 12 chars Stored in env or vault
Certificate directory /home/root/.node-red/opcua Created on first start
Server certificate Self-signed (default) Replace with CA-signed for prod

For the initial commissioning keep Security mode = NONE and disable the certificate check. Tighten the policy once the connection is verified, because the self-signed certificate generated on first launch has to be trusted by every client.

Step 2 - Build the Address Space

The reference flow uses the dynamic address-space pattern. Three Folder objects and several variables are created on startup. A user can later add and remove folders and variables from the Dashboard.

RootFolder (ns=0;i=84) Devices (Folder) PLC1 (Folder) PLC2 (Folder) IO2040 (Folder) Temperature Pressure Status

Drop an inject node set to fire once at start and wire it to a function node that builds the parent NodeId for the dynamic folder:

// Build a string NodeId for a dynamic folder
msg.payload = {
  nodeId:  "ns=1;s=Devices",
  browseName: "Devices",
  type: "folder"
};
return msg;

Wire the output of this function into an OPCUA-Folder node from the palette. The folder node takes the configuration endpoint from Step 1, and the NodeId from msg.payload.nodeId. Repeat the pattern to create the inner folders (PLC1, PLC2, IO2040).

Step 3 - Add Variables Under a Folder

Variables are added with the OPCUA-Variable node. Three pieces of metadata are required: the nodeId of the variable, its dataType, and the initial value. A useful production pattern is to source all of them from upstream nodes so that a single function can parameterise the entire address space.

// Add a new Double variable under PLC1
msg.payload = {
  nodeId:   "ns=1;s=PLC1.Temperature",
  browseName: "Temperature",
  type:     "variable",
  dataType: "Double",
  value:    21.5
};
return msg;

Supported dataType values include Boolean, SByte, Byte, Int16, Int32, Int64, UInt16, UInt32, UInt64, Float, Double, String, DateTime, Guid, and ByteString. Pick the smallest type that still covers the engineering range; the IOT2040 only has 1 GB RAM and millions of subscribed doubles will strain the heap.

Step 4 - Read, Subscribe, and Write Variables

Three OPC UA nodes cover the read, subscribe, and write operations. Each takes the same nodeId string and an action property:

  • OPCUA-Read — one-shot read triggered by an upstream inject or dashboard button.
  • OPCUA-Subscribe — registers a monitored item; the server pushes value changes at the configured sampling interval.
  • OPCUA-Write — writes msg.payload.value into the target NodeId.

Set the samplingInterval on the Subscribe node to 500 ms for dashboard gauges, 100 ms for high-speed process data, or 5000 ms for energy and counter tags. Setting the interval below 100 ms on the Quark CPU will quickly saturate the OPC UA stack.

Step 5 - Build the Dashboard UI

Drop a UI Tab and a UI Group named OPCUA Browser. The Browse command is wired as follows:

  1. UI Button (label: Browse) → function that sets msg.payload = { nodeId: "ns=0;i=84" } → OPCUA-Browser node → UI Table.
  2. UI Form with two text inputs (Folder name, Variable name) → function that concatenates the NodeId → OPCUA-Folder and OPCUA-Variable nodes.
  3. UI Slider (0–100) → OPCUA-Write for live tuning.
  4. UI Button (label: Restart Server) → OPCUA-Server node with action: "restart".

Open the dashboard at http://<iot2040-ip>:1880/ui. You should see the address-space table populate within a second of pressing Browse.

Step 6 - Authentication

User authentication is mandatory before exposing the server on a plant network. Configure it on the OPCUA Server endpoint as follows:

  1. Enable User Identity Token → Username / Password on the server endpoint.
  2. Define the credentials in a separate file (for example /home/root/.node-red/opcua/users.json) and reference it from the server config node with an env lookup:
OPCUA_USER=opcuauser
OPCUA_PASS=<strong-password-here>
  1. In the server config node set User = ${OPCUA_USER} and Password = ${OPCUA_PASS}.
  2. Set the file permissions to chmod 600 /home/root/.node-red/opcua/users.json.
Do not hard-code production credentials in the flow JSON. Anyone with read access to flows_cred.json or flows.json on the IOT2040 can extract them.

Troubleshooting Matrix

Symptom Likely Cause Resolution
UI shows "Session is not ready to browse" Browser fired before the server finished initialising, or the session was reset by a server restart Use a Complete Deploy and reboot the IOT2040. Ensure the Browse button is only enabled after the first Server Started status message is received. Add a 2-second delay in the function node that wires the Browse button.
Client cannot connect, log shows BAD_TIMEOUT Firewall on port 4840, or wrong IP Open TCP/4840 inbound. Verify with nc -zv <ip> 4840 from the client host.
BAD_SECURITY_POLICY_REJECTED Client does not trust the server certificate Copy the server certificate from /home/root/.node-red/opcua/certs/ to the client trust store, or enable the trust-on-first-use option during commissioning only.
BAD_USER_ACCESS_DENIED Wrong credentials or no auth configured Verify the user in the server config node; check users.json permissions.
Server restarts every few minutes Out of memory (Quark only has 1 GB) Reduce subscription count, raise sampling interval, disable verbose --inspect flag, and disable Chromium hardware accel in Node-RED settings.
Node-RED won't start after install Node.js / Node-RED version mismatch Confirm node -v is in the supported range for the OPC UA package version. With Node-RED 3.1.0, Node 14 or 16 is required.
Inject at startup does not fire Deploy mode is set to "Modified Flows" Switch to "Full Deploy" and reboot the gateway. The original Siemens author flagged this exact bug.
Dashboard widgets stuck at "Connecting..." UI not enabled or wrong port Confirm the httpNodeRoot and httpAdminRoot in settings.js. Default UI port is 1880/ui.

Verification Procedure

  1. Open the Node-RED editor and check the OPCUA Server node. Its status indicator should show a green dot labelled active.
  2. Open a terminal on any client machine with opcua-client or Prosys OPC UA Browser installed, and connect to opc.tcp://<iot2040-ip>:4840.
  3. Browse to Root → Objects → Devices → PLC1. Confirm that Temperature, Pressure, and Status are present and writable.
  4. Subscribe to Temperature at 1000 ms. Move the Dashboard slider connected to Setpoint and confirm the subscribed value updates within one cycle.
  5. Press the Restart Server button. Within 5 seconds the status indicator should briefly go red, then green again with the same address space.
  6. Tail the server log: node-red-log -f | grep -i opcua. There should be no ERROR lines and no Unhandled rejection entries.

Performance and Limits

Metric Typical on IOT2040 Notes
Concurrent client sessions 10–15 More sessions require IOT2050
Monitored items per session 200 Hard ceiling is the OPC UA stack default
Minimum sampling interval 100 ms Below 50 ms CPU saturates
Address-space size 5,000 nodes Linear with RAM; 1 GB ceiling
CPU under load 35–60% Measured with 100 items @ 500 ms
OPC UA throughput ~2,500 value updates / s Single client, Float, Binary encoding

For workloads above these numbers, plan a migration to the SIMATIC IOT2050 (ARM Cortex-A53 quad-core, 1 GB / 2 GB RAM options) which runs the same Node-RED image and the same flow file. No code changes are required.

Migration to node-red-contrib-opcua (current branch)

If the IOT2040 firmware has been updated to Node-RED 3.x and Node.js 14/16, the legacy node-red-contrib-iiot-opcua package is no longer installable. The successor package is functionally identical but uses a different configuration namespace:

Legacy node Current node Behaviour
OPCUA-Server opcua-server Endpoint host/port unchanged
OPCUA-Folder opcua-folder Same msg.payload.nodeId contract
OPCUA-Variable opcua-variable dataType names unchanged
OPCUA-Read opcua-read msg.topic must contain action
OPCUA-Subscribe opcua-subscribe samplingInterval in ms
OPCUA-Write opcua-write msg.payload.value to write
OPCUA-Browser opcua-browser No change in API

The flow JSON can be migrated with a global find-and-replace on the node type strings; the underlying node-opcua client library is the same in both packages.

Security Hardening Checklist

  • Replace the self-signed certificate with a CA-signed certificate from the plant PKI.
  • Set Security mode to SIGNANDENCRYPT and Security policy to Basic256Sha256.
  • Set the IOT2040 to listen on a single internal interface (e.g. opc.tcp://192.168.10.50:4840) instead of 0.0.0.0.
  • Disable the Node-RED editor (httpAdminRoot) on the same port and only enable the dashboard (httpNodeRoot) for read-only users.
  • Add adminAuth with bcrypt-hashed credentials to settings.js to require login before the editor or dashboard is reachable.
  • Enable the Siemens IOT2040 firewall (iptables) and only allow TCP 4840 from the SCADA subnet.

Refer to the OPC UA Security specification for the complete list of recommended settings.

FAQ

What OPC UA package should I install on a current IOT2040 firmware?

Use node-red-contrib-opcua v0.2.x on Node-RED 3.1.0 and Node.js 14 or 16. The legacy node-red-contrib-iiot-opcua only installs on Node.js 0.10 and Node-RED 0.17.x; the new package is a drop-in replacement that uses the same flow JSON contract.

How do I fix the "Session is not ready to browse" error in the Dashboard?

The OPC UA session is not yet established when the Browse button is pressed. Switch to a Full Deploy, reboot the IOT2040, and gate the Browse button on the Server Started status message from the OPCUA-Server node. Adding a 2-second delay in the function node that calls the browser is the most reliable workaround.

Can the IOT2040 host an OPC UA server and an OPC UA client at the same time?

Yes. Add a second OPCUA-Client endpoint config node pointing at the S7-1500 (using the S7 node set) and a third OPCUA-Read/OPCUA-Subscribe set. The Quark CPU can sustain roughly 200 monitored items in this mode, but watch RAM usage and avoid 100 ms sampling intervals on more than 50 items.

What is the maximum address-space size on the IOT2040?

Empirically about 5,000 nodes before Node-RED starts swapping. The OPC UA stack itself is bounded by the 1 GB RAM ceiling and the Node.js default heap of 1.5 GB. For larger spaces, use the IOT2050 with 2 GB RAM or move the server to an industrial PC.

Why does the IOT2040 not retain variables across power cycles?

The Node-RED flow in this article uses volatile variables stored only in RAM. To persist values, add a file or context node that serialises flow.context to /home/root/.node-red/context/ on every write, or wire each OPCUA-Variable node to a function that calls global.set() with the latest value and write to eMMC every N seconds.

Back to blog