Merge b647-opcua-histstatus: OpcUaClient HistoryRead honours per-node StatusCode (#649)
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -124,6 +124,21 @@ DurationGood/Bad, PercentGood/Bad, WorstQuality, NumberOfTransitions, Annotation
|
||||
population StandardDeviation/Variance — each mapped to its OPC UA Part 13 standard aggregate NodeId; #285),
|
||||
and at-time reads are supported; each
|
||||
returned `DataValue` keeps its upstream `StatusCode` and timestamps verbatim.
|
||||
**The per-node `HistoryReadResult.StatusCode` is honoured (#649).** The driver never reads a Bad node status as
|
||||
empty data: `BadAggregateNotSupported` on a Processed read throws `HistoryAggregateNotSupportedException`, and any
|
||||
other Bad status (`BadUserAccessDenied`, `BadNodeIdUnknown`, `BadHistoryOperationUnsupported`, ...) throws
|
||||
`HistoryReadStatusException` carrying the code (the constructor rejects non-Bad codes). `Good`, `GoodNoData`,
|
||||
`GoodMoreData` (continuation point) and `Uncertain` are unchanged, and a node-level `BadNoData` is still an empty
|
||||
result. The status is matched on its code bits, so an info/overflow sub-status does not dodge the match.
|
||||
|
||||
⚠️ **This is currently latent.** The OtOpcUa server does not dispatch HistoryRead to a driver's `IHistoryProvider`
|
||||
(it serves only the server-wide `IHistorianDataSource`, see `docs/Historian.md`), so no OPC UA client of OtOpcUa
|
||||
sees this driver's history results or its refusals today. The server's HistoryRead arms (`ServeNodeAsync`,
|
||||
`ServeRawPagedAsync`) do map a `HistoryReadStatusException` thrown by an `IHistorianDataSource` to that node's
|
||||
status verbatim, and the driver/wire tests exercise that path; if driver history is ever routed to the server,
|
||||
refusals will reach clients correctly instead of as empty Good data. A routed deterministic refusal would also
|
||||
need excluding from the HistoryRead pipeline's retry/breaker handling.
|
||||
|
||||
Event-history (`ReadEventsAsync`) is left at the interface default — the
|
||||
interface doesn't yet carry the EventFilter surface needed to forward it.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user