Files
histsdk/AGENTS.md
T
dohertj2 c95824a65d Initial commit: managed .NET 10 AVEVA Historian SDK + reverse-engineering toolkit
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>
2026-05-04 06:31:48 -04:00

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:

  1. Decompile current\aahClientManaged.dll to understand the managed wrapper surface, connection flow, query types, data models, error handling, and native calls.
  2. Inspect current\aahClient.dll and the matching AVEVA install DLLs to map the native ABI and identify transport/framing responsibilities.
  3. Capture traffic from real Historian sessions and derive the on-the-wire protocol for the required read-only operations.
  4. 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.dll
  • aveva-install-x86\aahClient.dll
  • aahClientCommon.dll
  • aahDataSetClient.dll
  • aahClientConfig.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_HOST
  • HISTORIAN_PORT
  • HISTORIAN_USER
  • HISTORIAN_PASSWORD
  • HISTORIAN_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\ or aveva-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.dll or aahClient.dll at runtime.