Wire SDK for remote-TCP end to end; live-verify RemoteTcpIntegrated
Executes docs/plans/tcp-connection-validation.md. Full read-only SDK
surface now works against a remote AVEVA Historian over Net.TCP with
Windows transport authentication. 124/124 tests pass; the +10 new live
integration tests in RemoteTcpIntegrationTests.cs are gated by
HISTORIAN_REMOTE_TCP_HOST + HISTORIAN_REMOTE_TCP_TAG.
Two SDK bugs found while executing the plan:
1. Historian2020ProtocolDialect.ReadRawAsync / ReadAggregateAsync /
ReadAtTimeAsync / ReadEventsAsync had explicit
`if (_options.Transport != HistorianTransport.LocalPipe) return Missing<T>`
guards. These were a guardrail from before the orchestrators handled
TCP; the orchestrators have always used CreateBindingPair(options)
which dispatches on transport correctly. Gates removed.
2. HistorianWcfStatusClient and HistorianWcfEventOrchestrator hardcoded
HistorianWcfBindingFactory.CreatePipeEndpointAddress for the auxiliary
services (Stat, Trx, Retr). Worked for LocalPipe; for TCP it produced
an EndpointAddress with scheme net.pipe attached to a TCP binding
(channel factory rejected the URI). Worse, when only the endpoint was
transport-aware, the binding still requested a Windows-transport-
security upgrade that the Stat endpoint over TCP doesn't support
(auxiliaries don't repeat the auth — the Hist session is already
authenticated). Added two helpers:
- HistorianWcfBindingFactory.CreateAuxiliaryEndpointAddress(options, name)
-> net.pipe for LocalPipe, net.tcp for remote
- HistorianWcfBindingFactory.CreateAuxiliaryBinding(options)
-> NamedPipe for LocalPipe, plain MdasNetTcpBinding for remote
Both call sites updated.
Live verification against the remote (probed previously in prior
sessions; reachability re-confirmed today):
- ProbeAsync over RemoteTcpIntegrated and RemoteTcpCertificate
- ReadRawAsync (8 samples returned for SysTimeSec)
- ReadAggregateAsync (TimeWeightedAverage, 1-min cycle, 10-min window)
- ReadAtTimeAsync (3 timestamps)
- BrowseTagNamesAsync (finds the test tag)
- GetTagMetadataAsync (full metadata populated)
- ReadEventsAsync (chain runs without throwing)
- GetConnectionStatusAsync (ConnectedToServer=true)
- GetSystemParameterAsync (HistorianVersion="20,0,000,000")
The default 'NT SERVICE\aahClientAccessPoint' SPN turned out to work
for the remote too — discovery workstream A (SPN-finding) was not
needed in practice.
README and the TCP plan doc updated to reflect the executed status.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,29 @@
|
||||
# TCP Connection Validation Plan
|
||||
|
||||
Status: PLAN ONLY (no implementation yet). Scope is **live verification of
|
||||
the existing remote-TCP transport plumbing**, not new wire-protocol
|
||||
reverse-engineering — the wire format itself is the same MDAS-encoded SOAP
|
||||
already verified end-to-end over `LocalPipe`.
|
||||
Status: **EXECUTED on 2026-05-04**. RemoteTcpIntegrated transport is now
|
||||
live-verified end-to-end against `10.100.0.48` (Historian InterfaceVersion=11)
|
||||
for ProbeAsync, ReadRawAsync, ReadAggregateAsync, ReadAtTimeAsync,
|
||||
ReadEventsAsync, BrowseTagNamesAsync, GetTagMetadataAsync,
|
||||
GetConnectionStatusAsync, GetSystemParameterAsync. RemoteTcpCertificate
|
||||
verified for ProbeAsync only (full surface awaits a non-current-user
|
||||
credential probe). Test count 114 → 124 (+10) per success criteria.
|
||||
|
||||
Two SDK bugs were uncovered and fixed during execution:
|
||||
1. `Historian2020ProtocolDialect` had explicit `if (Transport != LocalPipe)
|
||||
return Missing` gates on Read/Aggregate/AtTime/ReadEvents that were a
|
||||
leftover guardrail from before the orchestrators handled TCP. Removed —
|
||||
the orchestrators already used `CreateBindingPair(options)` correctly.
|
||||
2. `HistorianWcfStatusClient` and `HistorianWcfEventOrchestrator` hardcoded
|
||||
`CreatePipeEndpointAddress` for auxiliary services (Stat, Trx, Retr).
|
||||
Added `HistorianWcfBindingFactory.CreateAuxiliaryEndpointAddress` and
|
||||
`CreateAuxiliaryBinding` helpers that dispatch on `Transport`; for TCP
|
||||
the auxiliaries use plain `MdasNetTcpBinding` (no transport upgrade —
|
||||
the Hist endpoint already authenticated the session).
|
||||
|
||||
Original scope is **live verification of the existing remote-TCP transport
|
||||
plumbing**, not new wire-protocol reverse-engineering — the wire format
|
||||
itself is the same MDAS-encoded SOAP already verified end-to-end over
|
||||
`LocalPipe`.
|
||||
|
||||
Read together with:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user