Files
lmxopcua/docs/drivers/Galaxy.md
T
Joseph Doherty d731ed98fa docs(audit): drivers/Galaxy.md — interface list + accuracy pass
CODE-REALITY (known defect): the capability-surface declaration line
omitted IAlarmSource and IAsyncDisposable. GalaxyDriver.cs:39 actually
declares: IDriver, ITagDiscovery, IReadable, IWritable, ISubscribable,
IRediscoverable, IHostConnectivityProbe, IAlarmSource, IDisposable,
IAsyncDisposable. Doc line corrected to match exactly, and an IAlarmSource
row added to the capability table (Runtime/GatewayGalaxyAlarmFeed.cs +
Runtime/GatewayGalaxyAlarmAcknowledger.cs).

STALE-STATUS: the v1-doc move note claimed Galaxy-Repository.md /
Galaxy-Test-Fixture.md 'are being moved to docs/v1/ by a parallel cleanup
track' — that move is complete; they live at docs/v1/drivers/. Rewrote to
present tense and linked the real targets.

Verified against source: deploy-watch is a gRPC stream
(GatewayGalaxyDeployWatchSource forwards WatchDeployEventsAsync via
GalaxyRepositoryClient, not a direct DB poll); contained-name<->tag-name
translation (GalaxyDiscoverer.cs:49,60); DataTypeMap at Browse/DataTypeMap.cs;
IGalaxyHierarchySource / IGalaxyDeployWatchSource / DeployWatcher all present.

check_links.py: zero rows for docs/drivers/Galaxy.md.
2026-06-03 15:58:32 -04:00

8.9 KiB

Galaxy Driver

The Galaxy driver bridges OtOpcUa to AVEVA System Platform (Wonderware) Galaxies. It is a Tier-A in-process driver that runs in the OtOpcUa server's .NET 10 AnyCPU process and speaks gRPC to a separately installed mxaccessgw server (sibling repo at c:\Users\dohertj2\Desktop\mxaccessgw\). The gateway owns the MXAccess COM apartment, the STA + Win32 message pump, the Galaxy Repository SQL reader, and the Historian SDK — all the bits that need x86 / .NET Framework 4.8 / COM interop. The driver itself is platform-agnostic and contains no COM, no STA thread, and no x86 bitness constraint.

For the driver spec (capability surface, config shape, addressing), see docs/v2/driver-specs.md §1. For the gateway setup recipe, see docs/v2/Galaxy.ParityRig.md. For tracing, metrics, and soak profile, see docs/v2/Galaxy.Performance.md.

Note

: the related docs Galaxy-Repository.md and Galaxy-Test-Fixture.md describe the previous v1 / out-of-process topology and now live under docs/v1/drivers/. For current testing use Galaxy.ParityRig.md and the mxaccessgw repo.

