Joseph Doherty afd6c33d9d Add client-side failover to CLI tool for redundancy testing
All commands gain --failover-urls (-F) to specify alternate endpoints.
Short-lived commands try each URL in order on initial connect. The
subscribe command monitors KeepAlive and automatically reconnects to
the next available server, re-creating the subscription on failover.
Verified with live service start/stop: primary down triggers failover
to secondary, primary restart allows failback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 14:41:06 -04:00

LmxOpcUa Server

OPC UA server on .NET Framework 4.8 (x86) that exposes AVEVA System Platform (Wonderware) Galaxy tags via the MXAccess toolkit. Mirrors the Galaxy object hierarchy as an OPC UA address space, translating between contained-name browse paths and tag-name runtime references.

Architecture

                                    OPC UA Clients
                                         |
                                         v
+-----------------+     +------------------+     +-----------------+
| Galaxy Repo DB  |---->|   OPC UA Server  |<--->| MXAccess Client |
|   (SQL Server)  |     | (address space)  |     | (STA + COM)     |
+-----------------+     +------------------+     +-----------------+
                                |                        |
                        +-------+--------+     +---------+---------+
                        | Status Dashboard|     | Historian Runtime |
                        |  (HTTP/JSON)   |     |   (SQL Server)    |
                        +----------------+     +-------------------+

Galaxy Repository queries the ZB database for the deployed object hierarchy and attribute definitions, building the OPC UA address space at startup and incrementally syncing on deploy changes.

MXAccess Client connects to the Galaxy runtime via COM interop on a dedicated STA thread with a Win32 message pump. Handles subscriptions, read/write, reconnection, and probe-based health monitoring.

OPC UA Server exposes the hierarchy as browse nodes (folders for areas, objects for containers) with variable nodes for each attribute. Clients browse using contained names but reads/writes translate to tag_name.AttributeName for MXAccess.

Historian Runtime provides historical data access via SQL queries against the Wonderware Historian Runtime database, serving OPC UA HistoryRead requests for raw and aggregate data.

Contained Name vs Tag Name

Browse Path (contained names) Runtime Reference (tag name)
TestMachine_001/DelmiaReceiver/DownloadPath DelmiaReceiver_001.DownloadPath
TestMachine_001/MESReceiver/MoveInBatchID MESReceiver_001.MoveInBatchID

Quick Start

Prerequisites

  • .NET Framework 4.8 SDK
  • AVEVA System Platform with ArchestrA Framework installed
  • Galaxy repository database (SQL Server, Windows Auth)
  • MXAccess COM registered (LMXProxy.LMXProxyServer)
  • Wonderware Historian (optional, for historical data access)

Build and run

dotnet restore ZB.MOM.WW.LmxOpcUa.slnx
dotnet build ZB.MOM.WW.LmxOpcUa.slnx
dotnet run --project src/ZB.MOM.WW.LmxOpcUa.Host

The server starts on opc.tcp://localhost:4840/LmxOpcUa with the None security profile by default. Configure Security.Profiles in appsettings.json to enable Basic256Sha256-Sign or Basic256Sha256-SignAndEncrypt for transport security. See Security Guide.

Install as Windows service

cd src/ZB.MOM.WW.LmxOpcUa.Host/bin/Debug/net48
ZB.MOM.WW.LmxOpcUa.Host.exe install
ZB.MOM.WW.LmxOpcUa.Host.exe start

Test with CLI tool

# Connect
dotnet run --project tools/opcuacli-dotnet -- connect -u opc.tcp://localhost:4840/LmxOpcUa

# Browse Galaxy hierarchy
dotnet run --project tools/opcuacli-dotnet -- browse -u opc.tcp://localhost:4840/LmxOpcUa -n "ns=1;s=ZB" -r -d 5

# Read a tag
dotnet run --project tools/opcuacli-dotnet -- read -u opc.tcp://localhost:4840/LmxOpcUa -n "ns=1;s=TestMachine_001.MachineID"

# Write a tag
dotnet run --project tools/opcuacli-dotnet -- write -u opc.tcp://localhost:4840/LmxOpcUa -n "ns=1;s=TestChildObject.TestString" -v "Hello"

# Subscribe to changes
dotnet run --project tools/opcuacli-dotnet -- subscribe -u opc.tcp://localhost:4840/LmxOpcUa -n "ns=1;s=TestChildObject.TestInt" -i 500

# Read historical data
dotnet run --project tools/opcuacli-dotnet -- historyread -u opc.tcp://localhost:4840/LmxOpcUa -n "ns=1;s=TestMachine_001.TestHistoryValue" --start "2026-03-25" --end "2026-03-30"

# Subscribe to alarm events
dotnet run --project tools/opcuacli-dotnet -- alarms -u opc.tcp://localhost:4840/LmxOpcUa -n "ns=1;s=TestMachine_001" --refresh

Run tests

dotnet test ZB.MOM.WW.LmxOpcUa.slnx

Project Structure

src/ZB.MOM.WW.LmxOpcUa.Host/
    Configuration/       Config binding and validation
    Domain/              Interfaces, DTOs, enums, mappers
    Historian/           Wonderware Historian data source
    Metrics/             Performance tracking (rolling P95)
    MxAccess/            STA thread, COM interop, subscriptions
    GalaxyRepository/    SQL queries, change detection
    OpcUa/               Server, node manager, address space, alarm conditions, diff
    Status/              HTTP dashboard, health checks
    OpcUaService.cs      Service wiring (startup/shutdown)
    Program.cs           TopShelf entry point

tests/ZB.MOM.WW.LmxOpcUa.Tests/
    Domain/              Type mapping, security classification, quality tests
    Historian/           Historian quality mapping tests
    Integration/         Access levels, historizing, alarm events, incremental sync
    Metrics/             Performance metrics tests
    MxAccess/            STA thread, connection, subscription, R/W tests
    GalaxyRepository/    Change detection tests
    OpcUa/               Address space build/rebuild, diff, data conversion tests
    Wiring/              Component integration tests

tools/opcuacli-dotnet/   OPC UA CLI test tool
gr/                      Galaxy repository docs, SQL queries, schema

Component Documentation

Component Description
OPC UA Server Endpoint, sessions, security policy, server lifecycle
Address Space Hierarchy nodes, variable nodes, primitive grouping, NodeId scheme
Galaxy Repository SQL queries, deployed package chain, change detection
MXAccess Bridge STA thread, COM interop, subscriptions, reconnection
Data Type Mapping Galaxy → OPC UA types, arrays, security classification
Read/Write Operations Value reads, writes, access level enforcement, array element writes
Subscriptions Ref-counted MXAccess subscriptions, data change dispatch
Alarm Tracking AlarmConditionState nodes, InAlarm monitoring, event reporting
Historical Data Access Historian data source, HistoryReadRaw, HistoryReadProcessed
Incremental Sync Diff computation, subtree teardown/rebuild, subscription preservation
Configuration appsettings.json binding, feature flags, validation
Status Dashboard HTTP server, health checks, metrics reporting
Service Hosting TopShelf, startup/shutdown sequence, error handling
CLI Tool Connect, browse, read, write, subscribe, historyread, alarms commands
Security Transport security profiles, certificate trust, production hardening
Redundancy Non-transparent warm/hot redundancy, ServiceLevel, paired deployment

License

Internal use only.

Description
No description provided
Readme 11 MiB
Languages
C# 94.6%
TSQL 4.9%
Python 0.3%
Batchfile 0.2%