Search in sources :

Example 1 with PublishResponse

use of org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse in project milo by eclipse.

the class Subscription method returnKeepAlive.

private void returnKeepAlive(ServiceRequest service) {
    ResponseHeader header = service.createResponseHeader();
    UInteger sequenceNumber = uint(currentSequenceNumber());
    NotificationMessage notificationMessage = new NotificationMessage(sequenceNumber, DateTime.now(), new ExtensionObject[0]);
    UInteger[] available = getAvailableSequenceNumbers();
    StatusCode[] acknowledgeResults = service.attr(KEY_ACK_RESULTS).get();
    PublishResponse response = new PublishResponse(header, subscriptionId, available, moreNotifications, notificationMessage, acknowledgeResults, new DiagnosticInfo[0]);
    service.setResponse(response);
    logger.debug("[id={}] returned keep-alive NotificationMessage sequenceNumber={}.", subscriptionId, sequenceNumber);
}
Also used : PublishResponse(org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse) ResponseHeader(org.eclipse.milo.opcua.stack.core.types.structured.ResponseHeader) NotificationMessage(org.eclipse.milo.opcua.stack.core.types.structured.NotificationMessage) UInteger(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger) StatusCode(org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode)

Example 2 with PublishResponse

use of org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse in project milo by eclipse.

the class OpcUaSubscriptionManager method onPublishComplete.