Architecture

                    +---------------------------------------+
                    |  OtOpcUa.Server (.NET 10 AnyCPU)      |
                    |   GalaxyDriver (in-process)           |
                    |    ITagDiscovery / IReadable /        |
                    |    IWritable / ISubscribable /        |
                    |    IRediscoverable /                  |
                    |    IHostConnectivityProbe /           |
                    |    IAlarmSource                       |
                    +-------------------+-------------------+
                                        |
                                       gRPC (default http://localhost:5120)
                                        |
                                        v
                    +---------------------------------------+
                    |  mxaccessgw  (sibling repo)           |
                    |    +-------------------------------+  |
                    |    | MxGateway.Worker (x86 net48)  |  |
                    |    |   STA + WM_APP pump           |  |
                    |    |   ArchestrA.MxAccess COM      |  |
                    |    |   Galaxy Repository SQL       |  |
                    |    |   Wonderware Historian SDK    |  |
                    |    +-------------------------------+  |
                    +---------------------------------------+

History reads moved server-side in PR 7.2 (IHistoryRouter). Galaxy no longer implements IHistoryProvider of its own.

IAlarmSource was retired with PR 7.2 and restored in PR B.2 of the alarms-over-gateway epic (docs/plans/alarms-over-gateway.md). Alarm transitions arrive on the same gateway StreamEvents channel as data-change events under the new MX_EVENT_FAMILY_ON_ALARM_TRANSITION family; acknowledgements route through the gateway's AcknowledgeAlarm RPC. The previous value-driven sub-attribute path remains as a fallback for Galaxy templates without $Alarm* extensions — the server-side AlarmConditionService dedups when both paths fire on the same condition. See docs/AlarmTracking.md for the v2-final architecture.

Project Layout

The driver ships as a single project: src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/ (.NET 10, AnyCPU). Sub-folders:

Folder Role
Browse/ Static-side discovery: GalaxyDiscoverer walks the gateway's hierarchy + attribute-set RPCs, DataTypeMap and SecurityMap translate Galaxy types and security classifications into OPC UA equivalents, AlarmRefBuilder extracts alarm-bearing attribute references for the server-layer alarm engine. IGalaxyHierarchySource + GatewayGalaxyHierarchySource + TracedGalaxyHierarchySource decorate the gateway browse RPC; IGalaxyDeployWatchSource + GatewayGalaxyDeployWatchSource + DeployWatcher drive IRediscoverable.
Runtime/ Live data path: EventPump runs the gateway's StreamEvents RPC and fans out to subscribers via a bounded channel; GalaxyMxSession is the read-side handle; GatewayGalaxySubscriber + GatewayGalaxyDataWriter (each with a Traced* decorator) implement ISubscribable / IWritable; SubscriptionRegistry tracks subscription state for replay; ReconnectSupervisor owns the backoff loop and triggers ReplaySubscriptions on session loss; StatusCodeMap translates gateway StatusCodes to OPC UA; MxValueDecoder / MxValueEncoder handle scalar + array marshalling; GalaxyTelemetry + GalaxySubscriptionHandle round out the surface.
Health/ HostStatusAggregator rolls per-platform probe state into the driver's IHostConnectivityProbe view; PerPlatformProbeWatcher listens on the gateway's per-host status stream; HostConnectivityForwarder pushes transitions out to the server's connectivity bus.
Config/ GalaxyDriverOptions and the four nested option records (GalaxyGatewayOptions, GalaxyMxAccessOptions, GalaxyRepositoryOptions, GalaxyReconnectOptions).

Project root files:

  • GalaxyDriver.csIDriver + capability-interface implementation; composes the Browse / Runtime / Health collaborators.
  • GalaxyDriverFactoryExtensions.cs — DI registration helper used by the server's driver bootstrap.

Capability Surface

GalaxyDriver : IDriver, ITagDiscovery, IReadable, IWritable, ISubscribable, IRediscoverable, IHostConnectivityProbe, IAlarmSource, IDisposable, IAsyncDisposable.

Capability Implementation entry point
ITagDiscovery Browse/GalaxyDiscoverer.cs
IRediscoverable Browse/DeployWatcher.cs
IReadable Runtime/GalaxyMxSession.cs
IWritable Runtime/GatewayGalaxyDataWriter.cs
ISubscribable Runtime/GatewayGalaxySubscriber.cs (driven by EventPump)
IHostConnectivityProbe Health/HostStatusAggregator.cs
IAlarmSource Runtime/GatewayGalaxyAlarmFeed.cs (transitions) + Runtime/GatewayGalaxyAlarmAcknowledger.cs (acks)

Configuration

DriverConfig JSON binds to Config/GalaxyDriverOptions.cs. The four sections are:

  • Gateway — endpoint, API key secret ref, TLS knobs, connect/call/stream timeouts. StreamTimeoutSeconds = 0 keeps the long-lived StreamEvents RPC open for the driver's lifetime.
  • MxAccessClientName (must be unique per OtOpcUa instance — redundancy pairs enforce uniqueness at install time), PublishingIntervalMs (forwarded as buffered_update_interval_ms on subscribe), WriteUserId for ArchestrA secured-write, EventPumpChannelCapacity (default 50_000 — one second of headroom at 50k tags / 1Hz; tune via the galaxy.events.dropped metric).
  • RepositoryDiscoverPageSize, WatchDeployEvents.
  • ReconnectInitialBackoffMs, MaxBackoffMs, ReplayOnSessionLost (calls the gateway's ReplaySubscriptions RPC after reconnect rather than re-issuing subscribe-bulk for every tag).

Full per-field descriptions live in Config/GalaxyDriverOptions.cs. The full JSON skeleton is reproduced in docs/v2/driver-specs.md §1.

Reconnect + Replay

ReconnectSupervisor owns an exponential-backoff loop bounded by Reconnect.InitialBackoffMs / MaxBackoffMs. On session loss it tears down the gRPC channel, redials, and — when ReplayOnSessionLost = true — calls the gateway's ReplaySubscriptions RPC with the cached subscription set from SubscriptionRegistry instead of re-subscribing tag-by-tag. The gateway's worker then re-issues AdviseSupervisory server-side under the apartment lock.

Testing

  • Unit tests: tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Tests/ — fakes the gateway gRPC surface; covers Browse, Runtime, Health, and Config in isolation.
  • Parity rig + dev-rig walkthrough: see docs/v2/Galaxy.ParityRig.md. The rig stands up a real mxaccessgw against a live Galaxy and exercises the full read / write / subscribe / rediscover path.
  • Performance + soak: see docs/v2/Galaxy.Performance.md.

Operational Notes

  • MXAccess ClientName collisions: two OtOpcUa instances sharing a ClientName cause the older Wonderware session to lose subscription state. Redundancy pairs (decision #149) enforce uniqueness via install scripts.
  • Channel saturation: galaxy.events.dropped > 0 indicates EventPump is back-pressured. Raise EventPumpChannelCapacity or investigate downstream slowness in the server-side fan-out.
  • Connectivity surface: per-platform probe state is exposed through IHostConnectivityProbe and aggregated by the server's connectivity bus — there is no driver-private dashboard surface anymore. The Admin UI's Host Status panel is the consumer.