Files
scadalink-design/docs/test_infra/test_infra_opcua.md
Joseph Doherty efed8352c3 feat(infra): add second OPC UA server instance (opcua2) on port 50010
Enables multi-server testing with independent state. Both instances
share the same nodes.json tag config. Updated all infra documentation.
2026-03-22 07:31:56 -04:00

4.4 KiB

Test Infrastructure: OPC UA Server

Overview

The test OPC UA server uses Azure IoT OPC PLC, a simulated OPC UA server that generates realistic data. It is configured with custom nodes that match ScadaLink attribute patterns.

Image & Ports

Two identical OPC UA server instances run with the same tag configuration, on different ports:

Instance OPC UA Endpoint Web UI Container
opcua opc.tcp://localhost:50000 http://localhost:8080 scadalink-opcua
opcua2 opc.tcp://localhost:50010 http://localhost:8081 scadalink-opcua2
  • Image: mcr.microsoft.com/iotedge/opc-plc:latest

Startup Flags

--autoaccept            Accept all client certificates
--unsecuretransport     Enable plain (non-TLS) OPC UA connections for dev tools
--sph                   Show PLC heartbeat on console
--sn=5 --sr=10 --st=uint   5 slow-changing nodes (10s cycle, uint)
--fn=5 --fr=1 --ft=uint    5 fast-changing nodes (1s cycle, uint)
--gn=5                      5 stepping nodes
--nf=/app/config/nodes.json Custom node definitions
--pn=50000                  Listen port

Custom Nodes

The file infra/opcua/nodes.json defines a single ConfigFolder object (not an array) with a root "ScadaLink" folder containing four equipment subfolders. Tags match typical ScadaLink instance attribute patterns:

Folder Tags Types
Motor Speed, Temperature, Current, Running, FaultCode Double, Boolean, UInt32
Pump FlowRate, Pressure, Running Double, Boolean
Tank Level, Temperature, HighLevel, LowLevel Double, Boolean
Valve Position, Command Double, UInt32
JoeAppEngine BTCS, AlarmCntsBySeverity, Scheduler/ScanTime String, Int32[], DateTime

All custom nodes hold their initial/default values (0 for numerics, false for booleans, empty for strings, epoch for DateTime) until written. OPC PLC's custom node format does not support random value generation for these nodes.

Custom nodes live in namespace 3 (http://microsoft.com/Opc/OpcPlc/). Node IDs follow the pattern ns=3;s=<Folder>.<Tag> (e.g., ns=3;s=Motor.Speed). Nested folders use dot notation: ns=3;s=JoeAppEngine.Scheduler.ScanTime.

The browse path from the Objects root is: OpcPlc > ScadaLink > Motor|Pump|Tank|Valve|JoeAppEngine.

Verification

  1. Check both containers are running:
docker ps --filter name=scadalink-opcua
  1. Verify both OPC UA endpoints using any OPC UA client (e.g., UaExpert, opcua-commander):
# Using opcua-commander (npm install -g opcua-commander)
opcua-commander -e opc.tcp://localhost:50000
opcua-commander -e opc.tcp://localhost:50010
  1. Check the web UIs at http://localhost:8080 (opcua) and http://localhost:8081 (opcua2) for server status and node listing.

CLI Tool

The infra/tools/opcua_tool.py script provides a convenient CLI for interacting with the OPC UA server.

Install dependencies (one-time):

pip install -r infra/tools/requirements.txt

Commands:

# Check server status, namespaces, and endpoints
python infra/tools/opcua_tool.py check

# Browse the Objects folder (top-level)
python infra/tools/opcua_tool.py browse

# Browse a specific equipment folder
python infra/tools/opcua_tool.py browse --path "3:OpcPlc.3:ScadaLink.3:Motor"

# Read a tag value
python infra/tools/opcua_tool.py read --node "ns=3;s=Motor.Speed"

# Write a value to a tag
python infra/tools/opcua_tool.py write --node "ns=3;s=Motor.Running" --value true --type Boolean

# Monitor value changes for 15 seconds
python infra/tools/opcua_tool.py monitor --nodes "ns=3;s=Motor.Speed,ns=3;s=Pump.FlowRate" --duration 15

Use --endpoint to override the default endpoint (opc.tcp://localhost:50000). For the second instance:

python infra/tools/opcua_tool.py --endpoint opc.tcp://localhost:50010 check
python infra/tools/opcua_tool.py --endpoint opc.tcp://localhost:50010 browse --path "3:OpcPlc.3:ScadaLink.3:Motor"

Run with --help for full usage.

  • Data Connection Layer — connect to this server to test OPC UA subscription, read/write, and reconnection behavior.
  • Site Runtime / Instance Actors — deploy instances with tag mappings pointing at these nodes.
  • Template Engine — design templates with attributes matching the Motor/Pump/Tank/Valve folder structure.