/// <summary> /// Subscription data changed /// </summary> /// <param name="subscription"></param> /// <param name="notification"></param> /// <param name="stringTable"></param> private void OnSubscriptionDataChanged(Subscription subscription, DataChangeNotification notification, IList <string> stringTable) { try { if (OnSubscriptionChange == null) { return; } var message = new SubscriptionNotificationModel { ServiceMessageContext = subscription.Session.MessageContext, ApplicationUri = subscription.Session.Endpoint.Server.ApplicationUri, EndpointUrl = subscription.Session.Endpoint.EndpointUrl, SubscriptionId = Id, Notifications = notification .ToMonitoredItemNotifications(subscription.MonitoredItems) .ToList() }; OnSubscriptionChange?.Invoke(this, message); } catch (Exception ex) { _logger.Debug(ex, "Exception processing subscription notification"); } }
/// <summary> /// Subscription data changed /// </summary> /// <param name="subscription"></param> /// <param name="notification"></param> /// <param name="stringTable"></param> private void OnSubscriptionDataChanged(Subscription subscription, DataChangeNotification notification, IList <string> stringTable) { try { if (OnSubscriptionChange == null) { return; } if (notification == null) { _logger.Warning("DataChange for subscription: {Subscription} having empty notification", subscription.DisplayName); return; } if (_currentlyMonitored == null) { _logger.Information("DataChange for subscription: {Subscription} having no monitored items yet", subscription.DisplayName); return; } // check if notification is a keep alive var isKeepAlive = notification?.MonitoredItems?.Count == 1 && notification?.MonitoredItems?.First().ClientHandle == 0 && notification?.MonitoredItems?.First().Message?.NotificationData?.Count == 0; var sequenceNumber = notification?.MonitoredItems?.First().Message?.SequenceNumber; var publishTime = (notification?.MonitoredItems?.First().Message?.PublishTime). GetValueOrDefault(DateTime.MinValue); _logger.Debug("DataChange for subscription: {Subscription}, sequence#: " + "{Sequence} isKeepAlive{KeepAlive}, publishTime: {PublishTime}", subscription.DisplayName, sequenceNumber, isKeepAlive, publishTime); var message = new SubscriptionNotificationModel { ServiceMessageContext = subscription.Session.MessageContext, ApplicationUri = subscription.Session.Endpoint.Server.ApplicationUri, EndpointUrl = subscription.Session.Endpoint.EndpointUrl, SubscriptionId = Id, Notifications = (!isKeepAlive) ? notification.ToMonitoredItemNotifications( subscription.MonitoredItems).ToList() : new List <MonitoredItemNotificationModel>() }; message.IsKeyMessage = true; // add the heartbeat for monitored items that did not receive a a datachange notification // Try access lock if we cannot continue... List <MonitoredItemWrapper> currentlyMonitored = null; if (_lock.Wait(0)) { try { currentlyMonitored = _currentlyMonitored; } finally { _lock.Release(); } } if (currentlyMonitored != null) { // add the heartbeat for monitored items that did not receive a // a datachange notification foreach (var item in currentlyMonitored) { if (isKeepAlive || !notification.MonitoredItems.Exists(m => m.ClientHandle == item.Item.ClientHandle)) { if (item.TriggerHeartbeat(publishTime)) { var heartbeatValue = item.Item.LastValue.ToMonitoredItemNotification(item.Item); if (heartbeatValue != null) { heartbeatValue.SequenceNumber = sequenceNumber; heartbeatValue.IsHeartbeat = true; heartbeatValue.PublishTime = publishTime; message.Notifications.Add(heartbeatValue); } } else { // just reset the heartbeat for the items already processed item.TriggerHeartbeat(publishTime); } } } } OnSubscriptionChange?.Invoke(this, message); } catch (Exception ex) { _logger.Debug(ex, "Exception processing subscription notification"); } }