Wire Galaxy security_classification to OPC UA AccessLevel (ReadOnly for SecuredWrite/VerifiedWrite/ViewOnly). Use deployed package chain for attribute queries to exclude undeployed attributes. Group primitive attributes under their parent variable node (merged Variable+Object). Add is_historized and is_alarm detection via HistoryExtension/AlarmExtension primitives. Implement OPC UA HistoryRead backed by Wonderware Historian Runtime database. Implement AlarmConditionState nodes driven by InAlarm with condition refresh support. Add historyread and alarms CLI commands for testing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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|
| (HTTP/JSON) |
+----------------+
Galaxy Repository queries the ZB database for the deployed object hierarchy and attribute definitions, building the OPC UA address space at startup and rebuilding 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.
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)
Build & 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 SecurityPolicy None.
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
Run Tests
dotnet test ZB.MOM.WW.LmxOpcUa.slnx
Configuration
All settings in appsettings.json, overridable via environment variables:
| Section | Key | Default | Description |
|---|---|---|---|
| OpcUa | Port | 4840 | OPC UA server port |
| OpcUa | EndpointPath | /LmxOpcUa | Endpoint path |
| OpcUa | GalaxyName | ZB | Galaxy name (used in namespace URI) |
| OpcUa | MaxSessions | 100 | Maximum concurrent sessions |
| MxAccess | ClientName | LmxOpcUa | MXAccess registration name |
| MxAccess | AutoReconnect | true | Auto-reconnect on disconnect |
| MxAccess | ProbeTag | null | Tag for connection health probing |
| GalaxyRepository | ConnectionString | Server=localhost;Database=ZB;... | ZB database connection |
| GalaxyRepository | ChangeDetectionIntervalSeconds | 30 | Deploy change polling interval |
| Dashboard | Enabled | true | Enable HTTP status dashboard |
| Dashboard | Port | 8081 | Dashboard port |
Project Structure
src/ZB.MOM.WW.LmxOpcUa.Host/
Configuration/ Config binding and validation
Domain/ Interfaces, DTOs, enums, mappers
Metrics/ Performance tracking (rolling P95)
MxAccess/ STA thread, COM interop, subscriptions
GalaxyRepository/ SQL queries, change detection
OpcUa/ Server, node manager, address space
Status/ HTTP dashboard, health checks
OpcUaService.cs Service wiring (startup/shutdown)
Program.cs TopShelf entry point
tests/ZB.MOM.WW.LmxOpcUa.Tests/
Configuration/ Config binding tests
Domain/ Type mapping, quality, error code tests
Metrics/ Performance metrics tests
MxAccess/ STA thread, connection, subscription, R/W tests
GalaxyRepository/ Change detection tests
OpcUa/ Address space build/rebuild, data conversion tests
Status/ Health check, dashboard, web server tests
Wiring/ Component integration tests
EndToEnd/ Full data flow smoke test
tools/opcuacli-dotnet/ OPC UA CLI test tool
gr/ Galaxy repository docs, SQL queries, schema
Data Type Mapping
| Galaxy Type | mx_data_type | OPC UA Type | NodeId |
|---|---|---|---|
| Boolean | 1 | Boolean | i=1 |
| Integer | 2 | Int32 | i=6 |
| Float | 3 | Float | i=10 |
| Double | 4 | Double | i=11 |
| String | 5 | String | i=12 |
| DateTime | 6 | DateTime | i=13 |
| ElapsedTime | 7 | Double (seconds) | i=11 |
| Reference | 8 | String | i=12 |
| Enumeration | 13 | Int32 | i=6 |
| InternationalizedString | 15 | LocalizedText | i=21 |
Array attributes use ValueRank=1 with ArrayDimensions from the Galaxy attribute definition.
Startup Sequence
- Load and validate configuration
- Register
AppDomain.UnhandledExceptionhandler - Create performance metrics
- Connect MXAccess (STA thread + COM registration)
- Start MXAccess monitor loop
- Test Galaxy database connection
- Start OPC UA server with programmatic config
- Query hierarchy + attributes, build address space
- Start change detection polling (rebuilds on deploy)
- Start status dashboard (HTML + JSON + health endpoint)
License
Internal use only.