Page 1 of 1

Milo client for UAautomation server to receive events

Posted: 25 Nov 2017, 15:29
by isuru
Hi,
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?

package com.yukon.opc.testclient.ua;

import static com.google.common.collect.Lists.newArrayList;
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);

@Override
public void run(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception {
// synchronous connect
client.connect().get();

// 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(
n,
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();
//eo=createEventFilter();
MonitoringParameters parameters = new MonitoringParameters(
clientHandle,
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(
TimestampsToReturn.Both,
newArrayList(request),
onItemCreated
).get();

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

// let the example run for 5 seconds then terminate
Thread.sleep(5000000);
future.complete(client);
}

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

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




private ExtensionObject createEF2( ) {

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, "Severity")},
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)
);

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);





//filter..setSelectClauses(selectClauses);

// 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) {

System.out.println(qualifiedName.getName());
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;
}


}


THanks
Isuru