use of org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemNotification in project milo by eclipse.
the class OpcUaSubscriptionManager method deliverNotificationMessage.
private CompletableFuture<Unit> deliverNotificationMessage(OpcUaSubscription subscription, NotificationMessage notificationMessage) {
CompletableFuture<Unit> delivered = new CompletableFuture<>();
subscription.getNotificationSemaphore().acquire().thenAccept(permit -> deliveryQueue.submit(() -> {
try {
Map<UInteger, OpcUaMonitoredItem> items = subscription.getItemsByClientHandle();
List<ExtensionObject> notificationData = l(notificationMessage.getNotificationData());
if (notificationData.isEmpty()) {
subscriptionListeners.forEach(listener -> listener.onKeepAlive(subscription, notificationMessage.getPublishTime()));
subscription.getNotificationListeners().forEach(listener -> listener.onKeepAliveNotification(subscription, notificationMessage.getPublishTime()));
}
for (ExtensionObject xo : notificationData) {
Object o = xo.decode(client.getStaticSerializationContext());
if (o instanceof DataChangeNotification) {
DataChangeNotification dcn = (DataChangeNotification) o;
List<MonitoredItemNotification> monitoredItemNotifications = l(dcn.getMonitoredItems());
int notificationCount = monitoredItemNotifications.size();
logger.debug("Received {} MonitoredItemNotifications", notificationCount);
for (MonitoredItemNotification min : monitoredItemNotifications) {
logger.trace("MonitoredItemNotification: clientHandle={}, value={}", min.getClientHandle(), min.getValue());
OpcUaMonitoredItem item = items.get(min.getClientHandle());
if (item != null)
item.onValueArrived(min.getValue());
else
logger.warn("no item for clientHandle=" + min.getClientHandle());
}
if (notificationCount == 0) {
subscriptionListeners.forEach(listener -> listener.onKeepAlive(subscription, notificationMessage.getPublishTime()));
subscription.getNotificationListeners().forEach(listener -> listener.onKeepAliveNotification(subscription, notificationMessage.getPublishTime()));
} else {
if (!subscription.getNotificationListeners().isEmpty()) {
List<UaMonitoredItem> monitoredItems = new ArrayList<>();
List<DataValue> dataValues = new ArrayList<>();
for (MonitoredItemNotification n : monitoredItemNotifications) {
UaMonitoredItem item = subscription.getItemsByClientHandle().get(n.getClientHandle());
if (item != null) {
monitoredItems.add(item);
dataValues.add(n.getValue());
}
}
subscription.getNotificationListeners().forEach(listener -> listener.onDataChangeNotification(subscription, monitoredItems, dataValues, notificationMessage.getPublishTime()));
}
}
} else if (o instanceof EventNotificationList) {
EventNotificationList enl = (EventNotificationList) o;
List<EventFieldList> eventFieldLists = l(enl.getEvents());
for (EventFieldList efl : eventFieldLists) {
logger.trace("EventFieldList: clientHandle={}, values={}", efl.getClientHandle(), Arrays.toString(efl.getEventFields()));
OpcUaMonitoredItem item = items.get(efl.getClientHandle());
if (item != null)
item.onEventArrived(efl.getEventFields());
}
if (!subscription.getNotificationListeners().isEmpty()) {
List<UaMonitoredItem> monitoredItems = new ArrayList<>();
List<Variant[]> eventFields = new ArrayList<>();
for (EventFieldList efl : eventFieldLists) {
UaMonitoredItem item = subscription.getItemsByClientHandle().get(efl.getClientHandle());
if (item != null) {
monitoredItems.add(item);
eventFields.add(efl.getEventFields());
}
}
subscription.getNotificationListeners().forEach(listener -> listener.onEventNotification(subscription, monitoredItems, eventFields, notificationMessage.getPublishTime()));
}
} else if (o instanceof StatusChangeNotification) {
StatusChangeNotification scn = (StatusChangeNotification) o;
logger.debug("StatusChangeNotification: {}", scn.getStatus());
subscriptionListeners.forEach(listener -> listener.onStatusChanged(subscription, scn.getStatus()));
subscription.getNotificationListeners().forEach(listener -> listener.onStatusChangedNotification(subscription, scn.getStatus()));
if (scn.getStatus().getValue() == StatusCodes.Bad_Timeout) {
subscriptions.remove(subscription.getSubscriptionId());
}
}
}
} finally {
permit.release();
delivered.complete(Unit.VALUE);
}
}));
return delivered;
}
use of org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemNotification in project milo by eclipse.
the class Subscription method sendNotifications.
private void sendNotifications(ServiceRequest service, List<UaStructure> notifications) {
List<MonitoredItemNotification> dataNotifications = Lists.newArrayList();
List<EventFieldList> eventNotifications = Lists.newArrayList();
notifications.forEach(notification -> {
if (notification instanceof MonitoredItemNotification) {
dataNotifications.add((MonitoredItemNotification) notification);
} else if (notification instanceof EventFieldList) {
eventNotifications.add((EventFieldList) notification);
}
});
List<ExtensionObject> notificationData = Lists.newArrayList();
if (dataNotifications.size() > 0) {
DataChangeNotification dataChange = new DataChangeNotification(dataNotifications.toArray(new MonitoredItemNotification[0]), new DiagnosticInfo[0]);
notificationData.add(ExtensionObject.encode(serializationContext, dataChange, dataChange.getBinaryEncodingId(), OpcUaDefaultBinaryEncoding.getInstance()));
subscriptionDiagnostics.getDataChangeNotificationsCount().add(dataNotifications.size());
}
if (eventNotifications.size() > 0) {
EventNotificationList eventChange = new EventNotificationList(eventNotifications.toArray(new EventFieldList[0]));
notificationData.add(ExtensionObject.encode(serializationContext, eventChange, eventChange.getBinaryEncodingId(), OpcUaDefaultBinaryEncoding.getInstance()));
subscriptionDiagnostics.getEventNotificationsCount().add(eventNotifications.size());
}
subscriptionDiagnostics.getNotificationsCount().add(notificationData.size());
UInteger sequenceNumber = uint(nextSequenceNumber());
NotificationMessage notificationMessage = new NotificationMessage(sequenceNumber, DateTime.now(), notificationData.toArray(new ExtensionObject[0]));
availableMessages.put(notificationMessage.getSequenceNumber(), notificationMessage);
while (availableMessages.size() > MAX_AVAILABLE_MESSAGES) {
Map.Entry<UInteger, NotificationMessage> entry = availableMessages.pollFirstEntry();
if (entry != null) {
subscriptionDiagnostics.getDiscardedMessageCount().increment();
logger.debug("Discarded cached NotificationMessage with sequenceNumber={}", entry.getKey());
}
}
UInteger[] available = getAvailableSequenceNumbers();
StatusCode[] acknowledgeResults = service.attr(KEY_ACK_RESULTS).get();
ResponseHeader header = service.createResponseHeader();
PublishResponse response = new PublishResponse(header, subscriptionId, available, moreNotifications, notificationMessage, acknowledgeResults, new DiagnosticInfo[0]);
service.setResponse(response);
logger.debug("[id={}] returning {} DataChangeNotification(s) and " + "{} EventNotificationList(s) sequenceNumber={} moreNotifications={}.", subscriptionId, dataNotifications.size(), eventNotifications.size(), sequenceNumber, moreNotifications);
}
use of org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemNotification in project milo by eclipse.
the class MonitoredDataItem method wrapQueueValue.
@Override
protected MonitoredItemNotification wrapQueueValue(DataValue value) {
boolean includeSource = timestamps == TimestampsToReturn.Source || timestamps == TimestampsToReturn.Both;
boolean includeServer = timestamps == TimestampsToReturn.Server || timestamps == TimestampsToReturn.Both;
// remove the source timestamp if not requested
boolean sourceTimeUpdated = false;
DateTime sourceTime = value.getSourceTime();
UShort sourcePicoseconds = value.getSourcePicoseconds();
if (!includeSource && (sourceTime != null || sourcePicoseconds != null)) {
sourceTime = null;
sourcePicoseconds = null;
sourceTimeUpdated = true;
}
// remove server timestamp if not requested, add if requested but not present
boolean serverTimeUpdated = false;
DateTime serverTime = value.getServerTime();
UShort serverPicoseconds = value.getServerPicoseconds();
if (!includeServer && (serverTime != null || serverPicoseconds != null)) {
serverTime = null;
serverPicoseconds = null;
serverTimeUpdated = true;
} else if (includeServer && serverTime == null) {
serverTime = DateTime.now();
serverTimeUpdated = true;
}
// create a new DataValue instance if anything changed
if (sourceTimeUpdated || serverTimeUpdated) {
value = new DataValue(value.getValue(), value.getStatusCode(), sourceTime, sourcePicoseconds, serverTime, serverPicoseconds);
}
return new MonitoredItemNotification(uint(getClientHandle()), value);
}
Aggregations