### Build the project with Maven Source: https://github.com/eclipse-milo/milo/blob/main/README.md Execute a clean install of the project using the toolchain managed by mise. ```shell mise exec -- mvn clean install ``` -------------------------------- ### Install project dependencies with mise Source: https://github.com/eclipse-milo/milo/blob/main/README.md Use this command to install the project's pinned Java and Maven toolchain versions. ```shell mise install ``` -------------------------------- ### Browse References and Nodes with UaNode API Source: https://github.com/eclipse-milo/milo/wiki/Client Use UaNode#browse to get ReferenceDescriptions or UaNode#browseNodes to get target UaNode instances. This example demonstrates browsing for HasProperty references. ```java BrowseOptions browseOptions = BrowseOptions.builder() .setReferenceType(Identifiers.HasProperty) .build(); // Browse for HasProperty references List references = node.browse(browseOptions); // Browse for HasProperty references and get the UaNodes they target List nodes = node.browseNodes(browseOptions); ``` -------------------------------- ### Browse Nodes with Custom Options Source: https://github.com/eclipse-milo/milo/wiki/Client Use AddressSpace#browseNodes with custom BrowseOptions to filter the types of references to retrieve. This example specifically retrieves nodes referenced by HasProperty. ```java AddressSpace addressSpace = client.getAddressSpace(); UaNode serverNode = addressSpace.getNode(Identifiers.Server); BrowseOptions browseOptions = addressSpace.getBrowseOptions().copy( b -> b.setReferenceType(BuiltinReferenceType.HasProperty) ); // just UaNodes referenced by HasProperty references List nodes = addressSpace.browseNodes(serverNode, browseOptions); ``` -------------------------------- ### Get Endpoints with DiscoveryClient Source: https://github.com/eclipse-milo/milo/wiki/Client Retrieves a list of EndpointDescriptions from a remote OPC UA server using the DiscoveryClient. This is a prerequisite for establishing a connection. ```java List endpoints = DiscoveryClient.getEndpoints(endpointUrl).get(); ``` -------------------------------- ### Write Node Value with UaNode API Source: https://github.com/eclipse-milo/milo/wiki/Client Write node values using UaNode#writeValue() or UaNode#writeAttribute(). This example demonstrates writing a new value to the Value attribute. ```java UaVariableNode testNode = (UaVariableNode) addressSpace.getNode( new NodeId(2, "TestInt32") ); // Write the Value attribute; throws UaException if the write fails testNode.writeValue(new Variant(42)); // Most servers don't allow quality or timestamps to be written, // hence the use of DataValue.valueOnly(), but this method could // be used to write to a server that did support it if necessary StatusCode statusCode = testNode.writeAttribute( AttributeId.Value, DataValue.valueOnly(new Variant(42)) ); ``` -------------------------------- ### Access Local UaNode Attributes Source: https://github.com/eclipse-milo/milo/wiki/Client Access local copies of UaNode attributes using get() methods. These values are available without a server round-trip. ```java Use the `get()` methods to access these values. ``` -------------------------------- ### Read Node Attributes with UaNode API Source: https://github.com/eclipse-milo/milo/wiki/Client Read node attributes directly using UaNode methods like readValue() or readAttribute(). This example shows reading the Value and BrowseName attributes. ```java UaVariableNode testNode = (UaVariableNode) addressSpace.getNode( new NodeId(2, "TestInt32") ); // Read the Value attribute DataValue value = testNode.readValue(); // Read the BrowseName attribute QualifiedName browseName = testNode.readBrowseName(); // Read the Description attribute, with timestamps and quality intact DataValue descriptionValue = testNode.readAttribute(AttributeId.Description); ``` -------------------------------- ### Execute build and verification commands Source: https://github.com/eclipse-milo/milo/blob/main/CONTRIBUTING.md Commands to run the test suite and apply code formatting using mise and Maven. ```bash mise exec -- mvn clean verify ``` ```bash mise exec -- mvn spotless:apply ``` -------------------------------- ### Configure Wireshark Key Logging for Server Source: https://github.com/eclipse-milo/milo/blob/main/docs/features/wireshark-key-log.md Use WiresharkKeyLogWriter to log server-side security keys to a file for later decryption in Wireshark. ```java Path keyLogFile = Path.of("/tmp/opcua_server_keys.log"); var writer = new WiresharkKeyLogWriter(keyLogFile); OpcUaServerConfig config = OpcUaServerConfig.builder() .setSecurityKeysListener(writer) // ... other config ... .build(); OpcUaServer server = new OpcUaServer(config, transportFactory); server.startup().get(); // ... server runs ... writer.close(); ``` -------------------------------- ### Run Wireshark Key Log Tests Source: https://github.com/eclipse-milo/milo/blob/main/docs/features/wireshark-key-log.md Executes the specific test classes for SecurityKeyset and WiresharkKeyLogWriter using Maven. ```bash mise exec -- mvn -q verify -pl opc-ua-stack/stack-core \ -Dtest="SecurityKeysetTest,WiresharkKeyLogWriterTest" ``` -------------------------------- ### Configure Wireshark Key Logging for Client Source: https://github.com/eclipse-milo/milo/blob/main/docs/features/wireshark-key-log.md Use WiresharkKeyLogWriter to log client-side security keys to a file for later decryption in Wireshark. ```java Path keyLogFile = Path.of("/tmp/opcua_client_keys.log"); var writer = new WiresharkKeyLogWriter(keyLogFile); OpcUaClientConfig config = OpcUaClientConfig.builder() .setSecurityKeysListener(writer) // ... other config ... .build(); OpcUaClient client = OpcUaClient.create(config); client.connect(); // ... use the client ... writer.close(); // flush and close when done ``` -------------------------------- ### Calling Methods Source: https://github.com/eclipse-milo/milo/wiki/Client Demonstrates three ways to call methods on an OPC UA server: using UaObjectNode#callMethod, finding a UaMethod and invoking call, and using the lower-level OpcUaClient#call API. ```APIDOC ## Calling Methods Methods can be called using either the high or low level APIs: 1. Using `UaObjectNode#callMethod`: ```java UaObjectNode serverNode = addressSpace.getObjectNode(Identifiers.Server); Variant[] outputs = serverNode.callMethod( "GetMonitoredItems", new Variant[]{ new Variant(subscription.getSubscription().getSubscriptionId()) } ); ``` 2. Finding a `UaMethod` and invoking `UaMethod#call`: ```java UaObjectNode serverNode = addressSpace.getObjectNode(Identifiers.Server); UaMethod getMonitoredItems = serverNode.getMethod("GetMonitoredItems"); Variant[] outputs = getMonitoredItems.call( new Variant[]{ new Variant(subscription.getSubscription().getSubscriptionId()) } ); ``` The `UaMethod` object also has a copy of the input and output defined by the method: ```java Argument[] inputArguments = getMonitoredItems.getInputArguments(); Argument[] outputArguments = getMonitoredItems.getOutputArguments(); ``` When a method does not define input or output arguments the corresponding `Argument[]` will be empty. 3. `OpcUaClient#call`, a lower level API That takes parameters corresponding directly to those defined by the Call service in the OPC UA spec: ```java NodeId objectId = NodeId.parse("ns=2;s=HelloWorld"); NodeId methodId = NodeId.parse("ns=2;s=HelloWorld/sqrt(x)"); CallMethodRequest request = new CallMethodRequest( objectId, methodId, new Variant[]{new Variant(input)} ); return client.call(request).thenCompose(result -> { StatusCode statusCode = result.getStatusCode(); if (statusCode.isGood()) { Double value = (Double) l(result.getOutputArguments()).get(0).getValue(); return CompletableFuture.completedFuture(value); } else { StatusCode[] inputArgumentResults = result.getInputArgumentResults(); for (int i = 0; i < inputArgumentResults.length; i++) { logger.error("inputArgumentResults[{}]={}", i, inputArgumentResults[i]); } CompletableFuture f = new CompletableFuture<>(); f.completeExceptionally(new UaException(statusCode)); return f; } }); ``` See `MethodExample.java` in the `client-examples` Maven module for the full source code. ``` -------------------------------- ### Create ManagedSubscription Source: https://github.com/eclipse-milo/milo/wiki/Client Instantiate a `ManagedSubscription` using `ManagedSubscription.create(client)` for managing subscriptions and monitored items at a higher level. ```java ManagedSubscription subscription = ManagedSubscription.create(client); ``` ```java ManagedSubscription subscription = ManagedSubscription.create(client, 250.0); ``` -------------------------------- ### Browse Nodes with Default Options Source: https://github.com/eclipse-milo/milo/wiki/Client Use AddressSpace#browseNodes with default BrowseOptions to retrieve nodes referenced by a given node. ```java AddressSpace addressSpace = client.getAddressSpace(); UaNode serverNode = addressSpace.getNode(Identifiers.Server); List nodes = addressSpace.browseNodes(serverNode); ``` -------------------------------- ### Low-Level Browse Service Source: https://github.com/eclipse-milo/milo/wiki/Client Use OpcUaClient#browse for direct interaction with the Browse service as defined in the OPC UA spec. This method requires manual handling of continuation points for full results. ```java // Browse for forward hierarchal references from the Objects folder // that lead to other Object and Variable nodes. BrowseDescription browse = new BrowseDescription( Identifiers.ObjectsFolder, BrowseDirection.Forward, Identifiers.References, true, uint(NodeClass.Object.getValue() | NodeClass.Variable.getValue()), uint(BrowseResultMask.All.getValue()) ); BrowseResult browseResult = client.browse(browse).get(); ``` -------------------------------- ### Create Subscription with OpcUaSubscriptionManager Source: https://github.com/eclipse-milo/milo/wiki/Client Use OpcUaSubscriptionManager to create a UaSubscription object, which is the entry point for creating MonitoredItems. ```java `OpcUaSubscriptionManager#createSubscription` is used to create a `UaSubscription` object. MonitoredItems can then be created using `UaSubscription#createMonitoredItems`. The parameters and data structures used in these API calls correspond directly to those defined by the Subscription and MonitoredItems services in the OPC UA spec. ``` -------------------------------- ### Apply license header to source files Source: https://github.com/eclipse-milo/milo/blob/main/CONTRIBUTING.md Required license header for all new source files in the project. ```java /* * Copyright (c) 2025 the Eclipse Milo Authors * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ ``` -------------------------------- ### Low-Level Write Service Source: https://github.com/eclipse-milo/milo/wiki/Client Use OpcUaClient#write for direct interaction with the Write service. This requires constructing a list of WriteValue objects specifying the nodes, attributes, and data to write. ```java List writeValues = new ArrayList<>(); writeValues.add( new WriteValue( new NodeId(2, "TestInt32"), AttributeId.Value.uid(), null, // indexRange DataValue.valueOnly(new Variant(42)) ) ); WriteResponse writeResponse = client.write(writeValues).get(); ``` -------------------------------- ### Configure Sonatype snapshot repository Source: https://github.com/eclipse-milo/milo/blob/main/README.md Add this repository configuration to your pom.xml to access SNAPSHOT releases. ```xml oss-sonatype oss-sonatype https://oss.sonatype.org/content/repositories/snapshots/ ``` -------------------------------- ### Add OPC UA Server SDK dependency Source: https://github.com/eclipse-milo/milo/blob/main/README.md Include this dependency in your Maven pom.xml to use the Milo server SDK. ```xml org.eclipse.milo milo-sdk-server 1.1.6 ``` -------------------------------- ### Add OPC UA Client SDK dependency Source: https://github.com/eclipse-milo/milo/blob/main/README.md Include this dependency in your Maven pom.xml to use the Milo client SDK. ```xml org.eclipse.milo milo-sdk-client 1.1.6 ``` -------------------------------- ### Implement Custom SecurityKeysListener Source: https://github.com/eclipse-milo/milo/blob/main/docs/features/wireshark-key-log.md Implement the SecurityKeysListener interface to handle derived key material. Implementations must be thread-safe. ```java SecurityKeysListener listener = keyset -> { logger.debug( "Keys derived for channel={}, token={}", keyset.channelId(), keyset.tokenId() ); // write to database, send to remote service, etc. }; OpcUaClientConfig config = OpcUaClientConfig.builder() .setSecurityKeysListener(listener) .build(); ``` -------------------------------- ### OpcUaClient#browse Source: https://github.com/eclipse-milo/milo/wiki/Client Low-level API for performing a single browse request, corresponding directly to the OPC UA Browse service. Requires manual handling of continuation points for subsequent requests. ```APIDOC ## OpcUaClient#browse ### Description Low-level API for performing a single browse request, corresponding directly to the OPC UA Browse service. Requires manual handling of continuation points for subsequent requests. ### Method ```java CompletableFuture client.browse(BrowseDescription browseDescription) ``` ### Parameters - **browseDescription** (BrowseDescription) - The description of the browse request, including node ID, direction, reference type, node class mask, and result mask. ### Request Example ```java // Browse for forward hierarchal references from the Objects folder // that lead to other Object and Variable nodes. BrowseDescription browse = new BrowseDescription( Identifiers.ObjectsFolder, BrowseDirection.Forward, Identifiers.References, true, uint(NodeClass.Object.getValue() | NodeClass.Variable.getValue()), uint(BrowseResultMask.All.getValue()) ); BrowseResult browseResult = client.browse(browse).get(); ``` ### Response #### Success Response (200) - **browseResult** (BrowseResult) - The result of the browse operation, which may include a continuation point. ``` -------------------------------- ### Create ManagedDataItem Source: https://github.com/eclipse-milo/milo/wiki/Client Create a `ManagedDataItem` to monitor an attribute value using `ManagedSubscription#createDataItem`. Always verify the returned `StatusCode` for success. ```java ManagedDataItem dataItem = subscription.createDataItem(Identifiers.Server_ServerStatus_CurrentTime); if (!dataItem.getStatusCode.isGood()) { throw new RuntimeException("uh oh!") } ``` -------------------------------- ### ManagedSubscription Source: https://github.com/eclipse-milo/milo/wiki/Client Explains how to create and use ManagedSubscription for managing OPC UA subscriptions and monitored items. It covers adding data change listeners. ```APIDOC ## Subscriptions ### ManagedSubscription `ManagedSubscription` is the entry point in the higher level API for creating Subscriptions and MonitoredItems. Create a `ManagedSubscription` using an `OpcUaClient` instance like this: ```java ManagedSubscription subscription = ManagedSubscription.create(client); ``` Optionally, specify a publishing interval when creating the subscription: ```java ManagedSubscription subscription = ManagedSubscription.create(client, 250.0); ``` Once the Subscription is created you can add a data or event listener to it. This listener will receive all data changes for all items belonging to the subscription. ```java subscription.addChangeListener(new ChangeListener() { @Override public void onDataReceived(List dataItems, List dataValues) { // Each item in the dataItems list has a corresponding value at // the same index in the dataValues list. // Some items may appear multiple times if the item has a queue // size greater than 1 and the value changed more than once within // the publishing interval of the subscription. // The items and values appear in the order of the changes. } }); ``` ``` -------------------------------- ### Call Method using UaMethod Source: https://github.com/eclipse-milo/milo/wiki/Client Find a `UaMethod` by name and then invoke it using `UaMethod#call`. This approach allows inspection of method input and output arguments. ```java UaObjectNode serverNode = addressSpace.getObjectNode(Identifiers.Server); UaMethod getMonitoredItems = serverNode.getMethod("GetMonitoredItems"); Variant[] outputs = getMonitoredItems.call( new Variant[]{ new Variant(subscription.getSubscription().getSubscriptionId()) } ); ``` ```java Argument[] inputArguments = getMonitoredItems.getInputArguments(); Argument[] outputArguments = getMonitoredItems.getOutputArguments(); ``` -------------------------------- ### Low-Level Read Service Source: https://github.com/eclipse-milo/milo/wiki/Client Use OpcUaClient#read for direct interaction with the Read service. This requires constructing a list of ReadValueId objects specifying the nodes and attributes to read. ```java List readValueIds = new ArrayList<>(); readValueIds.add( new ReadValueId( new NodeId(2, "TestInt32"), AttributeId.Value.uid(), null, // indexRange QualifiedName.NULL_VALUE ) ); ReadResponse readResponse = client.read( 0.0, // maxAge TimestampsToReturn.Both, readValueIds ).get(); ``` -------------------------------- ### Create and Connect OpcUaClient Source: https://github.com/eclipse-milo/milo/wiki/Client Creates an OpcUaClient instance by selecting an endpoint that uses SecurityPolicy.None and automatically attempts to reconnect if the connection is lost. Call disconnect() to stop this behavior. ```java OpcUaClient client = OpcUaClient.create( "opc.tcp://milo.digitalpetri.com:62541/milo", endpoints -> endpoints.stream() .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri())) .findFirst(), configBuilder -> configBuilder.build() ); client.connect().get(); ``` -------------------------------- ### Call Method using OpcUaClient Source: https://github.com/eclipse-milo/milo/wiki/Client Utilize `OpcUaClient#call` for direct interaction with the OPC UA Call service. This method requires constructing `CallMethodRequest` objects and handling `CompletableFuture` responses. ```java NodeId objectId = NodeId.parse("ns=2;s=HelloWorld"); NodeId methodId = NodeId.parse("ns=2;s=HelloWorld/sqrt(x)"); CallMethodRequest request = new CallMethodRequest( objectId, methodId, new Variant[]{new Variant(input)} ); return client.call(request).thenCompose(result -> { StatusCode statusCode = result.getStatusCode(); if (statusCode.isGood()) { Double value = (Double) l(result.getOutputArguments()).get(0).getValue(); return CompletableFuture.completedFuture(value); } else { StatusCode[] inputArgumentResults = result.getInputArgumentResults(); for (int i = 0; i < inputArgumentResults.length; i++) { logger.error("inputArgumentResults[{}]={}", i, inputArgumentResults[i]); } CompletableFuture f = new CompletableFuture<>(); f.completeExceptionally(new UaException(statusCode)); return f; } }); ``` -------------------------------- ### AddressSpace#browse Source: https://github.com/eclipse-milo/milo/wiki/Client High-level API for browsing the OPC UA address space with default or custom browse options. Supports blocking or non-blocking operations. ```APIDOC ## AddressSpace#browse ### Description High-level API for browsing the OPC UA address space with default or custom browse options. Supports blocking or non-blocking operations. ### Method ```java List addressSpace.browseNodes(UaNode node) List addressSpace.browseNodes(UaNode node, BrowseOptions options) ``` ### Parameters #### `browseNodes(UaNode node)` - **node** (UaNode) - The starting node for the browse operation. #### `browseNodes(UaNode node, BrowseOptions options)` - **node** (UaNode) - The starting node for the browse operation. - **options** (BrowseOptions) - Custom options to configure the browse operation. ### Request Example ```java // Using default BrowseOptions AddressSpace addressSpace = client.getAddressSpace(); UaNode serverNode = addressSpace.getNode(Identifiers.Server); List nodes = addressSpace.browseNodes(serverNode); // Using custom BrowseOptions AddressSpace addressSpace = client.getAddressSpace(); UaNode serverNode = addressSpace.getNode(Identifiers.Server); BrowseOptions browseOptions = addressSpace.getBrowseOptions().copy( b -> b.setReferenceType(BuiltinReferenceType.HasProperty) ); List nodes = addressSpace.browseNodes(serverNode, browseOptions); ``` ### Response #### Success Response - **nodes** (List) - A list of UaNode objects found during the browse operation. ``` -------------------------------- ### Create ManagedEventItem with EventFilter Source: https://github.com/eclipse-milo/milo/wiki/Client Create an EventFilter to specify event types and fields, then use it to create a ManagedEventItem from a ManagedSubscription. ```java EventFilter eventFilter = new EventFilter( new SimpleAttributeOperand[]{ new SimpleAttributeOperand( Identifiers.BaseEventType, new QualifiedName[]{new QualifiedName(0, "EventId")}, AttributeId.Value.uid(), null), new SimpleAttributeOperand( Identifiers.BaseEventType, new QualifiedName[]{new QualifiedName(0, "Time")}, AttributeId.Value.uid(), null), new SimpleAttributeOperand( Identifiers.BaseEventType, new QualifiedName[]{new QualifiedName(0, "Message")}, AttributeId.Value.uid(), null) }, new ContentFilter(null) ); // Subscribe for Events from the Server Node's EventNotifier attribute. ManagedEventItem eventItem = subscription.createEventItem(Identifiers.Server, eventFilter); ``` -------------------------------- ### UaNode#browse Source: https://github.com/eclipse-milo/milo/wiki/Client API for browsing references or nodes directly from a UaNode instance. Allows specifying reference types and other browse options. ```APIDOC ## UaNode#browse ### Description API for browsing references or nodes directly from a UaNode instance. Allows specifying reference types and other browse options. ### Method ```java List node.browse(BrowseOptions options) List node.browseNodes(BrowseOptions options) ``` ### Parameters - **options** (BrowseOptions) - Options to configure the browse operation, such as reference type. ### Request Example ```java BrowseOptions browseOptions = BrowseOptions.builder() .setReferenceType(Identifiers.HasProperty) .build(); // Browse for HasProperty references List references = node.browse(browseOptions); // Browse for HasProperty references and get the UaNodes they target List nodes = node.browseNodes(browseOptions); ``` ### Response #### Success Response - **references** (List) - A list of ReferenceDescription objects. - **nodes** (List) - A list of UaNode objects referenced by the browse operation. ``` -------------------------------- ### OpcUaClient#write Source: https://github.com/eclipse-milo/milo/wiki/Client Low-level API for performing a write request, corresponding directly to the OPC UA Write service. Allows writing multiple attribute values in a single request. ```APIDOC ## OpcUaClient#write ### Description Low-level API for performing a write request, corresponding directly to the OPC UA Write service. Allows writing multiple attribute values in a single request. ### Method ```java CompletableFuture client.write(List writeValues) ``` ### Parameters - **writeValues** (List) - A list of WriteValue objects specifying the nodes, attributes, and data to write. ### Request Example ```java List writeValues = new ArrayList<>(); writeValues.add(new WriteValue(new NodeId(2, "TestInt32"), AttributeId.Value.uid(), null, DataValue.valueOnly(new Variant(42)))); WriteResponse writeResponse = client.write(writeValues).get(); ``` ### Response #### Success Response (200) - **writeResponse** (WriteResponse) - The response containing the status of the write operations. ``` -------------------------------- ### Call Method using UaObjectNode Source: https://github.com/eclipse-milo/milo/wiki/Client Use `UaObjectNode#callMethod` for a high-level way to invoke a method by its name. Ensure the `UaObjectNode` and method are accessible. ```java UaObjectNode serverNode = addressSpace.getObjectNode(Identifiers.Server); Variant[] outputs = serverNode.callMethod( "GetMonitoredItems", new Variant[]{ new Variant(subscription.getSubscription().getSubscriptionId()) } ); ``` -------------------------------- ### UaNode#read Source: https://github.com/eclipse-milo/milo/wiki/Client High-level API for reading attributes directly from a UaNode instance. Allows reading specific attributes like Value or BrowseName. ```APIDOC ## UaNode#read ### Description High-level API for reading attributes directly from a UaNode instance. Allows reading specific attributes like Value or BrowseName. ### Method ```java DataValue testNode.readValue() QualifiedName testNode.readBrowseName() DataValue testNode.readAttribute(AttributeId attributeId) ``` ### Parameters - **attributeId** (AttributeId) - The ID of the attribute to read. ### Request Example ```java UaVariableNode testNode = (UaVariableNode) addressSpace.getNode(new NodeId(2, "TestInt32")); // Read the Value attribute DataValue value = testNode.readValue(); // Read the BrowseName attribute QualifiedName browseName = testNode.readBrowseName(); // Read the Description attribute DataValue descriptionValue = testNode.readAttribute(AttributeId.Description); ``` ### Response #### Success Response - **value** (DataValue) - The data value of the attribute. - **browseName** (QualifiedName) - The browse name of the node. - **descriptionValue** (DataValue) - The data value of the description attribute. ``` -------------------------------- ### Read Fresh UaNode Attributes Source: https://github.com/eclipse-milo/milo/wiki/Client Obtain fresh attribute values from the server using read() methods. A successful read also updates the local attribute value. ```java Fresh attribute values can be obtained using `read()` methods and written using the `write()` methods. When a read or a write succeeds it also updates the local attribute value. ``` -------------------------------- ### OpcUaClient#read Source: https://github.com/eclipse-milo/milo/wiki/Client Low-level API for performing a read request, corresponding directly to the OPC UA Read service. Allows reading multiple attribute values in a single request. ```APIDOC ## OpcUaClient#read ### Description Low-level API for performing a read request, corresponding directly to the OPC UA Read service. Allows reading multiple attribute values in a single request. ### Method ```java CompletableFuture client.read(double maxAge, TimestampsToReturn timestampsToReturn, List readValueIds) ``` ### Parameters - **maxAge** (double) - The maximum age of the values to return. - **timestampsToReturn** (TimestampsToReturn) - Specifies whether to return timestamps. - **readValueIds** (List) - A list of IDs specifying which values to read. ### Request Example ```java List readValueIds = new ArrayList<>(); readValueIds.add(new ReadValueId(new NodeId(2, "TestInt32"), AttributeId.Value.uid(), null, QualifiedName.NULL_VALUE)); ReadResponse readResponse = client.read(0.0, TimestampsToReturn.Both, readValueIds).get(); ``` ### Response #### Success Response (200) - **readResponse** (ReadResponse) - The response containing the requested values. ``` -------------------------------- ### UaNode#write Source: https://github.com/eclipse-milo/milo/wiki/Client High-level API for writing attribute values directly to a UaNode instance. Supports writing the Value attribute or any other attribute. ```APIDOC ## UaNode#write ### Description High-level API for writing attribute values directly to a UaNode instance. Supports writing the Value attribute or any other attribute. ### Method ```java void testNode.writeValue(Variant value) StatusCode testNode.writeAttribute(AttributeId attributeId, DataValue dataValue) ``` ### Parameters - **value** (Variant) - The new value to write. - **attributeId** (AttributeId) - The ID of the attribute to write. - **dataValue** (DataValue) - The DataValue containing the new attribute value. ### Request Example ```java UaVariableNode testNode = (UaVariableNode) addressSpace.getNode(new NodeId(2, "TestInt32")); // Write the Value attribute testNode.writeValue(new Variant(42)); // Write the Value attribute using writeAttribute StatusCode statusCode = testNode.writeAttribute(AttributeId.Value, DataValue.valueOnly(new Variant(42))); ``` ### Response #### Success Response - **statusCode** (StatusCode) - The status code of the write operation. ``` -------------------------------- ### ManagedDataItem Source: https://github.com/eclipse-milo/milo/wiki/Client Details the creation and usage of ManagedDataItem for monitoring attribute values. Emphasizes the importance of checking the StatusCode after creation or modification. ```APIDOC ### ManagedDataItem A `ManagedDataItem` represents a MonitoredItem monitoring an attribute value (as opposed to an Event). Create a `ManagedDataItem` using a `ManagedSubscription` instance like this: ```java ManagedDataItem dataItem = subscription.createDataItem(Identifiers.Server_ServerStatus_CurrentTime); if (!dataItem.getStatusCode.isGood()) { throw new RuntimeException("uh oh!") } ``` Always check the StatusCode after creating or modifying a `ManagedDataItem`. ``` -------------------------------- ### Synchronize UaNode Attributes Source: https://github.com/eclipse-milo/milo/wiki/Client Perform a bulk write of local attribute values to the server using UaNode#synchronize() for a specified set of attributes. ```java `UaNode#synchronize(Set)` will do a bulk write for the identified set of attributes using the local attribute values. ``` -------------------------------- ### Set Local UaNode Attribute Values Source: https://github.com/eclipse-milo/milo/wiki/Client Set local attribute values using set() methods. These changes only affect the local value and can be written to the server using `#synchronize()`. ```java Local attribute values can be set using the `set()` methods, which affects only the local value. See `#synchronize()` to write these values to the server. ``` -------------------------------- ### Register ChangeListener for Events Source: https://github.com/eclipse-milo/milo/wiki/Client Register a ChangeListener on a ManagedSubscription to receive events from all associated ManagedEventItems. ```java subscription.addChangeListener(new ChangeListener() { @Override public void onEventReceived(List eventItems, List eventFields) { // Each item in the eventItems list has a corresponding set of // event field values at the same index in the eventFields list. // The number of fields and their meaning depend on the filter. } }); ``` -------------------------------- ### Add Change Listener to ManagedSubscription Source: https://github.com/eclipse-milo/milo/wiki/Client Attach a `ChangeListener` to a `ManagedSubscription` to receive notifications for data changes on monitored items. The listener's `onDataReceived` method provides lists of `ManagedDataItem` and corresponding `DataValue` objects. ```java subscription.addChangeListener(new ChangeListener() { @Override public void onDataReceived(List dataItems, List dataValues) { // Each item in the dataItems list has a corresponding value at // the same index in the dataValues list. // Some items may appear multiple times if the item has a queue // size greater than 1 and the value changed more than once within // the publishing interval of the subscription. // The items and values appear in the order of the changes. } }); ``` -------------------------------- ### Sign-off a Git commit Source: https://github.com/eclipse-milo/milo/blob/main/CONTRIBUTING.md Use the -s flag during commit to sign off on changes as required by the Eclipse contribution process. ```bash $> git commit -s -m "Shave the yak some more" ``` -------------------------------- ### Refresh UaNode Attributes Source: https://github.com/eclipse-milo/milo/wiki/Client Perform a bulk read for a specified set of attributes using UaNode#refresh() to update local attribute values. ```java `UaNode#refresh(Set)` will do a bulk read for the identified set of attributes and update the local attribute values if it succeeds. ``` -------------------------------- ### Register EventValueListener on ManagedEventItem Source: https://github.com/eclipse-milo/milo/wiki/Client Register an EventValueListener directly on a ManagedEventItem for simpler event handling when dealing with individual items. ```java eventItem.addEventValueListener(new ManagedEventItem.EventValueListener() { @Override public void onEventValueReceived(ManagedEventItem item, Variant[] value) { // A new event arrived, do something with it. } }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.