Enables multi-server testing with independent state. Both instances share the same nodes.json tag config. Updated all infra documentation.
112 lines
4.4 KiB
Markdown
112 lines
4.4 KiB
Markdown
# Test Infrastructure: OPC UA Server
|
|
|
|
## Overview
|
|
|
|
The test OPC UA server uses [Azure IoT OPC PLC](https://github.com/Azure-Samples/iot-edge-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:
|
|
|
|
```bash
|
|
docker ps --filter name=scadalink-opcua
|
|
```
|
|
|
|
2. Verify both OPC UA endpoints using any OPC UA client (e.g., UaExpert, opcua-commander):
|
|
|
|
```bash
|
|
# Using opcua-commander (npm install -g opcua-commander)
|
|
opcua-commander -e opc.tcp://localhost:50000
|
|
opcua-commander -e opc.tcp://localhost:50010
|
|
```
|
|
|
|
3. 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):
|
|
```bash
|
|
pip install -r infra/tools/requirements.txt
|
|
```
|
|
|
|
**Commands**:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
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.
|
|
|
|
## Relevance to ScadaLink Components
|
|
|
|
- **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.
|