R1.2 GetRuntimeParameter + string-handle wall RESOLVED (handle-format bug)
Execute HCAL roadmap R1.2 (GetRuntimeParameterAsync) end-to-end, and in doing so
discover that the "string-handle wall" blocking R1.1/R1.4/R1.5/R1.6 was a handle
FORMAT bug, not a missing native session/filter registration.
R1.2 (shipped, live-verified):
- Captured native GetRuntimeParameter -> WCF op aa/Stat/GETRP (string-handle op,
GETHI's shape), via scripts/Capture-RuntimeParam.ps1 + instrument-wcf-{write,read}message.
- HistorianRuntimeParameterProtocol serializes pRequestBuff (54 67 01 00 + uint
nameCount + per-name uint charCount + UTF-16) and parses pResponseBuff (version +
uint resultCount + CRetVariant 0x43 VT_BSTR + uint16 len + uint16 charCount + UTF-16).
- IStatusServiceContract2.GetRuntimeParameter (GETRP) op; HistorianWcfStatusClient
passes the Open2 storage-session GUID as the string handle, UPPERCASE.
- Public HistorianClient.GetRuntimeParameterAsync(name) via the dialect.
- Golden WcfRuntimeParameterProtocolTests + gated live test; returns HistorianVersion.
String-handle wall RESOLVED (proven, public APIs deferred):
- The Open2 storage GUID works as the string handle when sent UPPERCASE
(ToString("D").ToUpperInvariant()); earlier "blocked" probes used lowercase.
- Live-probed GETHI (R1.4) -> returns data; ExeC (R1.1) -> Retr.GetV prime -> ExeC ->
GetR returns a BinaryFormatter-serialized .NET DataTable. Gated
StringHandleProbeDiagnosticTests + scripts/Capture-ExecSql.ps1 + exec-sql harness scenario.
- Docs flipped: wcf-string-handle-wall.md RESOLVED banner; roadmap R1.1/R1.4 reachable,
R1.5/R1.6 likely; wcf-status-localhost.md GETRP section.
- R1.1/R1.4 public APIs NOT shipped: ExeC needs a GetR paging loop + a BinaryFormatter-
stream parser (BinaryFormatter is removed from .NET 10); GETHI full-info struct needs
its own capture.
223 unit tests pass; gated live tests green against the local 2020 Historian.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B6mcaT2PjRFKcogzp9UkfC
This commit is contained in:
@@ -273,6 +273,29 @@ public sealed class HistorianClientIntegrationTests
|
||||
Assert.False(string.IsNullOrWhiteSpace(value));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetRuntimeParameterAsync_AgainstLocalHistorian_ReturnsHistorianVersion()
|
||||
{
|
||||
string? host = Environment.GetEnvironmentVariable("HISTORIAN_HOST");
|
||||
if (string.IsNullOrWhiteSpace(host) || !string.Equals(host, "localhost", StringComparison.OrdinalIgnoreCase) || !OperatingSystem.IsWindows())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HistorianClient client = new(new HistorianClientOptions
|
||||
{
|
||||
Host = host,
|
||||
IntegratedSecurity = true,
|
||||
Transport = HistorianTransport.LocalPipe
|
||||
});
|
||||
|
||||
// GETRP rides the storage-session GUID as an uppercase string handle. HistorianVersion is
|
||||
// a known-good runtime parameter returning the server version (e.g. "20,0,000,000").
|
||||
string? value = await client.GetRuntimeParameterAsync("HistorianVersion", CancellationToken.None);
|
||||
|
||||
Assert.False(string.IsNullOrWhiteSpace(value));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetConnectionStatusAsync_AgainstLocalHistorian_ReportsConnectedToServer()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user