Provides technical documentation covering OPC UA server, address space, Galaxy repository, MXAccess bridge, data types, read/write, subscriptions, alarms, historian, incremental sync, configuration, dashboard, service hosting, and CLI tool. Updates README with component documentation table. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
246 lines
12 KiB
Markdown
246 lines
12 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
dotnet test ZB.MOM.WW.LmxOpcUa.slnx
|
|
```
|
|
|
|
## Security Classification
|
|
|
|
Galaxy attributes carry a `security_classification` that controls OPC UA write access. The server maps these to `AccessLevel` on each variable node:
|
|
|
|
| Classification | Galaxy Level | OPC UA Access |
|
|
|---|---|---|
|
|
| 0 | FreeAccess | ReadWrite |
|
|
| 1 | Operate | ReadWrite |
|
|
| 2 | SecuredWrite | ReadOnly |
|
|
| 3 | VerifiedWrite | ReadOnly |
|
|
| 4 | Tune | ReadWrite |
|
|
| 5 | Configure | ReadWrite |
|
|
| 6 | ViewOnly | ReadOnly |
|
|
|
|
See `gr/data_type_mapping.md` for the full mapping table.
|
|
|
|
## Alarm Tracking
|
|
|
|
When `AlarmTrackingEnabled` is true, the server creates `AlarmConditionState` nodes for Galaxy attributes with `AlarmExtension` primitives. It auto-subscribes to each alarm's `InAlarm` tag and reports OPC UA alarm events on state transitions:
|
|
|
|
- `InAlarm` TRUE → alarm active event (severity from `Priority`, message from `DescAttrName`)
|
|
- `InAlarm` FALSE → alarm cleared event
|
|
- Condition refresh reports all currently retained alarms to newly subscribing clients
|
|
|
|
## Historical Data Access
|
|
|
|
When `Historian.Enabled` is true, the server handles OPC UA `HistoryRead` requests by querying the Wonderware Historian `Runtime` database:
|
|
|
|
- **Raw reads** query `Runtime.dbo.History` with time range and max values
|
|
- **Processed reads** query `Runtime.dbo.AnalogSummaryHistory` with aggregates (Average, Minimum, Maximum, Count)
|
|
- Historized variables advertise `Historizing=true` and `AccessLevel` includes `HistoryRead`
|
|
|
|
## Incremental Address Space Sync
|
|
|
|
When the Galaxy detects a new deployment, the server compares the previous hierarchy and attributes against the new snapshot. Only changed gobject subtrees are torn down and rebuilt — unchanged nodes, subscriptions, and alarm tracking remain intact. See `partial_update.md` for details.
|
|
|
|
## 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 (namespace URI) |
|
|
| `OpcUa` | `MaxSessions` | `100` | Maximum concurrent sessions |
|
|
| `OpcUa` | `AlarmTrackingEnabled` | `false` | Enable alarm condition tracking |
|
|
| `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 |
|
|
| `GalaxyRepository` | `ExtendedAttributes` | `false` | Include primitive/system attributes |
|
|
| `Historian` | `Enabled` | `false` | Enable OPC UA historical data access |
|
|
| `Historian` | `ConnectionString` | `Server=localhost;Database=Runtime;...` | Historian Runtime database connection |
|
|
| `Historian` | `MaxValuesPerRead` | `10000` | Maximum values per HistoryRead request |
|
|
| `Dashboard` | `Enabled` | `true` | Enable HTTP status dashboard |
|
|
| `Dashboard` | `Port` | `8081` | Dashboard port |
|
|
|
|
## 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.
|
|
|
|
## 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 (connect, browse, read, write, subscribe, historyread, alarms)
|
|
gr/ Galaxy repository docs, SQL queries, schema
|
|
```
|
|
|
|
## Startup Sequence
|
|
|
|
1. Load and validate configuration
|
|
2. Register `AppDomain.UnhandledException` handler
|
|
3. Create performance metrics
|
|
4. Connect MXAccess (STA thread + COM registration)
|
|
5. Start MXAccess monitor loop
|
|
6. Test Galaxy database connection
|
|
7. Start OPC UA server with programmatic config
|
|
8. Query hierarchy + attributes, build address space
|
|
9. Create alarm condition nodes and auto-subscribe to InAlarm tags (if enabled)
|
|
10. Start change detection polling (incremental sync on deploy)
|
|
11. Start status dashboard (HTML + JSON + health endpoint)
|
|
|
|
## Component Documentation
|
|
|
|
| Component | Description |
|
|
|---|---|
|
|
| [OPC UA Server](docs/OpcUaServer.md) | Endpoint, sessions, security policy, server lifecycle |
|
|
| [Address Space](docs/AddressSpace.md) | Hierarchy nodes, variable nodes, primitive grouping, NodeId scheme |
|
|
| [Galaxy Repository](docs/GalaxyRepository.md) | SQL queries, deployed package chain, change detection |
|
|
| [MXAccess Bridge](docs/MxAccessBridge.md) | STA thread, COM interop, subscriptions, reconnection |
|
|
| [Data Type Mapping](docs/DataTypeMapping.md) | Galaxy → OPC UA types, arrays, security classification |
|
|
| [Read/Write Operations](docs/ReadWriteOperations.md) | Value reads, writes, access level enforcement, array element writes |
|
|
| [Subscriptions](docs/Subscriptions.md) | Ref-counted MXAccess subscriptions, data change dispatch |
|
|
| [Alarm Tracking](docs/AlarmTracking.md) | AlarmConditionState nodes, InAlarm monitoring, event reporting |
|
|
| [Historical Data Access](docs/HistoricalDataAccess.md) | Historian data source, HistoryReadRaw, HistoryReadProcessed |
|
|
| [Incremental Sync](docs/IncrementalSync.md) | Diff computation, subtree teardown/rebuild, subscription preservation |
|
|
| [Configuration](docs/Configuration.md) | appsettings.json binding, feature flags, validation |
|
|
| [Status Dashboard](docs/StatusDashboard.md) | HTTP server, health checks, metrics reporting |
|
|
| [Service Hosting](docs/ServiceHosting.md) | TopShelf, startup/shutdown sequence, error handling |
|
|
| [CLI Tool](docs/CliTool.md) | Connect, browse, read, write, subscribe, historyread, alarms commands |
|
|
|
|
## Related Documentation
|
|
|
|
- [Galaxy Repository Queries](gr/CLAUDE.md) — SQL queries for hierarchy, attributes, and change detection
|
|
- [Data Type Mapping](gr/data_type_mapping.md) — Galaxy to OPC UA type mapping with security classification
|
|
- [Alarm Plan](hda_plan.md) — Alarm detection and OPC UA alarm condition design
|
|
- [Historian Plan](historian_plan.md) — Historical data access via Wonderware Historian
|
|
- [Incremental Sync Plan](partial_update.md) — Subtree-level address space sync design
|
|
- [Galaxy Security](gr_security.md) — Users, roles, and permissions in the Galaxy repository
|
|
|
|
## License
|
|
|
|
Internal use only.
|