Repository navigation
Client Writing
Write a value only after checking its model and the user's permission. A connected client, a writable Variable, and the correct value representation are prerequisites.
Milo 1.2.0-SNAPSHOT, Java 17. Source baseline 7faaf4f0516c.
Read the Variable's DataType, ValueRank, ArrayDimensions, AccessLevel, and UserAccessLevel when discovering a writable node. Access metadata is useful guidance; the Write result is authoritative and permissions may change between discovery and writing. An Int32 expects an Integer, not a Long or a numeric String. Use Milo unsigned types for unsigned values. Supply an array or matrix representation compatible with ValueRank and dimensions. Use the encoding/structure rules in Data types for custom values.
Use DataValue.valueOnly(...) for a normal value write. Supplying status or timestamps asks the server to accept those fields too; many Variables do not support them and can return Bad_WriteNotSupported.
This helper writes one Int32 value and accepts only Good operation status. Its caller supplies an existing connected client and the target NodeId.
static void writeInt32(OpcUaClient client, NodeId nodeId, int value) throws UaException {
DataValue dataValue = DataValue.valueOnly(new Variant(value));
List<StatusCode> results = client.writeValues(List.of(nodeId), List.of(dataValue));
StatusCode status = results.get(0);
if (!status.isGood()) {
throw new UaException(status);
}
}The local fixture writes 42 and reads it back, then sends a String to the same Int32 Variable. It checks Bad_TypeMismatch and verifies the successful value remains. Reading back confirms what this server exposes after the Write; it does not establish that an external actuator physically reached a state.
For several Variables, writeValues(nodeIds, values) requires corresponding input lists. Its result list follows that order. write(List<WriteValue>) exposes attribute IDs and optional index ranges, and returns the full WriteResponse. Check each operation result even when the service itself succeeds. Common failures include Bad_NodeIdUnknown, Bad_TypeMismatch, Bad_NotWritable, Bad_UserAccessDenied, and unsupported index ranges.
A batch may partially succeed. It is not a transaction and Milo does not roll back successful operations when another fails. Record which operations succeeded before deciding what to retry or compensate.
UaVariableNode.writeValue(...) and its attribute writers throw only for Bad status; Uncertain returns normally and updates the local cache. Common UaNode attribute writers reject any non-Good result. Most generated model-property writers do too, but 23 generated writers with multiline signatures still discard the returned status at this baseline, including ServerDiagnosticsTypeNode.writeServerDiagnosticsSummary(...). Use the async property writer and inspect its StatusCode when that guarantee matters. Successful attribute writers update their cached attribute; generated property writers delegate to raw attribute writes and do not refresh the property cache. This differs from low-level status-returning methods such as writeAttribute(...) and client.writeValues(...). Do not write code that ignores those returned statuses because a typed writer elsewhere throws.
For asynchronous Value writes, use writeAttributeAsync(AttributeId.Value, ...), which returns a future containing a StatusCode; there is no UaVariableNode.writeValueAsync(...). Generated asynchronous property writers also expose a status. Inspect it after normal completion; exceptional completion still represents a service, transport, or application error. For batch writes, writeValuesAsync(...) returns the status list and writeAsync(...) returns the complete response.
A local setValue(...) on a client node changes its cache. It does not send a Write. Use a remote writeValue(...), or deliberately synchronize selected cached attributes as described in Client nodes.
A timeout or broken connection can leave the outcome unknown: the server may have acted before the response was lost. Do not automatically repeat a command-like write. Read back when that establishes the desired postcondition, or use an application operation identifier/deduplication scheme when the server supports one. Request partitioning must preserve this per-operation accounting.
Writes allocate no long-lived server resource. The caller retains the client and controls its shutdown. Avoid blocking subscription callbacks while performing synchronous writes; hand work to an application executor with bounded queues and explicit error handling.
-
WriteExample: Write scalar values and inspect their statuses.
-
ReadWriteCustomDataTypeNodeExample: Read and write application structures with typed model nodes.
Client SDK · Data types · Client nodes · Recovery and limits
User guide for Milo 1.2.0-RC1 at source 69cb25087, 2026-10-12. Home · Getting started · Examples · Troubleshooting · Release notes
- Home
- Start here
- Client guide
- Server guide
- Feature guides
- Reference
- Operations
- Examples
- Release notes
- Contributing