Auto: opcuaclient-12 — IHistoryProvider.ReadEventsAsync EventFilter spec + impl
Adds a filter-aware overload of IHistoryProvider.ReadEventsAsync that carries EventFilter SelectClauses + WhereClause, and implements it on the OPC UA Client driver via Session.HistoryReadAsync + ReadEventDetails. The change is additive (default-impl returns NotSupportedException) so the existing Galaxy.Proxy.GalaxyProxyDriver implementation keeps compiling against the fixed-field overload — no cross-driver refactor required. * Core.Abstractions: new EventHistoryRequest / SimpleAttributeSpec / ContentFilterSpec records mirror the OPC UA wire shape transport-neutrally. HistoricalEventBatch / HistoricalEventRow carry an open-ended Fields bag keyed by SimpleAttributeSpec.FieldName so server-side dispatch can re-align with the client's wire-side SelectClause order. * OpcUaClient driver: new ReadEventsAsync(fullReference, EventHistoryRequest, ct) builds an EventFilter, calls Session.HistoryReadAsync, and unwraps HistoryEvent.Events into HistoricalEventBatch rows. Default SelectClause set matches BuildHistoryEvent on the server side. ContentFilter bytes are decoded through the live session's MessageContext (passthrough — the driver does not evaluate filters). * Unit tests: 7 new tests cover SelectClause translation, default-clause fallback, malformed where-clause swallowing, uninitialized-driver guard, null-request guard, and IHistoryProvider default fallback. * Integration scaffold: build-only [Fact] gated on opc-plc --alm; flips to green when the fixture image is upgraded. * Docs: HistoryRead Events section in docs/drivers/OpcUaClient.md plus a cross-link from Client.CLI.md historyread page. * E2E: -HistoryEvents switch on scripts/e2e/test-opcuaclient.ps1 confirms the gateway round-trips HistoryReadEvents without BadHistoryOperationUnsupported (gated; defaults to skip). Closes #284
This commit is contained in:
@@ -86,7 +86,16 @@ param(
|
||||
[string]$UpstreamNodeId = "ns=3;s=StepUp",
|
||||
[int]$ChangeWaitSec = 10,
|
||||
[switch]$ReverseConnect,
|
||||
[string]$ReverseListenerUrl = "opc.tcp://0.0.0.0:4844"
|
||||
[string]$ReverseListenerUrl = "opc.tcp://0.0.0.0:4844",
|
||||
# PR-12: HistoryReadEvents passthrough check. Requires the upstream to be running
|
||||
# in alarm-history mode (opc-plc --alm) AND the OtOpcUa server to expose a notifier
|
||||
# node bridged to the upstream's events source. The CLI doesn't have a dedicated
|
||||
# event-history command yet; this stage runs a regular historyread against the
|
||||
# bridged notifier and confirms the gateway round-trips the request without
|
||||
# surfacing BadHistoryOperationUnsupported, which would indicate the filter-aware
|
||||
# ReadEventsAsync path lost wiring.
|
||||
[switch]$HistoryEvents,
|
||||
[string]$EventsNotifierNodeId = "i=2253"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -164,6 +173,33 @@ if ($triggerCmd) {
|
||||
$results += [pscustomobject]@{ Stage = "Topology-change"; Status = "SKIP" }
|
||||
}
|
||||
|
||||
# Stage 5 (gated): HistoryReadEvents passthrough
|
||||
#
|
||||
# PR-12 lands the filter-aware IHistoryProvider.ReadEventsAsync overload on the
|
||||
# OPC UA Client driver. End-to-end coverage requires:
|
||||
# (a) the upstream in alarm-history mode (opc-plc --alm or a real server);
|
||||
# (b) the OtOpcUa server forwarding HistoryReadEvents to the gateway driver.
|
||||
# Gated behind -HistoryEvents because the default opc-plc fixture image isn't
|
||||
# launched with --alm. When set, the stage issues a historyread against the
|
||||
# bridged notifier ($EventsNotifierNodeId) and confirms the gateway returns
|
||||
# the request without BadHistoryOperationUnsupported.
|
||||
if ($HistoryEvents) {
|
||||
Write-Host "[INFO] HistoryEvents stage: issuing historyread against $EventsNotifierNodeId"
|
||||
$start = (Get-Date).ToUniversalTime().AddMinutes(-30).ToString("o")
|
||||
$end = (Get-Date).ToUniversalTime().AddMinutes(1).ToString("o")
|
||||
$eventOut = & $opcUaCli.Cmd @($opcUaCli.Args + @(
|
||||
"historyread", "-u", $OpcUaUrl, "-n", $EventsNotifierNodeId,
|
||||
"--start", $start, "--end", $end))
|
||||
if ($LASTEXITCODE -eq 0 -and $eventOut -notmatch "BadHistoryOperationUnsupported") {
|
||||
$results += [pscustomobject]@{ Stage = "HistoryReadEvents"; Status = "PASS" }
|
||||
} elseif ($eventOut -match "BadHistoryOperationUnsupported") {
|
||||
Write-Host "[INFO] Upstream returned BadHistoryOperationUnsupported — re-run with --alm + a notifier that has event history."
|
||||
$results += [pscustomobject]@{ Stage = "HistoryReadEvents"; Status = "SKIP" }
|
||||
} else {
|
||||
$results += [pscustomobject]@{ Stage = "HistoryReadEvents"; Status = "FAIL" }
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=== test-opcuaclient.ps1 results ==="
|
||||
$results | Format-Table -AutoSize
|
||||
|
||||
Reference in New Issue
Block a user