private void onPublishComplete(PublishResponse response, AtomicLong pendingCount) {
    logger.debug("onPublishComplete() response for subscriptionId={}", response.getSubscriptionId());
    UInteger subscriptionId = response.getSubscriptionId();
    OpcUaSubscription subscription = subscriptions.get(subscriptionId);
    if (subscription == null) {
        WatchdogTimer watchdogTimer = watchdogTimers.remove(subscriptionId);
        if (watchdogTimer != null)
            watchdogTimer.cancel();
        pendingCount.getAndUpdate(p -> (p > 0) ? p - 1 : 0);
        maybeSendPublishRequests();
        return;
    }
    WatchdogTimer watchdogTimer = watchdogTimers.get(subscriptionId);
    if (watchdogTimer != null)
        watchdogTimer.kick();
    NotificationMessage notificationMessage = response.getNotificationMessage();
    long sequenceNumber = notificationMessage.getSequenceNumber().longValue();
    long expectedSequenceNumber = subscription.getLastSequenceNumber() + 1;
    if (sequenceNumber > expectedSequenceNumber) {
        logger.warn("[id={}] expected sequence={}, received sequence={}. Calling Republish service...", subscriptionId, expectedSequenceNumber, sequenceNumber);
        processingQueue.pause();
        processingQueue.submitToHead(() -> onPublishComplete(response, pendingCount));
        republish(subscriptionId, expectedSequenceNumber, sequenceNumber).whenComplete((dataLost, ex) -> {
            if (ex != null) {
                logger.debug("Republish failed: {}", ex.getMessage(), ex);
                subscriptionListeners.forEach(l -> l.onNotificationDataLost(subscription));
                subscription.getNotificationListeners().forEach(l -> l.onNotificationDataLost(subscription));
            } else {
                // Republish succeeded, possibly with some data loss, resume processing.
                if (dataLost) {
                    subscriptionListeners.forEach(l -> l.onNotificationDataLost(subscription));
                    subscription.getNotificationListeners().forEach(l -> l.onNotificationDataLost(subscription));
                }
            }
            subscription.setLastSequenceNumber(sequenceNumber - 1);
            processingQueue.resume();
        });
        return;
    }
    if (notificationMessage.getNotificationData() != null && notificationMessage.getNotificationData().length > 0) {
        // Set last sequence number only if this isn't a keep-alive
        subscription.setLastSequenceNumber(sequenceNumber);
    }
    UInteger[] availableSequenceNumbers = response.getAvailableSequenceNumbers();
    synchronized (subscription.availableAcknowledgements) {
        subscription.availableAcknowledgements.clear();
        if (availableSequenceNumbers != null && availableSequenceNumbers.length > 0) {
            Collections.addAll(subscription.availableAcknowledgements, availableSequenceNumbers);
        }
    }
    if (logger.isDebugEnabled() && availableSequenceNumbers != null) {
        String[] seqStrings = Arrays.stream(availableSequenceNumbers).map(sequence -> String.format("id=%s/seq=%s", subscriptionId, sequence)).toArray(String[]::new);
        logger.debug("[id={}] PublishResponse sequence={}, available sequences={}", subscriptionId, sequenceNumber, Arrays.toString(seqStrings));
    }
    DateTime publishTime = notificationMessage.getPublishTime();
    logger.debug("onPublishComplete(), subscriptionId={}, sequenceNumber={}, publishTime={}", subscriptionId, notificationMessage.getSequenceNumber(), publishTime);
    deliverNotificationMessage(subscription, notificationMessage).thenRunAsync(() -> {
        pendingCount.getAndUpdate(p -> (p > 0) ? p - 1 : 0);
        maybeSendPublishRequests();
    }, client.getConfig().getExecutor());
}
Also used : Arrays(java.util.Arrays) ScheduledFuture(java.util.concurrent.ScheduledFuture) BiFunction(java.util.function.BiFunction) CompletableFuture.completedFuture(java.util.concurrent.CompletableFuture.completedFuture) UaSubscriptionManager(org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscriptionManager) LoggerFactory(org.slf4j.LoggerFactory) ExtensionObject(org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject) PublishRequest(org.eclipse.milo.opcua.stack.core.types.structured.PublishRequest) DateTime(org.eclipse.milo.opcua.stack.core.types.builtin.DateTime) Unsigned.uint(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint) UaSubscription(org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription) Unit(org.eclipse.milo.opcua.stack.core.util.Unit) Map(java.util.Map) BigInteger(java.math.BigInteger) CreateSubscriptionResponse(org.eclipse.milo.opcua.stack.core.types.structured.CreateSubscriptionResponse) NodeId(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId) UByte(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UByte) EventNotificationList(org.eclipse.milo.opcua.stack.core.types.structured.EventNotificationList) RepublishResponse(org.eclipse.milo.opcua.stack.core.types.structured.RepublishResponse) SubscriptionAcknowledgement(org.eclipse.milo.opcua.stack.core.types.structured.SubscriptionAcknowledgement) List(java.util.List) Lists.newArrayList(com.google.common.collect.Lists.newArrayList) Variant(org.eclipse.milo.opcua.stack.core.types.builtin.Variant) EventFieldList(org.eclipse.milo.opcua.stack.core.types.structured.EventFieldList) StatusCode(org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode) UaSession(org.eclipse.milo.opcua.sdk.client.api.UaSession) DataValue(org.eclipse.milo.opcua.stack.core.types.builtin.DataValue) OpcUaClient(org.eclipse.milo.opcua.sdk.client.OpcUaClient) NotificationMessage(org.eclipse.milo.opcua.stack.core.types.structured.NotificationMessage) CompletableFuture(java.util.concurrent.CompletableFuture) DataChangeNotification(org.eclipse.milo.opcua.stack.core.types.structured.DataChangeNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) ArrayList(java.util.ArrayList) ConcurrentMap(java.util.concurrent.ConcurrentMap) RequestHeader(org.eclipse.milo.opcua.stack.core.types.structured.RequestHeader) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) ConversionUtil.l(org.eclipse.milo.opcua.stack.core.util.ConversionUtil.l) UaMonitoredItem(org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem) StatusCodes(org.eclipse.milo.opcua.stack.core.StatusCodes) FutureUtils.failedUaFuture(org.eclipse.milo.opcua.stack.core.util.FutureUtils.failedUaFuture) SessionActivityListener(org.eclipse.milo.opcua.sdk.client.SessionActivityListener) StatusChangeNotification(org.eclipse.milo.opcua.stack.core.types.structured.StatusChangeNotification) ExecutionQueue(org.eclipse.milo.opcua.stack.core.util.ExecutionQueue) Logger(org.slf4j.Logger) MonitoredItemNotification(org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemNotification) PublishResponse(org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse) UInteger(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger) Maps(com.google.common.collect.Maps) TimeUnit(java.util.concurrent.TimeUnit) AtomicLong(java.util.concurrent.atomic.AtomicLong) ModifySubscriptionResponse(org.eclipse.milo.opcua.stack.core.types.structured.ModifySubscriptionResponse) UaException(org.eclipse.milo.opcua.stack.core.UaException) Comparator(java.util.Comparator) Collections(java.util.Collections) NotificationMessage(org.eclipse.milo.opcua.stack.core.types.structured.NotificationMessage) UInteger(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger) DateTime(org.eclipse.milo.opcua.stack.core.types.builtin.DateTime)

Example 3 with PublishResponse

use of org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse 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);
}
Also used : MonitoredItemNotification(org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemNotification) EventNotificationList(org.eclipse.milo.opcua.stack.core.types.structured.EventNotificationList) PublishResponse(org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse) ResponseHeader(org.eclipse.milo.opcua.stack.core.types.structured.ResponseHeader) ExtensionObject(org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject) DataChangeNotification(org.eclipse.milo.opcua.stack.core.types.structured.DataChangeNotification) StatusCode(org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode) NotificationMessage(org.eclipse.milo.opcua.stack.core.types.structured.NotificationMessage) EventFieldList(org.eclipse.milo.opcua.stack.core.types.structured.EventFieldList) UInteger(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger) Map(java.util.Map) ConcurrentSkipListMap(java.util.concurrent.ConcurrentSkipListMap)

