ICommAdapter

ifw::fnd::defs::ICommAdapter is the protocol-agnostic communication-adapter contract that every protocol-specific client library implements. It models the value-oriented control plane: read / write / call / browse / subscribe / configure / connect over arbitrary transports (OPC UA, Modbus, REST, MQTT, GenICam control plane, …).

Bulk media streaming (e.g. GenICam image acquisition) is out of scope and belongs to a peer interface composed alongside ICommAdapter, not derived from it.

Implementations

  • eso::uatools::Client (in uatools/ualib) – OPC UA over open62541. This is the reference implementation and exercises every surface op of the contract.

  • Other adapters (Modbus, REST, …) are downstream of ifw-fnd; ifw-fnd itself only owns the contract.

Core types

The contract is defined in <ifw/fnd/defs/iCommAdapter.hpp>. Key types:

Type

Purpose

Address

String identifier of a remote item (e.g. "ns=2;s=system.Counter" for OPC UA, a register address for Modbus). Adapter-specific format; the core treats it opaquely.

Value

A std::variant of supported scalar/vector types plus a PropertyMap. Carries the on-wire value for read/write/call.

PropertyMap

Order-preserving string-keyed dictionary used both as a configuration escape hatch and as a structured Value payload.

Status

Protocol-agnostic outcome classification: Ok, Timeout, NotConnected, BadRequest, NotFound, AccessDenied, Cancelled, Unsupported, RemoteError, …

RequestOptions

Per-call options bundle. Carries timeout, an optional CancellationToken, and per-call properties.

CancellationToken / CancellationSource

Cooperative cancellation. The token is cheap to copy; the source is held by the issuing thread and used to abort an in-flight call.

RegistrationToken

RAII handle for observer registration (connection-state handler). Move-only; destruction unregisters.

Operations

The contract is built by addition – new methods carry default implementations returning Status::Unsupported so existing implementers keep compiling. The current surface:

Method

Purpose

Configure(opts)

Apply connection / behavioural options (endpoint, credentials, transport-specific knobs). Must not run concurrently with Connect / Disconnect or data ops.

Connect() / Disconnect()

Open / close the underlying transport. State transitions are observable via a connection-state handler.

Read(request) / Write(request)

Batched read / write of node values.

Call(request)

Invoke a remote method / RPC with typed arguments and outputs.

Browse(request)

List the address space (children of a starting node).

Subscribe(nodes, handler, opts)

Register a per-node SubscriptionHandler for change notifications. The handler is invoked off the data-plane thread (no ifw-fnd mutex held).

Unsubscribe(nodes) / UnsubscribeAll()

Drop subscriptions individually or globally.

Discover(request)

Endpoint / device discovery. Deferred in current implementations (returns Status::Unsupported).

Thread-safety contract

The contract specifies the threading guarantees consumers can rely on:

  • Const query methods (Is*, Get*) are callable from any thread at any time.

  • Read / Write / Call / Browse / Discover may be called concurrently with each other and with active subscriptions; implementations serialise as needed.

  • Configure / Connect / Disconnect must NOT run concurrently with each other or with data operations; the caller owns lifecycle ordering.

  • SubscriptionHandler and connection-state handlers run on the adapter’s internal thread(s). Each handler’s specific contract is documented at the registration point.

Versioning

kCommAdapterContractVersion is the integer version stamp on the contract. Bumps on additive evolution are silent for callers (they keep compiling because new methods carry default implementations). Breaking bumps require a coordinated migration across all implementers and consumers; before the first adapter shipped, breaking changes were free.

For the full type definitions, read <ifw/fnd/defs/iCommAdapter.hpp> – it’s the source of truth.