Commit Graph

15 Commits

Author SHA1 Message Date
Joseph Doherty
bbd043e97b Add authentication and role-based write access control
Implements configurable user authentication (anonymous + username/password)
with pluggable credential provider (IUserAuthenticationProvider). Anonymous
writes can be disabled via AnonymousCanWrite setting while reads remain
open. Adds -U/-P flags to all CLI commands for authenticated sessions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:14:37 -04:00
Joseph Doherty
b27d355763 Fix alarm acknowledge EventId validation and add auth plan
Set a new EventId (GUID) on AlarmConditionState each time an alarm event
is reported so the framework can match it when clients call Acknowledge.
Without this, the framework rejected all ack attempts with BadEventIdUnknown.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:39:21 -04:00
Joseph Doherty
9368767b1b Add alarm acknowledge plan and incorporate code review fixes
Adds alarm_ack.md documenting the two-way acknowledge flow (OPC UA client
writes AckMsg, Galaxy confirms via Acked data change). Includes external
code review fixes for subscriptions and node manager, and removes stale
plan files now superseded by component documentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 01:02:47 -04:00
Joseph Doherty
ce0b291664 Refine XML docs for historian, OPC UA, and tests 2026-03-26 15:33:14 -04:00
Joseph Doherty
3c326e2d45 Replace full address space rebuild with incremental subtree sync
On Galaxy deploy changes, only the affected gobject subtrees are torn down
and rebuilt instead of destroying the entire address space. Unchanged nodes,
subscriptions, and alarm tracking continue uninterrupted.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 15:23:11 -04:00
Joseph Doherty
bfd360a6db Add enable/disable configuration for alarm tracking and historian integration
Both features now default to disabled and require explicit opt-in via
OpcUa.AlarmTrackingEnabled and Historian.Enabled in appsettings.json,
preventing errors in environments without a Historian database or alarm setup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 13:56:38 -04:00
Joseph Doherty
415e62c585 Add security classification, alarm detection, historical data access, and primitive grouping
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>
2026-03-26 11:32:33 -04:00
Joseph Doherty
bb0a89b2a1 Publish default values for null static arrays 2026-03-25 14:12:37 -04:00
Joseph Doherty
ed42b33512 Use bracketless OPC UA node IDs for arrays 2026-03-25 12:57:05 -04:00
Joseph Doherty
4833765606 Expand XML docs across bridge and test code 2026-03-25 11:45:12 -04:00
Joseph Doherty
3f813b3869 Add OPC UA array element write integration test 2026-03-25 11:05:04 -04:00
Joseph Doherty
4351854754 Fix service deployment: set working directory for correct log paths and use MasterNodeManager for Objects→ZB reference
Windows services default to System32 as working directory, causing logs to land in the wrong location. Set Environment.CurrentDirectory to AppDomain.CurrentDomain.BaseDirectory before Serilog init. Also fix ZB root folder not appearing under Objects folder — BuildAddressSpace runs after CreateAddressSpace completes so the externalReferences dict is already consumed; use Server.NodeManager.AddReferences instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:57:18 -04:00
Joseph Doherty
09ed15bdda Fix second-pass review findings: subscription leak on rebuild, metrics accuracy, and MxAccess startup recovery
- Preserve and replay subscription ref counts across address space rebuilds to prevent MXAccess subscription leaks
- Mark read timeouts and write failures as unsuccessful in PerformanceMetrics for accurate health reporting
- Add deferred MxAccess reconnect path when initial connection fails at startup
- Update code review document with verified completions and new findings
- Add covering tests for all fixes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:41:12 -04:00
Joseph Doherty
71254e005e Fix 5 code review findings (P1-P3)
P1: Wire OPC UA monitored items to MXAccess subscriptions
  - Override OnCreateMonitoredItemsComplete/OnDeleteMonitoredItemsComplete
    in LmxNodeManager to trigger ref-counted SubscribeTag/UnsubscribeTag
  - Clients subscribing to tags now start live MXAccess data pushes

P1: Write timeout now returns false instead of true
  - Previously a missing OnWriteComplete callback was treated as success
  - Now correctly reports failure so OPC UA clients see the error

P1: Auto-reconnect retries from Error state (not just Disconnected)
  - Monitor loop now checks both Disconnected and Error states
  - Prevents permanent outages after a single failed reconnect attempt

P2: Topological sort on hierarchy before building address space
  - Parents guaranteed to appear before children regardless of input order
  - Prevents misplaced nodes when SQL returns unsorted results

P3: Skip redundant first-poll rebuild on startup
  - ChangeDetectionService accepts initial deploy time from OpcUaService
  - First poll only triggers rebuild if deploy time is actually unknown
  - Eliminates duplicate DB fetch and address space rebuild at startup

All 212 tests pass (205 unit + 7 integration).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 07:16:23 -04:00
Joseph Doherty
a7576ffb38 Implement LmxOpcUa server — all 6 phases complete
Full OPC UA server on .NET Framework 4.8 (x86) exposing AVEVA System
Platform Galaxy tags via MXAccess. Mirrors Galaxy object hierarchy as
OPC UA address space, translating contained-name browse paths to
tag-name runtime references.

Components implemented:
- Configuration: AppConfiguration with 4 sections, validator
- Domain: ConnectionState, Quality, Vtq, MxDataTypeMapper, error codes
- MxAccess: StaComThread, MxAccessClient (partial classes), MxProxyAdapter
  using strongly-typed ArchestrA.MxAccess COM interop
- Galaxy Repository: SQL queries (hierarchy, attributes, change detection),
  ChangeDetectionService with auto-rebuild on deploy
- OPC UA Server: LmxNodeManager (CustomNodeManager2), LmxOpcUaServer,
  OpcUaServerHost with programmatic config, SecurityPolicy None
- Status Dashboard: HTTP server with HTML/JSON/health endpoints
- Integration: Full 14-step startup, graceful shutdown, component wiring

175 tests (174 unit + 1 integration), all passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 05:55:27 -04:00