Example 4 with PublishResponse

use of org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse in project milo by eclipse.

the class Subscription method returnStatusChangeNotification.

void returnStatusChangeNotification(ServiceRequest service, StatusCode status) {
    StatusChangeNotification statusChange = new StatusChangeNotification(status, null);
    UInteger sequenceNumber = uint(nextSequenceNumber());
    NotificationMessage notificationMessage = new NotificationMessage(sequenceNumber, DateTime.now(), new ExtensionObject[] { ExtensionObject.encode(serializationContext, statusChange) });
    ResponseHeader header = service.createResponseHeader();
    PublishResponse response = new PublishResponse(header, subscriptionId, new UInteger[0], false, notificationMessage, service.attr(KEY_ACK_RESULTS).get(), new DiagnosticInfo[0]);
    service.setResponse(response);
    logger.debug("[id={}] returned StatusChangeNotification ({}) sequenceNumber={}.", subscriptionId, status, sequenceNumber);
}
Also used : PublishResponse(org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse) ResponseHeader(org.eclipse.milo.opcua.stack.core.types.structured.ResponseHeader) NotificationMessage(org.eclipse.milo.opcua.stack.core.types.structured.NotificationMessage) UInteger(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger) StatusChangeNotification(org.eclipse.milo.opcua.stack.core.types.structured.StatusChangeNotification)

Example 5 with PublishResponse

use of org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse in project milo by eclipse.

the class OpcUaSubscriptionManager method sendPublishRequest.

