Replace direct SQL queries against Historian Runtime database with the Wonderware Historian managed SDK (ArchestrA.HistorianAccess). Add HistoryServerCapabilities node, AggregateFunctions folder, continuation points, ReadAtTime interpolation, ReturnBounds, ReadModified rejection, HistoricalDataConfiguration per node, historical event access, and client-side StandardDeviation aggregate support. Remove screenshot tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
10 KiB
Historian Implementation Gap Analysis
Comparison of the current LmxOpcUa server historian implementation against the OPC UA Part 11 Historical Access specification requirements.
Current Implementation Summary
| Feature | Status |
|---|---|
| HistoryRead — ReadRawModifiedDetails | Implemented (raw only, no modified) |
| HistoryRead — ReadProcessedDetails | Implemented (7 aggregates) |
| Historizing attribute on nodes | Implemented |
| AccessLevel.HistoryRead on nodes | Implemented |
| Quality mapping (OPC DA → OPC UA) | Implemented |
| Historian SDK (aahClientManaged) | Implemented (replaced direct SQL) |
| Configurable enable/disable | Implemented |
| SDK packet timeout | Implemented |
| Max values per read | Implemented |
| HistoryServerCapabilities node | Implemented |
| AggregateFunctions folder | Implemented (7 functions) |
| Continuation points for history reads | Implemented |
Gaps
1. HistoryServerCapabilities Node (Required) — RESOLVED
Spec requirement: All OPC UA servers supporting Historical Access SHALL include a HistoryServerCapabilities object under ServerCapabilities. This is mandatory, not optional.
Current state: Implemented. The server populates all HistoryServerCapabilities variables at startup via LmxOpcUaServer.ConfigureHistoryCapabilities(). All boolean capabilities are set, and MaxReturnDataValues reflects the configured limit.
Required variables:
| Variable | Expected Value | Priority |
|---|---|---|
AccessHistoryDataCapability |
true |
High |
AccessHistoryEventsCapability |
false |
High |
MaxReturnDataValues |
configurable (e.g., 10000) | High |
MaxReturnEventValues |
0 | Medium |
InsertDataCapability |
false |
Medium |
ReplaceDataCapability |
false |
Medium |
UpdateDataCapability |
false |
Medium |
DeleteRawCapability |
false |
Medium |
DeleteAtTimeCapability |
false |
Medium |
InsertAnnotationCapability |
false |
Low |
InsertEventCapability |
false |
Low |
ReplaceEventCapability |
false |
Low |
UpdateEventCapability |
false |
Low |
DeleteEventCapability |
false |
Low |
ServerTimestampSupported |
true |
Medium |
Files to modify: LmxOpcUaServer.cs or LmxNodeManager.cs — create and populate the HistoryServerCapabilities node in the server's address space during startup.
2. AggregateFunctions Folder (Required) — RESOLVED
Spec requirement: The HistoryServerCapabilities object SHALL contain an AggregateFunctions folder listing all supported aggregate functions as child nodes. Clients browse this folder to discover available aggregates.
Current state: Implemented. The AggregateFunctions folder under HistoryServerCapabilities is populated with references to all 7 supported aggregate function ObjectIds at startup.
Required: Create AggregateFunctions folder under HistoryServerCapabilities with references to the 7 supported aggregate ObjectIds:
AggregateFunction_AverageAggregateFunction_MinimumAggregateFunction_MaximumAggregateFunction_CountAggregateFunction_StartAggregateFunction_EndAggregateFunction_StandardDeviationPopulation
Priority: Medium
3. Continuation Points for History Reads (Required) — RESOLVED
Spec requirement: When a HistoryRead result exceeds MaxReturnDataValues or the client's NumValuesPerNode, the server SHALL return a ContinuationPoint in the result. The client then issues follow-up HistoryRead calls with the continuation point to retrieve remaining data. The server must maintain state for active continuation points and release them when complete or on timeout.
Current state: Implemented. HistoryContinuationPointManager stores remaining data keyed by GUID. Both HistoryReadRawModified and HistoryReadProcessed return a ContinuationPoint when results exceed NumValuesPerNode. Follow-up requests with the continuation point resume from stored state. Points expire after 5 minutes. Invalid or expired points return BadContinuationPointInvalid.
Priority: High (resolved)
4. ReadModified Support — RESOLVED
Spec requirement: ReadRawModifiedDetails has an IsReadModified flag. When true, the server should return the original value before modification along with the modification info (who modified, when, what the original value was). This is part of audit trail / data integrity use cases.
Current state: Implemented. HistoryReadRawModified checks details.IsReadModified and returns BadHistoryOperationUnsupported when true, since the Wonderware Historian does not expose modification history.
5. ReadAtTimeDetails — RESOLVED
Spec requirement: ReadAtTimeDetails allows a client to request interpolated values at specific timestamps (not raw samples). The server interpolates between the two nearest raw values for each requested timestamp.
Current state: Implemented. LmxNodeManager overrides HistoryReadAtTime. HistorianDataSource.ReadAtTimeAsync uses the Historian SDK with HistorianRetrievalMode.Interpolated to query interpolated values at each requested timestamp.
6. HistoryUpdate Service (Insert/Replace/Delete) — RESOLVED (N/A)
Spec requirement: The HistoryUpdate service allows clients to insert new values, replace existing values, update (insert or replace), and delete historical data. Each capability is separately advertised via the HistoryServerCapabilities node.
Current state: Not applicable. The Historian is read-only. All write capability booleans (InsertDataCapability, ReplaceDataCapability, UpdateDataCapability, DeleteRawCapability, DeleteAtTimeCapability) are explicitly set to false in ConfigureHistoryCapabilities(). No HistoryUpdate override exists, which is correct.
7. HistoryReadEventDetails (Historical Events) — RESOLVED
Spec requirement: Servers supporting historical event access implement HistoryReadEventDetails to retrieve past event notifications (e.g., alarm history).
Current state: Implemented. LmxNodeManager overrides HistoryReadEvents. HistorianDataSource.ReadEventsAsync uses the Historian SDK with a separate HistorianConnectionType.Event connection and EventQuery to retrieve historical alarm/event records. Events are mapped to OPC UA HistoryEventFieldList entries with standard fields (EventId, EventType, SourceNode, SourceName, Time, ReceiveTime, Message, Severity). AccessHistoryEventsCapability is set to true when alarm tracking is enabled.
8. HistoricalDataConfiguration Node — RESOLVED
Spec requirement: Each historized node SHOULD have a HistoricalDataConfiguration child object with properties describing how its history is stored: Stepped (interpolation type), MinTimeInterval, MaxTimeInterval, ExceptionDeviation, etc.
Current state: Implemented. Historized variables receive a HistoricalDataConfigurationState child node with Stepped = false and Definition = "Wonderware Historian". Recording parameters (intervals, deadbands) are not available from the Galaxy DB, so default values are used.
9. AggregateConfiguration — RESOLVED (N/A)
Spec requirement: The AggregateConfiguration object (child of HistoricalDataConfiguration or HistoryServerCapabilities) defines default aggregate behavior: TreatUncertainAsBad, PercentDataBad, PercentDataGood, UseSlopedExtrapolation.
Current state: Not applicable. The server delegates aggregation entirely to the Wonderware Historian's pre-computed summary tables, so these parameters are not actionable. Aggregate discovery is fully supported via the AggregateFunctions folder.
10. ReturnBounds Parameter — RESOLVED
Spec requirement: When ReturnBounds=true in ReadRawModifiedDetails, the server should return bounding values at the start and end of the requested time range, even if no raw samples exist at those exact times.
Current state: Implemented. When ReturnBounds is true, AddBoundingValues inserts boundary DataValue entries at StartTime and EndTime with StatusCodes.BadBoundNotFound if no sample exists at those exact times.
11. Client-Side: StandardDeviation Aggregate — RESOLVED
Current state: Implemented. AggregateType.StandardDeviation added to enum, AggregateTypeMapper, CLI parser (aliases: stddev, stdev), and UI dropdown. Full end-to-end support from client to server for the AggregateFunction_StandardDeviationPopulation aggregate.
Recommended Implementation Order
| Priority | Gap | Effort |
|---|---|---|
References
- OPC UA Part 11: Historical Access — Concepts
- OPC UA Part 11: Historical Access — HistoryServerCapabilitiesType
- OPC UA Part 11: Historical Access — Service Usage
- OPC UA Part 11: Historical Access — Data Architecture
- UA-.NETStandard Historical Access Overview
- OPC Foundation Historical Data Access Wiki