/// <summary> /// Gets a default event filter. /// </summary> /// <returns></returns> private static EventFilter GetDefaultEventFilter() { var filter = new EventFilter(); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.EventId); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.EventType); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.SourceNode); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.SourceName); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.Time); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.ReceiveTime); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.LocalTime); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.Message); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.Severity); return(filter); }
/// <summary> /// Sets the default event filter. /// </summary> private void UseDefaultEventFilter() { EventFilter filter = filter = new EventFilter(); filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.EventId); filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.EventType); filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.SourceNode); filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.SourceName); filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.Time); filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.ReceiveTime); filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.LocalTime); filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.Message); filter.AddSelectClause(ObjectTypes.BaseEventType, Opc.Ua.BrowseNames.Severity); m_filter = filter; }
/// <summary> /// Creates a new MonitoredItem for events. Applies the standard event filters for condition events /// and adds the filters necessary to obtain event attributes -- properties of event types/subtypes /// </summary> /// <param name="nodeId">The node id.</param> /// <returns></returns> public MonitoredItem CreateMonitoredItemForEvents(NodeId nodeId) { MonitoredItem monitoredItem = new MonitoredItem(m_Subscription.DefaultItem); monitoredItem.AttributeId = Attributes.EventNotifier; monitoredItem.DisplayName = m_Subscription.Session.NodeCache.GetDisplayText((ExpandedNodeId)nodeId); monitoredItem.StartNodeId = nodeId; monitoredItem.NodeClass = NodeClass.Object; //get all attribute values from all events EventFilter filter = new EventFilter(); foreach (EventAttribute attr in m_configFile.Attributes) { if (attr.strEventNodeId != "") { filter.AddSelectClause(new NodeId(attr.strEventNodeId), attr.BrowseName); // Utils.Trace("AddSelectClause ( {0}: {1}, {2} )", i++, attr.strEventNodeId, attr.BrowseName); } } // Add Condition-related attributes to the filter so that we have enough info to determine // Enabled/Disabled, Active/Inactive including time of active transition, Acked/Unacked and active subcondition filter.AddSelectClause(Opc.Ua.ObjectTypes.ConditionType, "/EnabledState/Id", Attributes.Value); filter.AddSelectClause(Opc.Ua.ObjectTypes.ConditionType, "/Quality", Attributes.Value); filter.AddSelectClause(Opc.Ua.ObjectTypes.AcknowledgeableConditionType, "/AckedState/Id", Attributes.Value); filter.AddSelectClause(Opc.Ua.ObjectTypes.AcknowledgeableConditionType, "", Attributes.NodeId); filter.AddSelectClause(Opc.Ua.ObjectTypes.AlarmConditionType, "/ActiveState/Id", Attributes.Value); filter.AddSelectClause(Opc.Ua.ObjectTypes.AlarmConditionType, "/ActiveState/TransitionTime", Attributes.Value); filter.AddSelectClause(Opc.Ua.ObjectTypes.AlarmConditionType, "/ActiveState/EffectiveDisplayName", Attributes.Value); monitoredItem.Filter = filter; monitoredItem.Notification += new MonitoredItemNotificationEventHandler(MonitoredItem_Notification); return monitoredItem; }
//ns=2;s=Scalar_CreateTime public void Execte() { string storePath = AppContext.BaseDirectory; var config = new ApplicationConfiguration() { ApplicationName = "Axiu-Opcua", ApplicationUri = Utils.Format(@"urn:{0}:Axiu-Opcua", System.Net.Dns.GetHostName()), ApplicationType = ApplicationType.Client, SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = Path.Combine(storePath, @"OPC Foundation/CertificateStores/MachineDefault"), SubjectName = Utils.Format(@"CN={0}, DC={1}", "Axiu-Opcua", System.Net.Dns.GetHostName()) }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = Path.Combine(storePath, @"OPC Foundation/CertificateStores/UA Certificate Authorities") }, TrustedPeerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = Path.Combine(storePath, @"OPC Foundation/CertificateStores/UA Applications") }, RejectedCertificateStore = new CertificateTrustList { StoreType = @"Directory", StorePath = Path.Combine(storePath, @"OPC Foundation/CertificateStores/RejectedCertificates") }, AutoAcceptUntrustedCertificates = true, AddAppCertToTrustedStore = true }, TransportConfigurations = new TransportConfigurationCollection(), TransportQuotas = new TransportQuotas { OperationTimeout = 15000 }, ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }, TraceConfiguration = new TraceConfiguration() }; config.Validate(ApplicationType.Client).GetAwaiter().GetResult(); if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); }; } var application = new ApplicationInstance { ApplicationName = "Axiu-Opcua", ApplicationType = ApplicationType.Client, ApplicationConfiguration = config }; application.CheckApplicationInstanceCertificate(false, 2048).GetAwaiter().GetResult(); var selectedEndpoint = CoreClientUtils.SelectEndpoint(url, useSecurity: true, int.MaxValue); Console.WriteLine("配置已准备完毕,即将打开链接会话..."); using (var session = Session.Create(config, new ConfiguredEndpoint(null, selectedEndpoint, EndpointConfiguration.Create(config)), false, "", int.MaxValue, null, null).GetAwaiter().GetResult()) { #region 读取目录下所有节点 //读取目录下所有节点 List <string> idList = new List <string>(); ReferenceDescriptionCollection nextRefs; byte[] nextCp; ////session.Browse(null, null, "ns=2;s=1_6_20", 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out nextCp, out nextRefs); ////foreach (var nextRd in nextRefs) ////{ //// //Console.WriteLine("{0}: {1}, {2}", nextRd.DisplayName, nextRd.BrowseName, nextRd.NodeClass); //// idList.Add(nextRd.NodeId.ToString()); ////} Console.Write("请输入监听通道ID:"); string devStr = Console.ReadLine(); if (string.IsNullOrEmpty(devStr)) { return; } List <string> folders = new List <string>(); string nodeId = "ns=2;s=1_" + devStr; session.Browse(null, null, nodeId, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out nextCp, out nextRefs); foreach (var nextRd in nextRefs) { //Console.WriteLine("{0}: {1}, {2}", nextRd.DisplayName, nextRd.BrowseName, nextRd.NodeClass); folders.Add(nextRd.NodeId.ToString()); } List <string> nodes = new List <string>(); foreach (var item in folders) { session.Browse(null, null, item, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out nextCp, out nextRefs); foreach (var nextRd in nextRefs) { //Console.WriteLine("{0}: {1}, {2}", nextRd.DisplayName, nextRd.BrowseName, nextRd.NodeClass); nodes.Add(nextRd.NodeId.ToString()); } } Console.WriteLine("通道总节点数:" + nodes.Count + "; 第一个:" + nodes[0]); #endregion #region 读单个节点 //读单个节点 //ReadValueIdCollection nodesToRead = new ReadValueIdCollection //{ // new ReadValueId( ) // { // NodeId = "ns=2;s=0_0_0_1_7", // AttributeId = Attributes.Value // } //}; //// read the current value //session.Read(null, 0, TimestampsToReturn.Neither, nodesToRead, out DataValueCollection results, out DiagnosticInfoCollection diagnosticInfos); //ClientBase.ValidateResponse(results, nodesToRead); //ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); //Console.WriteLine("取到单值结果: " + results[0].ToString()); #endregion #region 读取历史数据 //读取历史数据 //HistoryReadValueIdCollection historyReads = new HistoryReadValueIdCollection() //{ // new HistoryReadValueId( ) // { // NodeId = "ns=2;s=0_0_0_1_7" // } //}; //ExtensionObject extension = new ExtensionObject(); //ReadProcessedDetails details = new ReadProcessedDetails() { StartTime = DateTime.Now.AddMinutes(-5), EndTime = DateTime.Now }; //extension.Body = details; //session.HistoryRead(null, extension, TimestampsToReturn.Neither, true, historyReads, out HistoryReadResultCollection hresults, out DiagnosticInfoCollection hdiagnosticInfos); //foreach (var item in hresults) //{ // var res = item.HistoryData.Body as Opc.Ua.KeyValuePair; // Console.WriteLine("历史数据:" + res.Key.Name + " --- " + res.Value); //} #endregion #region 读取历史事件 //HistoryReadValueIdCollection historyEvents = new HistoryReadValueIdCollection() //{ // new HistoryReadValueId( ) // { // NodeId = "ns=2;s=1_1_1" // } //}; //EventFilter hFilter = new EventFilter(); //hFilter.AddSelectClause(ObjectTypeIds.BaseEventType, new QualifiedName("id=0101")); //ExtensionObject extension2 = new ExtensionObject(); //ReadEventDetails details2 = new ReadEventDetails() { StartTime = DateTime.Now.AddDays(-1), EndTime = DateTime.Now, Filter = hFilter }; //extension2.Body = details2; //session.HistoryRead(null, extension2, TimestampsToReturn.Neither, false, historyEvents, out HistoryReadResultCollection hresults2, out DiagnosticInfoCollection hdiagnosticInfos2); //foreach (var item in hresults2) //{ // if (item.HistoryData.Body!=null) // { // var res = item.HistoryData.Body as byte[]; // Console.WriteLine(Encoding.UTF8.GetString(res)); // } //} #endregion #region 订阅事件 var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 3000 }; EventFilter eventFilter = new EventFilter(); eventFilter.AddSelectClause(ObjectTypeIds.BaseEventType, new QualifiedName(BrowseNames.Message)); List <MonitoredItem> list = new List <MonitoredItem>(); foreach (var item in folders) { MonitoredItem model = new MonitoredItem(subscription.DefaultItem) { DisplayName = item + "的事件", StartNodeId = item, Filter = eventFilter, AttributeId = 12 }; model.Notification += OnEventNotification; list.Add(model); break; } subscription.AddItems(list); bool radd = session.AddSubscription(subscription); subscription.Create(); #endregion #region 订阅测点 Console.WriteLine("即将开始订阅固定节点消息..."); //var submeas = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 }; //List<MonitoredItem> measlist = new List<MonitoredItem>(); //int index = 0, jcount = 0; //foreach (var item in nodes) //{ // index++; jcount++; // MonitoredItem monitor = new MonitoredItem(submeas.DefaultItem) { DisplayName = "测点:" + item, StartNodeId = item }; // monitor.Notification += OnNotification; // measlist.Add(monitor); // if (index > 5999) // { // submeas.AddItems(measlist); // session.AddSubscription(submeas); // submeas.Create(); // index = 0; // submeas = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 }; // measlist.Clear(); // } //} //if (measlist.Count > 0) //{ // submeas.AddItems(measlist); // session.AddSubscription(submeas); // submeas.Create(); //} //Console.WriteLine("订阅节点数:" + jcount); //var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 }; //List<MonitoredItem> list = new List<MonitoredItem>(); //foreach (var item in nodes.Take(5000)) //{ // MonitoredItem monitor = new MonitoredItem(subscription.DefaultItem) { DisplayName = "测点:" + item, StartNodeId = item }; // list.Add(monitor); //} //list.ForEach(i => i.Notification += OnNotification); //subscription.AddItems(list); //session.AddSubscription(subscription); //subscription.Create(); #endregion #region 写入内容 //WriteValueCollection writeValues = new WriteValueCollection() //{ // new WriteValue() // { // NodeId="ns=2;s=1_ctr_1", // AttributeId=Attributes.Value, // Value=new DataValue(){ Value="false" } // } //}; //session.Write(null, writeValues, out StatusCodeCollection wresults, out DiagnosticInfoCollection wdiagnosticInfos); //foreach (var item in wresults) //{ // Console.WriteLine("写入结果:" + item.ToString()); //} #endregion Console.WriteLine("指定节点消息已订阅,请勿关闭程序..."); while (true) { Thread.Sleep(3000); Console.WriteLine("测点更新次数:" + ntCount); ntCount = 0; } Console.ReadKey(true); //subscription.DeleteItems(); } Console.WriteLine("Press any key to exit..."); Console.ReadKey(true); }
MonitoringFilter GetFilter() { aliasMap.Clear(); var eventFilter = new EventFilter(); eventFilter.AddSelectClause(Opc.Ua.ObjectTypeIds.BaseEventType, null, Attributes.NodeId); // Requests condition id // Ensure all required properties are in the event filter var propsToRequest = new List <TheEventProperty>(EventInfo.Properties); foreach (var prop in requiredEventFields) { if (EventInfo.Properties.FirstOrDefault(p => p.Name == prop && string.IsNullOrEmpty(p.CustomTypeId)) == null) { propsToRequest.Add(new TheEventProperty { Name = prop }); } } // Remove ConditionId, because it is added by requesting the BaseEventType attibute 1 above var conditionIdProp = EventInfo.Properties.FirstOrDefault(p => p.Name == "ConditionId" && string.IsNullOrEmpty(p.CustomTypeId)); if (conditionIdProp != null) { propsToRequest.Remove(conditionIdProp); } var alarmConditionProps = typeof(AlarmConditionState).GetProperties(); int index = eventFilter.SelectClauses.Count; foreach (var eventProp in propsToRequest) { if (eventProp.Name == "ConditionId" && string.IsNullOrEmpty(eventProp.CustomTypeId)) { continue; } var propertyType = Opc.Ua.ObjectTypeIds.BaseEventType; ushort nameSpaceId = 0; var propDef = alarmConditionProps.FirstOrDefault(p => p.Name == eventProp.Name && string.IsNullOrEmpty(eventProp.CustomTypeId)); if (propDef != null) { switch (propDef.DeclaringType.Name) { case nameof(AlarmConditionState): propertyType = Opc.Ua.ObjectTypeIds.AlarmConditionType; break; case nameof(AcknowledgeableConditionState): propertyType = Opc.Ua.ObjectTypeIds.AcknowledgeableConditionType; break; case nameof(ConditionState): propertyType = Opc.Ua.ObjectTypeIds.ConditionType; break; case nameof(BaseEventState): default: propertyType = Opc.Ua.ObjectTypeIds.BaseEventType; break; } } else { if (!string.IsNullOrEmpty(eventProp.CustomTypeId)) { // Custom Type: must be specified in the request var exNodeId = ExpandedNodeId.Parse(eventProp.CustomTypeId); propertyType = ExpandedNodeId.ToNodeId(exNodeId, MyOPCServer?.m_session?.NamespaceUris); nameSpaceId = propertyType.NamespaceIndex; } else { TheBaseAssets.MySYSLOG.WriteToLog(78122, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(MyOPCServer.GetBaseThing().EngineName, $"Unrecognized Event Property Name '{eventProp}' for {GetNodeIdForLogs()}. Use <nodeid>::<name> for custom types.", eMsgLevel.l2_Warning)); } } QualifiedName eventPropQName; var indexOfNamespaceSeparator = eventProp.Name.LastIndexOf(':'); // namespace Uri typically contains ":" so must use last index instead of Split if (indexOfNamespaceSeparator > 0) { var namespacePrefix = eventProp.Name.Substring(0, indexOfNamespaceSeparator); var name = eventProp.Name.Substring(indexOfNamespaceSeparator + 1); if (!char.IsDigit(namespacePrefix[0])) { eventPropQName = QualifiedName.Create(name, namespacePrefix, MyOPCServer?.m_session?.NamespaceUris); } else { eventPropQName = QualifiedName.Parse(eventProp.Name); } } else { eventPropQName = new QualifiedName(eventProp.Name, nameSpaceId); } eventFilter.AddSelectClause(propertyType, eventPropQName); if (!string.IsNullOrEmpty(eventProp.Alias)) { aliasMap.Add(index, eventProp.Alias); } index++; } // Incomplete/untested, syntax is very cumbersome. Leaving in for now as a starting point should this become a high priority //if (EventInfo.WhereClauses != null) //{ // try // { // var whereClause = new ContentFilter(); // var filterElements = new ContentFilterElementCollection(EventInfo.WhereClauses.Select((clause) => // { // FilterOperator filterOperator; // try // { // filterOperator = (FilterOperator)Enum.Parse(typeof(FilterOperator), clause.Operator); // } // catch // { // filterOperator = (FilterOperator)(-1); // invalid operator: assume that it will be rejected by server or client stack // } // var operands = clause.Operands.Select<TheFilterOperand, ExtensionObject>(operand => // { // if (operand.Value != null) // { // return new ExtensionObject(new LiteralOperand(operand.Value)); // } // if (operand.SimpleAttribute != null) // { // return new ExtensionObject(new SimpleAttributeOperand // { // AttributeId = operand.SimpleAttribute.AttributeId ?? Opc.Ua.Attributes.Value, // TODO support symbolic names // BrowsePath = new QualifiedNameCollection(operand.SimpleAttribute.BrowsePaths.Select(p => new QualifiedName(p))), // TODO support namespace qualifiers etc. // TypeDefinitionId = ExpandedNodeId.ToNodeId(ExpandedNodeId.Parse(operand.SimpleAttribute.TypeId), nameTable), // // TODO Why is SimpleAttributeOperand.IndexRange a string? Should be a Range. Not supported for now // }); // } // //if (operand.Attribute != null) // //{ // // return new ExtensionObject(new AttributeOperand // // { // // // TODO implement, not supported for now // // //AttributeId = operand.Attribute.AttributeId, // // // BrowsePath = operand.Attribute.BrowsePath, // // }); // //} // return null; // }); // var element = new ContentFilterElement // { // FilterOperator = filterOperator, // FilterOperands = new ExtensionObjectCollection(operands), // }; // return element; // })); // eventFilter.WhereClause = new ContentFilter { Elements = filterElements, }; // } // catch (Exception e) // { // // Log errors, fail filter etc. // } //} // Original approach relied on server providing proper type information for the events; not all OPC Servers do so //NodeId eventTypeId = this.TagRef; //var desc = new BrowseDescription //{ // NodeId = this.TagRef, // ReferenceTypeId = Opc.Ua.ReferenceTypeIds.GeneratesEvent, // ResultMask = (uint)BrowseResultMask.TargetInfo, //}; //var references = ClientUtils.Browse(MyOPCServer.m_session, desc, false); //if (references.Count > 0) //{ // eventTypeId = (NodeId)references[0].NodeId; //} //TypeDeclaration type = new TypeDeclaration(); //type.NodeId = eventTypeId; //type.Declarations = ClientUtils.CollectInstanceDeclarationsForType(MyOPCServer.m_session, type.NodeId); //// the filter to use. //var filter = new FilterDeclaration(type, null); //var eventFilter2 = filter.GetFilter(); //eventFilter2.WhereClause = null; return(eventFilter); }