Joseph Doherty ffacbe0370 sidecar: wire IAlarmEventWriter into Program.cs (PR C.2)
Fifth PR of the alarms-over-gateway epic
(docs/plans/alarms-over-gateway.md). Depends on PR C.1
(AahClientManagedAlarmEventWriter), already merged.

Today HistorianFrameHandler is constructed at Program.cs line 57
without an alarmWriter, so every WriteAlarmEvents frame replies
"Sidecar not configured with an alarm-event writer" and the lmxopcua
side keeps the row queued. C.2 wires a real writer behind a new
OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED toggle.

- Program.BuildAlarmWriter — gated on the env var (default true,
  fail-open under accidental misconfiguration). Constructs an
  AahClientManagedAlarmEventWriter wrapping a
  SdkAlarmHistorianWriteBackend with the same connection config the
  read path uses.
- Install-Services.ps1 — appends OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED=true
  to the OtOpcUaWonderwareHistorian service env block when the
  sidecar is installed. Read-only deployments flip it to false at
  service-config edit time without re-installing.
- HistorianFrameHandler signature already accepts
  IAlarmEventWriter? — supplying non-null at line 57 lights up
  the WriteAlarmEvents reply path that's been dormant since PR 3.3.

Until PR D.1 pins the live aahClientManaged entry point, the
SdkAlarmHistorianWriteBackend reports RetryPlease for every event
with a structured diagnostic. The lmxopcua-side
SqliteStoreAndForwardSink retains queued events; same effective
behaviour as today's NullAlarmHistorianSink fallback but with
visible diagnostics rather than silent discard.

Tests:
- 6 BuildAlarmWriter env-var cases — unset / true / false /
  unrecognized → default-on / capitalization variants.
- Full sidecar test suite: 56 passed (was 48; 8 new).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 16:20:11 -04:00
Pin libplctag ab_server to v2.6.16 — real release tag + SHA256 hashes for all three Windows arches. Closes the "pick a current version + pin" deferral left by the #180 PR docs stub. Verified the release lands ab_server.exe inside libplctag_2.6.16_windows_<arch>_tools.zip alongside plctag.dll + list_tags_* helpers by downloading each tools zip + unzip -l'ing to confirm ab_server.exe is present at 331264 bytes. New ci/ab-server.lock.json is the single source of truth — one file the CI YAML reads via ConvertFrom-Json instead of duplicating the hash across the workflow + the docs. Structure: repo (libplctag/libplctag) + tag (v2.6.16) + published date (2026-03-29) + assets keyed by platform (windows-x64 / windows-x86 / windows-arm64) each carrying filename + sha256. docs/v2/test-data-sources.md §2.CI updated — replaces the prior placeholder (ver = '<pinned libplctag release tag>', expected = '<pinned sha256>') with the real v2.6.16 + 9b78a3de... hashes pinned table, and replaces the hardcoded URL with a lockfile-driven pwsh step that picks windows-x64 by default but swaps to x86/arm64 by changing one line for non-x64 CI runners. Hash-mismatch path throws with both the expected + actual values so on the first drift the CI log tells the maintainer exactly what to update in the lockfile. Two verification notes from the release fetch: (1) libplctag v2.6.16 tools zips ship ab_server.exe + plctag.dll together — tests don't need a separate libplctag NuGet download for the integration path, the extracted tools dir covers both the simulator + the driver's native dependency; (2) the three Windows arches all carry ab_server.exe, so ARM64 Windows GitHub runners (when they arrive) can run the integration suite without changes beyond swapping the asset key. No code changes in this PR — purely docs + the new lockfile. Admin tests + Core tests unchanged + passing per the prior commit.
2026-04-20 00:04:35 -04:00

OtOpcUa

OPC UA server (.NET 10 AnyCPU) that exposes a fleet of industrial drivers as a single OPC UA address space. Drivers ship in-process for AVEVA System Platform Galaxy (via the sibling mxaccessgw repo), Modbus TCP, Siemens S7, Allen-Bradley CIP (ControlLogix / CompactLogix), Allen-Bradley Legacy (SLC 500 / MicroLogix), Beckhoff TwinCAT (ADS), FANUC FOCAS, and OPC UA Client (gateway).

A cross-platform client stack (.NET 10) — shared library, CLI, and Avalonia desktop app — connects to any OPC UA server.

