Files
scadalink-design/deprecated/lmxproxy/CLAUDE.md
Joseph Doherty 9dccf8e72f deprecate(lmxproxy): move all LmxProxy code, tests, and docs to deprecated/
LmxProxy is no longer needed. Moved the entire lmxproxy/ workspace, DCL
adapter files, and related docs to deprecated/. Removed LmxProxy registration
from DataConnectionFactory, project reference from DCL, protocol option from
UI, and cleaned up all requirement docs.
2026-04-08 15:56:23 -04:00

4.5 KiB

CLAUDE.md

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

What This Is

LmxProxy is a gRPC proxy that bridges ScadaLink's Data Connection Layer to AVEVA System Platform via the ArchestrA MXAccess COM API. It has two projects:

  • Host (ZB.MOM.WW.LmxProxy.Host) — .NET Framework 4.8, x86-only Windows service. Hosts a gRPC server (Grpc.Core) that fronts an MxAccessClient talking to ArchestrA MXAccess. Runs as a Windows service via Topshelf.
  • Client (ZB.MOM.WW.LmxProxy.Client) — .NET 10, AnyCPU library. Code-first gRPC client (protobuf-net.Grpc) consumed by ScadaLink's DCL. This is a NuGet-packable library.

The two projects use different gRPC stacks: Host uses proto-file-generated code (Grpc.Core + Grpc.Tools), Client uses code-first contracts (protobuf-net.Grpc with [DataContract]/[ServiceContract] attributes). They are wire-compatible because both target the same scada.ScadaService gRPC service.

Build Commands

dotnet build ZB.MOM.WW.LmxProxy.slnx           # Build entire solution
dotnet build src/ZB.MOM.WW.LmxProxy.Host        # Host only (requires x86 platform)
dotnet build src/ZB.MOM.WW.LmxProxy.Client      # Client only

The Host project requires the ArchestrA.MXAccess.dll COM interop assembly in lib/. It targets x86 exclusively (MXAccess is 32-bit COM).

Architecture

Host Service Startup Chain

Program.Main → Topshelf HostFactoryLmxProxyService.Start() which:

  1. Validates configuration (appsettings.json bound to LmxProxyConfiguration)
  2. Creates MxAccessClient (the IScadaClient impl that wraps ArchestrA.MXAccess COM)
  3. Connects to MxAccess synchronously at startup
  4. Starts connection monitor loop (auto-reconnect)
  5. Creates SubscriptionManager, SessionManager, PerformanceMetrics, ApiKeyService
  6. Creates ScadaGrpcService (the proto-generated service impl) with all dependencies
  7. Starts Grpc.Core Server on configured port (default 50051)
  8. Starts HTTP status web server (default port 8080)

Key Host Components

  • MxAccessClient — Partial class split across 6 files (Connection, ReadWrite, Subscription, EventHandlers, NestedTypes, main). Wraps LMXProxyServer COM object. Uses semaphores for concurrency control.
  • ScadaGrpcService — Inherits proto-generated ScadaService.ScadaServiceBase. All RPCs validate session first, then delegate to IScadaClient. Values are string-serialized on the wire (v1 protocol).
  • SessionManager — Tracks client sessions by GUID.
  • SubscriptionManager — Manages MxAccess subscriptions, fans out updates via System.Threading.Channels.
  • ApiKeyInterceptor — gRPC server interceptor for API key validation.

Client Architecture

  • ILmxProxyClient — Public interface for consumers. Connect/Read/Write/Subscribe/Dispose.
  • LmxProxyClient — Partial class split across multiple files (Connection, Subscription, Metrics, etc.). Uses protobuf-net.Grpc code-first contracts (IScadaService in Domain/ScadaContracts.cs).
  • LmxProxyClientBuilder — Fluent builder for configuring client instances.
  • Domain/ScadaContracts.cs — All gRPC message types as [DataContract] POCOs and the IScadaService interface with [ServiceContract].
  • Value conversion: Client parses string values from wire using double → bool → string heuristic in ConvertToVtq(). Writes use .ToString() via ConvertToString().

Protocol

Proto definition: src/ZB.MOM.WW.LmxProxy.Host/Grpc/Protos/scada.proto

Currently v1 protocol (string-encoded values, string quality). A v2 protocol spec exists in docs/lmxproxy_updates.md that introduces TypedValue (protobuf oneof) and QualityCode (OPC UA status codes) — not yet implemented.

RPCs: Connect, Disconnect, GetConnectionState, Read, ReadBatch, Write, WriteBatch, WriteBatchAndWait, Subscribe (server streaming), CheckApiKey.

Configuration

Host configured via appsettings.json bound to LmxProxyConfiguration. Key sections: GrpcPort, Connection (timeouts, auto-reconnect), Subscription (channel capacity), Tls, WebServer, Serilog, RetryPolicies, HealthCheck.

Important Constraints

  • Host must target x86 and .NET Framework 4.8 (ArchestrA.MXAccess is 32-bit COM interop).
  • Host uses Grpc.Core (the deprecated C-core gRPC library), not Grpc.Net. This is required because .NET 4.8 doesn't support Grpc.Net.Server.
  • Client uses Grpc.Net.Client and targets .NET 10 — it runs in the ScadaLink central/site clusters.
  • The solution file is .slnx format (XML-based, not the older text format).