Tento projekt je venovaný:
- vytvoreniu lokálnej kópie projektu
- preskúmaniu informačného modelu informačného modelu(IM) založeného na Device Information Model(DI) .
- vytvoreniu vlastného IM. Predpokladá sa prostredie Windows 7 a vyššie.
Ako prvé je potrebné nainštalovať git do počítača a stiahnuť si dáta z úložiska git. Vytvoríme nový adresár c:\informationmodel a vytvoríme klon projektu git UA ModelCompiler a DI-InformationModel cez prostredie powershell:
PS C:\> mkdir informationmodel
PS C:\> cd .\informationmodel\
PS C:\informationmodel> git clone https://github.com/OPCFoundation/UA-ModelCompiler.git --recursive
PS C:\informationmodel> git clone https://github.com/STUBA-rupr/DI-InformationModel.git
Projekt riešenie UA-ModelCompiler je potrebné skompilovať, odporúčam MS Visual Studiu 2017 Community.
Návrh objektového typu váhy (WeightScaleType) založeného na špecifikácii DI:
Kód ktorý popisuje daný model by mohol vyzerať nasledovne: modeldesignscale.xml.
Súbor popisujúci informačný model obsahuje hlavičku v ktorej sú zadefinované menné priestory jazyka XML a OPC UA.
xmlns:uax="http://opcfoundation.org/UA/2008/02/Types.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:OpcUa="http://opcfoundation.org/UA/"
xmlns:DI="http://opcfoundation.org/UA/DI/"
xmlns:WS="http://phi-ware.com/FEISTU/WS/"
Kde
- uax je menný priestor základných dátových typov OPC UA
- xsi je menný priestor jadra XML
- OpcUa je menný priestor základných objektov OPC UA
- DI je menný priestor objektov Device Information Model
- WS je menný priestor objektov Weight Scale Information Model
Poznámka: Názvy menných priestorov rozpoznávaju veľké a malé písmená.
<Namespaces>
<Namespace Name="OpcUaWs" Prefix="Opc.Ua.Ws" XmlNamespace="http://phi-ware.com/FEISTU/WS/Types.xsd" XmlPrefix="WS">http://phi-ware.com/FEISTU/WS/</Namespace>
<Namespace Name="OpcUaDi" Prefix="Opc.Ua.Di" XmlNamespace="http://opcfoundation.org/UA/DI/Types.xsd" XmlPrefix="DI" FilePath="OpcUaDiModel">http://opcfoundation.org/UA/DI/</Namespace>
<Namespace Name="OpcUa" Prefix="Opc.Ua" InternalPrefix="Opc.Ua.Server" XmlNamespace="http://opcfoundation.org/UA/2008/02/Types.xsd" XmlPrefix="OpcUa">http://opcfoundation.org/UA/</Namespace>
</Namespaces>
Menné priestory XML a OPC UA sú spárované cez kľúčové slovo XmlPrefix
v definícii OPC UA menného priestoru.
Definícia objektového typu má nasledovnú syntax:
<ObjectType SymbolicName="WS:WeightScaleType" BaseType="DI:DeviceType" IsAbstract="false" SupportsEvents="true">
Kde SymbolicName
je názov objektového typu, predpona WS: špecifikuje menný priestor a WeightScaleType je samotný názov typu. Rodič (parent) objektového typu WeightScaleType sa definuje cez BaseType
, kde rovnako predpona DI: definuje menný priestor a DeviceType je objektový typ pre všeobecné zariadenie. IsAbstract="false"
hovorí že typ nie je abstraktný a že teda je možné z neho vytvoriť inštanciu objektu.
Objektový typ DeviceType je odvodený od typu TopologyElementType, ktorý obsahuje nasledovnú definíciu podobjektov (Children):
<Children>
<Object SymbolicName="DI:ParameterSet" TypeDefinition="OpcUa:BaseObjectType" ModellingRule="Optional">
<Description>Flat list of Parameters</Description>
<Children>
<Variable SymbolicName="DI:ParameterIdentifier" TypeDefinition="OpcUa:BaseDataVariableType" ModellingRule="MandatoryPlaceholder">
<BrowseName><ParameterIdentifier></BrowseName>
<Description>A parameter which belongs to the topology element.</Description>
</Variable>
</Children>
</Object>
<Object SymbolicName="DI:MethodSet" TypeDefinition="OpcUa:BaseObjectType" ModellingRule="Optional">
<Description>Flat list of Methods</Description>
<Children>
<Method SymbolicName="DI:MethodIdentifier" ModellingRule="MandatoryPlaceholder">
<BrowseName><MethodIdentifier></BrowseName>
<Description>A method which belongs to the topology element.</Description>
</Method>
</Children>
</Object>
...
Tento kód definuje kontajnéry kde sú vymenované premenné Variable
a metódy Method
. Aby bolo možné v objektovom type WeightScaleType definovať metódy a premenné je treba tento kód zreplikovať a modifikovať:
<ObjectType SymbolicName="WS:WeightScaleType" BaseType="DI:DeviceType" IsAbstract="false" SupportsEvents="true">
<Description>Base weight scale type.</Description>
<Children>
<!-- Parameter set-->
<Object SymbolicName="WS:ParameterSet" TypeDefinition="OpcUa:BaseObjectType" ModellingRule="Mandatory">
<Description>Flat list of Parameters</Description>
<Children>
<Variable SymbolicName="WS:weightScale" TypeDefinition="OpcUa:AnalogItemType" DataType="OpcUa:Double" ModellingRule="Mandatory">
<BrowseName>weightScale</BrowseName>
<Description>Actual weight.</Description>
<Children>
<Property SymbolicName="OpcUa:InstrumentRange" ModellingRule="Optional" DataType="OpcUa:Range" />
<Property SymbolicName="OpcUa:EURange" ModellingRule="Optional" DataType="OpcUa:Range" />
<Property SymbolicName="OpcUa:EngineeringUnits" ModellingRule="Mandatory" DataType="OpcUa:EUInformation" />
</Children>
</Variable>
</Children>
</Object>
<!-- Method set-->
<Object SymbolicName="WS:MethodSet" TypeDefinition="OpcUa:BaseObjectType" ModellingRule="Mandatory">
<Description>Flat list of Methods</Description>
<Children>
<Method SymbolicName="WS:Tare" ModellingRule="Mandatory">
<BrowseName>Tare</BrowseName>
<Description>Tare balnace.</Description>
</Method>
<Method SymbolicName="WS:Zero" ModellingRule="Mandatory">
<BrowseName>Zero</BrowseName>
<Description>Zero balnace.</Description>
</Method>
</Children>
</Object>
</Children>
</ObjectType>
Ako je vidieť pribudla definícia premennej WS:weightScale
a metód WS:Tare
a WS:Zero
. Dôležité je tiež poznamenať, že ModellingRule
sa zmenilo na Mandatory, čo značí že uzly (objekty, premenné, motódy) sú povinné pre objekty odvodené od WeightScaleType. Inými slovami, všetky objekty odvodené od WeightScaleType budú obsahovať WS:weightScale
, WS:Tare
a WS:Zero
.
Súbor modeldesignscale.xml obsahuje v sekcii <!-- Object instances -->
definíciu inštancie objektového typu WeightScaleType:
<Object SymbolicName="WS:WeightScale01" TypeDefinition="WS:WeightScaleType">
<Description>Weight scale number 01</Description>
<References>
<Reference IsInverse="true">
<ReferenceType>OpcUa:Organizes</ReferenceType>
<TargetId>DI:DeviceSet</TargetId>
</Reference>
</References>
</Object>
Inštancia objektu sa vytvára cez kľúčové slovo Object
. Podobne ako pri definícii objektového typu názov objektu obsahuje menný priestor. Uzol <References>
obsahuje zoznam referencií. V tomto prípade ide o referenciu pomocou ktorej je možné objekt usporiadať do požadovanej hierarchie - zaradenie do adresáru DeviceSet.
Súbor modeldesignscale.xml skompilujeme spustením dávkového súboru:
PS C:\informationmodel> cd .\DI-InformationModel\
PS C:\informationmodel\DI-InformationModel> .\PublishModel.bat
Building Model WS
..\UA-ModelCompiler\Bin\debug\Opc.Ua.ModelCompiler.exe -d2 "Design\modeldesignscale.xml" -cg "Design\modeldesignscale.csv" -o2 "Published\master\WS\"
Trying file: C:\informationmodel\DI-InformationModel\Design\OpcUaDiModel.xml
Trying file: C:\informationmodel\DI-InformationModel\Design\OpcUaDiModel.csv
Copying Model files to Published\master\WS\modeldesignscale
1 file(s) copied.
1 file(s) copied.
Program na vytváranie OPC UA informačného modelu UA Modeler je možné stiahnuť na stránke: Unified-Automation. Po spustení programu UA Modeler je treba otvoriť projekt weightscalenodeset.tt2pro. Uzly obsahúce objektové typy DI informačného modelu sú v adresáry Types>ObjectTypes>TopologyElementType. Všetky uzly DI IM sú popísané v špecifikácii Part 100: Device Information Model.
Projekt obsahuje aj informačný model pre zariadenie váha:
Ako prvé je potrebné vytvoriť kópiu OPC UA serveru podľa návodu. Ale v našom prípade miesto Reference Server použijeme Boiler Server. Upravený projekt je možné stiahnuť z git do nášho koreňového adresára:
PS C:\informationmodel> git clone https://github.com/STUBA-rupr/UA-.NETStandard.git
Popis zmien zdrojového kódu, spustenie servera ako aj preskúmanie objektov servera sa dá nájsť v readme-SK.md súbore. Adresný priestor OPC UA serveru pre váhu:
Ďalším krokom je vytvorenie obslužného kódu pre metódy Zero, Tare a aktualizáciu premennej weightScale. Príklad ako by kód mohol vyzerať je tu.