Files
lmxopcua/CLAUDE.md
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

6.3 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Goal

Build an OPC UA server on .NET Framework 4.8 (32-bit) that exposes AVEVA System Platform (Wonderware) Galaxy tags via the MXAccess toolkit. The server mirrors the Galaxy object hierarchy as an OPC UA address space, translating between contained-name browse paths and tag-name runtime references.

Architecture Overview

Data Flow

  1. Galaxy Repository DB (ZB) — SQL Server database holding the deployed object hierarchy and attribute definitions. Queried at startup and on change detection to build/rebuild the OPC UA address space.
  2. MXAccess COM API — Runtime data access layer. Subscribes to Galaxy tag attributes for live read/write. Requires a dedicated STA thread with a Win32 message pump for COM callbacks.
  3. OPC UA Server — Exposes the hierarchy as browse nodes and attributes as variable nodes. Clients browse via contained names but reads/writes are translated to tag_name.AttributeName format for MXAccess.

Key Concept: Contained Name vs Tag Name

Galaxy objects have two names:

  • contained_name — human-readable name scoped to parent (used for OPC UA browse tree)
  • tag_name — globally unique system name (used for MXAccess read/write)

Example: browsing TestMachine_001/DelmiaReceiver/DownloadPath translates to MXAccess reference DelmiaReceiver_001.DownloadPath.

See gr/layout.md for the full mapping and target OPC UA structure.

Data Type Mapping

Galaxy mx_data_type values map to OPC UA types (Boolean, Int32, Float, Double, String, DateTime, etc.). Array attributes use ValueRank=1 with ArrayDimensions from the Galaxy attribute definition. Full mapping in gr/data_type_mapping.md.

Change Detection

Poll galaxy.time_of_last_deploy in the ZB database to detect redeployments, then rebuild the address space. See gr/build_layout_plan.md for the step-by-step plan.

Reference Implementation

An existing MXAccess client implementation is at: C:\Users\dohertj2\Desktop\scadalink-design\lmxproxy\src\ZB.MOM.WW.LmxProxy.Host

Key patterns from that codebase:

  • StaComThread — Dedicated STA thread with Win32 message pump (GetMessage/DispatchMessage loop). All MXAccess COM objects must be created and called on this thread. Uses PostThreadMessage(WM_APP) to marshal work items.
  • LMXProxyServer COM objectRegister(clientName) returns a connection handle. AddItem(handle, address) + AdviseSupervisory(handle, itemHandle) for subscriptions. OnDataChange/OnWriteComplete events for callbacks.
  • Reconnect — Stored subscriptions are replayed after reconnect. A probe tag subscription monitors connection health.
  • COM cleanupMarshal.ReleaseComObject() on disconnect. Event handlers must be unwired before unregister.

MXAccess Documentation

mxaccess_documentation.md in the project root contains the full ArchestrA MXAccess Toolkit User's Guide. Key API: ArchestrA.MxAccess namespace, LMXProxyServer class. The toolkit DLLs are in Program Files (x86)\ArchestrA\Framework\bin.

Galaxy Repository Database

Connection: sqlcmd -S localhost -d ZB -E (Windows Auth). See gr/connectioninfo.md.

The gr/ folder contains:

  • queries/ — SQL for hierarchy extraction, attribute lookup, and change detection
  • ddl/tables/ and ddl/views/ — Schema definitions
  • schema.md — Full table/view reference
  • build_layout_plan.md — Step-by-step plan for building the OPC UA address space from DB queries
  • gr/CLAUDE.md — Detailed guidance for working within the gr/ subfolder

Key tables: gobject (hierarchy/deployment), template_definition (object categories), dynamic_attribute (user-defined attributes), primitive_instance (primitive-to-attribute links), galaxy (change detection).

Build Commands

dotnet restore ZB.MOM.WW.LmxOpcUa.slnx
dotnet build ZB.MOM.WW.LmxOpcUa.slnx
dotnet test ZB.MOM.WW.LmxOpcUa.slnx                          # all tests
dotnet test tests/ZB.MOM.WW.LmxOpcUa.Tests                    # unit tests only
dotnet test tests/ZB.MOM.WW.LmxOpcUa.IntegrationTests         # integration tests only
dotnet test --filter "FullyQualifiedName~MyTestClass.MyMethod"  # single test

Build & Runtime Constraints

  • Language: C#, .NET Framework 4.8, x86 (32-bit) platform target — required for MXAccess COM interop
  • MXAccess requires a deployed ArchestrA Platform on the machine running the server
  • COM apartment: MXAccess objects must live on an STA thread with a message pump

Library Preferences

  • Logging: Serilog with rolling daily file sink
  • Unit tests: xUnit + Shouldly for assertions
  • Service hosting: TopShelf (Windows service install/uninstall/run as console)
  • OPC UA: OPC Foundation UA .NET Standard stack (https://github.com/opcfoundation/ua-.netstandard) — NuGet: OPCFoundation.NetStandard.Opc.Ua.Server

OPC UA .NET Standard Documentation

Use the DeepWiki MCP (mcp__deepwiki) to query documentation for the OPC UA .NET Standard stack: https://deepwiki.com/OPCFoundation/UA-.NETStandard. Tools: read_wiki_structure, read_wiki_contents, and ask_question with repo OPCFoundation/UA-.NETStandard.

Testing

Use the dotnet OPC UA CLI tool at tools/opcuacli-dotnet/ for manual testing against the running OPC UA server. Supports connect, read, write, subscribe, and browse commands. See tools/opcuacli-dotnet/README.md for usage details.

cd tools/opcuacli-dotnet
dotnet run -- connect -u opc.tcp://localhost:4840
dotnet run -- browse -u opc.tcp://localhost:4840 -r -d 3
dotnet run -- read -u opc.tcp://localhost:4840 -n "ns=2;s=SomeNode"
dotnet run -- subscribe -u opc.tcp://localhost:4840 -n "ns=2;s=SomeNode" -i 500

OPC PLC Sample Server

A test OPC UA server is available at tools/opcsampleserver/ (Azure IoT OPC PLC). It generates simulated data nodes (slow, fast, anomaly, GUID) on opc.tcp://localhost:50000. Must run from the publish directory or use the provided batch scripts. Requires --unsecuretransport flag for the CLI tool to connect. See tools/opcsampleserver/README.md for full details.

# Start the test server
cd tools/opcsampleserver/publish && dotnet opcplc.dll --pn=50000 --autoaccept --unsecuretransport --sn=5 --sr=10 --st=uint --fn=5 --fr=1 --ft=uint

# Or use the batch script
tools/opcsampleserver/start-server.bat