private void sendPublishRequest(UaSession session, AtomicLong pendingCount) {
    List<SubscriptionAcknowledgement> subscriptionAcknowledgements = new ArrayList<>();
    subscriptions.values().forEach(subscription -> {
        synchronized (subscription.availableAcknowledgements) {
            subscription.availableAcknowledgements.forEach(sequenceNumber -> subscriptionAcknowledgements.add(new SubscriptionAcknowledgement(subscription.getSubscriptionId(), sequenceNumber)));
            subscription.availableAcknowledgements.clear();
        }
    });
    RequestHeader requestHeader = client.getStackClient().newRequestHeader(session.getAuthenticationToken(), getTimeoutHint());
    UInteger requestHandle = requestHeader.getRequestHandle();
    PublishRequest request = new PublishRequest(requestHeader, subscriptionAcknowledgements.toArray(new SubscriptionAcknowledgement[0]));
    if (logger.isDebugEnabled()) {
        String[] ackStrings = subscriptionAcknowledgements.stream().map(ack -> String.format("id=%s/seq=%s", ack.getSubscriptionId(), ack.getSequenceNumber())).toArray(String[]::new);
        logger.debug("Sending PublishRequest, requestHandle={}, acknowledgements={}", requestHandle, Arrays.toString(ackStrings));
    }
    client.<PublishResponse>sendRequest(request).whenComplete((response, ex) -> {
        if (response != null) {
            logger.debug("Received PublishResponse, sequenceNumber={}", response.getNotificationMessage().getSequenceNumber());
            processingQueue.submit(() -> onPublishComplete(response, pendingCount));
        } else {
            StatusCode statusCode = UaException.extract(ex).map(UaException::getStatusCode).orElse(StatusCode.BAD);
            logger.debug("Publish service failure (requestHandle={}): {}", requestHandle, statusCode, ex);
            pendingCount.getAndUpdate(p -> (p > 0) ? p - 1 : 0);
            if (statusCode.getValue() != StatusCodes.Bad_NoSubscription && statusCode.getValue() != StatusCodes.Bad_TooManyPublishRequests) {
                maybeSendPublishRequests();
            }
            UaException uax = UaException.extract(ex).orElse(new UaException(ex));
            subscriptionListeners.forEach(l -> l.onPublishFailure(uax));
        }
    });
}
Also used : Arrays(java.util.Arrays) ScheduledFuture(java.util.concurrent.ScheduledFuture) BiFunction(java.util.function.BiFunction) CompletableFuture.completedFuture(java.util.concurrent.CompletableFuture.completedFuture) UaSubscriptionManager(org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscriptionManager) LoggerFactory(org.slf4j.LoggerFactory) ExtensionObject(org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject) PublishRequest(org.eclipse.milo.opcua.stack.core.types.structured.PublishRequest) DateTime(org.eclipse.milo.opcua.stack.core.types.builtin.DateTime) Unsigned.uint(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint) UaSubscription(org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription) Unit(org.eclipse.milo.opcua.stack.core.util.Unit) Map(java.util.Map) BigInteger(java.math.BigInteger) CreateSubscriptionResponse(org.eclipse.milo.opcua.stack.core.types.structured.CreateSubscriptionResponse) NodeId(org.eclipse.milo.opcua.stack.core.types.builtin.NodeId) UByte(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UByte) EventNotificationList(org.eclipse.milo.opcua.stack.core.types.structured.EventNotificationList) RepublishResponse(org.eclipse.milo.opcua.stack.core.types.structured.RepublishResponse) SubscriptionAcknowledgement(org.eclipse.milo.opcua.stack.core.types.structured.SubscriptionAcknowledgement) List(java.util.List) Lists.newArrayList(com.google.common.collect.Lists.newArrayList) Variant(org.eclipse.milo.opcua.stack.core.types.builtin.Variant) EventFieldList(org.eclipse.milo.opcua.stack.core.types.structured.EventFieldList) StatusCode(org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode) UaSession(org.eclipse.milo.opcua.sdk.client.api.UaSession) DataValue(org.eclipse.milo.opcua.stack.core.types.builtin.DataValue) OpcUaClient(org.eclipse.milo.opcua.sdk.client.OpcUaClient) NotificationMessage(org.eclipse.milo.opcua.stack.core.types.structured.NotificationMessage) CompletableFuture(java.util.concurrent.CompletableFuture) DataChangeNotification(org.eclipse.milo.opcua.stack.core.types.structured.DataChangeNotification) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) ArrayList(java.util.ArrayList) ConcurrentMap(java.util.concurrent.ConcurrentMap) RequestHeader(org.eclipse.milo.opcua.stack.core.types.structured.RequestHeader) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) ConversionUtil.l(org.eclipse.milo.opcua.stack.core.util.ConversionUtil.l) UaMonitoredItem(org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem) StatusCodes(org.eclipse.milo.opcua.stack.core.StatusCodes) FutureUtils.failedUaFuture(org.eclipse.milo.opcua.stack.core.util.FutureUtils.failedUaFuture) SessionActivityListener(org.eclipse.milo.opcua.sdk.client.SessionActivityListener) StatusChangeNotification(org.eclipse.milo.opcua.stack.core.types.structured.StatusChangeNotification) ExecutionQueue(org.eclipse.milo.opcua.stack.core.util.ExecutionQueue) Logger(org.slf4j.Logger) MonitoredItemNotification(org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemNotification) PublishResponse(org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse) UInteger(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger) Maps(com.google.common.collect.Maps) TimeUnit(java.util.concurrent.TimeUnit) AtomicLong(java.util.concurrent.atomic.AtomicLong) ModifySubscriptionResponse(org.eclipse.milo.opcua.stack.core.types.structured.ModifySubscriptionResponse) UaException(org.eclipse.milo.opcua.stack.core.UaException) Comparator(java.util.Comparator) Collections(java.util.Collections) SubscriptionAcknowledgement(org.eclipse.milo.opcua.stack.core.types.structured.SubscriptionAcknowledgement) UaException(org.eclipse.milo.opcua.stack.core.UaException) Lists.newArrayList(com.google.common.collect.Lists.newArrayList) ArrayList(java.util.ArrayList) UInteger(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger) RequestHeader(org.eclipse.milo.opcua.stack.core.types.structured.RequestHeader) PublishRequest(org.eclipse.milo.opcua.stack.core.types.structured.PublishRequest) StatusCode(org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode)

Aggregations

UInteger (org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger)5 NotificationMessage (org.eclipse.milo.opcua.stack.core.types.structured.NotificationMessage)5 PublishResponse (org.eclipse.milo.opcua.stack.core.types.structured.PublishResponse)5 StatusCode (org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode)4 Map (java.util.Map)3 ExtensionObject (org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject)3 ImmutableList (com.google.common.collect.ImmutableList)2 Lists (com.google.common.collect.Lists)2 Lists.newArrayList (com.google.common.collect.Lists.newArrayList)2 Maps (com.google.common.collect.Maps)2 BigInteger (java.math.BigInteger)2 ArrayList (java.util.ArrayList)2 Arrays (java.util.Arrays)2 Collections (java.util.Collections)2 Comparator (java.util.Comparator)2 List (java.util.List)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 CompletableFuture.completedFuture (java.util.concurrent.CompletableFuture.completedFuture)2 ConcurrentMap (java.util.concurrent.ConcurrentMap)2 ScheduledFuture (java.util.concurrent.ScheduledFuture)2