/// <summary> /// Processes a Publish repsonse from the server. /// </summary> void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { if (InvokeRequired) { BeginInvoke(m_MonitoredItemNotification, monitoredItem, e); return; } else if (!IsHandleCreated) { return; } try { // ignore notifications for other monitored items. if (!Object.ReferenceEquals(m_monitoredItem, monitoredItem)) { return; } // notify controls of the change. EventsCTRL.NotificationReceived(e); DataChangesCTRL.NotificationReceived(e); if (e != null) { MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification; LatestValueCTRL.ShowValue(notification, true); } // update item status. UpdateStatus(); } catch (Exception exception) { GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception); } }
private void SubCallback(string key, MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args) { if (InvokeRequired) { Invoke(new Action <string, MonitoredItem, MonitoredItemNotificationEventArgs>(SubCallback), key, monitoredItem, args); return; } if (key == "A") { // 如果有多个的订阅值都关联了当前的方法,可以通过key和monitoredItem来区分 MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification; if (notification != null) { textBox3.Text = notification.Value.WrappedValue.Value.ToString(); } } else if (key == "B") { // 需要区分出来每个不同的节点信息 MonitoredItemNotification notification = args.NotificationValue as MonitoredItemNotification; if (monitoredItem.StartNodeId.ToString() == MonitorNodeTags[0]) { textBox5.Text = notification.Value.WrappedValue.Value.ToString(); } else if (monitoredItem.StartNodeId.ToString() == MonitorNodeTags[1]) { textBox9.Text = notification.Value.WrappedValue.Value.ToString(); } else if (monitoredItem.StartNodeId.ToString() == MonitorNodeTags[2]) { textBox10.Text = notification.Value.WrappedValue.Value.ToString(); } } }
private void MonitoredItemNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { try { if (!(e.NotificationValue is MonitoredItemNotification monitoredItemNotification)) { return; } for (int index = 0; index < monitoredVariablePanel.Controls.Count; index++) { if (monitoredVariablePanel.Controls[index].Name != monitoredItem.ResolvedNodeId.ToString()) { continue; } ArgumentUserControl argumentUserControl = (ArgumentUserControl)monitoredVariablePanel.Controls[index]; argumentUserControl.ValueInput = monitoredItemNotification.Value.WrappedValue.ToString(); } } catch (Exception ex) { InformationDisplay($"Monitored Item Notification exception: {ex.StackTrace}"); } }
public void addConnection(BaseVariableState collectorNode, ReferenceDescription clientNode) { // test if clientNode is Variable if (clientNode.NodeClass == NodeClass.Variable)//&& collectorNode.GetType()==typeof(VariableNode)) { MonitoredItem monitoredItem = new MonitoredItem(); monitoredItem.StartNodeId = ExpandedNodeId.ToNodeId(clientNode.NodeId, session.NamespaceUris); monitoredItem.AttributeId = Attributes.Value; monitoredItem.Notification += new MonitoredItemNotificationEventHandler(connectVariable); Debug.Print("Client.cs: not fully implemented new session, just easily created"); Subscription sub = new Subscription(); sub.PublishingEnabled = true; sub.PublishingInterval = 1000; sub.Priority = 1; sub.KeepAliveCount = 10; sub.LifetimeCount = 20; sub.MaxNotificationsPerPublish = 1000; sub.AddItem(monitoredItem); session.AddSubscription(sub); sub.Create(); connectedVariables.Add(monitoredItem, collectorNode); } }
private void OnFastDataChange(Subscription subscription, DataChangeNotification notification, IList <string> stringTable) { OpcUaDeviceOutParamEntity opcUaDeviceOutParamEntity = new OpcUaDeviceOutParamEntity(); opcUaDeviceOutParamEntity.StatusCode = (uint)DeviceStatusCode.SubscriptionOK; opcUaDeviceOutParamEntity.SubScriptionValueList = new List <Tuple <string, object> >(); foreach (MonitoredItemNotification itemNotification in notification.MonitoredItems) { MonitoredItem item = subscription.FindItemByClientHandle(itemNotification.ClientHandle); if (item == null) { continue; } foreach (var value in item.DequeueValues()) { opcUaDeviceOutParamEntity.SubScriptionValueList.Add(Tuple.Create(item.ResolvedNodeId.ToString(), value.Value)); } } DeviceEventArgs <DeviceParamEntityBase> args = new DeviceEventArgs <DeviceParamEntityBase>(opcUaDeviceOutParamEntity); Notification.Invoke(this, args); }
/// <summary> /// Removes the monitored item from the collection. /// </summary> /// <param name="source">The source.</param> /// <param name="monitoredItem">The monitored item.</param> private HdaSubscribeAttributeRequest Remove(NodeState source, MonitoredItem monitoredItem) { lock (m_lock) { m_monitoredItems.Remove(monitoredItem.Id); // get the HDA item id. string itemId = GetItemId(source); // delete the subscribe request for the HDA item. if (itemId != null) { HdaSubscribeAttributeRequest request = FindAttributeRequest(itemId, false); if (request != null) { request.Remove(m_context, monitoredItem); return(request); } } return(null); } }
/// <summary> /// Adds the monitored item to the collection. /// </summary> /// <param name="source">The source.</param> /// <param name="monitoredItem">The monitored item.</param> private HdaSubscribeAttributeRequest Add(NodeState source, MonitoredItem monitoredItem) { lock (m_lock) { m_monitoredItems.Add(monitoredItem.Id, monitoredItem); // get the HDA item id. string itemId = GetItemId(source); // create/update the subscribe request for the HDA item. if (itemId != null) { HdaSubscribeAttributeRequest request = FindAttributeRequest(itemId, true); if (request != null) { request.Add(m_context, monitoredItem); return(request); } } return(null); } }
/// <summary> /// Updates the filter. /// </summary> private void UpdateFilter() { if (m_subscription != null) { // changing the filter changes the fields requested. this makes it // impossible to process notifications sent before the change. // to avoid this problem we create a new item and remove the old one. MonitoredItem monitoredItem = m_filter.CreateMonitoredItem(m_session); // set up callback for notifications. monitoredItem.Notification += m_MonitoredItem_Notification; m_subscription.AddItem(monitoredItem); m_subscription.RemoveItem(m_monitoredItem); m_subscription.ApplyChanges(); // replace monitored item. m_monitoredItem.Notification -= m_MonitoredItem_Notification; m_monitoredItem = monitoredItem; // send a refresh since previously filtered conditions may be now available. Conditions_RefreshMI_Click(this, null); } }
/// <summary> /// Changes the area monitored by the control. /// </summary> public void ChangeArea(NodeId areaId, bool fetchRecent) { m_areaId = areaId; EventsLV.Items.Clear(); if (fetchRecent) { ReadRecentHistory(); } if (m_subscription != null) { MonitoredItem monitoredItem = new MonitoredItem(m_monitoredItem); monitoredItem.StartNodeId = areaId; m_subscription.AddItem(monitoredItem); m_subscription.RemoveItem(m_monitoredItem); m_monitoredItem = monitoredItem; monitoredItem.Notification += new MonitoredItemNotificationEventHandler(MonitoredItem_Notification); m_subscription.ApplyChanges(); } }
/// <summary> /// Callback method for updating values of subscibed nodes /// </summary> /// <param name="monitoredItem"></param> /// <param name="e"></param> private void Notification_MonitoredItem(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { if (!(e.NotificationValue is MonitoredItemNotification notification)) { return; } var value = notification.Value; var variable = ArchiveVariables.FirstOrDefault(x => x.Name == monitoredItem.StartNodeId && monitoredItem.DisplayName == $"{x.Name} [{ArchiveInterval.None}]"); if (variable == null) { return; } _unitOfWork.Records.Add(new RecordEntity() { ArchiveTime = value.SourceTimestamp, VariableId = variable.Id, Value = value.Value.ToString() }); }
void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { if (InvokeRequired) { BeginInvoke(new MonitoredItemNotificationEventHandler(MonitoredItem_Notification), monitoredItem, e); return; } try { MonitoredItemNotification datachange = e.NotificationValue as MonitoredItemNotification; if (datachange == null) { return; } CurrentStateTB.Text = datachange.Value.WrappedValue.ToString(); } catch (Exception exception) { ClientUtils.HandleException(this.Text, exception); } }
/// <summary> /// Updates the request after adding/removing items. /// </summary> private void UpdateSamplingInterval() { double samplingInterval = Double.MaxValue; for (int ii = 0; ii < MonitoredItems.Count; ii++) { MonitoredItem monitoredItem = MonitoredItems[ii]; // find the handle associated with the item. NodeHandle handle = monitoredItem.ManagerHandle as NodeHandle; if (handle == null) { continue; } // ignore disabled items. if (monitoredItem.MonitoringMode == MonitoringMode.Disabled) { continue; } // find the fastest sampling interval. if (samplingInterval > monitoredItem.SamplingInterval) { samplingInterval = monitoredItem.SamplingInterval; } } // update values. if (samplingInterval != m_samplingInterval) { m_samplingInterval = (int)samplingInterval; m_nextUpdateTime = DateTime.UtcNow; } }
void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { if (InvokeRequired) { BeginInvoke(new MonitoredItemNotificationEventHandler(MonitoredItem_Notification), monitoredItem, e); return; } try { MonitoredItemNotification datachange = e.NotificationValue as MonitoredItemNotification; if (datachange == null) { return; } CurrentStateTB.Text = datachange.Value.WrappedValue.ToString(); } catch (Exception exception) { MessageBox.Show(exception.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <summary> /// Monitored item notification handler /// </summary> /// <param name="monitoredItem"></param> /// <param name="e"></param> private void OnMonitoredItemChanged(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { try { if (OnMonitoredItemChange == null) { return; } if (e?.NotificationValue == null || monitoredItem?.Subscription?.Session == null) { return; } if (!(e.NotificationValue is MonitoredItemNotification notification)) { return; } if (!(notification.Value is DataValue value)) { return; } var message = new SubscriptionNotificationModel { ServiceMessageContext = monitoredItem.Subscription.Session.MessageContext, ApplicationUri = monitoredItem.Subscription.Session.Endpoint.Server.ApplicationUri, EndpointUrl = monitoredItem.Subscription.Session.Endpoint.EndpointUrl, SubscriptionId = Id, Notifications = new List <MonitoredItemNotificationModel> { notification.ToMonitoredItemNotification(monitoredItem) } }; OnMonitoredItemChange(this, message); } catch (Exception ex) { _logger.Debug(ex, "Exception processing monitored item notification"); } }
private void ViewValueMI_Click(object sender, EventArgs e) { try { MonitoredItem monitoredItem = null; DataValue value = null; foreach (DataGridViewRow row in ResultsDV.SelectedRows) { DataRowView source = row.DataBoundItem as DataRowView; monitoredItem = (MonitoredItem)source.Row[0]; value = (DataValue)source.Row[11]; break; } if (monitoredItem == null) { return; } m_EditComplexValueDlg = new EditComplexValueDlg(); m_EditComplexValueDlg.Tag = monitoredItem; m_EditComplexValueDlg.ShowDialog( m_session, monitoredItem.ResolvedNodeId, monitoredItem.AttributeId, null, value.Value, true, "View Data Change"); m_EditComplexValueDlg = null; } catch (Exception exception) { ClientUtils.HandleException(this.Text, exception); } }
private void OnMonitorNotification(MonitoredItem monitoreditem, MonitoredItemNotificationEventArgs e) { VariableNode varNode = (VariableNode)monitoreditem.Subscription.Session.ReadNode(monitoreditem.StartNodeId); foreach (var value in monitoreditem.DequeueValues()) { Console.WriteLine("Got a value"); var typeManager = new DataTypeManager(monitoreditem.Subscription.Session); UaValue opcvalue = typeManager.GetUaValue(varNode, value, false); dynamic monitorInfoPair; lock (_monitorPublishInfo) { monitorInfoPair = _monitorPublishInfo .SelectMany(pair => pair.Value, (parent, child) => new { ServerUrl = parent.Key, Info = child }) .First(couple => couple.Info.Subscription == monitoreditem.Subscription); } var message = $"[TOPIC: {monitorInfoPair.Info.Topic}] \t ({monitoreditem.DisplayName}): {opcvalue.Value}"; monitorInfoPair.Info.Forward(message); Console.WriteLine(message); } }
/// <summary> /// Handles a set monitoring mode request. /// </summary> public void SetMonitoringMode(List <MonitoringRequest> requests) { lock (m_lock) { if (m_session == null) { throw new ServiceResultException(StatusCodes.BadCommunicationError); } for (int ii = 0; ii < requests.Count; ii++) { MonitoredItem monitoredItem = null; if (!m_monitoredItems.TryGetValue(requests[ii].MonitoredItem.Id, out monitoredItem)) { continue; } monitoredItem.MonitoringMode = requests[ii].MonitoredItem.MonitoringMode; } m_subscription.ApplyChanges(); } }
private void DeleteMI_Click(object sender, EventArgs e) { try { if (m_state != DisplayState.EditItems) { return; } foreach (DataGridViewRow row in ItemsDV.SelectedRows) { DataRowView source = row.DataBoundItem as DataRowView; MonitoredItem monitoredItem = (MonitoredItem)source.Row[0]; m_subscription.RemoveItem(monitoredItem); source.Row.Delete(); } m_dataset.AcceptChanges(); } catch (Exception exception) { ClientUtils.HandleException(this.Text, exception); } }
private void NewMI_Click(object sender, EventArgs e) { try { MonitoredItem monitoredItem = null; foreach (DataGridViewRow row in ResultsDV.SelectedRows) { DataRowView source = row.DataBoundItem as DataRowView; monitoredItem = (MonitoredItem)source.Row[0]; break; } if (monitoredItem == null) { monitoredItem = new MonitoredItem(m_subscription.DefaultItem); } else { monitoredItem = new MonitoredItem(monitoredItem); } if (new EditMonitoredItemDlg().ShowDialog(m_session, monitoredItem, false)) { m_subscription.AddItem(monitoredItem); DataRow row = m_dataset.Tables[0].NewRow(); monitoredItem.Handle = row; UpdateRow(row, monitoredItem); m_dataset.Tables[0].Rows.Add(row); } } catch (Exception exception) { ClientUtils.HandleException(this.Text, exception); } }
/// <summary> /// Constructs an event object from a notification. /// </summary> /// <param name="session">The session.</param> /// <param name="monitoredItem">The monitored item that produced the notification.</param> /// <param name="notification">The notification.</param> /// <param name="knownEventTypes">The known event types.</param> /// <param name="eventTypeMappings">Mapping between event types and known event types.</param> /// <returns> /// The event object. Null if the notification is not a valid event type. /// </returns> public static BaseEventState ConstructEvent( Session session, MonitoredItem monitoredItem, EventFieldList notification, Dictionary <NodeId, Type> knownEventTypes, Dictionary <NodeId, NodeId> eventTypeMappings) { // find the event type. NodeId eventTypeId = FindEventType(monitoredItem, notification); if (eventTypeId == null) { return(null); } // look up the known event type. Type knownType = null; NodeId knownTypeId = null; if (eventTypeMappings.TryGetValue(eventTypeId, out knownTypeId)) { knownType = knownEventTypes[knownTypeId]; } // try again. if (knownType == null) { if (knownEventTypes.TryGetValue(eventTypeId, out knownType)) { knownTypeId = eventTypeId; eventTypeMappings.Add(eventTypeId, eventTypeId); } } // try mapping it to a known type. if (knownType == null) { // browse for the supertypes of the event type. ReferenceDescriptionCollection supertypes = ClientUtils.BrowseSuperTypes(session, eventTypeId, false); // can't do anything with unknown types. if (supertypes == null) { return(null); } // find the first supertype that matches a known event type. for (int ii = 0; ii < supertypes.Count; ii++) { NodeId superTypeId = (NodeId)supertypes[ii].NodeId; if (knownEventTypes.TryGetValue(superTypeId, out knownType)) { knownTypeId = superTypeId; eventTypeMappings.Add(eventTypeId, superTypeId); } if (knownTypeId != null) { break; } } // can't do anything with unknown types. if (knownTypeId == null) { return(null); } } // construct the event based on the known event type. BaseEventState e = (BaseEventState)Activator.CreateInstance(knownType, new object[] { (NodeState)null }); // get the filter which defines the contents of the notification. EventFilter filter = monitoredItem.Status.Filter as EventFilter; // initialize the event with the values in the notification. e.Update(session.SystemContext, filter.SelectClauses, notification); // save the orginal notification. e.Handle = notification; return(e); }
private void BoilerCB_SelectedIndexChanged(object sender, EventArgs e) { try { if (m_session == null) { return; } if (m_subscription != null) { m_session.RemoveSubscription(m_subscription); m_subscription = null; } ReferenceDescription boiler = (ReferenceDescription)BoilerCB.SelectedItem; if (boiler == null) { return; } m_subscription = new Subscription(); m_subscription.PublishingEnabled = true; m_subscription.PublishingInterval = 1000; m_subscription.Priority = 1; m_subscription.KeepAliveCount = 10; m_subscription.LifetimeCount = 20; m_subscription.MaxNotificationsPerPublish = 1000; m_session.AddSubscription(m_subscription); m_subscription.Create(); NamespaceTable wellKnownNamespaceUris = new NamespaceTable(); wellKnownNamespaceUris.Append(Namespaces.Boiler); string[] browsePaths = new string[] { "1:PipeX001/1:FTX001/1:Output", "1:DrumX001/1:LIX001/1:Output", "1:PipeX002/1:FTX002/1:Output", "1:LCX001/1:SetPoint", }; List <NodeId> nodes = ClientUtils.TranslateBrowsePaths( m_session, (NodeId)boiler.NodeId, wellKnownNamespaceUris, browsePaths); Control[] controls = new Control[] { InputPipeFlowTB, DrumLevelTB, OutputPipeFlowTB, DrumLevelSetPointTB }; for (int ii = 0; ii < nodes.Count; ii++) { controls[ii].Text = "---"; if (nodes[ii] != null) { MonitoredItem monitoredItem = new MonitoredItem(); monitoredItem.StartNodeId = nodes[ii]; monitoredItem.AttributeId = Attributes.Value; monitoredItem.Handle = controls[ii]; monitoredItem.Notification += new MonitoredItemNotificationEventHandler(MonitoredItem_Notification); m_subscription.AddItem(monitoredItem); } } m_subscription.ApplyChanges(); } catch (Exception exception) { ClientUtils.HandleException(this.Text, exception); } }
/// <summary> /// Updates the display with a new value for a monitored variable. /// </summary> private void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { if (this.InvokeRequired) { this.BeginInvoke(new MonitoredItemNotificationEventHandler(MonitoredItem_Notification), monitoredItem, e); return; } try { EventFieldList notification = e.NotificationValue as EventFieldList; if (notification == null) { return; } // check the type of event. NodeId eventTypeId = FormUtils.FindEventType(monitoredItem, notification); // ignore unknown events. if (NodeId.IsNull(eventTypeId)) { return; } // check for refresh start. if (eventTypeId == ObjectTypeIds.RefreshStartEventType) { ConditionsLV.Items.Clear(); return; } // check for refresh end. if (eventTypeId == ObjectTypeIds.RefreshEndEventType) { return; } // construct the condition object. ConditionState condition = FormUtils.ConstructEvent( m_session, monitoredItem, notification, m_eventTypeMappings) as ConditionState; if (condition == null) { return; } // look for existing entry. ListViewItem item = null; for (int ii = 0; ii < ConditionsLV.Items.Count; ii++) { ConditionState current = (ConditionState)ConditionsLV.Items[ii].Tag; // the combination of a condition and branch id uniquely identify an item in the display. if (current.NodeId == condition.NodeId && BaseVariableState.GetValue(current.BranchId) == BaseVariableState.GetValue(condition.BranchId)) { // match found but watch out for out of order events (async processing can cause this to happen). if (BaseVariableState.GetValue(current.Time) > BaseVariableState.GetValue(condition.Time)) { return; } item = ConditionsLV.Items[ii]; break; } } // create a new entry. if (item == null) { item = new ListViewItem(String.Empty); item.SubItems.Add(String.Empty); // Condition item.SubItems.Add(String.Empty); // Branch item.SubItems.Add(String.Empty); // Type item.SubItems.Add(String.Empty); // Severity item.SubItems.Add(String.Empty); // Time item.SubItems.Add(String.Empty); // State item.SubItems.Add(String.Empty); // Message item.SubItems.Add(String.Empty); // Comment ConditionsLV.Items.Add(item); } // look up the condition type metadata in the local cache. INode type = m_session.NodeCache.Find(condition.TypeDefinitionId); // Source if (condition.SourceName != null) { item.SubItems[0].Text = Utils.Format("{0}", condition.SourceName.Value); } else { item.SubItems[0].Text = null; } // Condition if (condition.ConditionName != null) { item.SubItems[1].Text = Utils.Format("{0}", condition.ConditionName.Value); } else { item.SubItems[1].Text = null; } // Branch if (condition.BranchId != null && !NodeId.IsNull(condition.BranchId.Value)) { item.SubItems[2].Text = Utils.Format("{0}", condition.BranchId.Value); } else { item.SubItems[2].Text = null; } // Type if (type != null) { item.SubItems[3].Text = Utils.Format("{0}", type); } else { item.SubItems[3].Text = null; } // Severity if (condition.Severity != null) { item.SubItems[4].Text = Utils.Format("{0}", (EventSeverity)condition.Severity.Value); } else { item.SubItems[4].Text = null; } // Time if (condition.Time != null) { item.SubItems[5].Text = Utils.Format("{0:HH:mm:ss.fff}", condition.Time.Value.ToLocalTime()); } else { item.SubItems[5].Text = null; } // State if (condition.EnabledState != null && condition.EnabledState.EffectiveDisplayName != null) { item.SubItems[6].Text = Utils.Format("{0}", condition.EnabledState.EffectiveDisplayName.Value); } else { item.SubItems[6].Text = null; } // Message if (condition.Message != null) { item.SubItems[7].Text = Utils.Format("{0}", condition.Message.Value); } else { item.SubItems[7].Text = null; } // Comment if (condition.Comment != null) { item.SubItems[8].Text = Utils.Format("{0}", condition.Comment.Value); } else { item.SubItems[8].Text = null; } item.Tag = condition; // set the color based on the retain bit. if (!BaseVariableState.GetValue(condition.Retain)) { item.ForeColor = Color.DimGray; } else { if (NodeId.IsNull(BaseVariableState.GetValue(condition.BranchId))) { item.ForeColor = Color.Empty; } else { item.ForeColor = Color.DarkGray; } } // adjust the width of the columns. for (int ii = 0; ii < ConditionsLV.Columns.Count; ii++) { ConditionsLV.Columns[ii].Width = -2; } } catch (Exception exception) { ClientUtils.HandleException(this.Text, exception); } }
/// <summary> /// Updates the application after connecting to or disconnecting from the server. /// </summary> private void Server_ConnectComplete(object sender, EventArgs e) { try { m_session = ConnectServerCTRL.Session; // check for disconnect. if (m_session == null) { if (m_auditEventForm != null) { m_auditEventForm.Close(); m_auditEventForm = null; } return; } // set a suitable initial state. if (m_session != null && !m_connectedOnce) { m_connectedOnce = true; } // create the default subscription. m_subscription = new Subscription(); m_subscription.DisplayName = null; m_subscription.PublishingInterval = 1000; m_subscription.KeepAliveCount = 10; m_subscription.LifetimeCount = 100; m_subscription.MaxNotificationsPerPublish = 1000; m_subscription.PublishingEnabled = true; m_subscription.TimestampsToReturn = TimestampsToReturn.Both; m_session.AddSubscription(m_subscription); m_subscription.Create(); // must specify the fields that the form is interested in. m_filter.SelectClauses = m_filter.ConstructSelectClauses( m_session, NodeId.Parse("ns=2;s=4:2"), NodeId.Parse("ns=2;s=4:1"), ObjectTypeIds.DialogConditionType, ObjectTypeIds.ExclusiveLimitAlarmType, ObjectTypeIds.NonExclusiveLimitAlarmType); // create a monitored item based on the current filter settings. m_monitoredItem = m_filter.CreateMonitoredItem(m_session); // set up callback for notifications. m_monitoredItem.Notification += m_MonitoredItem_Notification; m_subscription.AddItem(m_monitoredItem); m_subscription.ApplyChanges(); // send an initial refresh. Conditions_RefreshMI_Click(sender, e); ConditionsMI.Enabled = true; ViewMI.Enabled = true; } catch (Exception exception) { ClientUtils.HandleException(this.Text, exception); } }
private async Task <Session> ConsoleSampleClient() { Console.WriteLine("1 - Create an Application Configuration."); ExitCode = ExitCode.ErrorCreateApplication; ApplicationInstance application = new ApplicationInstance { ApplicationName = "UA Core Complex Client", ApplicationType = ApplicationType.Client, ConfigSectionName = "Opc.Ua.ComplexClient" }; // load the application configuration. ApplicationConfiguration config = await application.LoadApplicationConfiguration(false).ConfigureAwait(false); // check the application certificate. bool haveAppCertificate = await application.CheckApplicationInstanceCertificate(false, 0).ConfigureAwait(false); if (!haveAppCertificate) { throw new Exception("Application instance certificate invalid!"); } ReverseConnectManager reverseConnectManager = null; if (ReverseConnectUri != null) { // start the reverse connection manager reverseConnectManager = new ReverseConnectManager(); reverseConnectManager.AddEndpoint(ReverseConnectUri); reverseConnectManager.StartService(config); } if (haveAppCertificate) { config.ApplicationUri = Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate); if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { m_autoAccept = true; } config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } else { Console.WriteLine(" WARN: missing application certificate, using unsecure connection."); } Console.WriteLine("2 - Discover endpoints of {0}.", m_endpointURL); ExitCode = ExitCode.ErrorDiscoverEndpoints; EndpointDescription selectedEndpoint; if (reverseConnectManager == null) { selectedEndpoint = CoreClientUtils.SelectEndpoint(m_endpointURL, haveAppCertificate, 15000); } else { Console.WriteLine(" Waiting for reverse connection."); ITransportWaitingConnection connection = await reverseConnectManager.WaitForConnection( new Uri(m_endpointURL), null, new CancellationTokenSource(60000).Token); if (connection == null) { throw new ServiceResultException(StatusCodes.BadTimeout, "Waiting for a reverse connection timed out."); } selectedEndpoint = CoreClientUtils.SelectEndpoint(config, connection, haveAppCertificate, 15000); } Console.WriteLine(" Selected endpoint uses: {0}", selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1)); Console.WriteLine("3 - Create a session with OPC UA server."); ExitCode = ExitCode.ErrorCreateSession; // create the user identity UserIdentity userIdentity; if (String.IsNullOrEmpty(Username) && String.IsNullOrEmpty(Password)) { userIdentity = new UserIdentity(new AnonymousIdentityToken()); } else { userIdentity = new UserIdentity(Username, Password); } // create worker session if (reverseConnectManager == null) { m_session = await CreateSession(config, selectedEndpoint, userIdentity).ConfigureAwait(false); } else { Console.WriteLine(" Waiting for reverse connection."); ITransportWaitingConnection connection = await reverseConnectManager.WaitForConnection( new Uri(m_endpointURL), null, new CancellationTokenSource(60000).Token); if (connection == null) { throw new ServiceResultException(StatusCodes.BadTimeout, "Waiting for a reverse connection timed out."); } m_session = await CreateSession(config, connection, selectedEndpoint, userIdentity).ConfigureAwait(false); } // register keep alive handler m_session.KeepAlive += Client_KeepAlive; Console.WriteLine("4 - Browse for all custom type variables."); ExitCode = ExitCode.ErrorReadComplexTypes; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); var allVariableNodes = BrowseAdddressSpace ? BrowseAllVariables() : new List <INode>(); var allCustomTypeVariables = allVariableNodes.Where(n => ((VariableNode)n).DataType.NamespaceIndex != 0).ToList(); stopWatch.Stop(); Console.WriteLine($" -- Browse all nodes took {stopWatch.ElapsedMilliseconds}ms."); Console.WriteLine($" -- Browsed {allVariableNodes.Count} nodes, from which {allCustomTypeVariables.Count} are custom type variables."); stopWatch.Reset(); // for testing clear the nodecache m_session.NodeCache.Clear(); stopWatch.Start(); if (LoadTypeSystem) { Console.WriteLine("5 - Load the server type dictionary."); ExitCode = ExitCode.ErrorLoadTypeDictionary; stopWatch.Reset(); stopWatch.Start(); var complexTypeSystem = new ComplexTypeSystem(m_session); await complexTypeSystem.Load().ConfigureAwait(false); stopWatch.Stop(); Console.WriteLine($"Load type system took {stopWatch.ElapsedMilliseconds}ms."); Console.WriteLine($"Custom types defined for this session:"); foreach (var type in complexTypeSystem.GetDefinedTypes()) { Console.WriteLine($"{type.Namespace}.{type.Name}"); } Console.WriteLine($"Loaded {m_session.DataTypeSystem.Count} dictionaries:"); foreach (var dictionary in m_session.DataTypeSystem) { Console.WriteLine($" + {dictionary.Value.Name}"); foreach (var type in dictionary.Value.DataTypes) { Console.WriteLine($" -- {type.Key}:{type.Value}"); } } } else { Console.WriteLine("4 - Not loading the server type dictionary."); } foreach (VariableNode variableNode in allCustomTypeVariables) { try { var value = m_session.ReadValue(variableNode.NodeId); CastInt32ToEnum(variableNode, value); Console.WriteLine($" -- {variableNode}:{value}"); if (value.Value is ExtensionObject extensionObject) { if (extensionObject.Body is BaseComplexType complexType) { foreach (var item in complexType.GetPropertyEnumerator()) { if (Verbose) { Console.WriteLine($" -- -- {item.Name}:{complexType[item.Name]}"); } if (WriteComplexInt && item.PropertyType == typeof(Int32)) { var data = complexType[item.Name]; if (data != null) { complexType[item.Name] = (Int32)data + 1; } Console.WriteLine($" -- -- Increment: {item.Name}, {complexType[item.Name]}"); WriteValue(m_session, variableNode.NodeId, value); } } } } if (PrintAsJson) { PrintValueAsJson(variableNode.BrowseName.Name, value); } } catch (ServiceResultException sre) { if (sre.StatusCode == StatusCodes.BadUserAccessDenied) { Console.WriteLine($" -- {variableNode}: Access denied!"); } } } Console.WriteLine("6 - Create test sessions which load only single types as needed."); if (LoadTypeSystem) { foreach (VariableNode variableNode in allCustomTypeVariables) { Session testSession = null; try { Console.WriteLine($"Open session for {variableNode}:"); testSession = await CreateSession(config, selectedEndpoint, userIdentity).ConfigureAwait(false); var complexTypeSystem = new ComplexTypeSystem(testSession); NodeId dataType = variableNode.DataType; Type nullType = testSession.Factory.GetSystemType(dataType); var valueBefore = testSession.ReadValue(variableNode.NodeId); Console.WriteLine($" -- {valueBefore}"); Type systemType = await complexTypeSystem.LoadType(dataType).ConfigureAwait(false); var valueAfter = testSession.ReadValue(variableNode.NodeId); Console.WriteLine($" -- {variableNode}: {systemType} {dataType}"); Console.WriteLine($" -- {valueAfter}"); Console.WriteLine($"Custom types defined for {variableNode}:"); foreach (var type in complexTypeSystem.GetDefinedTypes()) { Console.WriteLine($" -- {type.Namespace}.{type.Name}"); } } catch (ServiceResultException sre) { if (sre.StatusCode == StatusCodes.BadUserAccessDenied) { Console.WriteLine($" -- {variableNode}: Access denied!"); } } finally { testSession?.Close(); } } } else { Console.WriteLine("6 - Not testing to load individual types."); } Console.WriteLine("7 - Create a subscription with publishing interval of 1 second."); ExitCode = ExitCode.ErrorCreateSubscription; var subscription = new Subscription(m_session.DefaultSubscription) { PublishingInterval = 1000 }; Console.WriteLine("8 - Add all custom values and the server time to the subscription."); ExitCode = ExitCode.ErrorMonitoredItem; var list = new List <MonitoredItem> { new MonitoredItem(subscription.DefaultItem) { DisplayName = "ServerStatusCurrentTime", StartNodeId = "i=" + Variables.Server_ServerStatus_CurrentTime.ToString() } }; list.ForEach(i => i.Notification += OnNotification); foreach (var customVariable in allCustomTypeVariables) { var newItem = new MonitoredItem(subscription.DefaultItem) { DisplayName = customVariable.DisplayName.Text, StartNodeId = ExpandedNodeId.ToNodeId(customVariable.NodeId, m_session.NamespaceUris) }; newItem.Notification += OnComplexTypeNotification; list.Add(newItem); } subscription.AddItems(list); Console.WriteLine("9 - Add the subscription to the session."); ExitCode = ExitCode.ErrorAddSubscription; m_session.AddSubscription(subscription); subscription.Create(); Console.WriteLine("10 - Running...Press Ctrl-C to exit..."); ExitCode = ExitCode.ErrorRunning; return(m_session); }
/// <summary> /// Validates the items. /// </summary> /// <param name="group">The group.</param> /// <param name="requests">The requests.</param> /// <returns>The items. May contain null is validation failed.</returns> public ComDaGroupItem[] ValidateItems(ComDaGroup group, ComDaCreateItemRequest[] requests) { TraceState("ValidateItems", group.Name); // get the session to use for the operation. Session session = m_session; if (session == null) { throw ComUtils.CreateComException(ResultIds.E_FAIL); } // validate items. ComDaGroupItem[] items = new ComDaGroupItem[requests.Length]; for (int ii = 0; ii < requests.Length; ii += 10000) { ValidateItems(session, group, requests, items, ii, 10000); } // process results. for (int ii = 0; ii < requests.Length; ii++) { // check for the results. ComDaCreateItemRequest request = requests[ii]; if (request.Error < 0) { items[ii] = null; continue; } // check access path. if (!String.IsNullOrEmpty(request.AccessPath)) { items[ii] = null; request.Error = ResultIds.E_UNKNOWNPATH; continue; } ComDaGroupItem item = items[ii]; // validate the datatype. if (request.RequestedDataType != 0) { NodeId dataTypeId = ComUtils.GetDataTypeId(request.RequestedDataType); if (NodeId.IsNull(dataTypeId)) { items[ii] = null; request.Error = ResultIds.E_BADTYPE; continue; } bool reqTypeIsArray = (request.RequestedDataType & (short)VarEnum.VT_ARRAY) != 0; bool actualTypeIsArray = (item.CanonicalDataType & (short)VarEnum.VT_ARRAY) != 0; if (reqTypeIsArray != actualTypeIsArray) { items[ii] = null; request.Error = ResultIds.E_BADTYPE; continue; } } // create a new monitored item. MonitoredItem monitoredItem = new MonitoredItem(); monitoredItem.StartNodeId = item.NodeId; monitoredItem.RelativePath = null; monitoredItem.AttributeId = Attributes.Value; monitoredItem.MonitoringMode = (request.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled; monitoredItem.SamplingInterval = group.UpdateRate / 2; monitoredItem.QueueSize = 0; monitoredItem.DiscardOldest = true; monitoredItem.Filter = null; // update item. item.ServerHandle = (int)monitoredItem.ClientHandle; item.MonitoredItem = monitoredItem; // link the monitored item back to the group item. monitoredItem.Handle = item; // update return parameters. request.ServerHandle = item.ServerHandle; request.CanonicalDataType = item.CanonicalDataType; request.AccessRights = item.AccessRights; request.Error = ResultIds.S_OK; } return(items); }
/// <summary> // Handles the sampling interval procedure started from the menu bar. /// <summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void SamplingInterval_Click(object sender, EventArgs e) { try { // Check if operation is currently allowed. if (monitoredItemsControl.Subscription.Session == null || monitoredItemsControl.Subscription.innerSubscription == null || monitoredItemsControl.MonitoredItemsList.SelectedItems.Count == 0) { return; } // Determine the sampling interval being requested. double samplingInterval = 0; if (sender == toolStripMenuItem_SamplingInterval_100) { samplingInterval = 100; } else if (sender == toolStripMenuItem_SamplingInterval_500) { samplingInterval = 500; } else if (sender == toolStripMenuItem_SamplingInterval_1000) { samplingInterval = 1000; } // Update the monitoring mode. List <MonitoredItem> itemsToChange = new List <MonitoredItem>(); for (int ii = 0; ii < monitoredItemsControl.MonitoredItemsList.SelectedItems.Count; ii++) { MonitoredItem monitoredItem = monitoredItemsControl.MonitoredItemsList.SelectedItems[ii].Tag as MonitoredItem; if (monitoredItem != null) { // Set the current interval. monitoredItem.SamplingInterval = (int)samplingInterval; itemsToChange.Add(monitoredItem); // Apply the changes to the server. monitoredItemsControl.Subscription.ModifyMonitoredItem(monitoredItem); // Update the display. // Sampling column. monitoredItemsControl.MonitoredItemsList.SelectedItems[ii].SubItems[1].Text = samplingInterval.ToString(); // Error column. monitoredItemsControl.MonitoredItemsList.SelectedItems[ii].SubItems[5].Text = String.Empty; if (ServiceResult.IsBad(itemsToChange[ii].Status.Error)) { monitoredItemsControl.MonitoredItemsList.SelectedItems[ii].SubItems[5].Text = itemsToChange[ii].Status.Error.StatusCode.ToString(); } } } // Update status label. toolStripStatusLabel.Text = "Setting sampling interval succeeded."; } catch (Exception exception) { // Update status label. toolStripStatusLabel.Text = "An exception occured while setting sampling interval: " + exception.Message; toolStripStatusLabel.Image = global::Siemens.OpcUA.Client.Properties.Resources.error; } }
/// <summary> /// Shows a value in control. /// </summary> private async Task ShowValue(int index, bool overwrite, object value) { if (value == null) { return; } // show monitored items. MonitoredItem monitoredItem = value as MonitoredItem; if (monitoredItem != null) { m_monitoredItem = monitoredItem; ShowValue(ref index, ref overwrite, monitoredItem.LastValue.ToString()); return; } // show data changes MonitoredItemNotification datachange = value as MonitoredItemNotification; if (datachange != null) { ShowValue(ref index, ref overwrite, datachange.Value.ToString()); return; } // show events EventFieldList eventFields = value as EventFieldList; if (eventFields != null) { for (int ii = 0; ii < eventFields.EventFields.Count; ii++) { ShowValue(ref index, ref overwrite, eventFields, ii); } return; } // show extension bodies. ExtensionObject extension = value as ExtensionObject; if (extension != null) { ShowValue(ref index, ref overwrite, extension.Body.ToString()); return; } // show encodeables. IEncodeable encodeable = value as IEncodeable; if (encodeable != null) { PropertyInfo[] properties = encodeable.GetType().GetProperties(); foreach (PropertyInfo property in properties) { ShowValue(ref index, ref overwrite, encodeable, property); } return; } // show bytes. byte[] bytes = value as byte[]; if (bytes != null) { bool result = await PromptOnLongList(bytes.Length / 16); if (!result) { return; } for (int ii = 0; ii < bytes.Length; ii += 16) { ShowValue(ref index, ref overwrite, bytes, ii); } return; } // show arrays Array array = value as Array; if (array != null) { bool result = await PromptOnLongList(array.Length); if (!result) { return; } for (int ii = 0; ii < array.Length; ii++) { ShowValue(ref index, ref overwrite, array, ii); } return; } // show lists IList list = value as IList; if (list != null) { bool result = await PromptOnLongList(list.Count); if (!result) { return; } for (int ii = 0; ii < list.Count; ii++) { ShowValue(ref index, ref overwrite, list, ii); } return; } // show xml elements XmlElement xml = value as XmlElement; if (xml != null) { bool result = await PromptOnLongList(xml.ChildNodes.Count); if (!result) { return; } for (int ii = 0; ii < xml.ChildNodes.Count; ii++) { ShowValue(ref index, ref overwrite, xml, ii); } return; } // show data value. DataValue datavalue = value as DataValue; if (datavalue != null) { ShowValue(ref index, ref overwrite, datavalue, 0); ShowValue(ref index, ref overwrite, datavalue, 1); ShowValue(ref index, ref overwrite, datavalue, 2); ShowValue(ref index, ref overwrite, datavalue, 3); return; } // show node id value. NodeId nodeId = value as NodeId; if (nodeId != null) { ShowValue(ref index, ref overwrite, nodeId, 0); ShowValue(ref index, ref overwrite, nodeId, 1); ShowValue(ref index, ref overwrite, nodeId, 2); return; } // show expanded node id value. ExpandedNodeId expandedNodeId = value as ExpandedNodeId; if (expandedNodeId != null) { ShowValue(ref index, ref overwrite, expandedNodeId, 0); ShowValue(ref index, ref overwrite, expandedNodeId, 1); ShowValue(ref index, ref overwrite, expandedNodeId, 2); ShowValue(ref index, ref overwrite, expandedNodeId, 3); return; } // show qualified name value. QualifiedName qualifiedName = value as QualifiedName; if (qualifiedName != null) { ShowValue(ref index, ref overwrite, qualifiedName, 0); ShowValue(ref index, ref overwrite, qualifiedName, 1); return; } // show qualified name value. LocalizedText localizedText = value as LocalizedText; if (localizedText != null) { ShowValue(ref index, ref overwrite, localizedText, 0); ShowValue(ref index, ref overwrite, localizedText, 1); return; } // show variant. Variant?variant = value as Variant?; if (variant != null) { ShowValue(ref index, ref overwrite, variant.Value.Value.ToString()); return; } // show unknown types as strings. ShowValue(ref index, ref overwrite, String.Format("{0}", value)); }
private static string PrepareArgs(MonitoredItem monitoredItem) { return("-u " + monitoredItem.Url + " -e " + monitoredItem.ElementName + " -f " + monitoredItem.Frequency.ToString() + " -i " + monitoredItem.MonitItemId.ToString()); }
public void AddMonitoredItem(MonitoredItem monitoredItem) { _monitors.Add(monitoredItem); }
/// <summary> /// The notification that the data for a monitored item has changed on an OPC UA server. /// </summary> public void MonitoredItemNotificationEventHandler(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) { try { if (e == null || e.NotificationValue == null || monitoredItem == null || monitoredItem.Subscription == null || monitoredItem.Subscription.Session == null) { return; } if (!(e.NotificationValue is MonitoredItemNotification notification)) { return; } if (!(notification.Value is DataValue value)) { return; } MessageData messageData = new MessageData(); if (IotCentralMode) { // for IoTCentral we use the DisplayName as the key in the telemetry and the Value as the value. if (monitoredItem.DisplayName != null) { // use the DisplayName as reported in the MonitoredItem messageData.DisplayName = monitoredItem.DisplayName; } if (value.Value != null) { // use the Value as reported in the notification event argument encoded with the OPC UA JSON endcoder JsonEncoder encoder = new JsonEncoder(monitoredItem.Subscription.Session.MessageContext, false); value.ServerTimestamp = DateTime.MinValue; value.SourceTimestamp = DateTime.MinValue; value.StatusCode = StatusCodes.Good; encoder.WriteDataValue("Value", value); string valueString = encoder.CloseAndReturnText(); // we only want the value string, search for everything till the real value starts // and get it string marker = "{\"Value\":{\"Value\":"; int markerStart = valueString.IndexOf(marker, StringComparison.InvariantCulture); messageData.PreserveValueQuotes = true; if (markerStart >= 0) { // we either have a value in quotes or just a value int valueLength; int valueStart = marker.Length; if (valueString.IndexOf("\"", valueStart, StringComparison.InvariantCulture) >= 0) { // value is in quotes and two closing curly brackets at the end valueStart++; valueLength = valueString.Length - valueStart - 3; } else { // value is without quotes with two curly brackets at the end valueLength = valueString.Length - marker.Length - 2; messageData.PreserveValueQuotes = false; } messageData.Value = valueString.Substring(valueStart, valueLength); } Logger.Debug($" IoTCentral key: {messageData.DisplayName}"); Logger.Debug($" IoTCentral values: {messageData.Value}"); } } else { // update the required message data to pass only the required data to HubCommunication EndpointTelemetryConfiguration telemetryConfiguration = GetEndpointTelemetryConfiguration(EndpointUrl); // the endpoint URL is required to allow HubCommunication lookup the telemetry configuration messageData.EndpointUrl = EndpointUrl; if (telemetryConfiguration.NodeId.Publish == true) { messageData.NodeId = OriginalId; } if (telemetryConfiguration.MonitoredItem.ApplicationUri.Publish == true) { messageData.ApplicationUri = (monitoredItem.Subscription.Session.Endpoint.Server.ApplicationUri + (string.IsNullOrEmpty(OpcSession.PublisherSite) ? "" : $":{OpcSession.PublisherSite}")); } if (telemetryConfiguration.MonitoredItem.DisplayName.Publish == true && monitoredItem.DisplayName != null) { // use the DisplayName as reported in the MonitoredItem messageData.DisplayName = monitoredItem.DisplayName; } if (telemetryConfiguration.Value.SourceTimestamp.Publish == true && value.SourceTimestamp != null) { // use the SourceTimestamp as reported in the notification event argument in ISO8601 format messageData.SourceTimestamp = value.SourceTimestamp.ToString("o", CultureInfo.InvariantCulture); } if (telemetryConfiguration.Value.StatusCode.Publish == true && value.StatusCode != null) { // use the StatusCode as reported in the notification event argument messageData.StatusCode = value.StatusCode.Code; } if (telemetryConfiguration.Value.Status.Publish == true && value.StatusCode != null) { // use the StatusCode as reported in the notification event argument to lookup the symbolic name messageData.Status = StatusCode.LookupSymbolicId(value.StatusCode.Code); } if (telemetryConfiguration.Value.Value.Publish == true && value.Value != null) { // use the Value as reported in the notification event argument encoded with the OPC UA JSON endcoder JsonEncoder encoder = new JsonEncoder(monitoredItem.Subscription.Session.MessageContext, false); value.ServerTimestamp = DateTime.MinValue; value.SourceTimestamp = DateTime.MinValue; value.StatusCode = StatusCodes.Good; encoder.WriteDataValue("Value", value); string valueString = encoder.CloseAndReturnText(); // we only want the value string, search for everything till the real value starts // and get it string marker = "{\"Value\":{\"Value\":"; int markerStart = valueString.IndexOf(marker, StringComparison.InvariantCulture); messageData.PreserveValueQuotes = true; if (markerStart >= 0) { // we either have a value in quotes or just a value int valueLength; int valueStart = marker.Length; if (valueString.IndexOf("\"", valueStart, StringComparison.InvariantCulture) >= 0) { // value is in quotes and two closing curly brackets at the end valueStart++; valueLength = valueString.Length - valueStart - 3; } else { // value is without quotes with two curly brackets at the end valueLength = valueString.Length - marker.Length - 2; messageData.PreserveValueQuotes = false; } messageData.Value = valueString.Substring(valueStart, valueLength); } } // currently the pattern processing is done here, which adds runtime to the notification processing. // In case of perf issues it can be also done in CreateJsonMessageAsync of IoTHubMessaging.cs. // apply patterns messageData.ApplyPatterns(telemetryConfiguration); Logger.Debug($" ApplicationUri: {messageData.ApplicationUri}"); Logger.Debug($" EndpointUrl: {messageData.EndpointUrl}"); Logger.Debug($" DisplayName: {messageData.DisplayName}"); Logger.Debug($" Value: {messageData.Value}"); } // add message to fifo send queue if (monitoredItem.Subscription == null) { Logger.Debug($"Subscription already removed. No more details available."); } else { Logger.Debug($"Enqueue a new message from subscription {(monitoredItem.Subscription == null ? "removed" : monitoredItem.Subscription.Id.ToString(CultureInfo.InvariantCulture))}"); Logger.Debug($" with publishing interval: {monitoredItem.Subscription.PublishingInterval} and sampling interval: {monitoredItem.SamplingInterval}):"); } HubCommunication.Enqueue(messageData); } catch (Exception ex) { Logger.Error(ex, "Error processing monitored item notification"); } }
/// <summary> /// Starts monitoring the value of the currently selected item. /// </summary> public void CreateMonitoredItem(ReferenceDescription node) { ListOfMonitoredItemCreateRequest itemsToCreate = new ListOfMonitoredItemCreateRequest(); MonitoredItemCreateRequest itemToCreate = new MonitoredItemCreateRequest(); itemToCreate.ItemToMonitor = new ReadValueId(); itemToCreate.ItemToMonitor.NodeId = new NodeId(node.NodeId); itemToCreate.ItemToMonitor.AttributeId = Attributes.Value; itemToCreate.MonitoringMode = MonitoringMode.Reporting_2; itemToCreate.RequestedParameters = new MonitoringParameters(); itemToCreate.RequestedParameters.ClientHandle = ++m_monitoredItemCount; itemToCreate.RequestedParameters.SamplingInterval = 1000; itemToCreate.RequestedParameters.QueueSize = 0; itemToCreate.RequestedParameters.DiscardOldest = true; itemToCreate.RequestedParameters.Filter = new ExtensionObject(); itemsToCreate.Add(itemToCreate); ListOfMonitoredItemCreateResult results; ListOfDiagnosticInfo diagnosticInfos; m_client.CreateMonitoredItems( m_client.CreateRequestHeader(), m_subscriptionId, TimestampsToReturn.Both_2, itemsToCreate, out results, out diagnosticInfos); if (results != null) { // update the list view. MonitoredItemCreateResult result = results[0]; ListViewItem item = new ListViewItem(itemToCreate.RequestedParameters.ClientHandle.ToString()); item.SubItems.Add(new ListViewItem.ListViewSubItem()); item.SubItems[1].Text = node.DisplayName.Text; item.SubItems.Add(new ListViewItem.ListViewSubItem()); item.SubItems[2].Text = "<Unknown>"; item.SubItems.Add(new ListViewItem.ListViewSubItem()); item.SubItems[3].Text = String.Format("{0}", result.StatusCode); item.SubItems.Add(new ListViewItem.ListViewSubItem()); item.SubItems[4].Text = String.Format("{0:HH:mm:ss}", DateTime.Now); UpdatesLV.Items.Add(item); // save the monitored item. MonitoredItem monitoredItem = new MonitoredItem(); monitoredItem.MonitoredItemId = result.MonitoredItemId; monitoredItem.ItemToMonitor = itemToCreate.ItemToMonitor; monitoredItem.MonitoringMode = itemToCreate.MonitoringMode; monitoredItem.Parameters = itemToCreate.RequestedParameters; monitoredItem.Parameters.SamplingInterval = result.RevisedSamplingInterval; monitoredItem.Parameters.QueueSize = result.RevisedQueueSize; m_monitoredItems.Add(itemToCreate.RequestedParameters.ClientHandle, monitoredItem); item.Tag = monitoredItem; } }
/// <summary> /// Create Subscription and MonitoredItems for DataChanges /// </summary> public void SubscribeToDataChanges() { if (m_session == null || m_session.Connected == false) { m_output.WriteLine("Session not connected!"); return; } try { // Create a subscription for receiving data change notifications // Define Subscription parameters Subscription subscription = new Subscription(m_session.DefaultSubscription); subscription.DisplayName = "Console ReferenceClient Subscription"; subscription.PublishingEnabled = true; subscription.PublishingInterval = 1000; m_session.AddSubscription(subscription); // Create the subscription on Server side subscription.Create(); m_output.WriteLine("New Subscription created with SubscriptionId = {0}.", subscription.Id); // Create MonitoredItems for data changes (Reference Server) MonitoredItem intMonitoredItem = new MonitoredItem(subscription.DefaultItem); // Int32 Node - Objects\CTT\Scalar\Simulation\Int32 intMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Int32"); intMonitoredItem.AttributeId = Attributes.Value; intMonitoredItem.DisplayName = "Int32 Variable"; intMonitoredItem.SamplingInterval = 1000; intMonitoredItem.Notification += OnMonitoredItemNotification; subscription.AddItem(intMonitoredItem); MonitoredItem floatMonitoredItem = new MonitoredItem(subscription.DefaultItem); // Float Node - Objects\CTT\Scalar\Simulation\Float floatMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Float"); floatMonitoredItem.AttributeId = Attributes.Value; floatMonitoredItem.DisplayName = "Float Variable"; floatMonitoredItem.SamplingInterval = 1000; floatMonitoredItem.Notification += OnMonitoredItemNotification; subscription.AddItem(floatMonitoredItem); MonitoredItem stringMonitoredItem = new MonitoredItem(subscription.DefaultItem); // String Node - Objects\CTT\Scalar\Simulation\String stringMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_String"); stringMonitoredItem.AttributeId = Attributes.Value; stringMonitoredItem.DisplayName = "String Variable"; stringMonitoredItem.SamplingInterval = 1000; stringMonitoredItem.Notification += OnMonitoredItemNotification; subscription.AddItem(stringMonitoredItem); // Create the monitored items on Server side subscription.ApplyChanges(); m_output.WriteLine("MonitoredItems created for SubscriptionId = {0}.", subscription.Id); } catch (Exception ex) { m_output.WriteLine("Subscribe error: {0}", ex.Message); } }
/// <summary> /// Creates a monitored item. /// </summary> public void CreateMonitoredItem( TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest request, MonitoredItemCreateResult result, DiagnosticInfo diagnosticInfo) { lock (m_lock) { // initialize the monitored item. MonitoredItem monitoredItem = new MonitoredItem(); monitoredItem.Id = (uint)Interlocked.Increment(ref m_monitoredItemCounter); monitoredItem.ItemToMonitor = request.ItemToMonitor; monitoredItem.MonitoringMode = request.MonitoringMode; monitoredItem.Parameters = request.RequestedParameters; monitoredItem.NextScanTime = 0; // use the publishing interval as the default. if (monitoredItem.Parameters.SamplingInterval < 0) { monitoredItem.Parameters.SamplingInterval = m_publishingInterval; } // ensure the queue is at least one. if (monitoredItem.Parameters.QueueSize == 0) { monitoredItem.Parameters.QueueSize = 1; } result.MonitoredItemId = monitoredItem.Id; result.RevisedQueueSize = monitoredItem.Parameters.QueueSize; result.RevisedSamplingInterval = monitoredItem.Parameters.SamplingInterval; result.FilterResult = new ExtensionObject(); m_monitoredItems.Add(monitoredItem.Id, monitoredItem); // start a background thread that scans the items. if (m_monitoredItems.Count == 1) { ThreadPool.QueueUserWorkItem(OnScanItems); } } }