diff --git a/OPC/OpcUaClient.cs b/OPC/OpcUaClient.cs new file mode 100644 index 0000000..2b2cd34 --- /dev/null +++ b/OPC/OpcUaClient.cs @@ -0,0 +1,589 @@ +using Opc.Ua.Client; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using System; +using System.Collections; + +namespace Opc.Ua.Cloud.Publisher.OPC +{ + public class OpcUaClient + { + + #region Constructors + public OpcUaClient(ApplicationConfiguration configuration, TextWriter writer, Action validateResponse) + { + m_validateResponse = validateResponse; + m_output = writer; + m_configuration = configuration; + m_configuration.CertificateValidator.CertificateValidation += CertificateValidation; + } + #endregion + + #region Public Properties + /// + /// Gets the client session. + /// + public Session Session => m_session; + + /// + /// Auto accept untrusted certificates. + /// + public bool AutoAccept { get; set; } = false; + #endregion + + #region Public Methods + /// + /// Creates a session with the UA server + /// + public async Task ConnectAsync(string serverUrl) + { + if (serverUrl == null) throw new ArgumentNullException(nameof(serverUrl)); + + try + { + if (m_session != null && m_session.Connected == true) + { + m_output.WriteLine("Session already connected!"); + } + else + { + m_output.WriteLine("Connecting to... {0}", serverUrl); + + // Get the endpoint by connecting to server's discovery endpoint. + // Try to find the first endopint with security. + EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(m_configuration, serverUrl, true); + EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(m_configuration); + ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration); + + // Create the session + Session session = await Session.Create( + m_configuration, + endpoint, + false, + false, + m_configuration.ApplicationName, + 30 * 60 * 10000, + new UserIdentity(), + null + ); + + // Assign the created session + if (session != null && session.Connected) + { + m_session = session; + } + + // Session created successfully. + m_output.WriteLine("New Session Created with SessionName = {0}", m_session.SessionName); + } + + return true; + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine("Create Session Error : {0}", ex.Message); + return false; + } + } + + /// + /// Disconnects the session. + /// + public void Disconnect() + { + try + { + if (m_session != null) + { + m_output.WriteLine("Disconnecting..."); + + m_session.Close(); + m_session.Dispose(); + m_session = null; + + // Log Session Disconnected event + m_output.WriteLine("Session Disconnected."); + } + else + { + m_output.WriteLine("Session not created!"); + } + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Disconnect Error : {ex.Message}"); + } + } + public Node? ReadNode(NodeId nodeId) + { + Node? node = null; + if (m_session != null && m_session.Connected) + { + try + { + node = m_session.ReadNode(nodeId); + } + catch (Exception e) + { + Console.Out.Write(e); + } + } + return node; + } + + public List BrowseLocalNodeIds(NodeId rootNodeId, BrowseDirection browseDirection, uint nodeClassMask, NodeId referenceTypeIds, bool includeSubTypes) + { + List nodeList = new List(); + BrowseResultCollection browseResults = BrowseNode(rootNodeId, browseDirection, nodeClassMask, referenceTypeIds, includeSubTypes); + foreach (BrowseResult browseResult in browseResults) + { + ReferenceDescriptionCollection references = browseResult.References; + foreach (ReferenceDescription reference in references) + { + nodeList.Add(new NodeId(reference.NodeId.Identifier, reference.NodeId.NamespaceIndex)); + } + } + return nodeList; + } + public NodeId BrowseFirstLocalNodeIdWithType(NodeId rootNodeId, BrowseDirection browseDirection, uint nodeClassMask, NodeId referenceTypeIds, bool includeSubTypes, NodeId typeDefinition) + { + NodeId nodeId = null; + BrowseResultCollection browseResults = BrowseNode(rootNodeId, browseDirection, nodeClassMask, referenceTypeIds, includeSubTypes); + foreach (BrowseResult browseResult in browseResults) + { + ReferenceDescriptionCollection references = browseResult.References; + foreach (ReferenceDescription reference in references) + { + nodeId = new NodeId(reference.NodeId.Identifier, reference.NodeId.NamespaceIndex); + } + } + return nodeId; + } + public NodeId BrowseFirstLocalNodeIdWithTypeDefinition(NodeId rootNodeId, BrowseDirection browseDirection, uint nodeClassMask, NodeId referenceTypeIds, bool includeSubTypes, NodeId expectedTypeDefinition) + { + NodeId filteredNodeId = null; + List nodeIds = BrowseLocalNodeIds(rootNodeId, browseDirection, nodeClassMask, referenceTypeIds, includeSubTypes); + foreach (NodeId nodeId in nodeIds) + { + NodeId typeDefinition = getTypeDefinition(nodeId); + if (typeDefinition == expectedTypeDefinition) + { + filteredNodeId = nodeId; + break; + } + } + return filteredNodeId; + } + public List BrowseLocalNodeIdsWithTypeDefinition(NodeId rootNodeId, BrowseDirection browseDirection, uint nodeClassMask, NodeId referenceTypeIds, bool includeSubTypes, NodeId expectedTypeDefinition) + { + List filteredNodeIds = new List(); + List nodeIds = BrowseLocalNodeIds(rootNodeId, browseDirection, nodeClassMask, referenceTypeIds, includeSubTypes); + foreach (NodeId nodeId in nodeIds) + { + NodeId typeDefinition = getTypeDefinition(nodeId); + if (typeDefinition == expectedTypeDefinition) + { + filteredNodeIds.Add(nodeId); + } + } + return filteredNodeIds; + } + public NodeId getTypeDefinition(NodeId nodeId) + { + NodeId typeDefinition = null; + BrowseResultCollection browseResults = BrowseNode(nodeId, BrowseDirection.Forward, (uint)NodeClass.ObjectType | (uint)NodeClass.VariableType, ReferenceTypes.HasTypeDefinition, false); + foreach (BrowseResult browseResult in browseResults) + { + ReferenceDescriptionCollection references = browseResult.References; + foreach (ReferenceDescription reference in references) + { + typeDefinition = new NodeId(reference.NodeId.Identifier, reference.NodeId.NamespaceIndex); + break; + } + } + return typeDefinition; + } + public NodeId BrowseLocalNodeId(NodeId rootNodeId, BrowseDirection browseDirection, uint nodeClassMask, NodeId referenceTypeIds, bool includeSubTypes) + { + NodeId nodeId = null; + BrowseResultCollection browseResults = BrowseNode(rootNodeId, browseDirection, nodeClassMask, referenceTypeIds, includeSubTypes); + + return nodeId; + } + public List BrowseNodeList(Node rootNode, BrowseDirection browseDirection, uint nodeClassMask, NodeId referenceTypeIds, bool includeSubTypes) + { + List node = new List(); + return node; + } + public DataValue ReadValue(NodeId nodeId) + { + if (!checkSession()) + { + return null; + } + else + { + return m_session.ReadValue(nodeId); + } + } + public BrowseResultCollection BrowseNode(NodeId nodeId, BrowseDirection browseDirection, uint nodeClassMask, NodeId referenceTypeIds, Boolean includeSubTypes) + { + BrowseDescription nodeToBrowse = new BrowseDescription(); + nodeToBrowse.NodeId = nodeId; + nodeToBrowse.BrowseDirection = browseDirection; + nodeToBrowse.NodeClassMask = nodeClassMask; + nodeToBrowse.ReferenceTypeId = referenceTypeIds; + nodeToBrowse.IncludeSubtypes = includeSubTypes; + + BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); + nodesToBrowse.Add(nodeToBrowse); + m_session.Browse(null, null, 100, nodesToBrowse, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos); + return results; + } + public BrowseResultCollection BrowseNode(NodeId nodeId) + { + + BrowseDescription nodeToBrowse = new BrowseDescription(); + nodeToBrowse.NodeId = nodeId; + nodeToBrowse.BrowseDirection = BrowseDirection.Forward; + nodeToBrowse.NodeClassMask = (int)NodeClass.Object | (int)NodeClass.Variable; + nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences; + nodeToBrowse.IncludeSubtypes = true; + + BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); + nodesToBrowse.Add(nodeToBrowse); + m_session.Browse(null, null, 100, nodesToBrowse, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos); + return results; + } + /// + /// Read a list of nodes from Server + /// + public void ReadNodes() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return; + } + + try + { + #region Read a node by calling the Read Service + + // build a list of nodes to be read + ReadValueIdCollection nodesToRead = new ReadValueIdCollection() + { + // Value of ServerStatus + new ReadValueId() { NodeId = Variables.Server_ServerStatus, AttributeId = Attributes.Value }, + // BrowseName of ServerStatus_StartTime + new ReadValueId() { NodeId = Variables.Server_ServerStatus_StartTime, AttributeId = Attributes.BrowseName }, + // Value of ServerStatus_StartTime + new ReadValueId() { NodeId = Variables.Server_ServerStatus_StartTime, AttributeId = Attributes.Value } + }; + + // Read the node attributes + m_output.WriteLine("Reading nodes..."); + + // Call Read Service + m_session.Read( + null, + 0, + TimestampsToReturn.Both, + nodesToRead, + out DataValueCollection resultsValues, + out DiagnosticInfoCollection diagnosticInfos); + + // Validate the results + m_validateResponse(resultsValues, nodesToRead); + + // Display the results. + foreach (DataValue result in resultsValues) + { + m_output.WriteLine("Read Value = {0} , StatusCode = {1}", result.Value, result.StatusCode); + } + #endregion + + #region Read the Value attribute of a node by calling the Session.ReadValue method + // Read Server NamespaceArray + m_output.WriteLine("Reading Value of NamespaceArray node..."); + DataValue namespaceArray = m_session.ReadValue(Variables.Server_NamespaceArray); + // Display the result + m_output.WriteLine($"NamespaceArray Value = {namespaceArray}"); + #endregion + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Read Nodes Error : {ex.Message}."); + } + } + + /// + /// Write a list of nodes to the Server + /// + public void WriteNodes() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return; + } + + try + { + // Write the configured nodes + WriteValueCollection nodesToWrite = new WriteValueCollection(); + + // Int32 Node - Objects\CTT\Scalar\Scalar_Static\Int32 + WriteValue intWriteVal = new WriteValue(); + intWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Int32"); + intWriteVal.AttributeId = Attributes.Value; + intWriteVal.Value = new DataValue(); + intWriteVal.Value.Value = (int)100; + nodesToWrite.Add(intWriteVal); + + // Float Node - Objects\CTT\Scalar\Scalar_Static\Float + WriteValue floatWriteVal = new WriteValue(); + floatWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Float"); + floatWriteVal.AttributeId = Attributes.Value; + floatWriteVal.Value = new DataValue(); + floatWriteVal.Value.Value = (float)100.5; + nodesToWrite.Add(floatWriteVal); + + // String Node - Objects\CTT\Scalar\Scalar_Static\String + WriteValue stringWriteVal = new WriteValue(); + stringWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_String"); + stringWriteVal.AttributeId = Attributes.Value; + stringWriteVal.Value = new DataValue(); + stringWriteVal.Value.Value = "String Test"; + nodesToWrite.Add(stringWriteVal); + + // Write the node attributes + StatusCodeCollection results = null; + DiagnosticInfoCollection diagnosticInfos; + m_output.WriteLine("Writing nodes..."); + + // Call Write Service + m_session.Write(null, + nodesToWrite, + out results, + out diagnosticInfos); + + // Validate the response + m_validateResponse(results, nodesToWrite); + + // Display the results. + m_output.WriteLine("Write Results :"); + + foreach (StatusCode writeResult in results) + { + m_output.WriteLine(" {0}", writeResult); + } + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Write Nodes Error : {ex.Message}."); + } + } + + /// + /// Browse Server nodes + /// + public void Browse() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return; + } + + try + { + // Create a Browser object + Browser browser = new Browser(m_session); + + // Set browse parameters + browser.BrowseDirection = BrowseDirection.Forward; + browser.NodeClassMask = (int)NodeClass.Object | (int)NodeClass.Variable; + browser.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences; + + NodeId nodeToBrowse = ObjectIds.Server; + + // Call Browse service + m_output.WriteLine("Browsing {0} node...", nodeToBrowse); + ReferenceDescriptionCollection browseResults = browser.Browse(nodeToBrowse); + + // Display the results + m_output.WriteLine("Browse returned {0} results:", browseResults.Count); + + foreach (ReferenceDescription result in browseResults) + { + m_output.WriteLine(" DisplayName = {0}, NodeClass = {1}", result.DisplayName.Text, result.NodeClass); + } + } + catch (Exception ex) + { + // Log Error + m_output.WriteLine($"Browse Error : {ex.Message}."); + } + } + public IList CallMethod(NodeId objectId, NodeId methodId, object[] inputArguments) + { + IList outputArguments = null; + outputArguments = m_session.Call(objectId, methodId, inputArguments); + return outputArguments; + } + /// + /// Call UA method + /// + public void CallMethod() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return; + } + + try + { + // Define the UA Method to call + // Parent node - Objects\CTT\Methods + // Method node - Objects\CTT\Methods\Add + NodeId objectId = new NodeId("ns=2;s=Methods"); + NodeId methodId = new NodeId("ns=2;s=Methods_Add"); + + // Define the method parameters + // Input argument requires a Float and an UInt32 value + object[] inputArguments = new object[] { (float)10.5, (uint)10 }; + IList outputArguments = null; + + // Invoke Call service + m_output.WriteLine("Calling UAMethod for node {0} ...", methodId); + outputArguments = m_session.Call(objectId, methodId, inputArguments); + + // Display results + m_output.WriteLine("Method call returned {0} output argument(s):", outputArguments.Count); + + foreach (var outputArgument in outputArguments) + { + m_output.WriteLine(" OutputValue = {0}", outputArgument.ToString()); + } + } + catch (Exception ex) + { + m_output.WriteLine("Method call error: {0}", ex.Message); + } + } + /// + /// Create Subscription and MonitoredItems for DataChanges + /// + public uint SubscribeToDataChanges(NodeId nodeId, MonitoredItemNotificationEventHandler eventHandler) + { + uint subscriptionId = 0; + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return 0; + } + + try + { + // Create a subscription for receiving data change notifications + + // Define Subscription parameters + Subscription subscription = new Subscription(m_session.DefaultSubscription); + + subscription.DisplayName = string.Format("Subscription for NodeId: {0}", nodeId); + subscription.PublishingEnabled = true; + subscription.PublishingInterval = 1000; + + m_session.AddSubscription(subscription); + + // Create the subscription on Server side + subscription.Create(); + subscriptionId = subscription.Id; + 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 = nodeId; + intMonitoredItem.AttributeId = Attributes.Value; + intMonitoredItem.DisplayName = "Localized Text"; + intMonitoredItem.SamplingInterval = 1000; + intMonitoredItem.Notification += eventHandler; + + subscription.AddItem(intMonitoredItem); + + // Create the monitored items on Server side + subscription.ApplyChanges(); + m_output.WriteLine("MonitoredItems created for SubscriptionId = {0} with NodeId {1}.", subscription.Id, nodeId); + } + catch (Exception ex) + { + m_output.WriteLine("Subscribe error: {0}", ex.Message); + } + return subscriptionId; + } + #endregion + + #region Private Methods + + /// + /// Handles the certificate validation event. + /// This event is triggered every time an untrusted certificate is received from the server. + /// + private void CertificateValidation(CertificateValidator sender, CertificateValidationEventArgs e) + { + bool certificateAccepted = false; + + // **** + // Implement a custom logic to decide if the certificate should be + // accepted or not and set certificateAccepted flag accordingly. + // The certificate can be retrieved from the e.Certificate field + // *** + + ServiceResult error = e.Error; + m_output.WriteLine(error); + if (error.StatusCode == StatusCodes.BadCertificateUntrusted && AutoAccept) + { + certificateAccepted = true; + } + + if (certificateAccepted) + { + m_output.WriteLine("Untrusted Certificate accepted. Subject = {0}", e.Certificate.Subject); + e.Accept = true; + } + else + { + m_output.WriteLine("Untrusted Certificate rejected. Subject = {0}", e.Certificate.Subject); + } + } + private bool checkSession() + { + if (m_session == null || m_session.Connected == false) + { + m_output.WriteLine("Session not connected!"); + return false; + } + else + { + return true; + } + } + #endregion + + #region Private Fields + private ApplicationConfiguration m_configuration; + private Session m_session; + private readonly TextWriter m_output; + private readonly Action m_validateResponse; + #endregion + } +} diff --git a/OPC/OpcUaTypeReader.cs b/OPC/OpcUaTypeReader.cs new file mode 100644 index 0000000..4315411 --- /dev/null +++ b/OPC/OpcUaTypeReader.cs @@ -0,0 +1,332 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using Microsoft.Extensions.Logging; + +namespace Opc.Ua.Cloud.Publisher.OPC +{ + public class OpcUaTypeReader + { + ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); + private ILogger logger; + private List errorMemmory = new List(); + private TypeDictionaries typeDictionaries; + private OpcUaClient client; + public OpcUaTypeReader(OpcUaClient opcUaClient) { + this.client = opcUaClient; + logger = this.loggerFactory.CreateLogger(); + } + public void ReadTypeDictionary() + { + this.ReadOpcBinary(); + this.ReadDataTypes(); + this.ReadEventTypes(); + this.ReadInterfaceTypes(); + this.ReadObjectTypes(); + this.ReadReferenceTypes(); + this.ReadVariableTypes(); + Console.WriteLine("TypeDictionary Read Finished"); + } + private void ReadOpcBinary() + { + List binaryTypeDictionaries = new List(); + binaryTypeDictionaries = this.client.BrowseLocalNodeIdsWithTypeDefinition(ObjectIds.OPCBinarySchema_TypeSystem, BrowseDirection.Forward, (uint)NodeClass.Variable, ReferenceTypeIds.HasComponent, false, VariableTypeIds.DataTypeDictionaryType); + foreach (NodeId binaryTypeDictionary in binaryTypeDictionaries) + { + DataValue dv = this.client.ReadValue(binaryTypeDictionary); + string xmlString = Encoding.UTF8.GetString((byte[])dv.Value); + //Console.WriteLine(xmlString); + this.generateDataClasses(xmlString); + }; + List opcBinaryNodeIds = new List(); + this.ReadAndAppendTypeNodeIds(ObjectIds.OPCBinarySchema_TypeSystem, NodeClass.Variable, opcBinaryNodeIds, ReferenceTypeIds.HasComponent); + this.ReadAndAppendTypeNodeIds(ObjectIds.OPCBinarySchema_TypeSystem, NodeClass.Variable, opcBinaryNodeIds, ReferenceTypeIds.HasProperty); + Dictionary opcBinaryTypes = new Dictionary(); + //opcBinaryNodeIds = opcBinaryNodeIds.Distinct().ToList(); + foreach (NodeId opcBinaryNodeId in opcBinaryNodeIds) + { + Node? node = this.client.ReadNode(opcBinaryNodeId); + if (node != null) + { + opcBinaryTypes.Add(opcBinaryNodeId, node); + } + else + { + Console.WriteLine("Error Reading Node for NodeId:", opcBinaryNodeId); + } + } + this.typeDictionaries.SetOpcBinaryTypes(opcBinaryTypes); + } + private void generateDataClasses(string xmlString) + { + Console.Out.WriteLine(xmlString); + XmlTextReader reader = new XmlTextReader(new System.IO.StringReader(xmlString)); + GeneratedStructure generatedStructure = new GeneratedStructure(); + GeneratedEnumeratedType generatedEnumeratedType = new GeneratedEnumeratedType(); + GeneratedOpaqueType generatedOpaqueType = new GeneratedOpaqueType(); + //Structure or enumerated Type + GeneratedComplexTypes generatedComplexType = GeneratedComplexTypes.StructuredType; + string? Name = null; + string? BaseType = null; + string documentation = ""; + string? targetNamespace = null; + while (reader.Read()) + { + switch (reader.NodeType) + { + case XmlNodeType.Element: + string nodeElement = reader.Name; + switch (nodeElement) + { + case ("opc:StructuredType"): + generatedComplexType = GeneratedComplexTypes.StructuredType; + generatedStructure = new GeneratedStructure(); + Name = reader.GetAttribute("Name"); + BaseType = reader.GetAttribute("BaseType"); + generatedStructure.BaseType = BaseType; + if (Name != null) + { + generatedStructure.Name = Name; + } + else + { + this.errorMemmory.Add("The Name of the structure is null"); + } + break; + case ("opc:Documentation"): + documentation = reader.ReadInnerXml(); + if (generatedComplexType == GeneratedComplexTypes.StructuredType) + { + generatedStructure.Documentation = documentation; + } + else if (generatedComplexType == GeneratedComplexTypes.EnumeratedType) + { + generatedEnumeratedType.Documentation = documentation; + } + else if (generatedComplexType == GeneratedComplexTypes.OpaqueType) + { + + } + break; + case ("opc:Field"): + GeneratedField generatedField = new GeneratedField(); + string? typeName = reader.GetAttribute("TypeName"); + if (typeName != null) + { + generatedField.TypeName = typeName; + } + else + { + this.errorMemmory.Add("The TypeName of the Field is null"); + } + string? fieldname = reader.GetAttribute("Name"); + if (fieldname != null) + { + generatedField.Name = fieldname; + } + else + { + this.errorMemmory.Add("The Name of the Field is null"); + } + if (generatedComplexType == GeneratedComplexTypes.StructuredType) + { + generatedStructure.fields.Add(generatedField); + } + else + { + this.errorMemmory.Add("Trying to add a field to a non Structure."); + } + break; + case ("opc:EnumeratedType"): + generatedComplexType = GeneratedComplexTypes.EnumeratedType; + generatedEnumeratedType = new GeneratedEnumeratedType(); + Name = reader.GetAttribute("Name"); + if (Name != null) + { + generatedEnumeratedType.Name = Name; + } + else + { + this.errorMemmory.Add("The Name of the structure is null"); + } + break; + case ("opc:EnumeratedValue"): + break; + case ("opc:OpaqueType"): + generatedComplexType = GeneratedComplexTypes.OpaqueType; + break; + case ("opc:TypeDictionary"): + targetNamespace = reader.GetAttribute("TargetNamespace"); + if (targetNamespace == null) + { + this.errorMemmory.Add("The TargetNameSpace for the Typedictionary is null."); + } + break; + case ("opc:Import"): + break; + default: + Console.WriteLine("UnknownType: -> ##################" + "###" + reader.Name + "###"); + break; + } + //Console.WriteLine("###" + reader.Name + "###"); + + break; + case XmlNodeType.Text: + break; + case XmlNodeType.EndElement: + nodeElement = reader.Name; + switch (nodeElement) + { + case ("opc:StructuredType"): + if (targetNamespace != null) + { + this.typeDictionaries.generatedDataTypes.Add(new GeneratedDataTypeDefinition(targetNamespace, generatedStructure.Name), generatedStructure); + } + break; + } + break; + } + } + foreach (string error in this.errorMemmory) + { + logger.LogError(error); + } + } + private void ReadDataTypes() + { + List dataTypeNodeIds = new List(); + this.ReadAndAppendTypeNodeIds(DataTypeIds.BaseDataType, NodeClass.DataType, dataTypeNodeIds); + Dictionary dataTypes = new Dictionary(); + foreach (NodeId dataTypeNodeId in dataTypeNodeIds) + { + Node? node = this.client.ReadNode(dataTypeNodeId); + if (node != null) + { + dataTypes.Add(dataTypeNodeId, node); + } + else + { + Console.WriteLine("Error Reading Node for NodeId:", dataTypeNodeId); + } + } + this.typeDictionaries.SetDataTypes(dataTypes); + } + private void ReadEventTypes() + { + List eventTypeNodeIds = new List(); + this.ReadAndAppendTypeNodeIds(ObjectTypeIds.BaseEventType, NodeClass.ObjectType, eventTypeNodeIds); + Dictionary eventTypes = new Dictionary(); + foreach (NodeId eventTypeNodeId in eventTypeNodeIds) + { + Node? node = this.client.ReadNode(eventTypeNodeId); + if (node != null) + { + eventTypes.Add(eventTypeNodeId, node); + } + else + { + Console.WriteLine("Error Reading Node for NodeId:", eventTypeNodeId); + } + } + this.typeDictionaries.SetEventTypes(eventTypes); + } + private void ReadInterfaceTypes() + { + List interfaceTypeNodeIds = new List(); + this.ReadAndAppendTypeNodeIds(ObjectTypeIds.BaseInterfaceType, NodeClass.ObjectType, interfaceTypeNodeIds); + Dictionary interfaceTypes = new Dictionary(); + foreach (NodeId interfaceTypeNodeId in interfaceTypeNodeIds) + { + Node? node = this.client.ReadNode(interfaceTypeNodeId); + if (node != null) + { + interfaceTypes.Add(interfaceTypeNodeId, node); + } + else + { + Console.WriteLine("Error Reading Node for NodeId:", interfaceTypeNodeId); + } + } + this.typeDictionaries.SetInterfaceTypes(interfaceTypes); + } + + private void ReadObjectTypes() + { + List objectTypeNodeIds = new List(); + this.ReadAndAppendTypeNodeIds(ObjectTypeIds.BaseObjectType, NodeClass.ObjectType, objectTypeNodeIds); + Dictionary objectTypes = new Dictionary(); + foreach (NodeId objectTypeNodeId in objectTypeNodeIds) + { + Node? node = this.client.ReadNode(objectTypeNodeId); + if (node != null) + { + objectTypes.Add(objectTypeNodeId, node); + } + else + { + Console.WriteLine("Error Reading Node for NodeId:", objectTypeNodeId); + } + } + this.typeDictionaries.SetObjectTypes(objectTypes); + + } + private void ReadReferenceTypes() + { + List referenceTypeNodeIds = new List(); + this.ReadAndAppendTypeNodeIds(ReferenceTypeIds.References, NodeClass.ReferenceType, referenceTypeNodeIds); + Dictionary referenceTypes = new Dictionary(); + foreach (NodeId referenceTypeNodeId in referenceTypeNodeIds) + { + Node? node = this.client.ReadNode(referenceTypeNodeId); + if (node != null) + { + referenceTypes.Add(referenceTypeNodeId, node); + } + else + { + Console.WriteLine("Error Reading Node for NodeId:", referenceTypeNodeId); + } + } + this.typeDictionaries.SetReferenceTypes(referenceTypes); + } + + private void ReadVariableTypes() + { + List variableTypeNodeIds = new List(); + this.ReadAndAppendTypeNodeIds(VariableTypeIds.BaseVariableType, NodeClass.VariableType, variableTypeNodeIds); + Dictionary variableTypes = new Dictionary(); + foreach (NodeId variableTypeNodeId in variableTypeNodeIds) + { + Node? node = this.client.ReadNode(variableTypeNodeId); + if (node != null) + { + variableTypes.Add(variableTypeNodeId, node); + } + else + { + Console.WriteLine("Error Reading Node for NodeId:", variableTypeNodeId); + } + } + this.typeDictionaries.SetVariableTypes(variableTypes); + } + private void ReadAndAppendTypeNodeIds(NodeId nodeId, NodeClass nodeClass, List nodeIds) + { + nodeIds.Add(nodeId); + List subTypeNodeIds = this.client.BrowseLocalNodeIds(nodeId, BrowseDirection.Forward, (uint)nodeClass, ReferenceTypeIds.HasSubtype, true); + foreach (NodeId subTypeNodeId in subTypeNodeIds) + { + this.ReadAndAppendTypeNodeIds(subTypeNodeId, nodeClass, nodeIds); + } + } + private void ReadAndAppendTypeNodeIds(NodeId nodeId, NodeClass nodeClass, List nodeIds, NodeId referenceTypeId) + { + nodeIds.Add(nodeId); + List subTypeNodeIds = this.client.BrowseLocalNodeIds(nodeId, BrowseDirection.Forward, (uint)nodeClass, referenceTypeId, true); + foreach (NodeId subTypeNodeId in subTypeNodeIds) + { + this.ReadAndAppendTypeNodeIds(subTypeNodeId, nodeClass, nodeIds, referenceTypeId); + } + } + } +} diff --git a/OPC/TypeDictionaries.cs b/OPC/TypeDictionaries.cs new file mode 100644 index 0000000..707e14d --- /dev/null +++ b/OPC/TypeDictionaries.cs @@ -0,0 +1,217 @@ +using System.Collections.Generic; + +namespace Opc.Ua.Cloud.Publisher.OPC +{ + public class TypeDictionaries + { + public Dictionary generatedDataTypes = new Dictionary(); + private Dictionary opcBinary = new Dictionary(new NodeIdComparer()); + private Dictionary dataTypes = new Dictionary(); + private Dictionary eventTypes = new Dictionary(); + private Dictionary interfaceTypes = new Dictionary(); + private Dictionary objectTypes = new Dictionary(); + private Dictionary referenceTypes = new Dictionary(); + private Dictionary variableTypes = new Dictionary(); + private Dictionary xmlSchema = new Dictionary(); + public List dataTypeDefinition = new List(); + + public TypeDictionaries() + { + + } + public void SetOpcBinaryTypes(Dictionary opcBinary) + { + this.opcBinary.Clear(); + if (opcBinary != null) + { + this.opcBinary = opcBinary; + } + } + public Dictionary GetOpcBinary() + { + return this.opcBinary; + } + public void SetDataTypes(Dictionary dataTypes) + { + this.dataTypes.Clear(); + if (dataTypes != null) + { + this.dataTypes = dataTypes; + } + } + public Dictionary GetDataTypes() + { + return this.dataTypes; + } + public void SetEventTypes(Dictionary eventTypes) + { + this.eventTypes.Clear(); + if (eventTypes != null) + { + this.eventTypes = eventTypes; + } + } + public Dictionary GetEventTypes() + { + return this.eventTypes; + } + public void SetInterfaceTypes(Dictionary interfaceTypes) + { + this.interfaceTypes.Clear(); + if (interfaceTypes != null) + { + this.interfaceTypes = interfaceTypes; + } + } + public Dictionary GetInterfaceTypes() + { + return this.interfaceTypes; + } + public void SetObjectTypes(Dictionary objectTypes) + { + this.objectTypes.Clear(); + if (interfaceTypes != null) + { + this.objectTypes = objectTypes; + } + } + public Dictionary GetObjectTypes() + { + return this.objectTypes; + } + public void SetReferenceTypes(Dictionary referenceTypes) + { + this.referenceTypes.Clear(); + if (referenceTypes != null) + { + this.referenceTypes = referenceTypes; + } + } + public Dictionary GetReferenceTypes() + { + return this.referenceTypes; + } + public void SetVariableTypes(Dictionary variableTypes) + { + this.variableTypes.Clear(); + if (variableTypes != null) + { + this.variableTypes = variableTypes; + } + } + public Dictionary GetVariableTypes() + { + return this.variableTypes; + } + public Node? FindBinaryEncodingType(NodeId nodeId) + { + Node? encodingType = null; + encodingType = this.opcBinary[nodeId]; + return encodingType; + } + } + public class NodeIdComparer : IEqualityComparer + { + public bool Equals(NodeId? n1, NodeId? n2) + { + if (n1 == n2) + { + return true; + } + if (n1 == null || n2 == null) + { + return false; + } + return (n1.Identifier == n2.Identifier && n1.NamespaceIndex == n2.NamespaceIndex); + } + public int GetHashCode(NodeId n1) + { + return n1.Identifier.GetHashCode() + n1.NamespaceIndex.GetHashCode(); + } + } + public class GeneratedDataTypeDefinition + { + private string nameSpace; + private string name; + public GeneratedDataTypeDefinition(string nameSpace, string name) + { + this.nameSpace = nameSpace; + this.name = name; + } + } + public class GeneratedField + { + public string Name = ""; + public string TypeName = ""; + public GeneratedField() + { + + } + } + public class GeneratedDataClass + { + public string Name = ""; + public GeneratedDataClass() + { + } + } + public class GeneratedStructure : GeneratedDataClass + { + public string Documentation = ""; + public string? BaseType = null; + public List fields = new List(); + public GeneratedStructure() + { + + } + } + public class GeneratedEnumeratedType : GeneratedDataClass + { + public string Documentation = ""; + public GeneratedEnumeratedType() + { + + } + } + public class GeneratedOpaqueType : GeneratedDataClass + { + public string Documentation = ""; + public GeneratedOpaqueType() + { + + } + } + public enum GeneratedComplexTypes + { + StructuredType, + EnumeratedType, + OpaqueType + } + + public class StructuredNode + { + public NodeId nodeId; + public QualifiedName browsename; + public List childNodes = new List(); + public string? placeholderTypeDefinition = null; + public Dictionary> placeholderNodes = new Dictionary>(); + public StructuredNode(QualifiedName browseName, NodeId nodeId) + { + this.browsename = browseName; + this.nodeId = nodeId; + } + } + public class PlaceHolderNode + { + public QualifiedName browseName; + public NodeId nodeId; + public string typeDefinition; + public List childNodes = new List(); + public PlaceHolderNode(QualifiedName browseName, NodeId nodeId, string typeDefinition) + { + this.browseName = browseName; + this.nodeId = nodeId; + this.typeDefinition = typeDefinition; + } + } +}