diff --git a/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/ComplexTypeSystem.cs b/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/ComplexTypeSystem.cs index d2b8c27bcb..d045fed070 100644 --- a/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/ComplexTypeSystem.cs +++ b/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/ComplexTypeSystem.cs @@ -110,9 +110,12 @@ namespace Opc.Ua.Client.ComplexTypes } // load server types - if (!LoadBaseDataTypes(serverEnumTypes, serverStructTypes)) + if (DisableDataTypeDefinition || !LoadBaseDataTypes(serverEnumTypes, serverStructTypes)) { - await LoadDictionaryDataTypes(serverEnumTypes, serverStructTypes, false).ConfigureAwait(false); + if (!DisableDataTypeDictionary) + { + await LoadDictionaryDataTypes(serverEnumTypes, serverStructTypes, false).ConfigureAwait(false); + } } } return GetSystemType(nodeId); @@ -153,8 +156,12 @@ namespace Opc.Ua.Client.ComplexTypes serverEnumTypes = serverEnumTypes.Where(rd => rd.NodeId.NamespaceIndex == nameSpaceIndex).ToList(); serverStructTypes = serverStructTypes.Where(rd => rd.NodeId.NamespaceIndex == nameSpaceIndex).ToList(); // load types - if (!LoadBaseDataTypes(serverEnumTypes, serverStructTypes)) + if (DisableDataTypeDefinition || !LoadBaseDataTypes(serverEnumTypes, serverStructTypes)) { + if (DisableDataTypeDictionary) + { + return false; + } return await LoadDictionaryDataTypes(serverEnumTypes, serverStructTypes, false).ConfigureAwait(false); } return true; @@ -193,8 +200,12 @@ namespace Opc.Ua.Client.ComplexTypes // load server types IList serverEnumTypes = LoadDataTypes(DataTypeIds.Enumeration); IList serverStructTypes = onlyEnumTypes ? new List() : LoadDataTypes(DataTypeIds.Structure, true); - if (!LoadBaseDataTypes(serverEnumTypes, serverStructTypes)) + if (DisableDataTypeDefinition || !LoadBaseDataTypes(serverEnumTypes, serverStructTypes)) { + if (DisableDataTypeDictionary) + { + return false; + } return await LoadDictionaryDataTypes(serverEnumTypes, serverStructTypes, true).ConfigureAwait(false); } return true; @@ -219,6 +230,18 @@ namespace Opc.Ua.Client.ComplexTypes } #endregion + #region Internal Properties + /// + /// Disable the use of DataTypeDefinition to create the complex type definition. + /// + internal bool DisableDataTypeDefinition { get; set; } = false; + + /// + /// Disable the use of DataType Dictinaries to create the complex type definition. + /// + internal bool DisableDataTypeDictionary { get; set; } = false; + #endregion + #region Private Members /// /// Load listed custom types from dictionaries @@ -322,7 +345,11 @@ namespace Opc.Ua.Client.ComplexTypes } // Use DataTypeDefinition attribute, if available (>=V1.04) - StructureDefinition structureDefinition = GetStructureDefinition(dataTypeNode); + StructureDefinition structureDefinition = null; + if (!DisableDataTypeDefinition) + { + structureDefinition = GetStructureDefinition(dataTypeNode); + } if (structureDefinition == null) { try @@ -364,7 +391,7 @@ namespace Opc.Ua.Client.ComplexTypes complexType = AddStructuredType( complexTypeBuilder, structureDefinition, - dataTypeNode.BrowseName.Name, + dataTypeNode.BrowseName, typeId, binaryEncodingId, xmlEncodingId @@ -560,7 +587,7 @@ namespace Opc.Ua.Client.ComplexTypes newType = AddStructuredType( complexTypeBuilder, structureDefinition, - dataTypeNode.BrowseName.Name, + dataTypeNode.BrowseName, structType.NodeId, binaryEncodingId, xmlEncodingId @@ -635,11 +662,25 @@ namespace Opc.Ua.Client.ComplexTypes { return null; } + // Validate the structure according to Part3, Table 36 foreach (var field in structureDefinition.Fields) { + // validate if the DataTypeDefinition is correctly + // filled out, some servers don't do it yet... if (field.BinaryEncodingId.IsNull || field.DataType.IsNullNodeId || - field.TypeId.IsNull) + field.TypeId.IsNull || + field.Name == null) + { + return null; + } + if (!(field.ValueRank == -1 || + field.ValueRank >= 1)) + { + return null; + } + if (structureDefinition.StructureType == StructureType.Structure && + field.IsOptional) { return null; } @@ -678,6 +719,7 @@ namespace Opc.Ua.Client.ComplexTypes /// /// /// + /// /// true if successful, false otherwise private bool BrowseTypeIdsForDictionaryComponent( NodeId nodeId, @@ -977,7 +1019,7 @@ namespace Opc.Ua.Client.ComplexTypes Type newType = null; if (enumTypeNode != null) { - string name = enumTypeNode.BrowseName.Name; + QualifiedName name = enumTypeNode.BrowseName; if (enumTypeNode.DataTypeDefinition != null) { // 1. use DataTypeDefinition @@ -1014,7 +1056,7 @@ namespace Opc.Ua.Client.ComplexTypes private Type AddStructuredType( IComplexTypeBuilder complexTypeBuilder, StructureDefinition structureDefinition, - string typeName, + QualifiedName typeName, ExpandedNodeId complexTypeId, ExpandedNodeId binaryEncodingId, ExpandedNodeId xmlEncodingId @@ -1183,13 +1225,13 @@ namespace Opc.Ua.Client.ComplexTypes } } } -#endregion + #endregion -#region Private Fields + #region Private Fields private Session m_session; private IComplexTypeFactory m_complexTypeBuilderFactory; private string[] m_supportedEncodings = new string[] { BrowseNames.DefaultBinary, BrowseNames.DefaultXml, BrowseNames.DefaultJson }; private const string kOpcComplexTypesPrefix = "Opc.Ua.ComplexTypes."; -#endregion + #endregion } }//namespace diff --git a/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/IComplexTypeFactory.cs b/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/IComplexTypeFactory.cs index d4a8598c38..99feeb13cf 100644 --- a/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/IComplexTypeFactory.cs +++ b/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/IComplexTypeFactory.cs @@ -73,26 +73,26 @@ namespace Opc.Ua.Client.ComplexTypes /// Create an enum type from an EnumDefinition in an ExtensionObject. /// Available since OPC UA V1.04 in the DataTypeDefinition attribute. /// - Type AddEnumType(string typeName, ExtensionObject typeDefinition); + Type AddEnumType(QualifiedName typeName, ExtensionObject typeDefinition); /// /// Create an enum type from an EnumValue property of a DataType node. /// Available before OPC UA V1.04. /// - Type AddEnumType(string typeName, ExtensionObject[] enumDefinition); + Type AddEnumType(QualifiedName typeName, ExtensionObject[] enumDefinition); /// /// Create an enum type from the EnumString array of a DataType node. /// Available before OPC UA V1.04. /// - Type AddEnumType(string typeName, LocalizedText[] enumDefinition); + Type AddEnumType(QualifiedName typeName, LocalizedText[] enumDefinition); /// /// Create a complex type from a StructureDefinition. /// Available since OPC UA V1.04 in the DataTypeDefinition attribute. /// IComplexTypeFieldBuilder AddStructuredType( - string name, + QualifiedName name, StructureDefinition structureDefinition); } diff --git a/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/Opc.Ua.Client.ComplexTypes.csproj b/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/Opc.Ua.Client.ComplexTypes.csproj index 84c69697dc..a35cbc5e50 100644 --- a/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/Opc.Ua.Client.ComplexTypes.csproj +++ b/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/Opc.Ua.Client.ComplexTypes.csproj @@ -14,6 +14,10 @@ + + $(DefineConstants);SIGNASSEMBLY + + diff --git a/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/Properties/AssemblyInfo.cs b/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..4a0af6d91b --- /dev/null +++ b/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/Properties/AssemblyInfo.cs @@ -0,0 +1,24 @@ +/* Copyright (c) 1996-2019 The OPC Foundation. All rights reserved. + The source code in this file is covered under a dual-license scenario: + - RCL: for OPC Foundation members in good-standing + - GPL V2: everybody else + RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/ + GNU General Public License as published by the Free Software Foundation; + version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2 + This source code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ +using System.Runtime.CompilerServices; + +#if SIGNASSEMBLY +[assembly: InternalsVisibleTo("Opc.Ua.Client.ComplexTypes.Tests, PublicKey = " + + // OPC Foundation Strong Name Public Key + "0024000004800000940000000602000000240000525341310004000001000100d987b12f068b35" + + "80429f3dde01397508880fc7e62621397618456ca1549aeacfbdb90c62adfe918f05ce3677b390" + + "f78357b8745cb6e1334655afce1a9527ac92fc829ff585ea79f007e52ba0f83ead627e3edda40b" + + "ec5ae574128fc9342cb57cb8285aa4e5b589c0ebef3be571b5c8f2ab1067f7c880e8f8882a73c8" + + "0a12a1ef")] +#else +[assembly: InternalsVisibleTo("Opc.Ua.Client.ComplexTypes.Tests")] +#endif diff --git a/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeBuilder.cs b/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeBuilder.cs index d20c586e04..1f0a5c6dcf 100644 --- a/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeBuilder.cs +++ b/SampleApplications/SDK/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeBuilder.cs @@ -90,7 +90,7 @@ namespace Opc.Ua.Client.ComplexTypes /// Create an enum type from an EnumDefinition in an ExtensionObject. /// Available since OPC UA V1.04 in the DataTypeDefinition attribute. /// - public Type AddEnumType(string typeName, ExtensionObject typeDefinition) + public Type AddEnumType(QualifiedName typeName, ExtensionObject typeDefinition) { var enumDefinition = typeDefinition.Body as EnumDefinition; if (enumDefinition == null) @@ -115,7 +115,7 @@ namespace Opc.Ua.Client.ComplexTypes /// Create an enum type from an EnumValue property of a DataType node. /// Available before OPC UA V1.04. /// - public Type AddEnumType(string typeName, ExtensionObject[] enumDefinition) + public Type AddEnumType(QualifiedName typeName, ExtensionObject[] enumDefinition) { if (enumDefinition == null) { @@ -141,7 +141,7 @@ namespace Opc.Ua.Client.ComplexTypes /// Create an enum type from the EnumString array of a DataType node. /// Available before OPC UA V1.04. /// - public Type AddEnumType(string typeName, LocalizedText[] enumDefinition) + public Type AddEnumType(QualifiedName typeName, LocalizedText[] enumDefinition) { if (enumDefinition == null) { @@ -169,7 +169,7 @@ namespace Opc.Ua.Client.ComplexTypes /// Available since OPC UA V1.04 in the DataTypeDefinition attribute. /// public IComplexTypeFieldBuilder AddStructuredType( - string name, + QualifiedName name, StructureDefinition structureDefinition) { if (structureDefinition == null) @@ -212,9 +212,18 @@ namespace Opc.Ua.Client.ComplexTypes return moduleName; } - private string GetFullQualifiedTypeName(string name) + /// + /// Creates a unique full qualified type name for the assembly. + /// + /// The browse name of the type. + private string GetFullQualifiedTypeName(QualifiedName browseName) { - return "Opc.Ua.ComplexTypes." + m_moduleName + "." + name; + var result = "Opc.Ua.ComplexTypes." + m_moduleName + "."; + if (browseName.NamespaceIndex > 1) + { + result += browseName.NamespaceIndex + "."; + } + return result + browseName.Name; } #endregion diff --git a/SampleApplications/Samples/ClientControls.Net4/Common/ClientUtils.cs b/SampleApplications/Samples/ClientControls.Net4/Common/ClientUtils.cs index db3be707fd..3ca6e63cf3 100644 --- a/SampleApplications/Samples/ClientControls.Net4/Common/ClientUtils.cs +++ b/SampleApplications/Samples/ClientControls.Net4/Common/ClientUtils.cs @@ -27,18 +27,7 @@ * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Data; -using System.Text; using System.Windows.Forms; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Opc.Ua.Configuration; namespace Opc.Ua.Client.Controls { @@ -72,7 +61,7 @@ namespace Opc.Ua.Client.Controls private const int ArrayValue = 14; private const int InputArgument = 15; private const int OutputArgument = 16; - + /// /// Returns an image index for the specified method argument. /// @@ -89,6 +78,7 @@ namespace Opc.Ua.Client.Controls /// /// Returns an image index for the specified attribute. /// + #pragma warning disable 0162 public static int GetImageIndex(uint attributeId, object value) { // Workaround to avoid exception when accessing ImageList diff --git a/Stack/Opc.Ua.Core/Security/Certificates/RsaUtils.cs b/Stack/Opc.Ua.Core/Security/Certificates/RsaUtils.cs index 877729f0fc..b2ee2f697c 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/RsaUtils.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/RsaUtils.cs @@ -388,7 +388,7 @@ namespace Opc.Ua /// Lazy helper to allow runtime to check for Pss support. /// internal static readonly Lazy IsSupportingRSAPssSign = new Lazy(() => { -#if NET46 || NET461 || NET47 +#if NET46 || NET461 || NET462 || NET47 // The Pss check returns false on .Net4.6/4.7, although it is always supported with certs. // but not supported with Mono return !Utils.IsRunningOnMono(); @@ -417,6 +417,6 @@ namespace Opc.Ua rsa.Dispose(); } } -#endregion + #endregion } } diff --git a/Stack/Opc.Ua.Core/Types/Utils/TypeInfo.cs b/Stack/Opc.Ua.Core/Types/Utils/TypeInfo.cs index d1e80debc0..ee5b71216c 100644 --- a/Stack/Opc.Ua.Core/Types/Utils/TypeInfo.cs +++ b/Stack/Opc.Ua.Core/Types/Utils/TypeInfo.cs @@ -514,8 +514,40 @@ namespace Opc.Ua case DataTypes.Number: { return typeof(Variant); } case DataTypes.Integer: { return typeof(Variant); } case DataTypes.UInteger: { return typeof(Variant); } - case DataTypes.UtcTime: { return typeof(DateTime); } case DataTypes.Enumeration: { return typeof(Int32); } + + // subtype of DateTime + case DataTypes.Date: + case DataTypes.UtcTime: goto case DataTypes.DateTime; + // subtype of ByteString + case DataTypes.ApplicationInstanceCertificate: + case DataTypes.AudioDataType: + case DataTypes.ContinuationPoint: + case DataTypes.Image: + case DataTypes.ImageBMP: + case DataTypes.ImageGIF: + case DataTypes.ImageJPG: + case DataTypes.ImagePNG: goto case DataTypes.ByteString; + // subtype of NodeId + case DataTypes.SessionAuthenticationToken: goto case DataTypes.NodeId; + // subtype of Double + case DataTypes.Duration: goto case DataTypes.Double; + // subtype of UInt32 + case DataTypes.IntegerId: + case DataTypes.Index: + case DataTypes.VersionTime: + case DataTypes.Counter: goto case DataTypes.UInt32; + // subtype of UInt64 + case DataTypes.BitFieldMaskDataType: goto case DataTypes.UInt64; + // subtype of String + case DataTypes.DateString: + case DataTypes.DecimalString: + case DataTypes.DurationString: + case DataTypes.LocaleId: + case DataTypes.NormalizedString: + case DataTypes.NumericRange: + case DataTypes.Time: + case DataTypes.TimeString: goto case DataTypes.String; } return factory.GetSystemType(datatypeId);