Skip to content

Client Reading

Kevin Herron edited this page Oct 5, 2026 · 10 revisions

Read values with their quality and timestamps. These examples require a connected OpcUaClient and a NodeId the server exposes to the Session user.

Milo 1.2.0-SNAPSHOT, Java 17. Source baseline 7faaf4f0516c.

Read a value without discarding quality

client.readValue(maxAge, timestamps, nodeId) returns a DataValue. For a general attribute, build a ReadValueId and use client.read(...). Use NodeIds for standard namespace-zero nodes. For application nodes, resolve the namespace URI using the connected client's namespace table instead of persisting another server's numeric namespace index.

This helper requires an Int32 Variable. It rejects Bad and Uncertain results before interpreting the payload, and rejects a different Java type explicitly. The caller supplies nodeId; it neither connects nor disconnects the shared client.

static int readInt32(OpcUaClient client, NodeId nodeId) throws UaException {
  DataValue value = client.readValue(0.0, TimestampsToReturn.Both, nodeId);
  if (!value.statusCode().isGood()) throw new UaException(value.statusCode());
  Object body = value.value().value();
  if (!(body instanceof Integer integer)) {
    throw new IllegalArgumentException("Expected an Int32, got " + body);
  }
  return integer;
}

The fixture uses a local Int32 initially equal to zero, checks a missing node returns Bad_NodeIdUnknown, and checks that a DateTime payload does not pass as an Int32. Applications that deliberately accept some Uncertain qualities should implement that policy explicitly and preserve the original status.

Interpret DataValue and Variant

DataValue.value() is a Variant; the Variant's value() is its Java payload. A null payload is possible. Int32 uses Integer, Double uses Double, UInt32 uses UInteger, and OPC UA DateTime uses DateTime. An array or structure is not automatically a scalar Java value. Check the server's DataType and ValueRank before casting. Structured values commonly arrive as ExtensionObject; see Data types for decoding with the appropriate context.

statusCode() belongs to this operation or sample. A successful Read service does not make every returned value Good. An invalid NodeId, denied read, unavailable source, or invalid attribute can be reported in its individual DataValue while other results succeed.

sourceTime() describes the source's value timestamp; serverTime() describes the server's timestamp. They have different meanings and may be absent or null-valued. Request TimestampsToReturn.Both, Source, Server, or Neither according to need. Source timestamps apply to the Value attribute, not arbitrary node metadata. Do not use receipt time as a substitute without recording that change in meaning.

maxAge is in milliseconds. Zero requests a fresh read under the server's semantics; it does not guarantee a physical device acquisition for every call. Device caching, sampling, and unavailable sources remain server responsibilities.

Read batches and use asynchronous calls

readValues(maxAge, timestamps, nodeIds) returns results in request order. Keep that order associated with the input NodeIds, verify the expected number of results, and inspect each status. A batch is not a transaction or a guarantee that all source values were sampled together.

readValuesAsync(...) returns a future with the same per-item result semantics. readAsync(...) exposes the ReadResponse and its per-operation DataValues. High-level methods set ReturnDiagnostics=0, so they do not request DiagnosticInfos. To request them, construct a ReadRequest with a RequestHeader diagnostics mask and use sendRequest(...) or sendRequestAsync(...); the server may still omit them. Service faults and transport/session failures complete the future exceptionally; ordinary bad node results can arrive in a normally completed future. Attach error handling to the entire chain, including application decoding.

The service methods send the requested list as supplied. Partition large reads using Recovery and limits; MaxNodesPerRead is only one bound, and large arrays can hit message-size limits before node-count limits. Retrying an entire read batch is generally less consequential than retrying writes, but still decide whether historical consistency or cost makes a retry inappropriate.

Ownership and errors

Reads do not create a subscription or reserve a cursor. The client connection remains owned by its caller. Apply a bounded wait in top-level workflows; do not block callback threads. Retain status and timestamp data when handing a reading to storage or a UI. A cast exception describes an application/model mismatch and should not be reclassified as a network failure.

Examples and reference

Related pages

Client SDK · Client nodes · Data types · Recovery and limits

Clone this wiki locally