Full read-only SDK (src/AVEVA.Historian.Client) implementing the CLAUDE.md required
surface against AVEVA Historian's binary WCF protocol — no native AVEVA runtime
dependency. All operations live-verified against a local Historian:
- ProbeAsync, ReadRawAsync, ReadAggregateAsync, ReadAtTimeAsync, ReadEventsAsync
- BrowseTagNamesAsync, GetTagMetadataAsync (17 native data-type codes mapped)
- GetConnectionStatusAsync, GetStoreForwardStatusAsync, GetSystemParameterAsync
- 108/108 unit + integration tests pass
Includes the reverse-engineering toolkit (tools/AVEVA.Historian.ReverseEngineering)
used to decode the protocol: WCF probes, IL inspection via dnlib, and IL-rewrite
instrumentation (instrument-wcf-{write,read}message etc.) plus the .NET Framework
trace harness (tools/AVEVA.Historian.NativeTraceHarness) for parity testing.
Sanitized handoff evidence under docs/reverse-engineering/. Native AVEVA binaries
(current/, aveva-install-x64/, aveva-install-x86/) are gitignored — fetch separately
from the AVEVA installer.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.6 KiB
AGENTS.md
Mission
Build a fully managed .NET 10 replacement for AVEVA Historian's
aahClientManaged / aahClient.dll stack by reverse-engineering the native
binary Historian protocol.
The target is an in-process managed SDK that can replace the current .NET
Framework/native sidecar used by OtOpcUa.Driver.Historian.Wonderware.
Chosen Approach
Use the reverse-engineering path from instructions.md:
- Decompile
current\aahClientManaged.dllto understand the managed wrapper surface, connection flow, query types, data models, error handling, and native calls. - Inspect
current\aahClient.dlland the matching AVEVA install DLLs to map the native ABI and identify transport/framing responsibilities. - Capture traffic from real Historian sessions and derive the on-the-wire protocol for the required read-only operations.
- Implement the protocol in a pure managed .NET 10 client.
Do not pursue the REST API implementation unless explicitly asked. Do not build a P/Invoke shim as the primary solution; it is useful only as an analysis aid.
Repository Layout
This workspace is an SDK investigation folder, not a full application repo.
instructions.md- source planning document and decision record.current\- the seven DLLs the existing sidecar links against today.aveva-install-x64\- full 64-bit AVEVA Historian client-side DLL set.aveva-install-x86\- full 32-bit AVEVA Historian client-side DLL set.
Use current\ first because it represents the deployed sidecar dependency set.
Use aveva-install-* to compare architecture-specific behavior and locate
adjacent client APIs.
Required SDK Surface
Keep the managed SDK narrowly scoped to the operations used in production:
ReadRawAsync(tag, startUtc, endUtc, maxValues)ReadAggregateAsync(tag, startUtc, endUtc, mode, interval)ReadAtTimeAsync(tag, timestampsUtc)ReadEventsAsync(startUtc, endUtc)ProbeAsync()
The existing alarm-event write path is dormant. Do not implement write-back unless a new requirement is supplied.
Reverse-Engineering Workflow
1. Managed Wrapper Analysis
Use dnSpy or ILSpy on current\aahClientManaged.dll.
Document:
- Public types and methods used for connections and queries.
- P/Invoke or native interop entry points.
- Constructor arguments, enum values, flags, and default values.
- Query argument structures for raw, aggregate, at-time, and event reads.
- Returned sample/event models, quality fields, timestamp handling, and error propagation.
Prefer producing small Markdown notes under a future docs\reverse-engineering\
folder rather than relying on memory.
2. Native ABI Mapping
Inspect current\aahClient.dll and compare with:
aveva-install-x64\aahClient.dllaveva-install-x86\aahClient.dllaahClientCommon.dllaahDataSetClient.dllaahClientConfig.dll
Useful tools:
dumpbin /exports- Dependencies or Process Monitor
- API Monitor
- Detours or equivalent call hooks
Document function names, calling conventions, pointer ownership, HRESULT/error patterns, string encodings, and architecture differences.
3. Wire Capture
Capture real Historian sessions with Wireshark while running the existing Wonderware sidecar/client against a development Historian.
Capture each scenario independently:
- Connection open/close and health probe.
- Raw history query.
- Aggregate query for each required retrieval mode.
- At-time/interpolated query.
- Event query.
- Error cases: bad tag, empty range, invalid credentials, server offline.
For every capture, record:
- Historian version and architecture.
- Client DLL version and file hash.
- Server host/port.
- Query parameters.
- Expected logical result set.
- Packet capture filename.
Do not commit sensitive packet captures, credentials, server names, or customer tag names. Sanitize before adding any fixtures or notes.
4. Protocol Model
Derive and document:
- Session handshake.
- Authentication exchange, if present.
- Message framing and length prefixes.
- Message type identifiers.
- Request/response correlation.
- Endianness.
- Timestamp encoding.
- String encoding.
- Numeric value encoding.
- Quality/status encoding.
- Error frame format.
- Event payload format.
Add version notes whenever behavior differs between the installed 2020 DLLs and newer Historian versions.
5. Managed Implementation Shape
When implementation starts, use this project shape unless the real repo dictates otherwise:
src/AVEVA.Historian.Client/
AVEVA.Historian.Client.csproj
HistorianClient.cs
HistorianClientOptions.cs
Models/
HistorianSample.cs
HistorianAggregateSample.cs
HistorianEvent.cs
RetrievalMode.cs
Protocol/
HistorianConnection.cs
HistorianFrame.cs
HistorianMessageType.cs
HistorianProtocolReader.cs
HistorianProtocolWriter.cs
Transport/
TcpHistorianTransport.cs
ClusterEndpointPicker.cs
Internal/
BackoffPolicy.cs
Keep protocol parsing isolated from transport I/O so captured frames can be tested without a live Historian.
Testing Expectations
Start with deterministic tests around protocol encoding/decoding:
- Golden byte fixtures for each message kind.
- Round-trip tests for request builders.
- Parser tests for captured and sanitized response frames.
- Timestamp, quality, and string encoding edge cases.
- Error frame parsing.
Add live integration tests only behind explicit configuration, such as:
HISTORIAN_HOSTHISTORIAN_PORTHISTORIAN_USERHISTORIAN_PASSWORDHISTORIAN_TEST_TAG
Integration tests must skip cleanly when these values are not configured.
Constraints
- Keep the final SDK pure managed .NET 10.
- Avoid adding native runtime dependencies to the production SDK.
- Avoid broad API design. Implement only the operations listed above.
- Treat AVEVA protocol details as version-sensitive; document assumptions.
- Do not redistribute AVEVA binaries.
- Do not commit credentials, proprietary captures, or customer data.
- Do not delete or overwrite DLLs in
current\oraveva-install-*.
Definition of Done
For the reverse-engineering phase:
- Managed wrapper public surface and native entry points are documented.
- Required query flows have sanitized captures or byte-level notes.
- Message framing, request fields, response fields, and error frames are described well enough to implement parser tests.
For the SDK phase:
- The managed client implements the required read-only surface.
- Unit tests cover protocol parse/build behavior.
- Integration tests can validate against a configured live Historian.
- The SDK can replace the existing sidecar call sites without requiring
aahClientManaged.dlloraahClient.dllat runtime.