Skip to content

Commit 9b038e8

Browse files
authored
Added Possibility to read local bsd files. (#255)
Added Possibility to only Read Binaries on start up. Fixed set up so that config file is exported. Added bs file for Opc.UA and Opc.Ua.Di.
1 parent 65d260e commit 9b038e8

File tree

11 files changed

+3561
-38
lines changed

11 files changed

+3561
-38
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<!--
3+
* Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved.
4+
*
5+
* OPC Foundation MIT License 1.00
6+
*
7+
* Permission is hereby granted, free of charge, to any person
8+
* obtaining a copy of this software and associated documentation
9+
* files (the "Software"), to deal in the Software without
10+
* restriction, including without limitation the rights to use,
11+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the
13+
* Software is furnished to do so, subject to the following
14+
* conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be
17+
* included in all copies or substantial portions of the Software.
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25+
* OTHER DEALINGS IN THE SOFTWARE.
26+
*
27+
* The complete license agreement can be found here:
28+
* http://opcfoundation.org/License/MIT/1.00/
29+
-->
30+
31+
<opc:TypeDictionary
32+
xmlns:opc="http://opcfoundation.org/BinarySchema/"
33+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
34+
xmlns:ua="http://opcfoundation.org/UA/"
35+
xmlns:tns="http://opcfoundation.org/UA/DI/"
36+
DefaultByteOrder="LittleEndian"
37+
TargetNamespace="http://opcfoundation.org/UA/DI/"
38+
>
39+
<opc:Import Namespace="http://opcfoundation.org/UA/" Location="Opc.Ua.BinarySchema.bsd"/>
40+
41+
<opc:EnumeratedType Name="DeviceHealthEnumeration" LengthInBits="32">
42+
<opc:EnumeratedValue Name="NORMAL" Value="0" />
43+
<opc:EnumeratedValue Name="FAILURE" Value="1" />
44+
<opc:EnumeratedValue Name="CHECK_FUNCTION" Value="2" />
45+
<opc:EnumeratedValue Name="OFF_SPEC" Value="3" />
46+
<opc:EnumeratedValue Name="MAINTENANCE_REQUIRED" Value="4" />
47+
</opc:EnumeratedType>
48+
49+
<opc:StructuredType Name="FetchResultDataType" BaseType="ua:ExtensionObject">
50+
</opc:StructuredType>
51+
52+
<opc:StructuredType Name="TransferResultErrorDataType" BaseType="tns:FetchResultDataType">
53+
<opc:Field Name="Status" TypeName="opc:Int32" />
54+
<opc:Field Name="Diagnostics" TypeName="ua:DiagnosticInfo" />
55+
</opc:StructuredType>
56+
57+
<opc:StructuredType Name="TransferResultDataDataType" BaseType="tns:FetchResultDataType">
58+
<opc:Field Name="SequenceNumber" TypeName="opc:Int32" />
59+
<opc:Field Name="EndOfResults" TypeName="opc:Boolean" />
60+
<opc:Field Name="NoOfParameterDefs" TypeName="opc:Int32" />
61+
<opc:Field Name="ParameterDefs" TypeName="tns:ParameterResultDataType" LengthField="NoOfParameterDefs" />
62+
</opc:StructuredType>
63+
64+
<opc:StructuredType Name="ParameterResultDataType" BaseType="ua:ExtensionObject">
65+
<opc:Field Name="NoOfNodePath" TypeName="opc:Int32" />
66+
<opc:Field Name="NodePath" TypeName="ua:QualifiedName" LengthField="NoOfNodePath" />
67+
<opc:Field Name="StatusCode" TypeName="ua:StatusCode" />
68+
<opc:Field Name="Diagnostics" TypeName="ua:DiagnosticInfo" />
69+
</opc:StructuredType>
70+
71+
<opc:EnumeratedType Name="SoftwareVersionFileType" LengthInBits="32">
72+
<opc:EnumeratedValue Name="Current" Value="0" />
73+
<opc:EnumeratedValue Name="Pending" Value="1" />
74+
<opc:EnumeratedValue Name="Fallback" Value="2" />
75+
</opc:EnumeratedType>
76+
77+
<opc:EnumeratedType Name="UpdateBehavior" LengthInBits="32" IsOptionSet="true">
78+
<opc:EnumeratedValue Name="None" Value="0" />
79+
<opc:EnumeratedValue Name="KeepsParameters" Value="1" />
80+
<opc:EnumeratedValue Name="WillDisconnect" Value="2" />
81+
<opc:EnumeratedValue Name="RequiresPowerCycle" Value="4" />
82+
<opc:EnumeratedValue Name="WillReboot" Value="8" />
83+
<opc:EnumeratedValue Name="NeedsPreparation" Value="16" />
84+
</opc:EnumeratedType>
85+
86+
</opc:TypeDictionary>

umatiGateway/BsdFiles/Opc.Ua.Types.bsd

Lines changed: 3353 additions & 0 deletions
Large diffs are not rendered by default.

umatiGateway/Core/Configuration/UmatiConfiguration.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ public class OPCConnection
155155
public string CertificatePath { get; set; } = "";
156156
public string CertificatePassword { get; set; } = "";
157157
public bool ReadExtraLibs { get; set; } = false;
158+
public bool ResolveBinariesOnly { get; set; } = false;
158159
public override string ToString()
159160
{
160161
return $"OPCConnection(Server={ServerEndpoint}, Auth={Authentication}, User={UserName}, Password={UmatiConfigurationUtils.MaskPassword(Password)}, ReadExtraLibs={ReadExtraLibs})";

umatiGateway/Core/Configuration/UmatiConfigurationManager.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class UmatiConfigurationManager
6363
public const string INCLUDE_SUB_TYPES = "includeSubTypes";
6464
public const string IGNORED_PLACEHOLDER_TAGS = "IgnoredPlaceholderTags";
6565
public const string IGNORED_PLACEHOLDER_TAG = "IgnoredPlaceholderTag";
66+
public const string RESOLVE_BINARIES_ONLY = "resolveBinariesOnly";
6667

6768
public UmatiConfigurationManager() { }
6869

@@ -107,6 +108,8 @@ public UmatiConfiguration ReadConfiguration()
107108
configuration.OPCConnection.CertificatePassword = ReadAttribute(opcConnectionNode, CERT_PWD);
108109
string readExtraLibs = ReadAttribute(opcConnectionNode, READ_EXTRA_LIBS);
109110
configuration.OPCConnection.ReadExtraLibs = string.Equals(readExtraLibs, "true", StringComparison.OrdinalIgnoreCase) ? true : false;
111+
string resolveBinariesOnly = ReadAttribute(opcConnectionNode, RESOLVE_BINARIES_ONLY);
112+
configuration.OPCConnection.ResolveBinariesOnly = string.Equals(resolveBinariesOnly, "true", StringComparison.OrdinalIgnoreCase) ? true : false;
110113
}
111114
else
112115
{
@@ -276,6 +279,8 @@ public string GetConfigurationAsString(UmatiConfiguration configuration)
276279
opcPassword.Value = configuration.OPCConnection.Password;
277280
XmlAttribute readExtraLibs = xmlDocument.CreateAttribute(READ_EXTRA_LIBS);
278281
readExtraLibs.Value = configuration.OPCConnection.ReadExtraLibs.ToString();
282+
XmlAttribute resolveBinariesOnly = xmlDocument.CreateAttribute(RESOLVE_BINARIES_ONLY);
283+
resolveBinariesOnly.Value = configuration.OPCConnection.ResolveBinariesOnly.ToString();
279284
XmlAttribute certPath = xmlDocument.CreateAttribute(CERT_PATH);
280285
certPath.Value = configuration.OPCConnection.CertificatePath.ToString();
281286
XmlAttribute certPwd = xmlDocument.CreateAttribute(CERT_PWD);
@@ -285,6 +290,7 @@ public string GetConfigurationAsString(UmatiConfiguration configuration)
285290
opcConnectionNode.Attributes.Append(opcUser);
286291
opcConnectionNode.Attributes.Append(opcPassword);
287292
opcConnectionNode.Attributes.Append(readExtraLibs);
293+
opcConnectionNode.Attributes.Append(resolveBinariesOnly);
288294
opcConnectionNode.Attributes.Append(certPath);
289295
opcConnectionNode.Attributes.Append(certPwd);
290296
XmlElement mqttConnectionNode = xmlDocument.CreateElement(MQTT_PROVIDER);

umatiGateway/Core/OPC/OpcUaClient.cs

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -388,35 +388,42 @@ public async Task<bool> ConnectAsync()
388388
this.notifyOpcUaClientListeners();
389389
Logger.Info("Read Binaries");
390390
TypeDictionaries.ReadOpcBinary();
391-
this.ClientState.setState(OpcUaConnectionState.Connected, "Read DataTypes");
392-
this.ClientStateHistory.Add(this.ClientState.Copy());
393-
this.notifyOpcUaClientListeners();
394-
Logger.Info("Read DataTypes");
395-
TypeDictionaries.ReadDataTypes();
396-
this.ClientState.setState(OpcUaConnectionState.Connected, "Read EventTypes");
397-
this.ClientStateHistory.Add(this.ClientState.Copy());
398-
this.notifyOpcUaClientListeners();
399-
Logger.Info("Read EventTypes");
400-
TypeDictionaries.ReadEventTypes();
401-
this.ClientState.setState(OpcUaConnectionState.Connected, "Read InterfaceTypes");
402-
this.ClientStateHistory.Add(this.ClientState.Copy());
403-
this.notifyOpcUaClientListeners();
404-
Logger.Info("Read InterfaceTypes");
405-
TypeDictionaries.ReadInterfaceTypes();
406-
this.ClientState.setState(OpcUaConnectionState.Connected, "Read ObjectTypes");
407-
this.ClientStateHistory.Add(this.ClientState.Copy());
408-
this.notifyOpcUaClientListeners();
409-
Logger.Info("Read ObjectTypes");
410-
TypeDictionaries.ReadObjectTypes();
411-
this.ClientState.setState(OpcUaConnectionState.Connected, "Read ReferenceTypes");
412-
this.ClientStateHistory.Add(this.ClientState.Copy());
413-
Logger.Info("Read ReferenceTypes");
414-
TypeDictionaries.ReadReferenceTypes();
415-
this.ClientState.setState(OpcUaConnectionState.Connected, "Read VariableTypes");
416-
this.ClientStateHistory.Add(this.ClientState.Copy());
417-
this.notifyOpcUaClientListeners();
418-
Logger.Info("Read VariableTypes");
419-
TypeDictionaries.ReadVariableTypes();
391+
if (this.app.ActiveConfiguration.OPCConnection.ResolveBinariesOnly)
392+
{
393+
Logger.Info("Skip Reading Objects, ObjectTypes, Variables, VariableTypes, Interfaces and References");
394+
}
395+
else
396+
{
397+
this.ClientState.setState(OpcUaConnectionState.Connected, "Read DataTypes");
398+
this.ClientStateHistory.Add(this.ClientState.Copy());
399+
this.notifyOpcUaClientListeners();
400+
Logger.Info("Read DataTypes");
401+
TypeDictionaries.ReadDataTypes();
402+
this.ClientState.setState(OpcUaConnectionState.Connected, "Read EventTypes");
403+
this.ClientStateHistory.Add(this.ClientState.Copy());
404+
this.notifyOpcUaClientListeners();
405+
Logger.Info("Read EventTypes");
406+
TypeDictionaries.ReadEventTypes();
407+
this.ClientState.setState(OpcUaConnectionState.Connected, "Read InterfaceTypes");
408+
this.ClientStateHistory.Add(this.ClientState.Copy());
409+
this.notifyOpcUaClientListeners();
410+
Logger.Info("Read InterfaceTypes");
411+
TypeDictionaries.ReadInterfaceTypes();
412+
this.ClientState.setState(OpcUaConnectionState.Connected, "Read ObjectTypes");
413+
this.ClientStateHistory.Add(this.ClientState.Copy());
414+
this.notifyOpcUaClientListeners();
415+
Logger.Info("Read ObjectTypes");
416+
TypeDictionaries.ReadObjectTypes();
417+
this.ClientState.setState(OpcUaConnectionState.Connected, "Read ReferenceTypes");
418+
this.ClientStateHistory.Add(this.ClientState.Copy());
419+
Logger.Info("Read ReferenceTypes");
420+
TypeDictionaries.ReadReferenceTypes();
421+
this.ClientState.setState(OpcUaConnectionState.Connected, "Read VariableTypes");
422+
this.ClientStateHistory.Add(this.ClientState.Copy());
423+
this.notifyOpcUaClientListeners();
424+
Logger.Info("Read VariableTypes");
425+
TypeDictionaries.ReadVariableTypes();
426+
}
420427
this.ClientState.setState(OpcUaConnectionState.Connected, "Read TypeDictionary finished");
421428
this.ClientStateHistory.Add(this.ClientState.Copy());
422429
this.notifyOpcUaClientListeners();

umatiGateway/Core/OPC/TypeDictionaries.cs

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,62 @@ public void ReadOpcBinary()
5959
{
6060
List<NodeId> binaryTypeDictionaries = new List<NodeId>();
6161
IOpcUaClient client = app.OpcUaClient;
62+
//Read Local Bsd Files First
63+
string folderPath = "./BsdFiles";
64+
65+
if (Directory.Exists(folderPath))
66+
{
67+
string[] files = Directory.GetFiles(folderPath);
68+
69+
foreach (string file in files)
70+
{
71+
Logger.Info($"Read Bsd File: {file}");
72+
73+
byte[] binaryData = File.ReadAllBytes(file);
74+
string xmlString = Encoding.UTF8.GetString(binaryData);
75+
generateDataClasses(xmlString);
76+
}
77+
}
78+
else
79+
{
80+
Logger.Error($"Unable to find Folder: {folderPath}");
81+
}
82+
83+
6284
binaryTypeDictionaries = client.BrowseLocalNodeIdsWithTypeDefinition(ObjectIds.OPCBinarySchema_TypeSystem, BrowseDirection.Forward, (uint)NodeClass.Variable, ReferenceTypeIds.HasComponent, true, VariableTypeIds.DataTypeDictionaryType);
6385
foreach (NodeId binaryTypeDictionary in binaryTypeDictionaries)
6486
{
65-
DataValue? dv = client.ReadValue(binaryTypeDictionary);
66-
if (dv != null)
87+
try
6788
{
68-
string xmlString = Encoding.UTF8.GetString((byte[])dv.Value);
69-
generateDataClasses(xmlString);
89+
DataValue? dv = client.ReadValue(binaryTypeDictionary);
90+
if (dv != null)
91+
{
92+
string xmlString = Encoding.UTF8.GetString((byte[])dv.Value);
93+
bool skipReading = false;
94+
foreach (KeyValuePair<GeneratedDataTypeDefinition, GeneratedDataClass> generatedDataType in generatedDataTypes)
95+
{
96+
GeneratedDataTypeDefinition gtdd = generatedDataType.Key;
97+
if (xmlString.Contains($"TargetNamespace=\"{gtdd.nameSpace}\""))
98+
{
99+
Logger.Info($"Skipe reading BsdSchema from Server for NodeId: {binaryTypeDictionary} (Loaded Locally)");
100+
skipReading = true;
101+
break;
102+
}
103+
}
104+
if (!skipReading)
105+
{
106+
Logger.Info($"Reading BsdSchema from Server for NodeId: {binaryTypeDictionary} (Loaded From Server)");
107+
generateDataClasses(xmlString);
108+
}
109+
}
110+
else
111+
{
112+
Logger.Error($"Unable to read binaryTypeDictionary {binaryTypeDictionary}");
113+
}
70114
}
71-
else
115+
catch (Exception e)
72116
{
73-
Logger.Error($"Unable to read binaryTypeDictionary {binaryTypeDictionary}");
117+
Logger.Error(e, $"Unable to read Value of Node: {binaryTypeDictionary}");
74118
}
75119
}
76120
;
@@ -121,7 +165,7 @@ private void ReadAndAppendTypeNodeIds(NodeId nodeId, NodeClass nodeClass, List<N
121165
}
122166
private void generateDataClasses(string xmlString)
123167
{
124-
Logger.Debug(xmlString);
168+
Logger.Trace(xmlString);
125169
XmlTextReader reader = new XmlTextReader(new StringReader(xmlString));
126170
GeneratedStructure generatedStructure = new GeneratedStructure();
127171
GeneratedEnumeratedType generatedEnumeratedType = new GeneratedEnumeratedType();

umatiGateway/Pages/Configuration.cshtml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@
8181
</label>
8282
<span class="on">On</span>
8383
</div>
84+
<label for="ResolveBinariesOnly" class="settings-label">Resolve Binaries Only</label>
85+
<div class="settings-on-off-label">
86+
<span class="off">Off</span>
87+
<label class="settings-switch">
88+
<input id="ResolveBinariesOnly" size="60" type="checkbox" name="ResolveBinariesOnly" value="true" @(Model.Configuration.OPCConnection.ResolveBinariesOnly ? "checked" : "")>
89+
<span class="settings-slider"></span>
90+
</label>
91+
<span class="on">On</span>
92+
</div>
8493
<label for="CertPath" class="settings-label">Certificate Path</label>
8594
<input id="CertPath" class="settings-input" type="text" name="CertPath" value="@Model.Configuration.OPCConnection.CertificatePath" readonly>
8695
<label for="CertPassword" class="settings-label">Certificate Password</label>

umatiGateway/Pages/OPCConnection.cshtml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
<label for="OPCPassword" class="settings-label">OPC Password</label>
2323
<input id="OPCPassword" class="settings-input" type="text" name="OpcPassword" data-toggle-group="opc" value="@Model.app.ActiveConfiguration.OPCConnection.Password" @(Model.app.OpcUaClient.IsClientActive() ? "readonly" : "")>
2424
<label for="UseInternalLibs" class="settings-label">UseInternalLibs</label>
25-
<input id="UseInternalLibs" class="settings-input" type="text" name="UseInternalLibs" data-toggle-group="opc" value="@Model.app.ActiveConfiguration.OPCConnection.Password" @(Model.app.OpcUaClient.IsClientActive() ? "readonly" : "")>
25+
<input id="UseInternalLibs" class="settings-input" type="text" name="UseInternalLibs" data-toggle-group="opc" value="@Model.app.ActiveConfiguration.OPCConnection.ReadExtraLibs" @(Model.app.OpcUaClient.IsClientActive() ? "readonly" : "")>
26+
<label for="ResolveBinariesOnly" class="settings-label">Resolve Binaries Only</label>
27+
<input id="ResolveBinariesOnly" class="settings-input" type="text" name="ResolveBinariesOnly" data-toggle-group="opc" value="@Model.app.ActiveConfiguration.OPCConnection.ResolveBinariesOnly" @(Model.app.OpcUaClient.IsClientActive() ? "readonly" : "")>
2628
<label for="CertPath" class="settings-label">Certificate Path</label>
2729
<input id="CertPath" class="settings-input" type="text" name="CertPath" data-toggle-group="opc" value="@Model.app.ActiveConfiguration.OPCConnection.CertificatePath" @(Model.app.OpcUaClient.IsClientActive() ? "readonly" : "")>
2830
<label for="CertPwd" class="settings-label">Certificate Password</label>
@@ -69,6 +71,7 @@
6971
const user = document.getElementById('OPCUser').value;
7072
const password = document.getElementById('OPCPassword').value;
7173
const useInternalLibs = document.getElementById('UseInternalLibs').value;
74+
const resolveBinariesOnly = document.getElementById('ResolveBinariesOnly').value;
7275
const certPath = document.getElementById('CertPath').value;
7376
const certPwd = document.getElementById('CertPwd').value;
7477
@@ -82,6 +85,7 @@
8285
User: user,
8386
Password: password,
8487
UseInternalLibs: useInternalLibs,
88+
ResolveBinariesOnly: resolveBinariesOnly,
8589
CertPath: certPath,
8690
CertPwd: certPwd
8791
})
@@ -145,6 +149,7 @@
145149
document.getElementById("OPCUser").value = data.OpcUser;
146150
document.getElementById("OPCPassword").value = data.OpcPassword;
147151
document.getElementById("UseInternalLibs").value = data.UseInternalLibs;
152+
document.getElementById("ResolveBinariesOnly").value = data.ResolveBinariesOnly;
148153
document.getElementById("CertPath").value = data.CertPath;
149154
document.getElementById("CertPwd").value = data.CertPwd;
150155
document.getElementById("ConnectionStatus").value = data.ConnectionState;

0 commit comments

Comments
 (0)