upc ua 建模的方式通常是使用建模工具建模(比如uaModeler),直接输出C,C++,C# 源代码,然后与OPC UA 服务器的代码一起编译。opc ua 开源项目也是如此。它提供了一个python 编写的nodeset_compiler工具。将nodeset.XML 编译成为myNS.c和.h文件。然后结合到server 的代码中。
如果是开发一个特定的产品,它的opc ua 模型是预先确定的。那么这样做还能容忍,毕竟这是由程序员做的工作。但是,如果开发的产品是一个通用产品,需要OT 工程师来构建OPC UA 的模型。那么对于OT 工程师就太麻烦了。他们不擅长这样的工作。
解决的方法是由server 程序来动态构建opc ua 模型。在server 的程序中导入nodeset.xml 文档,由server 中的程序自动构建server 端的信息模型。实现opc ua 服务器的动态建模。
在Server 程序中利用nodeset.xml 构建的是对象的类型(objectType),然后将对象类型实例化,这时需要额外的信息。它们通过configuration.xml 提供。
首先使用uamodeler 软件建一个opcua的nodeset模型。并且输出nodeset.xml 文件.
- <?xml version="1.0" encoding="utf-8"?>
- <UANodeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:uax="http://opcfoundation.org/UA/2008/02/Types.xsd" xmlns="http://opcfoundation.org/UA/2011/03/UANodeSet.xsd" xmlns:s1="http://yourorganisation.org/demo2022/Types.xsd" xmlns:ua="http://unifiedautomation.com/Configuration/NodeSet.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <NamespaceUris>
- <Uri>http://yourorganisation.org/demo2022/</Uri>
- </NamespaceUris>
- <Aliases>
- <Alias Alias="Boolean">i=1</Alias>
- <Alias Alias="Double">i=11</Alias>
- <Alias Alias="HasTypeDefinition">i=40</Alias>
- <Alias Alias="HasComponent">i=47</Alias>
- </Aliases>
- <Extensions>
- <Extension>
- <ua:ModelInfo Tool="UaModeler" Hash="Yl8uWJaLMTz0jvkxYQoGkw==" Version="1.6.0"/>
- </Extension>
- </Extensions>
- <UAObject NodeId="ns=1;i=5001" BrowseName="1:Meter">
- <DisplayName>Meter</DisplayName>
- <References>
- <Reference ReferenceType="HasTypeDefinition">i=58</Reference>
- <Reference ReferenceType="HasComponent">ns=1;i=6001</Reference>
- <Reference ReferenceType="HasComponent">ns=1;i=5002</Reference>
- <Reference ReferenceType="HasComponent">ns=1;i=6002</Reference>
- <Reference ReferenceType="HasComponent" IsForward="false">i=85</Reference>
- </References>
- </UAObject>
- <UAVariable DataType="Double" NodeId="ns=1;i=6001" BrowseName="1:Current" AccessLevel="3">
- <DisplayName>Current</DisplayName>
- <References>
- <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
- <Reference ReferenceType="HasComponent" IsForward="false">ns=1;i=5001</Reference>
- </References>
- </UAVariable>
- <UAObject NodeId="ns=1;i=5002" BrowseName="1:Switch">
- <DisplayName>Switch</DisplayName>
- <References>
- <Reference ReferenceType="HasTypeDefinition">i=58</Reference>
- <Reference ReferenceType="HasComponent">ns=1;i=6004</Reference>
- <Reference ReferenceType="HasComponent" IsForward="false">ns=1;i=5001</Reference>
- </References>
- </UAObject>
- <UAVariable DataType="Boolean" NodeId="ns=1;i=6004" BrowseName="1:Status" AccessLevel="3">
- <DisplayName>Status</DisplayName>
- <References>
- <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
- <Reference ReferenceType="HasComponent" IsForward="false">ns=1;i=5002</Reference>
- </References>
- </UAVariable>
- <UAVariable DataType="Double" NodeId="ns=1;i=6002" BrowseName="1:Voltage" AccessLevel="3">
- <DisplayName>Voltage</DisplayName>
- <References>
- <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
- <Reference ReferenceType="HasComponent" IsForward="false">ns=1;i=5001</Reference>
- </References>
- </UAVariable>
- <UAVariable DataType="Double" NodeId="ns=1;i=6003" BrowseName="1:Temperature" AccessLevel="3">
- <DisplayName>Temperature</DisplayName>
- <References>
- <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
- <Reference ReferenceType="HasComponent" IsForward="false">i=85</Reference>
- </References>
- </UAVariable>
- </UANodeSet>
第二步:手工编写一个configuration.xml 文档。这一步以后可以使用一个小的软件工具,组态方式生成。
- <?xml version="1.0" encoding="utf-8"?>
- <UAObject NodeId="ns=1;i=5001" BrowseName="1:Meter">
- <Param BrowseName="Meter1">
- <DisplayName>
- Meter 1
- </DisplayName>
- <Description>Electricity Meter 1</Description>
- </Param>
- <UAVariable DataType="Double" NodeId="ns=1;i=6001" BrowseName="1:Current" AccessLevel="3">
- <Value>10</Value>
- <DataSource></DataSource>
- </UAVariable>
- <UAVariable DataType="Double" NodeId="ns=1;i=6002" BrowseName="1:Voltage" AccessLevel="3">
- <Value>220</Value>
- </UAVariable>
- <UAObject NodeId="ns=1;i=5002" BrowseName="1:Switch">
- <Param BrowseName="Meter1">
- <DisplayName>
- Meter 1
- </DisplayName>
- </Param>
- <UAVariable DataType="Boolean" NodeId="ns=1;i=6004" BrowseName="1:Status" AccessLevel="3">
- <Value>On</Value>
- </UAVariable>
- </UAObject>
- <UAVariable DataType="Double" NodeId="ns=1;i=6003" BrowseName="1:Temperature" AccessLevel="3">
- <Value>25.6</Value>
- </UAVariable>
- </UAObject>
从上面的代码看,configuration.XML 中添加了下面的内容
1 Object 节点的参数 BrowseName,DisplayName,Description 它们使用Param 描述
- <Param BrowseName="Meter1">
- <DisplayName>
- Meter 1
- </DisplayName>
- <Description>Electricity Meter 1</Description>
- </Param>
2 Variable节点添加了Value 和DataSource 分别是初始值(Value)和与硬件对应的地址(DataSource)
- <UAVariable DataType="Double" NodeId="ns=1;i=6001" BrowseName="1:Current" AccessLevel="3">
- <Value>10</Value>
- <DataSource></DataSource>
- </UAVariable>
第三步:由Nodeset.xml 产生ObjectType 节点(未完成)
第四步:由Configuration.XML 产生Object实例,并且初始化。(未完成)
目前只是技术方案,完成会更新。请多给意见呀!