Architecture

                      OPC UA Clients (CLI, Desktop UI, 3rd-party)
                                       |
                                       v
                    +-------------------------------------+
                    |  OtOpcUa.Server (.NET 10 AnyCPU)    |
                    |   address space + capability fan-out|
                    +-------------------------------------+
                    |    |    |    |    |    |    |    |
              Galaxy  Modbus  S7  AbCip AbLeg TwinCAT FOCAS OpcUaClient
                |
                v
       mxaccessgw (sibling repo, gRPC)
                |
                v
     MXAccess COM (x86 worker, on AVEVA box)

Galaxy is the only driver with an external runtime: it speaks gRPC to a separately installed mxaccessgw server (sibling repo at c:\Users\dohertj2\Desktop\mxaccessgw\) which owns the MXAccess COM apartment and the x86/STA bitness constraint server-side. Everything in this repo is platform-agnostic .NET 10.

Prerequisites

  • .NET 10 SDK (server, drivers, clients all target .NET 10)
  • SQL Server reachable for the central config DB
  • For Galaxy specifically: a running mxaccessgw deployment — see docs/v2/Galaxy.ParityRig.md
  • For Wonderware Historian read-back: optional OtOpcUaWonderwareHistorian sidecar — see docs/ServiceHosting.md

Quick Start

dotnet restore ZB.MOM.WW.OtOpcUa.slnx
dotnet build ZB.MOM.WW.OtOpcUa.slnx
dotnet test ZB.MOM.WW.OtOpcUa.slnx

# Run the server in dev (foreground)
dotnet run --project src/ZB.MOM.WW.OtOpcUa.Server

The server starts on opc.tcp://localhost:4840 with the None security profile. Configure Security.Profiles in src/ZB.MOM.WW.OtOpcUa.Server/appsettings.json to enable Basic256Sha256-Sign or Basic256Sha256-SignAndEncrypt. See docs/security.md.

Install as Windows Services

Production deployment is driven by scripts/install/Install-Services.ps1, which registers the OtOpcUa server service (and optionally the OtOpcUaWonderwareHistorian sidecar) under a chosen service account. Galaxy support requires a separately installed mxaccessgw — neither this repo nor the install script provisions it.

.\scripts\install\Install-Services.ps1 `
    -InstallRoot 'C:\Program Files\OtOpcUa' `
    -ServiceAccount 'DOMAIN\svc-otopcua'

Add -InstallWonderwareHistorian for the historian sidecar. See the script header and docs/ServiceHosting.md for full options.

Client CLI

dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- connect -u opc.tcp://localhost:4840
dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- browse  -u opc.tcp://localhost:4840 -r -d 3
dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- read    -u opc.tcp://localhost:4840 -n "ns=2;s=SomeNode"
dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- write   -u opc.tcp://localhost:4840 -n "ns=2;s=SomeNode" -v 42
dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- subscribe -u opc.tcp://localhost:4840 -n "ns=2;s=SomeNode" -i 500

See docs/Client.CLI.md and docs/Client.UI.md.

Documentation

Architecture deep-dives

Topic Doc
OPC UA server composition, namespace fan-out, Polly invoker docs/OpcUaServer.md
Address space layout docs/AddressSpace.md
Read / Write dispatch (driver vs virtual vs scripted-alarm) docs/ReadWriteOperations.md
Incremental sync (driver-backend rediscovery + config publishes) docs/IncrementalSync.md
Service hosting (Server + Admin + optional historian sidecar) docs/ServiceHosting.md
Security (transport, LDAP, certificates) docs/security.md
Redundancy docs/Redundancy.md
Status dashboard docs/StatusDashboard.md

Drivers

Topic Doc
Driver specs (per-driver capability surface, config, addressing) docs/v2/driver-specs.md
Galaxy driver docs/drivers/Galaxy.md
Modbus / S7 / AbCip / AbLegacy / TwinCAT / FOCAS / OpcUaClient docs/drivers/
Galaxy parity rig (mxaccessgw setup) docs/v2/Galaxy.ParityRig.md
Galaxy performance + tracing docs/v2/Galaxy.Performance.md

Clients

Topic Doc
Client CLI docs/Client.CLI.md
Client UI (Avalonia desktop) docs/Client.UI.md

v1 archive

The original v1 in-process MXAccess docs (Galaxy.Host topology, Configuration env vars, AlarmTracking, DataTypeMapping, HistoricalDataAccess, Subscriptions, etc.) are preserved under docs/v1/ — historical reference only. PR 7.2 retired the v1 architecture on 2026-04-30; current state is documented in the sections above.

License

Internal use only.

Description
No description provided
Readme 26 MiB
Languages
C# 90.2%
HTML 4.1%
PowerShell 3.1%
Python 1.7%
TSQL 0.7%