Milo client for UAautomation server to receive events

Questions regarding the use of the Java SDK for Server or Client development or integration into customer products ...

Moderator: uasdkjava

Post Reply
Jr. Member
Jr. Member
Posts: 1
Joined: 25 Nov 2017, 15:25

Milo client for UAautomation server to receive events

Post by isuru »

I have created a mydevice node with eventnotifier flag set to 1 to receive event through a monitored item by a subscription on Java based Milo client.
Monitored item creation is succesful via Milo.

When I create a trigger on device it is succesfully received by prosys client.

When using milo client (code attached) monitorevent suscription is created succesfully.But events are not sent to milo client but to prosys client.

Can somebody tell me what s wrong with the attached milo client?


import static;
import static com.yukon.opc.stack.core.types.builtin.unsigned.Unsigned.uint;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yukon.opc.sdk.client.OpcUaClient;
import com.yukon.opc.sdk.client.api.subscriptions.UaMonitoredItem;
import com.yukon.opc.sdk.client.api.subscriptions.UaSubscription;
import com.yukon.opc.stack.core.AttributeId;
import com.yukon.opc.stack.core.Identifiers;
import com.yukon.opc.stack.core.types.builtin.DataValue;
import com.yukon.opc.stack.core.types.builtin.ExtensionObject;
import com.yukon.opc.stack.core.types.builtin.NodeId;
import com.yukon.opc.stack.core.types.builtin.QualifiedName;
import com.yukon.opc.stack.core.types.builtin.Variant;
import com.yukon.opc.stack.core.types.builtin.unsigned.UInteger;
import com.yukon.opc.stack.core.types.enumerated.MonitoringMode;
import com.yukon.opc.stack.core.types.enumerated.TimestampsToReturn;
import com.yukon.opc.stack.core.types.structured.ContentFilter;
import com.yukon.opc.stack.core.types.structured.EventFilter;
import com.yukon.opc.stack.core.types.structured.MonitoredItemCreateRequest;
import com.yukon.opc.stack.core.types.structured.MonitoringParameters;
import com.yukon.opc.stack.core.types.structured.ReadValueId;
import com.yukon.opc.stack.core.types.structured.SimpleAttributeOperand;
import com.yukon.opc.testclient.ClientExample;
import com.yukon.opc.testclient.ClientExampleRunner;

public class SubscriptionExampleUA implements ClientExample {

public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
SubscriptionExampleUA example = new SubscriptionExampleUA();

new ClientExampleRunner(example).run();
private final Logger logger = LoggerFactory.getLogger(getClass());

private final AtomicLong clientHandles = new AtomicLong(1L);

public void run(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception {
// synchronous connect

// create a subscription @ 1000ms
UaSubscription subscription = client.getSubscriptionManager().createSubscription(0.0).get();

NodeId n=NodeId.parse("ns=2;s=MyDevice");

// subscribe to the Value attribute of the server's CurrentTime node
ReadValueId readValueId = new ReadValueId(
AttributeId.EventNotifier.uid(), null, QualifiedName.NULL_VALUE);

// important: client handle must be unique per item
UInteger clientHandle = uint(clientHandles.getAndIncrement());
//EventFilter ds = new EventFilter();
ExtensionObject eo = createEF2();
MonitoringParameters parameters = new MonitoringParameters(
0.0, // sampling interval
eo, // filter, null means use default
uint(10), // queue size
true // discard oldest

MonitoredItemCreateRequest request = new MonitoredItemCreateRequest(
readValueId, MonitoringMode.Reporting, parameters);

// when creating items in MonitoringMode.Reporting this callback is where each item needs to have its
// value/event consumer hooked up. The alternative is to create the item in sampling mode, hook up the
// consumer after the creation call completes, and then change the mode for all items to reporting.
BiConsumer<UaMonitoredItem, Integer> onItemCreated =
(item, id) -> item.setEventConsumer(this::onEventReceived);

List<UaMonitoredItem> items = subscription.createMonitoredItems(

for (UaMonitoredItem item : items) {
if (item.getStatusCode().isGood()) {"item created for nodeId={}", item.getReadValueId().getNodeId());
} else {
"failed to create item for nodeId={} (status={})",
item.getReadValueId().getNodeId(), item.getStatusCode());

// let the example run for 5 seconds then terminate

private void onSubscriptionValue(UaMonitoredItem item, DataValue value) {
"subscription value received: item={}, value={}",
item.getReadValueId().getNodeId(), value.getValue());

private void onEventReceived(UaMonitoredItem item, Variant[] var) {
"subscription value received: item={}, value={}",
item.getReadValueId().getNodeId(),var );

private ExtensionObject createEF2( ) {

EventFilter eventFilter = new EventFilter(
new SimpleAttributeOperand[]{
new SimpleAttributeOperand(
new QualifiedName[]{new QualifiedName(0, "EventId")},
new SimpleAttributeOperand(
new QualifiedName[]{new QualifiedName(0, "Severity")},
new SimpleAttributeOperand(
new QualifiedName[]{new QualifiedName(0, "Time")},
new SimpleAttributeOperand(
new QualifiedName[]{new QualifiedName(0, "Message")},
new ContentFilter(null)

ExtensionObject eo = ExtensionObject.encode(eventFilter);
return eo;

private ExtensionObject createEventFilter() {

QualifiedName[] eventFields = { new QualifiedName(2,"EventType"), new QualifiedName(2,"Message"),
new QualifiedName(2,"SourceName"), new QualifiedName(2,"Time"), new QualifiedName(2,"Severity")

NodeId eventTypeId = Identifiers.BaseEventType;
UInteger eventAttributeId =AttributeId.Value.uid();
String indexRange = null;
SimpleAttributeOperand[] selectClauses = new SimpleAttributeOperand[eventFields.length + 1];
for (int i = 0; i < eventFields.length; i++) {
QualifiedName[] browsePath = createBrowsePath(eventFields);
selectClauses = new SimpleAttributeOperand(eventTypeId, browsePath, eventAttributeId, indexRange);
// Add a field to get the NodeId of the event source
selectClauses[eventFields.length] = new SimpleAttributeOperand(eventTypeId, null, AttributeId.NodeId.uid(), null);


// Event filtering: the following sample creates a
// "Not OfType GeneralModelChangeEventType" filter
/* ContentFilterBuilder fb = new ContentFilterBuilder(client.getEncoderContext());
fb.add(FilterOperator.Not, new ElementOperand(UnsignedInteger.valueOf(1)));
final LiteralOperand filteredType = new LiteralOperand(new Variant(Identifiers.GeneralModelChangeEventType));
fb.add(FilterOperator.OfType, filteredType);*/

// The element operand refers to another operand -
// operand #1 in this case which is the next,
// LiteralOperand

EventFilter filter = new EventFilter(selectClauses,null);

ExtensionObject eo = ExtensionObject.encode(filter);
return eo;

protected QualifiedName[] createBrowsePath(QualifiedName qualifiedName) {

if (!qualifiedName.getName().contains("/"))
return new QualifiedName[] { qualifiedName };
int namespaceIndex = qualifiedName.getNamespaceIndex().intValue();
String[] names = qualifiedName.getName().split("/");
QualifiedName[] result = new QualifiedName[names.length];
for (int i = 0; i < names.length; i++)
result = new QualifiedName(namespaceIndex, names);
return result;



Post Reply