/// <summary> /// Subscribes or unsubscribes to events produced an event source. /// </summary> public override ServiceResult SubscribeToEvents( OperationContext context, object sourceId, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { ServerSystemContext systemContext = SystemContext.Copy(context); // send request to external system. try { MonitoredItem localItem = monitoredItem as MonitoredItem; if (localItem == null) { return ServiceResult.Good; } Opc.Ua.Client.Session client = GetClientSession(systemContext); if (unsubscribe) { lock (client) { // get the subscription. Opc.Ua.Client.Subscription target = null; foreach (Opc.Ua.Client.Subscription current in client.Subscriptions) { target = current; break; } if (target == null) { return ServiceResult.Good; } // find matching item. Opc.Ua.Client.MonitoredItem remoteItem = target.FindItemByClientHandle(monitoredItem.Id); if (remoteItem == null) { return ServiceResult.Good; } // apply changes. target.RemoveItem(remoteItem); target.ApplyChanges(); if (target.MonitoredItemCount == 0) { target.Session.RemoveSubscription(target); } } return ServiceResult.Good; } // create a request. Opc.Ua.Client.MonitoredItem request = new Opc.Ua.Client.MonitoredItem(localItem.Id); if (localItem.NodeId == ObjectIds.Server || localItem.NodeId == m_root.NodeId) { request.StartNodeId = ObjectIds.Server; } else { request.StartNodeId = m_mapper.ToRemoteId(localItem.NodeId); } request.AttributeId = Attributes.EventNotifier; request.MonitoringMode = localItem.MonitoringMode; request.SamplingInterval = (int)localItem.SamplingInterval; request.QueueSize = localItem.QueueSize; request.DiscardOldest = true; request.Filter = localItem.Filter; request.Handle = localItem; lock (client) { // create subscription. if (client.SubscriptionCount == 0) { Opc.Ua.Client.Subscription subscription = new Opc.Ua.Client.Subscription(); subscription.PublishingInterval = 250; subscription.KeepAliveCount = 100; subscription.LifetimeCount = 1000; subscription.MaxNotificationsPerPublish = 10000; subscription.Priority = 1; subscription.PublishingEnabled = true; subscription.TimestampsToReturn = TimestampsToReturn.Both; subscription.DisableMonitoredItemCache = true; subscription.FastDataChangeCallback = OnDataChangeNotification; subscription.FastEventCallback = OnEventNotification; client.AddSubscription(subscription); subscription.Create(); } // get the subscription. Opc.Ua.Client.Subscription target = null; foreach (Opc.Ua.Client.Subscription current in client.Subscriptions) { target = current; break; } if (target == null) { return ServiceResult.Good; } target.AddItem(request); target.ApplyChanges(); if (ServiceResult.IsBad(request.Status.Error)) { Utils.Trace((int)Utils.TraceMasks.Error, "Could not create event item. {0}", request.Status.Error.ToLongString()); } } } catch (Exception e) { Utils.Trace(e, "Could not access external system."); } return ServiceResult.Good; }
/// <summary> /// Called when a batch of monitored items has been created. /// </summary> protected override void OnCreateMonitoredItemsComplete(ServerSystemContext context, IList<IMonitoredItem> monitoredItems) { List<Opc.Ua.Client.MonitoredItem> requests = new List<Opc.Ua.Client.MonitoredItem>(); List<int> indexes = new List<int>(); for (int ii = 0; ii < monitoredItems.Count; ii++) { MonitoredItem monitoredItem = monitoredItems[ii] as MonitoredItem; if (monitoredItem == null || !Object.ReferenceEquals(monitoredItem.NodeManager, this)) { continue; } lock (Lock) { // determine if a local node. if (PredefinedNodes.ContainsKey(monitoredItem.NodeId)) { continue; } // create a request. Opc.Ua.Client.MonitoredItem request = new Opc.Ua.Client.MonitoredItem(monitoredItem.Id); request.StartNodeId = m_mapper.ToRemoteId(monitoredItem.NodeId); request.MonitoringMode = monitoredItem.MonitoringMode; request.SamplingInterval = (int)(monitoredItem.SamplingInterval/2); request.Handle = monitoredItem; requests.Add(request); indexes.Add(ii); } } // send request to external system. try { Opc.Ua.Client.Session client = GetClientSession(context); lock (client) { // create subscription. if (client.SubscriptionCount == 0) { Opc.Ua.Client.Subscription subscription = new Opc.Ua.Client.Subscription(); subscription.PublishingInterval = 250; subscription.KeepAliveCount = 100; subscription.LifetimeCount = 1000; subscription.MaxNotificationsPerPublish = 10000; subscription.Priority = 1; subscription.PublishingEnabled = true; subscription.TimestampsToReturn = TimestampsToReturn.Both; subscription.DisableMonitoredItemCache = true; subscription.FastDataChangeCallback = OnDataChangeNotification; subscription.FastEventCallback = OnEventNotification; client.AddSubscription(subscription); subscription.Create(); } // add items. Opc.Ua.Client.Subscription target = null; foreach (Opc.Ua.Client.Subscription current in client.Subscriptions) { target = current; break; } for (int ii = 0; ii < requests.Count; ii++) { target.AddItem(requests[ii]); } target.ApplyChanges(); // check status. int index = 0; foreach (Opc.Ua.Client.MonitoredItem monitoredItem in target.MonitoredItems) { if (ServiceResult.IsBad(monitoredItem.Status.Error)) { ((MonitoredItem)monitoredItems[indexes[index++]]).QueueValue(null, monitoredItem.Status.Error); } } } } catch (Exception e) { // handle unexpected communication error. ServiceResult error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Could not access external system."); for (int ii = 0; ii < requests.Count; ii++) { ((MonitoredItem)monitoredItems[indexes[ii]]).QueueValue(null, error); } } }