diff --git a/src/AasxCsharpLibrary/AdminShellUtil.cs b/src/AasxCsharpLibrary/AdminShellUtil.cs
index 244844e6..e85bfb8b 100644
--- a/src/AasxCsharpLibrary/AdminShellUtil.cs
+++ b/src/AasxCsharpLibrary/AdminShellUtil.cs
@@ -413,6 +413,7 @@ public static ISubmodelElement CreateSubmodelElementFromEnum(AasSubmodelElements
}
#endregion
+
public static string EvalToNonNullString(string fmt, object o, string elseString = "")
{
if (o == null)
@@ -427,6 +428,17 @@ public static string EvalToNonEmptyString(string fmt, string o, string elseStrin
return string.Format(fmt, o);
}
+ ///
+ /// Some syntactic sugar to easily take the first string which has content.
+ ///
+ public static string TakeFirstContent(params string[] choices)
+ {
+ foreach (var c in choices)
+ if (c != null && c.Trim().Length > 0)
+ return c;
+ return "";
+ }
+
///
/// If len of exceeds then
/// string is shortened and returned with an ellipsis(…) at the end.
@@ -789,18 +801,40 @@ public static string WrapLinesAtColumn(string text, int columnLimit)
// Reflection
//
+ ///
+ /// Returns type or the underlying type, if is a Nullable
+ ///
+ public static Type GetTypeOrUnderlyingType(Type type)
+ {
+ var nut = Nullable.GetUnderlyingType(type);
+ if (nut != null)
+ type = nut;
+ return type;
+ }
+
+ ///
+ /// Tries parsing the value, supposedly a string, to a field value
+ /// for reflection of type specific data.
+ /// Works for most scalars, dateTime, string.
+ ///
public static void SetFieldLazyValue(FieldInfo f, object obj, object value)
{
// access
if (f == null || obj == null)
return;
- switch (Type.GetTypeCode(f.FieldType))
+ // 2024-01-04: make function more suitable for
+ switch (Type.GetTypeCode(GetTypeOrUnderlyingType(f.FieldType)))
{
case TypeCode.String:
f.SetValue(obj, "" + value);
break;
+ case TypeCode.DateTime:
+ if (DateTime.TryParse("" + value, out var dt))
+ f.SetValue(obj, dt);
+ break;
+
case TypeCode.Byte:
if (Byte.TryParse("" + value, out var ui8))
f.SetValue(obj, ui8);
@@ -842,12 +876,24 @@ public static void SetFieldLazyValue(FieldInfo f, object obj, object value)
break;
case TypeCode.Single:
+ if (value is double vd)
+ f.SetValue(obj, vd);
+ else
+ if (value is float vf)
+ f.SetValue(obj, vf);
+ else
if (Single.TryParse("" + value, NumberStyles.Float,
CultureInfo.InvariantCulture, out var sgl))
f.SetValue(obj, sgl);
break;
case TypeCode.Double:
+ if (value is double vd2)
+ f.SetValue(obj, vd2);
+ else
+ if (value is float vf2)
+ f.SetValue(obj, vf2);
+ else
if (Double.TryParse("" + value, NumberStyles.Float,
CultureInfo.InvariantCulture, out var dbl))
f.SetValue(obj, dbl);
@@ -863,6 +909,102 @@ public static void SetFieldLazyValue(FieldInfo f, object obj, object value)
}
}
+ ///
+ /// Rathhe sepcialised: adding a type-specific value to a list
+ /// of type-specific values.
+ /// Works for most scalars, dateTime, string.
+ ///
+ public static void AddToListLazyValue(object obj, object value)
+ {
+ // access
+ if (obj == null)
+ return;
+
+ switch (obj)
+ {
+ case List lstr:
+ lstr.Add("" + value);
+ break;
+
+ case List ldt:
+ if (DateTime.TryParse("" + value, out var dt))
+ ldt.Add(dt);
+ break;
+
+ case List lbyte:
+ if (Byte.TryParse("" + value, out var ui8))
+ lbyte.Add(ui8);
+ break;
+
+ case List lsbyte:
+ if (SByte.TryParse("" + value, out var i8))
+ lsbyte.Add(i8);
+ break;
+
+ case List li16:
+ if (Int16.TryParse("" + value, out var i16))
+ li16.Add(i16);
+ break;
+
+ case List li32:
+ if (Int32.TryParse("" + value, out var i32))
+ li32.Add(i32);
+ break;
+
+ case List li64:
+ if (Int64.TryParse("" + value, out var i64))
+ li64.Add(i64);
+ break;
+
+ case List lui16:
+ if (UInt16.TryParse("" + value, out var ui16))
+ lui16.Add(ui16);
+ break;
+
+ case List lui32:
+ if (UInt32.TryParse("" + value, out var ui32))
+ lui32.Add(ui32);
+ break;
+
+ case List lui64:
+ if (UInt64.TryParse("" + value, out var ui64))
+ lui64.Add(ui64);
+ break;
+
+ case List lfloat:
+ if (value is double vd)
+ lfloat.Add((float) vd);
+ else
+ if (value is float vf)
+ lfloat.Add(vf);
+ else
+ if (Single.TryParse("" + value, NumberStyles.Float,
+ CultureInfo.InvariantCulture, out var sgl))
+ lfloat.Add(sgl);
+ break;
+
+ case List ldouble:
+ if (value is double vd2)
+ ldouble.Add(vd2);
+ else
+ if (value is float vf2)
+ ldouble.Add(vf2);
+ else
+ if (Double.TryParse("" + value, NumberStyles.Float,
+ CultureInfo.InvariantCulture, out var dbl))
+ ldouble.Add(dbl);
+ break;
+
+ case List lbool:
+ var isFalse = value == null
+ || (value is int vi && vi == 0)
+ || (value is string vs && (vs == "" || vs == "false"))
+ || (value is bool vb && !vb);
+ lbool.Add(!isFalse);
+ break;
+ }
+ }
+
//
// temp file utilities
//
diff --git a/src/AasxCsharpLibrary/Extensions/ExtendReference.cs b/src/AasxCsharpLibrary/Extensions/ExtendReference.cs
index 10a459f6..4026e6cb 100644
--- a/src/AasxCsharpLibrary/Extensions/ExtendReference.cs
+++ b/src/AasxCsharpLibrary/Extensions/ExtendReference.cs
@@ -186,6 +186,9 @@ public static bool Matches(this IReference reference, IReference otherReference,
return match;
}
+ ///
+ /// Useful, if the searched reference will have only on key (e.g. ECLASS properties)
+ ///
public static bool MatchesExactlyOneKey(this IReference reference, IKey key, MatchMode matchMode = MatchMode.Strict)
{
if (key == null || reference.Keys == null || reference.Keys.Count != 1)
diff --git a/src/AasxCsharpLibrary/Extensions/ExtendReferenceList.cs b/src/AasxCsharpLibrary/Extensions/ExtendReferenceList.cs
new file mode 100644
index 00000000..8708236c
--- /dev/null
+++ b/src/AasxCsharpLibrary/Extensions/ExtendReferenceList.cs
@@ -0,0 +1,35 @@
+/*
+Copyright (c) 2018-2023 Festo SE & Co. KG
+Author: Michael Hoffmeister
+
+This source code is licensed under the Apache License 2.0 (see LICENSE.txt).
+
+This source code may use other Open Source software components (see LICENSE.txt).
+*/
+using AdminShellNS.Exceptions;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Extensions
+{
+ public static class ExtendReferenceList
+ {
+ ///
+ /// Useful, if the searched reference will have only on key (e.g. ECLASS properties)
+ ///
+ public static bool MatchesAnyWithExactlyOneKey(this List reflist, IKey key, MatchMode matchMode = MatchMode.Strict)
+ {
+ if (key == null || reflist == null || reflist.Count < 1)
+ {
+ return false;
+ }
+
+ var found = false;
+ foreach (var r in reflist)
+ found = found || r.MatchesExactlyOneKey(key, matchMode);
+
+ return found;
+ }
+ }
+
+}
diff --git a/src/AasxPackageExplorer.sln b/src/AasxPackageExplorer.sln
index b9c9e43a..e4732969 100644
--- a/src/AasxPackageExplorer.sln
+++ b/src/AasxPackageExplorer.sln
@@ -162,6 +162,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AasxPluginContactInformatio
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AasxCore.Samm2_2_0", "AasxCore.Samm2_2_0\AasxCore.Samm2_2_0.csproj", "{DCFD6C2F-A7C5-4AA2-82F3-0D3856E7EA99}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AasxPluginAssetInterfaceDesc", "AasxPluginAssetInterfaceDesc\AasxPluginAssetInterfaceDesc.csproj", "{92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -419,8 +421,8 @@ Global
{6D1A03B2-EBA7-4CE2-9237-DF9AD7128947}.ReleaseWithoutCEF|x64.Build.0 = Release|Any CPU
{6D1A03B2-EBA7-4CE2-9237-DF9AD7128947}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU
{6D1A03B2-EBA7-4CE2-9237-DF9AD7128947}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU
- {042305D7-DB68-4D02-B08F-ED47BBCD705E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {042305D7-DB68-4D02-B08F-ED47BBCD705E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {042305D7-DB68-4D02-B08F-ED47BBCD705E}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {042305D7-DB68-4D02-B08F-ED47BBCD705E}.Debug|Any CPU.Build.0 = Debug|x64
{042305D7-DB68-4D02-B08F-ED47BBCD705E}.Debug|x64.ActiveCfg = Debug|Any CPU
{042305D7-DB68-4D02-B08F-ED47BBCD705E}.Debug|x64.Build.0 = Debug|Any CPU
{042305D7-DB68-4D02-B08F-ED47BBCD705E}.Debug|x86.ActiveCfg = Debug|Any CPU
@@ -1971,6 +1973,36 @@ Global
{DCFD6C2F-A7C5-4AA2-82F3-0D3856E7EA99}.ReleaseWithoutCEF|x64.Build.0 = Release|Any CPU
{DCFD6C2F-A7C5-4AA2-82F3-0D3856E7EA99}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU
{DCFD6C2F-A7C5-4AA2-82F3-0D3856E7EA99}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Debug|x64.Build.0 = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Debug|x86.Build.0 = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugSlow|Any CPU.ActiveCfg = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugSlow|Any CPU.Build.0 = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugSlow|x64.ActiveCfg = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugSlow|x64.Build.0 = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugSlow|x86.ActiveCfg = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugSlow|x86.Build.0 = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugWithoutCEF|Any CPU.ActiveCfg = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugWithoutCEF|Any CPU.Build.0 = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugWithoutCEF|x64.ActiveCfg = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugWithoutCEF|x64.Build.0 = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugWithoutCEF|x86.ActiveCfg = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.DebugWithoutCEF|x86.Build.0 = Debug|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Release|x64.ActiveCfg = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Release|x64.Build.0 = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Release|x86.ActiveCfg = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.Release|x86.Build.0 = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.ReleaseWithoutCEF|Any CPU.ActiveCfg = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.ReleaseWithoutCEF|Any CPU.Build.0 = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.ReleaseWithoutCEF|x64.ActiveCfg = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.ReleaseWithoutCEF|x64.Build.0 = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2035,6 +2067,7 @@ Global
{DA75828B-E5AC-4E9D-AE1F-398F8FF5AE25} = {66D730EB-B9D7-4C3A-8954-0F86240AD612}
{938BB137-DC45-4A84-B0C9-AC46DA321FDB} = {66D730EB-B9D7-4C3A-8954-0F86240AD612}
{DCFD6C2F-A7C5-4AA2-82F3-0D3856E7EA99} = {DDA9C372-F8ED-4099-A53C-01B9333FD985}
+ {92AC5ECF-6DB4-4ABD-8DD4-6EFA0BE65BA8} = {66D730EB-B9D7-4C3A-8954-0F86240AD612}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1AE21162-9541-4B98-A49C-A63B6AD03998}
diff --git a/src/AasxPackageExplorer/debug.MIHO.script b/src/AasxPackageExplorer/debug.MIHO.script
index 2997bd86..27dfc24c 100644
--- a/src/AasxPackageExplorer/debug.MIHO.script
+++ b/src/AasxPackageExplorer/debug.MIHO.script
@@ -11,7 +11,7 @@
Tool("editkey");
Select("Submodel", "First");
// Tool("sammaspectimport", "File", "C:\\HOMI\\Develop\\Aasx\\repo\\samm-test\\Aspect_Example_SML_MLP.ttl");
-Tool("exportpredefineconcepts", "File", "C:\HOMI\Develop\Aasx\repo\aid\new.txt");
+// Tool("exportpredefineconcepts", "File", "C:\HOMI\Develop\Aasx\repo\aid\new.txt");
// Tool("submodelinstancefromsmtconcepts");
// Select("ConceptDescription", "First");
// Select("ConceptDescription", "Next");
diff --git a/src/AasxPackageExplorer/options-debug.MIHO.json b/src/AasxPackageExplorer/options-debug.MIHO.json
index 57406223..7fff4025 100644
--- a/src/AasxPackageExplorer/options-debug.MIHO.json
+++ b/src/AasxPackageExplorer/options-debug.MIHO.json
@@ -33,7 +33,8 @@
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\samm-test\\SMT_and_SAMM_Showcase_v02.aasx",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\samm-test\\Aspect_Example_SML_MLP.ttl",
// "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\8001203_SPAU-P10R-T-R18M-L-PNLK-PNVBA-M8D_060ff64f-9fd2-422d-81ce-b17e49f007c5_work.aasx",
- "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\aid\\2023_AID1.0_Template_Rework_MIHO.aasx",
+ // "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\aid\\2023_AID1.0_Template_Rework_MIHO.aasx",
+ "AasxToLoad": "C:\\HOMI\\Develop\\Aasx\\repo\\aid\\aid-test-2.aasx",
// "AasxRepositoryFn": "C:\\HOMI\\Develop\\Aasx\\repo_Festo_demo_case_V3\\Festo-DemoCase-repo-V3-local.json",
"WindowLeft": 200,
"WindowTop": -1,
@@ -120,6 +121,10 @@
"Args": []
},
*/
+ {
+ "Path": "..\\..\\..\\..\\..\\..\\AasxPluginAssetInterfaceDesc\\bin\\Debug\\net6.0-windows\\AasxPluginAssetInterfaceDesc.dll",
+ "Args": []
+ },
{
"Path": "..\\..\\..\\..\\..\\..\\AasxPluginKnownSubmodels\\bin\\Debug\\net6.0-windows\\AasxPluginKnownSubmodels.dll",
"Args": []
diff --git a/src/AasxPluginAssetInterfaceDesc/AasxPluginAssetInterfaceDesc.csproj b/src/AasxPluginAssetInterfaceDesc/AasxPluginAssetInterfaceDesc.csproj
new file mode 100644
index 00000000..1041bb6d
--- /dev/null
+++ b/src/AasxPluginAssetInterfaceDesc/AasxPluginAssetInterfaceDesc.csproj
@@ -0,0 +1,51 @@
+
+
+ net6.0-windows
+ library
+ false
+ true
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
diff --git a/src/AasxPluginAssetInterfaceDesc/AasxPluginAssetInterfaceDesc.options.json b/src/AasxPluginAssetInterfaceDesc/AasxPluginAssetInterfaceDesc.options.json
new file mode 100644
index 00000000..5cba3995
--- /dev/null
+++ b/src/AasxPluginAssetInterfaceDesc/AasxPluginAssetInterfaceDesc.options.json
@@ -0,0 +1,46 @@
+{
+ "Records": [
+ {
+ "RecordType": 0,
+ "AllowSubmodelSemanticId": [
+ {
+ "type": "Submodel",
+ "local": false,
+ "value": "http://www.admin-shell.io/mtp/v1/submodel",
+ "index": 0,
+ "idType": "IRI"
+ }
+ ]
+ },
+ {
+ "RecordType": 1,
+ "AllowSubmodelSemanticId": [
+ {
+ "type": "Submodel",
+ "local": false,
+ "value": "http://www.admin-shell.io/mtp/v1/mtp-instance-submodel",
+ "index": 0,
+ "idType": "IRI"
+ }
+ ]
+ }
+ ],
+ "SymbolMappings": [
+ {
+ "EClassVersions": null,
+ "EClassClasses": "37010201",
+ "EClassIRDIs": null,
+ "SymbolDefault": "PNID_Festo.manual_valve_active-u-nozzled",
+ "SymbolActive": null,
+ "SymbolIntermediate": null,
+ "Comment": "V003,45fd1be7-d9fe-426a-aec7-ca16a09cb64b"
+ }
+ ],
+ "VisuOptions": {
+ "Background": "#707070",
+ "StateColorActive": "#2020ff",
+ "StateColorNonActive": "#202020",
+ "StateColorForward": "#2020ff",
+ "StateColorReverse": "#20ff20"
+ }
+}
\ No newline at end of file
diff --git a/src/AasxPluginAssetInterfaceDesc/AasxPluginAssetInterfaceDesc.plugin b/src/AasxPluginAssetInterfaceDesc/AasxPluginAssetInterfaceDesc.plugin
new file mode 100644
index 00000000..3beebdf2
--- /dev/null
+++ b/src/AasxPluginAssetInterfaceDesc/AasxPluginAssetInterfaceDesc.plugin
@@ -0,0 +1 @@
+This file tags the according .ddl to be a plug-in for AasxPackageExplorer.
\ No newline at end of file
diff --git a/src/AasxPluginAssetInterfaceDesc/AidInterfaceStatus.cs b/src/AasxPluginAssetInterfaceDesc/AidInterfaceStatus.cs
new file mode 100644
index 00000000..cd804d39
--- /dev/null
+++ b/src/AasxPluginAssetInterfaceDesc/AidInterfaceStatus.cs
@@ -0,0 +1,337 @@
+/*
+Copyright (c) 2018-2023 Festo SE & Co. KG
+Author: Michael Hoffmeister
+
+This source code is licensed under the Apache License 2.0 (see LICENSE.txt).
+
+This source code may use other Open Source software components (see LICENSE.txt).
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AasxPredefinedConcepts;
+using Aas = AasCore.Aas3_0;
+using AdminShellNS;
+using Extensions;
+using WpfMtpControl;
+using AasxIntegrationBase;
+using AasxPredefinedConcepts.AssetInterfacesDescription;
+using FluentModbus;
+using System.Net;
+using System.Text.RegularExpressions;
+using System.Globalization;
+
+namespace AasxPluginAssetInterfaceDescription
+{
+ public enum AidIfxItemKind { Unknown, Property, Action, Event };
+
+ public class AidIfxItemStatus
+ {
+ ///
+ /// Which kind of information: Property, Action, Event.
+ ///
+ public AidIfxItemKind Kind = AidIfxItemKind.Unknown;
+
+ ///
+ /// Contains the hierarchy information, where the item is stored in hierarchy
+ /// of the given interface (end-point).
+ ///
+ public string Location = "";
+
+ ///
+ /// Display name of the item. Could be from IdShort, key, title.
+ ///
+ public string DisplayName = "";
+
+ ///
+ /// Contains the forms information with all detailed information for the
+ /// technology.
+ ///
+ public CD_Forms FormData = null;
+
+ ///
+ /// String data for value incl. unit information.
+ ///
+ public string Value = "";
+
+ ///
+ /// Link to entity (property, action, event).
+ ///
+ public object Tag = null;
+ }
+
+ public enum AidInterfaceTechnology { HTTP, Modbus, MQTT }
+
+ public class AidInterfaceStatus
+ {
+ ///
+ /// Technology being used ..
+ ///
+ public AidInterfaceTechnology Technology = AidInterfaceTechnology.HTTP;
+
+ ///
+ /// Display name. Could be from SMC IdShort or title.
+ /// Will be printed in bold.
+ ///
+ public string DisplayName = "";
+
+ ///
+ /// Further infornation. Printed in light appearence.
+ ///
+ public string Info = "";
+
+ ///
+ /// The information items (properties, actions, events)
+ ///
+ public List Items = new List();
+
+ ///
+ /// Base connect information.
+ ///
+ public string EndpointBase = "";
+
+ ///
+ /// Link to entity (interface).
+ ///
+ public object Tag = null;
+
+ ///
+ /// Holds the technology connection currently used.
+ ///
+ public AidModbusConnection Connection = null;
+ }
+
+ public class AidModbusConnection
+ {
+ public Uri TargetUri;
+
+ public ModbusTcpClient Client;
+
+ public DateTime LastActive = default(DateTime);
+
+ public bool Open()
+ {
+ try
+ {
+ Client = new ModbusTcpClient();
+ Client.Connect(new IPEndPoint(IPAddress.Parse(TargetUri.Host), TargetUri.Port));
+ LastActive = DateTime.Now;
+ return true;
+ } catch (Exception ex)
+ {
+ Client = null;
+ return false;
+ }
+ }
+
+ public bool IsConnected()
+ {
+ return Client != null && Client.IsConnected;
+ }
+
+ public void Close()
+ {
+ if (IsConnected())
+ {
+ Client.Disconnect();
+ Client = null;
+ }
+ else
+ {
+ Client = null;
+ }
+ }
+
+ public void UpdateItemValue(AidModbusConnection conn, AidIfxItemStatus item)
+ {
+ // access
+ if (item?.FormData?.Href?.HasContent() != true
+ || item.FormData.Modbus_function?.HasContent() != true)
+ return;
+
+ // decode address + quantity
+ // (assumption: 1 quantity = 2 bytes)
+ var match = Regex.Match(item.FormData.Href, @"^(\d{1,5})(\?quantity=(\d+))?$");
+ if (!match.Success)
+ return;
+
+ if (!int.TryParse(match.Groups[1].ToString(), out var address))
+ return;
+ if (!int.TryParse(match.Groups[3].ToString(), out var quantity))
+ quantity = 1;
+ quantity = Math.Max(0, Math.Min(0xffff, quantity));
+
+ // perform function (id = in data)
+ byte[] id = null;
+ if (item.FormData.Modbus_function.Trim().ToLower() == "readholdingregisters")
+ {
+ // readHoldingRegisters
+ id = conn.Client.ReadHoldingRegisters(99, address, quantity).ToArray();
+ // time
+ conn.LastActive = DateTime.Now;
+ }
+
+ // success with reading?
+ if (id == null || id.Length < 1)
+ return;
+
+ // swapping (od = out data)
+ // https://doc.iobroker.net/#de/adapters/adapterref/iobroker.modbus/README.md?wp
+ var mbtp = item.FormData.Modbus_type?.ToLower().Trim();
+ byte[] od = id.ToArray();
+ if (quantity == 2)
+ {
+ // 32bit operation on AABBCCDD
+ if (mbtp.EndsWith("be"))
+ {
+ // big endian AABBCCDD => AABBCCDD
+ od[3] = id[3]; od[2] = id[2]; od[1] = id[1]; od[0] = id[0];
+ }
+ else
+ if (mbtp.EndsWith("le"))
+ {
+ // little endian AABBCCDD => DDCCBBAA
+ od[3] = id[0]; od[2] = id[1]; od[1] = id[2]; od[0] = id[3];
+ }
+ else
+ if (mbtp.EndsWith("sw"))
+ {
+ // Big Endian Word Swap AABBCCDD => CCDDAABB
+ od[3] = id[2]; od[2] = id[3]; od[1] = id[0]; od[0] = id[1];
+ }
+ else
+ if (mbtp.EndsWith("sb"))
+ {
+ // Big Endian Byte Swap AABBCCDD => DDCCBBAA
+ od[3] = id[0]; od[2] = id[1]; od[1] = id[2]; od[0] = id[3];
+ }
+ }
+ else
+ if (quantity == 1)
+ {
+ // 16bit operation on AABB
+ if (mbtp.EndsWith("le"))
+ {
+ // little endian AABB => BBAA
+ od[1] = id[0]; od[0] = id[1];
+ }
+ }
+
+ // conversion to value
+ // idea: (1) convert to binary type, (2) convert to adequate string representation
+ var strval = "";
+ if (mbtp.StartsWith("uint32") && quantity >= 2)
+ {
+ strval = BitConverter.ToUInt32(od).ToString();
+ }
+ else
+ if (mbtp.StartsWith("int32") && quantity >= 2)
+ {
+ strval = BitConverter.ToInt32(od).ToString();
+ }
+ else
+ if (mbtp.StartsWith("uint16") && quantity >= 1)
+ {
+ strval = BitConverter.ToUInt16(od).ToString();
+ }
+ else
+ if (mbtp.StartsWith("int16") && quantity >= 1)
+ {
+ strval = BitConverter.ToInt16(od).ToString();
+ }
+ else
+ if (mbtp.StartsWith("uint8") && quantity >= 1)
+ {
+ strval = Convert.ToByte(od[0]).ToString();
+ }
+ else
+ if (mbtp.StartsWith("int8") && quantity >= 1)
+ {
+ strval = Convert.ToSByte(od[0]).ToString();
+ }
+ else
+ if (mbtp.StartsWith("float") && quantity >= 2)
+ {
+ strval = BitConverter.ToSingle(od).ToString("R", CultureInfo.InvariantCulture);
+ }
+ else
+ if (mbtp.StartsWith("double") && quantity >= 4)
+ {
+ strval = BitConverter.ToDouble(od).ToString("R", CultureInfo.InvariantCulture);
+ }
+ else
+ if (mbtp.StartsWith("string") && quantity >= 1)
+ {
+ strval = BitConverter.ToString(od);
+ }
+
+ // save in item
+ item.Value = strval;
+ }
+ }
+
+ public class AidModbusConnections : Dictionary
+ {
+ public AidModbusConnection GetOrCreate(string target)
+ {
+ if (!Uri.TryCreate(target, UriKind.Absolute, out var uri))
+ return null;
+ if (this.ContainsKey(uri))
+ return this[uri];
+
+ var conn = new AidModbusConnection() { TargetUri = uri };
+ return conn;
+ }
+ }
+
+ ///
+ /// Holds track of all current Aid interface status information.
+ /// Idea: well be preset and updated by plug-in events.
+ /// Will then allow technical connect to asset interfaces.
+ /// Will exist **longer** than the invocation of just the plugin UI.
+ ///
+ public class AidAllInterfaceStatus
+ {
+ public List InterfaceStatus = new List();
+
+ public AidModbusConnections ModbusConnections = new AidModbusConnections();
+
+ ///
+ /// Will connect to each target once, get values and will disconnect again.
+ ///
+ public void UpdateValuesSingleShot()
+ {
+ // Modbus
+ // Open, connect and read all connections
+ foreach (var ifc in InterfaceStatus.Where((i) => i.Technology == AidInterfaceTechnology.Modbus))
+ {
+ // get a connection
+ if (ifc.EndpointBase?.HasContent() != true)
+ continue;
+ var conn = ModbusConnections.GetOrCreate(ifc.EndpointBase);
+ if (conn == null)
+ continue;
+
+ // open it
+ if (!conn.Open())
+ continue;
+ ifc.Connection = conn;
+
+ // go thru all items
+ foreach (var item in ifc.Items)
+ conn.UpdateItemValue(conn, item);
+ }
+
+ // close all connections
+ foreach (var ifc in InterfaceStatus.Where((i) => i.Technology == AidInterfaceTechnology.Modbus))
+ {
+ if (ifc.Connection?.IsConnected() == true)
+ ifc.Connection.Close();
+ }
+ }
+ }
+
+}
diff --git a/src/AasxPluginAssetInterfaceDesc/AssetInterfaceAnyUiControl.cs b/src/AasxPluginAssetInterfaceDesc/AssetInterfaceAnyUiControl.cs
new file mode 100644
index 00000000..aa2ddcf2
--- /dev/null
+++ b/src/AasxPluginAssetInterfaceDesc/AssetInterfaceAnyUiControl.cs
@@ -0,0 +1,437 @@
+/*
+Copyright (c) 2018-2023 Festo SE & Co. KG
+Author: Michael Hoffmeister
+
+This source code is licensed under the Apache License 2.0 (see LICENSE.txt).
+
+This source code may use other Open Source software components (see LICENSE.txt).
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using AasxIntegrationBase;
+using Aas = AasCore.Aas3_0;
+using AdminShellNS;
+using Extensions;
+using AnyUi;
+using Newtonsoft.Json;
+using AasxPredefinedConcepts;
+using AasxPredefinedConcepts.AssetInterfacesDescription;
+using System.Windows.Shapes;
+using AasxIntegrationBaseGdi;
+using FluentModbus;
+using System.Net;
+
+namespace AasxPluginAssetInterfaceDescription
+{
+ public class AssetInterfaceAnyUiControl
+ {
+ #region Members
+ //=============
+
+ private LogInstance _log = new LogInstance();
+ private AdminShellPackageEnv _package = null;
+ private Aas.Submodel _submodel = null;
+ private AssetInterfaceOptions _options = null;
+ private PluginEventStack _eventStack = null;
+ private AnyUiStackPanel _panel = null;
+
+ private AidAllInterfaceStatus _allInterfaceStatus = null;
+
+ protected AnyUiSmallWidgetToolkit _uitk = new AnyUiSmallWidgetToolkit();
+
+ protected Dictionary _dictTechnologyToBitmap =
+ new Dictionary();
+
+ #endregion
+
+ #region Members to be kept for state/ update
+ //=============
+
+ protected double _lastScrollPosition = 0.0;
+
+ protected int _selectedLangIndex = 0;
+ protected string _selectedLangStr = null;
+
+ #endregion
+
+ #region Constructors
+ //=============
+
+ // ReSharper disable EmptyConstructor
+ public AssetInterfaceAnyUiControl()
+ {
+ }
+ // ReSharper enable EmptyConstructor
+
+ public void Start(
+ LogInstance log,
+ AdminShellPackageEnv thePackage,
+ Aas.Submodel theSubmodel,
+ AssetInterfaceOptions theOptions,
+ PluginEventStack eventStack,
+ AnyUiStackPanel panel,
+ AidAllInterfaceStatus ifxStatus)
+ {
+ // internal members
+ _log = log;
+ _package = thePackage;
+ _submodel = theSubmodel;
+ _options = theOptions;
+ _eventStack = eventStack;
+ _panel = panel;
+ _allInterfaceStatus = ifxStatus;
+
+ // some required logos
+ _dictTechnologyToBitmap = new Dictionary();
+ if (OperatingSystem.IsWindowsVersionAtLeast(7))
+ {
+ _dictTechnologyToBitmap.Add(AidInterfaceTechnology.HTTP,
+ AnyUiGdiHelper.CreateAnyUiBitmapFromResource(
+ "AasxPluginAssetInterfaceDesc.Resources.logo-http.png",
+ assembly: Assembly.GetExecutingAssembly()));
+ _dictTechnologyToBitmap.Add(AidInterfaceTechnology.Modbus,
+ AnyUiGdiHelper.CreateAnyUiBitmapFromResource(
+ "AasxPluginAssetInterfaceDesc.Resources.logo-modbus.png",
+ assembly: Assembly.GetExecutingAssembly()));
+ _dictTechnologyToBitmap.Add(AidInterfaceTechnology.MQTT,
+ AnyUiGdiHelper.CreateAnyUiBitmapFromResource(
+ "AasxPluginAssetInterfaceDesc.Resources.logo-mqqt.png",
+ assembly: Assembly.GetExecutingAssembly()));
+ }
+
+ // fill given panel
+ RenderFullView(_panel, _uitk, _package, _submodel);
+ }
+
+ public static AssetInterfaceAnyUiControl FillWithAnyUiControls(
+ LogInstance log,
+ object opackage, object osm,
+ AssetInterfaceOptions options,
+ PluginEventStack eventStack,
+ object opanel,
+ AidAllInterfaceStatus ifxStatus)
+ {
+ // access
+ var package = opackage as AdminShellPackageEnv;
+ var sm = osm as Aas.Submodel;
+ var panel = opanel as AnyUiStackPanel;
+ if (package == null || sm == null || panel == null)
+ return null;
+
+ // the Submodel elements need to have parents
+ sm.SetAllParents();
+
+ // factory this object
+ var aidCntl = new AssetInterfaceAnyUiControl();
+ aidCntl.Start(log, package, sm, options, eventStack, panel, ifxStatus);
+
+ // return shelf
+ return aidCntl;
+ }
+
+ #endregion
+
+ #region Display Submodel
+ //=============
+
+ private void RenderFullView(
+ AnyUiStackPanel view, AnyUiSmallWidgetToolkit uitk,
+ AdminShellPackageEnv package,
+ Aas.Submodel sm)
+ {
+ // test trivial access
+ if (_options == null || _submodel?.SemanticId == null)
+ return;
+
+ // make sure for the right Submodel
+ var foundRecs = new List();
+ foreach (var rec in _options.LookupAllIndexKey(
+ _submodel?.SemanticId?.GetAsExactlyOneKey()))
+ foundRecs.Add(rec);
+
+ // render
+ RenderPanelOutside(view, uitk, foundRecs, package, sm);
+ }
+
+ protected void RenderPanelOutside(
+ AnyUiStackPanel view, AnyUiSmallWidgetToolkit uitk,
+ IEnumerable foundRecs,
+ AdminShellPackageEnv package,
+ Aas.Submodel sm)
+ {
+ // make an outer grid, very simple grid of two rows: header & body
+ var outer = view.Add(uitk.AddSmallGrid(rows: 7, cols: 1, colWidths: new[] { "*" }));
+
+ //
+ // Bluebar
+ //
+
+ var bluebar = uitk.AddSmallGridTo(outer, 0, 0, 1, cols: 5, colWidths: new[] { "*", "#", "#", "#", "#" });
+
+ bluebar.Margin = new AnyUiThickness(0);
+ bluebar.Background = AnyUiBrushes.LightBlue;
+
+ uitk.AddSmallBasicLabelTo(bluebar, 0, 0, margin: new AnyUiThickness(8, 6, 0, 6),
+ foreground: AnyUiBrushes.DarkBlue,
+ fontSize: 1.5f,
+ setBold: true,
+ content: $"Asset Interfaces Descriptions");
+
+ //
+ // Scroll area
+ //
+
+ // small spacer
+ outer.RowDefinitions[1] = new AnyUiRowDefinition(2.0, AnyUiGridUnitType.Pixel);
+ uitk.AddSmallBasicLabelTo(outer, 1, 0,
+ fontSize: 0.3f,
+ verticalAlignment: AnyUiVerticalAlignment.Top,
+ content: "", background: AnyUiBrushes.White);
+
+ // add the body, a scroll viewer
+ outer.RowDefinitions[2] = new AnyUiRowDefinition(1.0, AnyUiGridUnitType.Star);
+ var scroll = AnyUiUIElement.RegisterControl(
+ uitk.AddSmallScrollViewerTo(outer, 2, 0,
+ horizontalScrollBarVisibility: AnyUiScrollBarVisibility.Disabled,
+ verticalScrollBarVisibility: AnyUiScrollBarVisibility.Visible,
+ flattenForTarget: AnyUiTargetPlatform.Browser, initialScrollPosition: _lastScrollPosition),
+ (o) =>
+ {
+ if (o is Tuple positions)
+ {
+ _lastScrollPosition = positions.Item2;
+ }
+ return new AnyUiLambdaActionNone();
+ });
+
+ // content of the scroll viewer
+ // need a stack panel to add inside
+ var inner = new AnyUiStackPanel()
+ {
+ Orientation = AnyUiOrientation.Vertical,
+ Margin = new AnyUiThickness(2)
+ };
+ scroll.Content = inner;
+
+ if (foundRecs != null)
+ foreach (var rec in foundRecs)
+ RenderPanelInner(inner, uitk, rec, package, sm);
+ }
+
+ #endregion
+
+ #region Inner
+ //=============
+
+ protected void RenderPanelInner(
+ AnyUiStackPanel view, AnyUiSmallWidgetToolkit uitk,
+ AssetInterfaceOptionsRecord rec,
+ AdminShellPackageEnv package,
+ Aas.Submodel sm)
+ {
+ // access
+ if (view == null || uitk == null || sm == null || rec == null)
+ return;
+
+ var grid = view.Add(uitk.AddSmallGrid(rows: 3, cols: 2, colWidths: new[] { "110:", "*" }));
+
+ uitk.AddSmallLabelTo(grid, 0, 0, content: "Debug:");
+ AnyUiUIElement.RegisterControl(
+ uitk.AddSmallButtonTo(grid, 0, 1,
+ margin: new AnyUiThickness(2), setHeight: 21,
+ padding: new AnyUiThickness(2, 0, 2, 0),
+ content: "Test .."),
+ (o) =>
+ {
+ try
+ {
+ //var client = new ModbusTcpClient();
+ //client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5020));
+ //var byteData = client.ReadHoldingRegisters(99, 1, 8);
+
+ _allInterfaceStatus?.UpdateValuesSingleShot();
+ }
+ catch (Exception ex)
+ {
+ ;
+ }
+ return new AnyUiLambdaActionNone();
+ });
+
+ // get SM data and
+ _allInterfaceStatus.InterfaceStatus = PrepareAidInformation(sm);
+ RenderTripleRowData(view, uitk, _allInterfaceStatus.InterfaceStatus);
+ }
+
+ #endregion
+
+ #region Update
+ //=============
+
+ public void Update(params object[] args)
+ {
+ // check args
+ if (args == null || args.Length < 1
+ || !(args[0] is AnyUiStackPanel newPanel))
+ return;
+
+ // ok, re-assign panel and re-display
+ _panel = newPanel;
+ _panel.Children.Clear();
+
+ // the default: the full shelf
+ RenderFullView(_panel, _uitk, _package, _submodel);
+ }
+
+ #endregion
+
+ #region Interface items
+ //=====================
+
+ protected List PrepareAidInformation(Aas.Submodel sm)
+ {
+ // access
+ var res = new List();
+ if (sm == null)
+ return res;
+
+ // get data
+ var data = new AasxPredefinedConcepts.AssetInterfacesDescription.CD_AssetInterfacesDescription();
+ PredefinedConceptsClassMapper.ParseAasElemsToObject(_submodel, data);
+
+ // prepare
+ foreach (var tech in AdminShellUtil.GetEnumValues())
+ {
+ var ifxs = data?.InterfaceHTTP;
+ if (tech == AidInterfaceTechnology.Modbus) ifxs = data?.InterfaceMODBUS;
+ if (tech == AidInterfaceTechnology.MQTT) ifxs = data?.InterfaceMQTT;
+ if (ifxs == null || ifxs.Count < 1)
+ continue;
+ foreach (var ifx in ifxs)
+ {
+ // new interface
+ var dn = AdminShellUtil.TakeFirstContent(ifx.Title, ifx.__Info__?.Referable?.IdShort);
+ var aidIfx = new AidInterfaceStatus()
+ {
+ Technology = tech,
+ DisplayName = $"{dn}",
+ Info = $"{ifx.EndpointMetadata?.Base}",
+ EndpointBase = "" + ifx.EndpointMetadata?.Base,
+ Tag = ifx
+ };
+ res.Add(aidIfx);
+
+ // Properties .. lambda recursion
+ Action recurseProp = null;
+ recurseProp = (location, propName) =>
+ {
+ // add item
+ var ifcItem = new AidIfxItemStatus() {
+ Kind = AidIfxItemKind.Property,
+ Location = location,
+ DisplayName = AdminShellUtil.TakeFirstContent(
+ propName.Title, propName.Key, propName.__Info__?.Referable?.IdShort),
+ FormData = propName.Forms,
+ Value = "???"
+ };
+ aidIfx.Items.Add(ifcItem);
+
+ // directly recurse?
+ if (propName?.Properties?.Property != null)
+ foreach (var child in propName.Properties.Property)
+ recurseProp(location + " . " + ifcItem.DisplayName, child);
+ };
+
+ if (ifx.InterfaceMetadata?.Properties?.Property == null)
+ continue;
+ foreach (var propName in ifx.InterfaceMetadata?.Properties?.Property)
+ recurseProp("\u2302", propName);
+ }
+ }
+
+ return res;
+ }
+
+ protected void RenderTripleRowData(
+ AnyUiStackPanel view, AnyUiSmallWidgetToolkit uitk,
+ List interfaces)
+ {
+ // access
+ if (interfaces == null)
+ return;
+
+ // ok
+ var grid = view.Add(uitk.AddSmallGrid(rows: interfaces.Count, cols: 5, colWidths: new[] { "40:", "1*", "1*", "1*", "100:" }));
+ int rowIndex = 0;
+ foreach (var ifx in interfaces)
+ {
+ // heading
+ grid.RowDefinitions.Add(new AnyUiRowDefinition());
+
+ var headGrid = uitk.Set(
+ uitk.AddSmallGridTo(grid, rowIndex++, 0,
+ rows: 1, cols: 3, colWidths: new[] { "#", "#", "#" },
+ margin: new AnyUiThickness(0, 8, 0, 4)),
+ colSpan: 5);
+
+ if (_dictTechnologyToBitmap.ContainsKey(ifx.Technology))
+ uitk.AddSmallImageTo(headGrid, 0, 0,
+ margin: new AnyUiThickness(0, 0, 10, 0),
+ bitmap: _dictTechnologyToBitmap[ifx.Technology]);
+
+ uitk.AddSmallBasicLabelTo(headGrid, 0, 1, fontSize: 1.2f, setBold: true,
+ verticalAlignment: AnyUiVerticalAlignment.Center,
+ verticalContentAlignment: AnyUiVerticalAlignment.Center,
+ content: ifx.DisplayName);
+
+ uitk.AddSmallBasicLabelTo(headGrid, 0, 2, fontSize: 1.2f,
+ margin: new AnyUiThickness(10, 0, 0, 0),
+ verticalAlignment: AnyUiVerticalAlignment.Center,
+ verticalContentAlignment: AnyUiVerticalAlignment.Center,
+ content: ifx.Info);
+
+ // items?
+ if (ifx.Items != null)
+ foreach (var item in ifx.Items)
+ {
+ // normal row, 3 bordered cells
+ grid.RowDefinitions.Add(new AnyUiRowDefinition());
+ var cols = new[] {
+ "Prop.", item.Location, item.DisplayName, "" + item.FormData?.Href, item.Value };
+ for (int ci = 0; ci < 5; ci++)
+ {
+ var brd = uitk.AddSmallBorderTo(grid, rowIndex, ci,
+ margin: (ci == 0) ? new AnyUiThickness(0, -1, 0, 0)
+ : new AnyUiThickness(-1, -1, 0, 0),
+ borderThickness: new AnyUiThickness(1.0), borderBrush: AnyUiBrushes.DarkGray);
+ brd.Child = new AnyUiSelectableTextBlock()
+ {
+ Text = cols[ci],
+ Padding = new AnyUiThickness(3, 1, 3, 1),
+ FontSize = 1.0f,
+ FontWeight = AnyUiFontWeight.Normal
+ };
+ }
+ rowIndex++;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Callbacks
+ //===============
+
+
+ #endregion
+
+ #region Utilities
+ //===============
+
+
+ #endregion
+ }
+}
diff --git a/src/AasxPluginAssetInterfaceDesc/AssetInterfaceOptions.cs b/src/AasxPluginAssetInterfaceDesc/AssetInterfaceOptions.cs
new file mode 100644
index 00000000..71a7a8be
--- /dev/null
+++ b/src/AasxPluginAssetInterfaceDesc/AssetInterfaceOptions.cs
@@ -0,0 +1,50 @@
+/*
+Copyright (c) 2018-2023 Festo SE & Co. KG
+Author: Michael Hoffmeister
+
+This source code is licensed under the Apache License 2.0 (see LICENSE.txt).
+
+This source code may use other Open Source software components (see LICENSE.txt).
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using AasxPredefinedConcepts;
+using Aas = AasCore.Aas3_0;
+using AdminShellNS;
+using Extensions;
+using WpfMtpControl;
+using AasxIntegrationBase;
+
+namespace AasxPluginAssetInterfaceDescription
+{
+ public class AssetInterfaceOptionsRecord : AasxPluginOptionsLookupRecordBase
+ {
+ }
+
+ public class AssetInterfaceOptions : AasxPluginLookupOptionsBase
+ {
+ public List Records = new List();
+
+ ///
+ /// Create a set of minimal options
+ ///
+ public static AssetInterfaceOptions CreateDefault()
+ {
+ var defs = new DefinitionsMTP.ModuleTypePackage();
+
+ var rec1 = new AssetInterfaceOptionsRecord();
+ rec1.AllowSubmodelSemanticId = new[] {
+ new Aas.Key(Aas.KeyTypes.Submodel,
+ "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Submodel") }.ToList();
+
+ var opt = new AssetInterfaceOptions();
+ opt.Records.Add(rec1);
+
+ return opt;
+ }
+ }
+}
diff --git a/src/AasxPluginAssetInterfaceDesc/LICENSE.TXT b/src/AasxPluginAssetInterfaceDesc/LICENSE.TXT
new file mode 100644
index 00000000..21bf04b1
--- /dev/null
+++ b/src/AasxPluginAssetInterfaceDesc/LICENSE.TXT
@@ -0,0 +1,244 @@
+Copyright (c) 2018-2023 Festo SE & Co. KG
+,
+author: Michael Hoffmeister
+
+This software is licensed under the Apache Public License 2.0 (APL-2.0)
+(see below).
+The AutomationML.Engine is licensed under the MIT license (MIT)
+(see below).
+
+This application is a sample application for demonstration of the features
+of the Administration Shell.
+It is not allowed for productive use. The implementation uses the concepts
+of the document "Details of the Asset
+Administration Shell" published on www.plattform-i40.de which is licensed
+under Creative Commons CC BY-ND 3.0 DE.
+
+The MIT License (MIT)
+
+Copyright (c) 2007 James Newton-King
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+(http://www.apache.org/licenses/LICENSE-2.0)
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+
+With respect to AutomationML.Engine
+===================================
+
+(https://raw.githubusercontent.com/AutomationML/AMLEngine2.1/master/license.txt)
+
+The MIT License (MIT)
+
+Copyright 2017 AutomationML e.V.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/src/AasxPluginAssetInterfaceDesc/Opc.Ua.SampleClient.Config.xml b/src/AasxPluginAssetInterfaceDesc/Opc.Ua.SampleClient.Config.xml
new file mode 100644
index 00000000..8c8ea824
--- /dev/null
+++ b/src/AasxPluginAssetInterfaceDesc/Opc.Ua.SampleClient.Config.xml
@@ -0,0 +1,99 @@
+
+
+ UA Core Sample Client
+ urn:localhost:OPCFoundation:CoreSampleClient
+ http://opcfoundation.org/UA/CoreSampleClient
+ Client_1
+
+
+
+
+
+ X509Store
+ CurrentUser\My
+ CN=UA Core Sample Client, C=US, S=Arizona, O=OPC Foundation, DC=localhost
+
+
+
+
+ Directory
+ %LocalApplicationData%/OPC Foundation/pki/issuer
+
+
+
+
+ Directory
+ %LocalApplicationData%/OPC Foundation/pki/trusted
+
+
+
+
+ Directory
+ %LocalApplicationData%/OPC Foundation/pki/rejected
+
+
+
+ false
+
+
+
+
+
+
+ 600000
+ 1048576
+ 4194304
+ 65535
+ 4194304
+ 65535
+ 300000
+ 3600000
+
+
+
+
+
+
+ 600000
+
+
+
+ opc.tcp://{0}:4840/UADiscovery
+
+
+
+
+
+
+ 10000
+
+
+
+ %LocalApplicationData%/Logs/Opc.Ua.CoreSampleClient.log.txt
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
\ No newline at end of file
diff --git a/src/AasxPluginAssetInterfaceDesc/Plugin.cs b/src/AasxPluginAssetInterfaceDesc/Plugin.cs
new file mode 100644
index 00000000..89fd37de
--- /dev/null
+++ b/src/AasxPluginAssetInterfaceDesc/Plugin.cs
@@ -0,0 +1,177 @@
+/*
+Copyright (c) 2018-2023 Festo SE & Co. KG
+Author: Michael Hoffmeister
+
+This source code is licensed under the Apache License 2.0 (see LICENSE.txt).
+
+This source code may use other Open Source software components (see LICENSE.txt).
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Aas = AasCore.Aas3_0;
+using AdminShellNS;
+using Extensions;
+using JetBrains.Annotations;
+using Newtonsoft.Json;
+using AasxPluginAssetInterfaceDescription;
+
+namespace AasxIntegrationBase // the namespace has to be: AasxIntegrationBase
+{
+ [UsedImplicitlyAttribute]
+ // the class names has to be: AasxPlugin and subclassing IAasxPluginInterface
+ public class AasxPlugin : AasxPluginBase
+ {
+ private AasxPluginAssetInterfaceDescription.AssetInterfaceOptions _options
+ = new AasxPluginAssetInterfaceDescription.AssetInterfaceOptions();
+
+ // TODO: make this multi-session!!
+ private AidAllInterfaceStatus _allInterfaceStatus = new AidAllInterfaceStatus();
+
+ public class Session : PluginSessionBase
+ {
+ public AasxPluginAssetInterfaceDescription.AssetInterfaceAnyUiControl AnyUiControl = null;
+ }
+
+ public new void InitPlugin(string[] args)
+ {
+ // start ..
+ PluginName = "AasxPluginAssetInterfaceDescription";
+
+ // .. with built-in options
+ _options = AasxPluginAssetInterfaceDescription.AssetInterfaceOptions.CreateDefault();
+
+ // try load defaults options from assy directory
+ try
+ {
+ var newOpt =
+ AasxPluginOptionsBase
+ .LoadDefaultOptionsFromAssemblyDir(
+ this.GetPluginName(), Assembly.GetExecutingAssembly());
+ if (newOpt != null)
+ _options = newOpt;
+ }
+ catch (Exception ex)
+ {
+ _log.Error(ex, "Exception when reading default options {1}");
+ }
+
+ // index them!
+ _options.IndexListOfRecords(_options.Records);
+ }
+
+ public new object CheckForLogMessage()
+ {
+ return _log.PopLastShortTermPrint();
+ }
+
+ public new AasxPluginActionDescriptionBase[] ListActions()
+ {
+ var res = ListActionsBasicHelper(
+ enableCheckVisualExt: true,
+ enableOptions: true,
+ enableLicenses: true,
+ enablePanelAnyUi: true);
+ return res.ToArray();
+ }
+
+ public new AasxPluginResultBase ActivateAction(string action, params object[] args)
+ {
+ // for speed reasons, have the most often used at top!
+ if (action == "call-check-visual-extension")
+ {
+ // arguments
+ if (args.Length < 1)
+ return null;
+
+ // looking only for Submodels
+ var sm = args[0] as Aas.Submodel;
+ if (sm == null)
+ return null;
+
+ // check for a record in options, that matches Submodel
+ bool found = _options?.ContainsIndexKey(sm?.SemanticId?.GetAsExactlyOneKey()) ?? false;
+ if (!found)
+ return null;
+
+ // success prepare record
+ var cve = new AasxPluginResultVisualExtension("AID", "Asset Interfaces Description");
+
+ // ok
+ return cve;
+ }
+
+ // can basic helper help to reduce lines of code?
+ var help = ActivateActionBasicHelper(action, ref _options, args,
+ enableGetCheckVisuExt: true);
+ if (help != null)
+ return help;
+
+ // rest follows
+
+ if (action == "fill-anyui-visual-extension")
+ {
+ // arguments (package, submodel, panel, display-context, session-id)
+ if (args == null || args.Length < 5)
+ return null;
+
+ // create session and call
+ var session = _sessions.CreateNewSession(args[4]);
+ session.AnyUiControl = AasxPluginAssetInterfaceDescription.AssetInterfaceAnyUiControl.FillWithAnyUiControls(
+ _log, args[0], args[1], _options, _eventStack, args[2], _allInterfaceStatus);
+
+ // give object back
+ var res = new AasxPluginResultBaseObject();
+ res.obj = session.AnyUiControl;
+ return res;
+ }
+
+ if (action == "update-anyui-visual-extension"
+ && _sessions != null)
+ {
+ // arguments (panel, display-context, session-id)
+ if (args == null || args.Length < 3)
+ return null;
+
+ if (_sessions.AccessSession(args[2], out Session session))
+ {
+ // call
+ session.AnyUiControl.Update(args);
+
+ // give object back
+ var res = new AasxPluginResultBaseObject();
+ res.obj = 42;
+ return res;
+ }
+ }
+
+ if (action == "dispose-anyui-visual-extension"
+ && _sessions != null)
+ {
+ // arguments (session-id)
+ if (args == null || args.Length < 1)
+ return null;
+
+ // ReSharper disable UnusedVariable
+ if (_sessions.AccessSession(args[0], out Session session))
+ {
+ // dispose all ressources
+ ;
+
+ // remove
+ _sessions.Remove(args[0]);
+ }
+ // ReSharper enable UnusedVariable
+ }
+
+ // default
+ return null;
+ }
+
+ }
+}
diff --git a/src/AasxPluginAssetInterfaceDesc/Resources/LICENSE.TXT b/src/AasxPluginAssetInterfaceDesc/Resources/LICENSE.TXT
new file mode 100644
index 00000000..fc70527e
--- /dev/null
+++ b/src/AasxPluginAssetInterfaceDesc/Resources/LICENSE.TXT
@@ -0,0 +1,651 @@
+Copyright (c) 2018-2023 Festo SE & Co. KG , author: Michael Hoffmeister
+Copyright (c) 2019 PHOENIX CONTACT GmbH & Co. KG , author: Andreas Orzelski
+This software is licensed under the Eclipse Public License 2.0 (EPL-2.0) (see below)
+The browser functionality is licensed under the cefSharp license (see below)
+The Newtonsoft.JSON serialization is licensed under the MIT License (MIT) (see below)
+The QR code generation is licensed under the MIT license (MIT) (see below)
+The Zxing.Net Dot Matrix Code (DMC) generation is licensed under the Apache License 2.0 (Apache-2.0) (see below)
+The Grapevine REST server framework is licensed under Apache License 2.0 (Apache-2.0) (see below)
+The AutomationML.Engine is licensed under the MIT license (MIT) (see below)
+The MQTT server and client is licensed under the MIT license (MIT) (see below)
+
+This application is a sample application for demonstration of the features of the Administration Shell.
+It is not allowed for productive use. The implementation uses the concepts of the document "Details of the Asset
+Administration Shell" published on www.plattform-i40.de which is licensed under Creative Commons CC BY-ND 3.0 DE.
+
+Eclipse Public License 2.0 (EPL-2.0)
+====================================
+
+(https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt)
+
+ THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+ PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
+ OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+ a) in the case of the initial Contributor, the initial content
+ Distributed under this Agreement, and
+
+ b) in the case of each subsequent Contributor:
+ i) changes to the Program, and
+ ii) additions to the Program;
+ where such changes and/or additions to the Program originate from
+ and are Distributed by that particular Contributor. A Contribution
+ "originates" from a Contributor if it was added to the Program by
+ such Contributor itself or anyone acting on such Contributor's behalf.
+ Contributions do not include changes or additions to the Program that
+ are not Modified Works.
+
+"Contributor" means any person or entity that Distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which
+are necessarily infringed by the use or sale of its Contribution alone
+or when combined with the Program.
+
+"Program" means the Contributions Distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement
+or any Secondary License (as applicable), including Contributors.
+
+"Derivative Works" shall mean any work, whether in Source Code or other
+form, that is based on (or derived from) the Program and for which the
+editorial revisions, annotations, elaborations, or other modifications
+represent, as a whole, an original work of authorship.
+
+"Modified Works" shall mean any work in Source Code or other form that
+results from an addition to, deletion from, or modification of the
+contents of the Program, including, for purposes of clarity any new file
+in Source Code form that contains any contents of the Program. Modified
+Works shall not include works that contain only declarations,
+interfaces, types, classes, structures, or files of the Program solely
+in each case in order to link to, bind by name, or subclass the Program
+or Modified Works thereof.
+
+"Distribute" means the acts of a) distributing or b) making available
+in any manner that enables the transfer of a copy.
+
+"Source Code" means the form of a Program preferred for making
+modifications, including but not limited to software source code,
+documentation source, and configuration files.
+
+"Secondary License" means either the GNU General Public License,
+Version 2.0, or any later versions of that license, including any
+exceptions or additional permissions as identified by the initial
+Contributor.
+
+2. GRANT OF RIGHTS
+
+ a) Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free copyright
+ license to reproduce, prepare Derivative Works of, publicly display,
+ publicly perform, Distribute and sublicense the Contribution of such
+ Contributor, if any, and such Derivative Works.
+
+ b) Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free patent
+ license under Licensed Patents to make, use, sell, offer to sell,
+ import and otherwise transfer the Contribution of such Contributor,
+ if any, in Source Code or other form. This patent license shall
+ apply to the combination of the Contribution and the Program if, at
+ the time the Contribution is added by the Contributor, such addition
+ of the Contribution causes such combination to be covered by the
+ Licensed Patents. The patent license shall not apply to any other
+ combinations which include the Contribution. No hardware per se is
+ licensed hereunder.
+
+ c) Recipient understands that although each Contributor grants the
+ licenses to its Contributions set forth herein, no assurances are
+ provided by any Contributor that the Program does not infringe the
+ patent or other intellectual property rights of any other entity.
+ Each Contributor disclaims any liability to Recipient for claims
+ brought by any other entity based on infringement of intellectual
+ property rights or otherwise. As a condition to exercising the
+ rights and licenses granted hereunder, each Recipient hereby
+ assumes sole responsibility to secure any other intellectual
+ property rights needed, if any. For example, if a third party
+ patent license is required to allow Recipient to Distribute the
+ Program, it is Recipient's responsibility to acquire that license
+ before distributing the Program.
+
+ d) Each Contributor represents that to its knowledge it has
+ sufficient copyright rights in its Contribution, if any, to grant
+ the copyright license set forth in this Agreement.
+
+ e) Notwithstanding the terms of any Secondary License, no
+ Contributor makes additional grants to any Recipient (other than
+ those set forth in this Agreement) as a result of such Recipient's
+ receipt of the Program under the terms of a Secondary License
+ (if permitted under the terms of Section 3).
+
+3. REQUIREMENTS
+
+3.1 If a Contributor Distributes the Program in any form, then:
+
+ a) the Program must also be made available as Source Code, in
+ accordance with section 3.2, and the Contributor must accompany
+ the Program with a statement that the Source Code for the Program
+ is available under this Agreement, and informs Recipients how to
+ obtain it in a reasonable manner on or through a medium customarily
+ used for software exchange; and
+
+ b) the Contributor may Distribute the Program under a license
+ different than this Agreement, provided that such license:
+ i) effectively disclaims on behalf of all other Contributors all
+ warranties and conditions, express and implied, including
+ warranties or conditions of title and non-infringement, and
+ implied warranties or conditions of merchantability and fitness
+ for a particular purpose;
+
+ ii) effectively excludes on behalf of all other Contributors all
+ liability for damages, including direct, indirect, special,
+ incidental and consequential damages, such as lost profits;
+
+ iii) does not attempt to limit or alter the recipients' rights
+ in the Source Code under section 3.2; and
+
+ iv) requires any subsequent distribution of the Program by any
+ party to be under a license that satisfies the requirements
+ of this section 3.
+
+3.2 When the Program is Distributed as Source Code:
+
+ a) it must be made available under this Agreement, or if the
+ Program (i) is combined with other material in a separate file or
+ files made available under a Secondary License, and (ii) the initial
+ Contributor attached to the Source Code the notice described in
+ Exhibit A of this Agreement, then the Program may be made available
+ under the terms of such Secondary Licenses, and
+
+ b) a copy of this Agreement must be included with each copy of
+ the Program.
+
+3.3 Contributors may not remove or alter any copyright, patent,
+trademark, attribution notices, disclaimers of warranty, or limitations
+of liability ("notices") contained within the Program from any copy of
+the Program which they Distribute, provided that Contributors may add
+their own appropriate notices.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities
+with respect to end users, business partners and the like. While this
+license is intended to facilitate the commercial use of the Program,
+the Contributor who includes the Program in a commercial product
+offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes
+the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and indemnify every
+other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits
+and other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such
+Commercial Contributor in connection with its distribution of the Program
+in a commercial product offering. The obligations in this section do not
+apply to any claims or Losses relating to any actual or alleged
+intellectual property infringement. In order to qualify, an Indemnified
+Contributor must: a) promptly notify the Commercial Contributor in
+writing of such claim, and b) allow the Commercial Contributor to control,
+and cooperate with the Commercial Contributor in, the defense and any
+related settlement negotiations. The Indemnified Contributor may
+participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those performance
+claims and warranties, and if a court requires any other Contributor to
+pay any damages as a result, the Commercial Contributor must pay
+those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
+BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
+TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+PURPOSE. Each Recipient is solely responsible for determining the
+appropriateness of using and distributing the Program and assumes all
+risks associated with its exercise of rights under this Agreement,
+including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs
+or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
+SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other software
+or hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement,
+but in order to avoid inconsistency the Agreement is copyrighted and
+may only be modified in the following manner. The Agreement Steward
+reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement
+Steward has the right to modify this Agreement. The Eclipse Foundation
+is the initial Agreement Steward. The Eclipse Foundation may assign the
+responsibility to serve as the Agreement Steward to a suitable separate
+entity. Each new version of the Agreement will be given a distinguishing
+version number. The Program (including Contributions) may always be
+Distributed subject to the version of the Agreement under which it was
+received. In addition, after a new version of the Agreement is published,
+Contributor may elect to Distribute the Program (including its
+Contributions) under the new version.
+
+Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
+receives no rights or licenses to the intellectual property of any
+Contributor under this Agreement, whether expressly, by implication,
+estoppel or otherwise. All rights in the Program not expressly granted
+under this Agreement are reserved. Nothing in this Agreement is intended
+to be enforceable by any entity that is not a Contributor or Recipient.
+No third-party beneficiary rights are created under this Agreement.
+
+Exhibit A - Form of Secondary Licenses Notice
+
+"This Source Code may also be made available under the following
+Secondary Licenses when the conditions for such availability set forth
+in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
+version(s), and exceptions or additional permissions here}."
+
+ Simply including a copy of this Agreement, including this Exhibit A
+ is not sufficient to license the Source Code under Secondary Licenses.
+
+ If it is not possible or desirable to put the notice in a particular
+ file, then You may include the notice in a location (such as a LICENSE
+ file in a relevant directory) where a recipient would be likely to
+ look for such a notice.
+
+ You may add additional accurate notices of copyright ownership.
+
+With respect to cefSharp
+========================
+
+(https://raw.githubusercontent.com/cefsharp/CefSharp/master/LICENSE)
+
+// Copyright © The CefSharp Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// * Neither the name of Google Inc. nor the name Chromium Embedded
+// Framework nor the name CefSharp nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+With respect to Newtonsoft.Json
+===============================
+
+(https://github.com/JamesNK/Newtonsoft.Json/blob/master/LICENSE.md)
+
+The MIT License (MIT)
+
+Copyright (c) 2007 James Newton-King
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+With respect to QRcoder
+=======================
+
+(https://github.com/codebude/QRCoder/blob/master/LICENSE.txt)
+
+The MIT License (MIT)
+
+Copyright (c) 2013-2018 Raffael Herrmann
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+With respect to ZXing.Net
+=========================
+With respect to Grapevine
+=========================
+
+(http://www.apache.org/licenses/LICENSE-2.0)
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+
+With respect to AutomationML.Engine
+===================================
+
+(https://raw.githubusercontent.com/AutomationML/AMLEngine2.1/master/license.txt)
+
+The MIT License (MIT)
+
+Copyright 2017 AutomationML e.V.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+With respect to MQTTnet
+=======================
+
+(https://github.com/chkr1011/MQTTnet/blob/master/LICENSE)
+
+MIT License
+
+MQTTnet Copyright (c) 2016-2019 Christian Kratky
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+With respect to MSAGL (Microsoft Automatic Graph Layout)
+========================================================
+(see: https://github.com/microsoft/automatic-graph-layout/blob/master/LICENSE)
+
+Microsoft Automatic Graph Layout, MSAGL
+
+Copyright (c) Microsoft Corporation
+
+All rights reserved.
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+""Software""), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/src/AasxPluginAssetInterfaceDesc/Resources/logo-http.png b/src/AasxPluginAssetInterfaceDesc/Resources/logo-http.png
new file mode 100644
index 00000000..0424ef88
Binary files /dev/null and b/src/AasxPluginAssetInterfaceDesc/Resources/logo-http.png differ
diff --git a/src/AasxPluginAssetInterfaceDesc/Resources/logo-modbus.png b/src/AasxPluginAssetInterfaceDesc/Resources/logo-modbus.png
new file mode 100644
index 00000000..007f4acf
Binary files /dev/null and b/src/AasxPluginAssetInterfaceDesc/Resources/logo-modbus.png differ
diff --git a/src/AasxPluginAssetInterfaceDesc/Resources/logo-mqtt.png b/src/AasxPluginAssetInterfaceDesc/Resources/logo-mqtt.png
new file mode 100644
index 00000000..158d239a
Binary files /dev/null and b/src/AasxPluginAssetInterfaceDesc/Resources/logo-mqtt.png differ
diff --git a/src/AasxPredefinedConcepts/DefinitionsAssetInterfacesDescription.cs b/src/AasxPredefinedConcepts/DefinitionsAssetInterfacesDescription.cs
index cf30ee53..a318cc88 100644
--- a/src/AasxPredefinedConcepts/DefinitionsAssetInterfacesDescription.cs
+++ b/src/AasxPredefinedConcepts/DefinitionsAssetInterfacesDescription.cs
@@ -24,434 +24,500 @@ namespace AasxPredefinedConcepts.AssetInterfacesDescription
public class CD_GenericInterface
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#title", Card = AasxPredefinedCardinality.One)]
- string Title;
+ public string Title;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#created", Card = AasxPredefinedCardinality.ZeroToOne)]
- DateTime? Created;
+ public DateTime? Created;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#modified", Card = AasxPredefinedCardinality.ZeroToOne)]
- DateTime? Modified;
+ public DateTime? Modified;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#support", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Support;
+ public string Support;
[AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/EndpointMetadata", Card = AasxPredefinedCardinality.One)]
- CD_EndpointMetadata EndpointMetadata = new CD_EndpointMetadata();
+ public CD_EndpointMetadata EndpointMetadata = new CD_EndpointMetadata();
[AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/InterfaceMetadata", Card = AasxPredefinedCardinality.One)]
- CD_InterfaceMetadata InterfaceMetadata = new CD_InterfaceMetadata();
+ public CD_InterfaceMetadata InterfaceMetadata = new CD_InterfaceMetadata();
[AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/ExternalDescriptor", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_ExternalDescriptor ExternalDescriptor = null;
+ public CD_ExternalDescriptor ExternalDescriptor = null;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/EndpointMetadata")]
public class CD_EndpointMetadata
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#base", Card = AasxPredefinedCardinality.One)]
- string Base;
+ public string Base;
[AasConcept(Cd = "https://www.w3.org/2019/wot/hypermedia#forContentType", Card = AasxPredefinedCardinality.One)]
- string ContentType;
+ public string ContentType;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#hasSecurityConfiguration", Card = AasxPredefinedCardinality.One)]
- CD_Security Security = new CD_Security();
+ public CD_Security Security = new CD_Security();
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme", Card = AasxPredefinedCardinality.One)]
- CD_SecurityDefinitions SecurityDefinitions = new CD_SecurityDefinitions();
+ public CD_SecurityDefinitions SecurityDefinitions = new CD_SecurityDefinitions();
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#hasSecurityConfiguration")]
public class CD_Security
{
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme")]
public class CD_SecurityDefinitions
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#NoSecurityScheme", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Nosec_sc Nosec_sc = null;
+ public CD_Nosec_sc Nosec_sc = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#AutoSecurityScheme", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Auto_sc Auto_sc = null;
+ public CD_Auto_sc Auto_sc = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#BasicSecurityScheme", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Basic_sc Basic_sc = null;
+ public CD_Basic_sc Basic_sc = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#ComboSecurityScheme", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Combo_sc Combo_sc = null;
+ public CD_Combo_sc Combo_sc = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#APIKeySecurityScheme", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Apikey_sc Apikey_sc = null;
+ public CD_Apikey_sc Apikey_sc = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#PSKSecurityScheme", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Psk_sc Psk_sc = null;
+ public CD_Psk_sc Psk_sc = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#DigestSecurityScheme", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Digest_sc Digest_sc = null;
+ public CD_Digest_sc Digest_sc = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#BearerSecurityScheme", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Bearer_sc Bearer_sc = null;
+ public CD_Bearer_sc Bearer_sc = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#OAuth2SecurityScheme", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Oauth2_sc Oauth2_sc = null;
+ public CD_Oauth2_sc Oauth2_sc = null;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#NoSecurityScheme")]
public class CD_Nosec_sc
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme", Card = AasxPredefinedCardinality.One)]
- string Scheme;
+ public string Scheme;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#AutoSecurityScheme")]
public class CD_Auto_sc
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme", Card = AasxPredefinedCardinality.One)]
- string Scheme;
+ public string Scheme;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#proxy", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Proxy;
+ public string Proxy;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#BasicSecurityScheme")]
public class CD_Basic_sc
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme", Card = AasxPredefinedCardinality.One)]
- string Scheme;
+ public string Scheme;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#name", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Name;
+ public string Name;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#in", Card = AasxPredefinedCardinality.ZeroToOne)]
- string In;
+ public string In;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#proxy", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Proxy;
+ public string Proxy;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#ComboSecurityScheme")]
public class CD_Combo_sc
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme", Card = AasxPredefinedCardinality.One)]
- string Scheme;
+ public string Scheme;
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#oneOf", Card = AasxPredefinedCardinality.One)]
- CD_OneOf OneOf = new CD_OneOf();
+ public CD_OneOf OneOf = new CD_OneOf();
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#allOf", Card = AasxPredefinedCardinality.One)]
- CD_AllOf AllOf = new CD_AllOf();
+ public CD_AllOf AllOf = new CD_AllOf();
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#proxy", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Proxy;
+ public string Proxy;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#oneOf")]
public class CD_OneOf
{
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#allOf")]
public class CD_AllOf
{
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#APIKeySecurityScheme")]
public class CD_Apikey_sc
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme", Card = AasxPredefinedCardinality.One)]
- string Scheme;
+ public string Scheme;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#name", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Name;
+ public string Name;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#in", Card = AasxPredefinedCardinality.ZeroToOne)]
- string In;
+ public string In;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#proxy", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Proxy;
+ public string Proxy;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#PSKSecurityScheme")]
public class CD_Psk_sc
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme", Card = AasxPredefinedCardinality.One)]
- string Scheme;
+ public string Scheme;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#identity", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Identity;
+ public string Identity;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#proxy", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Proxy;
+ public string Proxy;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#DigestSecurityScheme")]
public class CD_Digest_sc
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme", Card = AasxPredefinedCardinality.One)]
- string Scheme;
+ public string Scheme;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#name", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Name;
+ public string Name;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#in", Card = AasxPredefinedCardinality.ZeroToOne)]
- string In;
+ public string In;
- string Qop;
+ public string Qop;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#proxy", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Proxy;
+ public string Proxy;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#BearerSecurityScheme")]
public class CD_Bearer_sc
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme", Card = AasxPredefinedCardinality.One)]
- string Scheme;
+ public string Scheme;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#name", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Name;
+ public string Name;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#in", Card = AasxPredefinedCardinality.ZeroToOne)]
- string In;
+ public string In;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#authorization", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Authorization;
+ public string Authorization;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#alg", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Alg;
+ public string Alg;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#format", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Format;
+ public string Format;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#proxy", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Proxy;
+ public string Proxy;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#OAuth2SecurityScheme")]
public class CD_Oauth2_sc
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#definesSecurityScheme", Card = AasxPredefinedCardinality.One)]
- string Scheme;
+ public string Scheme;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#token", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Token;
+ public string Token;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#refresh", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Refresh;
+ public string Refresh;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#authorization", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Authorization;
+ public string Authorization;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#scopes", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Scopes;
+ public string Scopes;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#flow", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Flow;
+ public string Flow;
[AasConcept(Cd = "https://www.w3.org/2019/wot/security#proxy", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Proxy;
+ public string Proxy;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/InterfaceMetadata")]
public class CD_InterfaceMetadata
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#PropertyAffordance", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_PropertiesAffordance Properties = null;
+ public CD_PropertiesAffordance Properties = null;
+ // public CD_Properties Properties = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#ActionAffordance", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Actions Actions = null;
+ public CD_Actions Actions = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#EventAffordance", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Events Events = null;
+ public CD_Events Events = null;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#PropertyAffordance")]
public class CD_PropertiesAffordance
{
[AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfaceDescription/1/0/PropertyDefinition", Card = AasxPredefinedCardinality.ZeroToMany)]
- List PropertyName = new List();
+ public List Property = new List();
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfaceDescription/1/0/PropertyDefinition")]
public class CD_PropertyName
{
[AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/key", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Key;
+ public string Key;
[AasConcept(Cd = "https://www.w3.org/1999/02/22-rdf-syntax-ns#type", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Type;
+ public string Type;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#title", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Title;
+ public string Title;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#isObservable", Card = AasxPredefinedCardinality.ZeroToOne)]
- bool? Observable;
+ public bool? Observable;
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#const", Card = AasxPredefinedCardinality.ZeroToOne)]
- int? Const;
+ public int? Const;
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#default", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Default;
+ public string Default;
[AasConcept(Cd = "https://schema.org/unitCode", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Unit;
+ public string Unit;
+
+ [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/minMaxRange", Card = AasxPredefinedCardinality.ZeroToOne)]
+ public AasClassMapperRange Min_max = null;
+
+ [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/lengthRange", Card = AasxPredefinedCardinality.ZeroToOne)]
+ public AasClassMapperRange LengthRange = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#items", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Items Items = null;
+ public CD_Items Items = null;
+
+ [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/itemsRange", Card = AasxPredefinedCardinality.ZeroToOne)]
+ public AasClassMapperRange ItemsRange = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#properties", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Properties Properties = null;
+ public CD_Properties Properties = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#hasForm", Card = AasxPredefinedCardinality.One)]
- CD_Forms Forms = new CD_Forms();
+ public CD_Forms Forms = new CD_Forms();
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#items")]
public class CD_Items
{
[AasConcept(Cd = "https://www.w3.org/1999/02/22-rdf-syntax-ns#type", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Type;
+ public string Type;
[AasConcept(Cd = "https://schema.org/unitCode", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Unit;
+ public string Unit;
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#default", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Default;
+ public string Default;
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#const", Card = AasxPredefinedCardinality.ZeroToOne)]
- int? Const;
+ public int? Const;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#isObservable", Card = AasxPredefinedCardinality.ZeroToOne)]
- bool? Observable;
+ public bool? Observable;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#title", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Title;
+ public string Title;
+
+ [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/minMaxRange", Card = AasxPredefinedCardinality.ZeroToOne)]
+ public AasClassMapperRange Min_max = null;
+
+ [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/lengthRange", Card = AasxPredefinedCardinality.ZeroToOne)]
+ public AasClassMapperRange LengthRange = null;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#properties")]
public class CD_Properties
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#propertyName", Card = AasxPredefinedCardinality.ZeroToMany)]
- List _propertyName_ = new List();
+ public List Property = new List();
- [AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#propertyName", Card = AasxPredefinedCardinality.ZeroToMany)]
- List PropertyName = new List();
- }
-
- [AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#propertyName")]
- public class CD__propertyName_
- {
- [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/key", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Key;
-
- [AasConcept(Cd = "https://www.w3.org/1999/02/22-rdf-syntax-ns#type", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Type;
-
- [AasConcept(Cd = "https://www.w3.org/2019/wot/td#title", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Title;
-
- [AasConcept(Cd = "https://www.w3.org/2019/wot/td#isObservable", Card = AasxPredefinedCardinality.ZeroToOne)]
- bool? Observable;
-
- [AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#const", Card = AasxPredefinedCardinality.ZeroToOne)]
- int? Const;
-
- [AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#default", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Default;
-
- [AasConcept(Cd = "https://schema.org/unitCode", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Unit;
-
- [AasConcept(Cd = "https://www.w3.org/2019/wot/json-schema#items", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Items Items = null;
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#hasForm")]
public class CD_Forms
{
[AasConcept(Cd = "https://www.w3.org/2019/wot/hypermedia#hasTarget", Card = AasxPredefinedCardinality.One)]
- string Href;
+ public string Href;
[AasConcept(Cd = "https://www.w3.org/2019/wot/hypermedia#forContentType", Card = AasxPredefinedCardinality.ZeroToOne)]
- string ContentType;
+ public string ContentType;
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#hasSecurityConfiguration", Card = AasxPredefinedCardinality.One)]
- CD_Security Security = new CD_Security();
+ public CD_Security Security = new CD_Security();
[AasConcept(Cd = "https://www.w3.org/2011/http#methodName", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Htv_methodName;
+ public string Htv_methodName;
[AasConcept(Cd = "https://www.w3.org/2011/http#headers", Card = AasxPredefinedCardinality.ZeroToOne)]
- CD_Htv_headers Htv_headers = null;
+ public CD_Htv_headers Htv_headers = null;
[AasConcept(Cd = "https://www.w3.org/2019/wot/modbus#Function", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Modbus_function;
+ public string Modbus_function;
[AasConcept(Cd = "https://www.w3.org/2019/wot/modbus#Entity", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Modbus_entity;
+ public string Modbus_entity;
[AasConcept(Cd = "https://www.w3.org/2019/wot/modbus#hasZeroBasedAddressingFlag", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Modbus_zeroBasedAddressing;
+ public string Modbus_zeroBasedAddressing;
[AasConcept(Cd = "https://www.w3.org/2019/wot/modbus#pollingTime", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Modbus_pollingTime;
+ public string Modbus_pollingTime;
[AasConcept(Cd = "https://www.w3.org/2019/wot/mqtt#hasQoSFlag", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Modbus_timeout;
+ public string Modbus_timeout;
[AasConcept(Cd = "https://www.w3.org/2019/wot/modbus#type", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Modbus_type;
+ public string Modbus_type;
[AasConcept(Cd = "https://www.w3.org/2019/wot/mqtt#hasRetainFlag", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Mqv_retain;
+ public string Mqv_retain;
[AasConcept(Cd = "https://www.w3.org/2019/wot/mqtt#ControlPacket", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Mqv_controlPacket;
+ public string Mqv_controlPacket;
[AasConcept(Cd = "https://www.w3.org/2019/wot/mqtt#hasQoSFlag", Card = AasxPredefinedCardinality.ZeroToOne)]
- string Mqv_qos;
+ public string Mqv_qos;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2011/http#headers")]
public class CD_Htv_headers
{
[AasConcept(Cd = "https://www.w3.org/2011/http#headers", Card = AasxPredefinedCardinality.OneToMany)]
- List Htv_headers = new List();
+ public List Htv_headers = new List();
[AasConcept(Cd = "https://www.w3.org/2011/http#fieldName", Card = AasxPredefinedCardinality.One)]
- string Htv_fieldName;
+ public string Htv_fieldName;
[AasConcept(Cd = "https://www.w3.org/2011/http#fieldValue", Card = AasxPredefinedCardinality.One)]
- string Htv_fieldValue;
+ public string Htv_fieldValue;
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#ActionAffordance")]
public class CD_Actions
{
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://www.w3.org/2019/wot/td#EventAffordance")]
public class CD_Events
{
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/ExternalDescriptor")]
public class CD_ExternalDescriptor
{
+
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
[AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Submodel")]
public class CD_AssetInterfacesDescription
{
- [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface", Card = AasxPredefinedCardinality.ZeroToMany)]
- List InterfaceHTTP = new List();
+ [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface", Card = AasxPredefinedCardinality.ZeroToMany,
+ SupplSemId = "http://www.w3.org/2011/http")]
+ public List InterfaceHTTP = new List();
+
+ [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface", Card = AasxPredefinedCardinality.ZeroToMany,
+ SupplSemId = "http://www.w3.org/2011/modbus")]
+ public List InterfaceMODBUS = new List();
- [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface", Card = AasxPredefinedCardinality.ZeroToMany)]
- List InterfaceMODBUS = new List();
+ [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface", Card = AasxPredefinedCardinality.ZeroToMany,
+ SupplSemId = "http://www.w3.org/2011/mqtt")]
+ public List InterfaceMQTT = new List();
- [AasConcept(Cd = "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface", Card = AasxPredefinedCardinality.ZeroToMany)]
- List InterfaceMQTT = new List();
+ // auto-generated informations
+ public AasClassMapperInfo __Info__ = null;
}
}
diff --git a/src/AasxPredefinedConcepts/PredefinedConceptsClassMapper.cs b/src/AasxPredefinedConcepts/PredefinedConceptsClassMapper.cs
index a737fc86..a8b8daef 100644
--- a/src/AasxPredefinedConcepts/PredefinedConceptsClassMapper.cs
+++ b/src/AasxPredefinedConcepts/PredefinedConceptsClassMapper.cs
@@ -7,15 +7,18 @@ This source code is licensed under the Apache License 2.0 (see LICENSE.txt).
This source code may use other Open Source software components (see LICENSE.txt).
*/
+using AasCore.Aas3_0;
using AasxIntegrationBase;
using AasxIntegrationBase.AasForms;
using AdminShellNS;
using Extensions;
+using Namotion.Reflection;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using System.Runtime.Intrinsics.X86;
using Aas = AasCore.Aas3_0;
namespace AasxPredefinedConcepts
@@ -29,6 +32,8 @@ public enum AasxPredefinedCardinality { ZeroToOne = 0, One, ZeroToMany, OneToMan
public class AasConceptAttribute : Attribute
{
public string Cd { get; set; }
+ public string SupplSemId { get; set; }
+
public AasxPredefinedCardinality Card { get; set; }
public AasConceptAttribute()
@@ -37,7 +42,25 @@ public AasConceptAttribute()
}
///
- /// This class provides methods to derive a set of C# class definitions from a SMZT definition and
+ /// This class is used in auto-generated files by AasxPredefinedConcepts.PredefinedConceptsClassMapper
+ ///
+ public class AasClassMapperRange
+ {
+ public T Min;
+ public T Max;
+ }
+
+ ///
+ /// If this class is present in an mapped class, then (source) information will be added to the
+ /// data objects.
+ ///
+ public class AasClassMapperInfo
+ {
+ public Aas.IReferable Referable;
+ }
+
+ ///
+ /// This class provides methods to derive a set of C# class definitions from a SMT definition and
/// to create runtime instances from it based on a concrete SM.
///
public class PredefinedConceptsClassMapper
@@ -46,6 +69,61 @@ public class PredefinedConceptsClassMapper
// Export C# classes
//
+ private static string CSharpTypeFrom(Aas.DataTypeDefXsd valueType)
+ {
+ switch (valueType)
+ {
+ case Aas.DataTypeDefXsd.Boolean:
+ return "bool";
+
+ case Aas.DataTypeDefXsd.Byte:
+ return "byte";
+
+ case Aas.DataTypeDefXsd.Date:
+ case Aas.DataTypeDefXsd.DateTime:
+ case Aas.DataTypeDefXsd.Time:
+ return "DateTime";
+
+ case Aas.DataTypeDefXsd.Float:
+ return "float";
+
+ case Aas.DataTypeDefXsd.Double:
+ return "double";
+
+ case Aas.DataTypeDefXsd.Int:
+ case Aas.DataTypeDefXsd.Integer:
+ return "int";
+
+ case Aas.DataTypeDefXsd.Long:
+ return "long";
+
+ case Aas.DataTypeDefXsd.NegativeInteger:
+ case Aas.DataTypeDefXsd.NonPositiveInteger:
+ return "int";
+
+ case Aas.DataTypeDefXsd.NonNegativeInteger:
+ case Aas.DataTypeDefXsd.PositiveInteger:
+ return "unsigned int";
+
+ case Aas.DataTypeDefXsd.Short:
+ return "short";
+
+ case Aas.DataTypeDefXsd.UnsignedByte:
+ return "unsigned byte";
+
+ case Aas.DataTypeDefXsd.UnsignedInt:
+ return "unsigned int";
+
+ case Aas.DataTypeDefXsd.UnsignedLong:
+ return "usingned long";
+
+ case Aas.DataTypeDefXsd.UnsignedShort:
+ return "unsigned short";
+ }
+
+ return "string";
+ }
+
private static void ExportCSharpMapperSingleItems(
string indent, Aas.Environment env, Aas.IReferable rf, System.IO.StreamWriter snippets,
bool noEmptyLineFirst = false)
@@ -109,22 +187,22 @@ private static void ExportCSharpMapperSingleItems(
var nullOp = (dt == "string") ? "" : "?";
if (card == FormMultiplicity.ZeroToOne)
- snippets.WriteLine($"{indent}{dt}{nullOp} {instance};");
+ snippets.WriteLine($"{indent}public {dt}{nullOp} {instance};");
else
if (card == FormMultiplicity.One)
- snippets.WriteLine($"{indent}{dt} {instance};");
+ snippets.WriteLine($"{indent}public {dt} {instance};");
else
- snippets.WriteLine($"{indent}List<{dt}> {instance} = new List<{dt}>();");
+ snippets.WriteLine($"{indent}public List<{dt}> {instance} = new List<{dt}>();");
}
else
{
if (card == FormMultiplicity.ZeroToOne)
- snippets.WriteLine($"{indent}{dt} {instance} = null;");
+ snippets.WriteLine($"{indent}public {dt} {instance} = null;");
else
if (card == FormMultiplicity.One)
- snippets.WriteLine($"{indent}{dt} {instance} = new {dt}();");
+ snippets.WriteLine($"{indent}public {dt} {instance} = new {dt}();");
else
- snippets.WriteLine($"{indent}List<{dt}> {instance} = new List<{dt}>();");
+ snippets.WriteLine($"{indent}public List<{dt}> {instance} = new List<{dt}>();");
}
};
@@ -134,74 +212,33 @@ private static void ExportCSharpMapperSingleItems(
if (rf is Aas.Property prop)
{
- var dt = "string";
- switch (prop.ValueType)
- {
- case Aas.DataTypeDefXsd.Boolean:
- dt = "bool";
- break;
-
- case Aas.DataTypeDefXsd.Byte:
- dt = "byte";
- break;
-
- case Aas.DataTypeDefXsd.Date:
- case Aas.DataTypeDefXsd.DateTime:
- case Aas.DataTypeDefXsd.Time:
- dt = "DateTime";
- break;
-
- case Aas.DataTypeDefXsd.Float:
- dt = "float";
- break;
-
- case Aas.DataTypeDefXsd.Double:
- dt = "double";
- break;
-
- case Aas.DataTypeDefXsd.Int:
- case Aas.DataTypeDefXsd.Integer:
- dt = "int";
- break;
-
- case Aas.DataTypeDefXsd.Long:
- dt = "long";
- break;
-
- case Aas.DataTypeDefXsd.NegativeInteger:
- case Aas.DataTypeDefXsd.NonPositiveInteger:
- dt = "int";
- break;
-
- case Aas.DataTypeDefXsd.NonNegativeInteger:
- case Aas.DataTypeDefXsd.PositiveInteger:
- dt = "unsigned int";
- break;
-
- case Aas.DataTypeDefXsd.Short:
- dt = "short";
- break;
-
- case Aas.DataTypeDefXsd.UnsignedByte:
- dt = "unsigned byte";
- break;
-
- case Aas.DataTypeDefXsd.UnsignedInt:
- dt = "unsigned int";
- break;
-
- case Aas.DataTypeDefXsd.UnsignedLong:
- dt = "usingned long";
- break;
-
- case Aas.DataTypeDefXsd.UnsignedShort:
- dt = "unsigned short";
- break;
- }
-
+ var dt = CSharpTypeFrom(prop.ValueType);
declareLambda(dt, true, idsff);
}
+ //
+ // Range
+ //
+
+ if (rf is Aas.Range rng)
+ {
+ var dt = CSharpTypeFrom(rng.ValueType);
+ declareLambda($"AasClassMapperRange<{dt}>", false, idsff);
+ }
+
+ //
+ // MultiLanguageProperty
+ //
+
+ if (rf is MultiLanguageProperty mlp)
+ {
+ declareLambda("List", false, idsff);
+ }
+
+ //
+ // SMC, SML ..
+ //
+
if (( rf is Aas.Submodel
|| rf is Aas.SubmodelElementCollection
|| rf is Aas.SubmodelElementList)
@@ -283,16 +320,12 @@ public void EnrichMembersFrom(ExportCSharpClassDef cld)
}
private static void ExportCSharpMapperOnlyClasses(
- string indent, Aas.Environment env, Aas.ISubmodel sm, System.IO.StreamWriter snippets)
+ string indent, Aas.Environment env, Aas.ISubmodel sm, System.IO.StreamWriter snippets,
+ bool addInfoObj = false)
{
- // which is a structual element?
- Func isStructRf = (rf) =>
- (rf is Aas.SubmodelElementCollection
- || rf is Aas.SubmodelElementList);
-
// list of class definitions (not merged, yet)
var elems = new List();
- foreach (var sme in sm.SubmodelElements?.FindDeep((sme) => isStructRf(sme)))
+ foreach (var sme in sm.SubmodelElements?.FindDeep((sme) => sme.IsStructured()))
elems.Add(new ExportCSharpClassDef(env, sme));
// list of merged class defs
@@ -346,8 +379,14 @@ private static void ExportCSharpMapperOnlyClasses(
}
}
+ if (addInfoObj)
+ {
+ snippets.WriteLine($"");
+ snippets.WriteLine($"{indent} // auto-generated informations");
+ snippets.WriteLine($"{indent} public AasClassMapperInfo __Info__ = null;");
+ }
- snippets.WriteLine($"{indent}}}");
+ snippets.WriteLine($"{indent}}}");
}
}
@@ -382,7 +421,8 @@ This source code was auto-generated by the AASX Package Explorer.
snippets.WriteLine($"namespace AasxPredefinedConcepts.{AdminShellUtil.FilterFriendlyName(sm?.IdShort)} {{");
- ExportCSharpMapperOnlyClasses(" ", env, sm, snippets);
+ ExportCSharpMapperOnlyClasses(" ", env, sm, snippets,
+ addInfoObj: true);
// ExportCSharpMapperSingleItems(" ", env, sm, snippets);
@@ -395,18 +435,167 @@ This source code was auto-generated by the AASX Package Explorer.
private class ElemAttrInfo
{
+ public object Obj;
public FieldInfo Fi;
public AasConceptAttribute Attr;
}
- private void ParseAasElemFillData(ElemAttrInfo eai, Aas.ISubmodelElement sme)
+ private static object CreateRangeObjectSpecific(Type genericType0, Aas.ISubmodelElement sme)
{
// access
- if (eai?.Fi == null || sme == null)
+ if (genericType0 == null || sme == null || !(sme is Aas.IRange rng))
+ return null;
+
+ // create generic instance
+ // see: https://stackoverflow.com/questions/4194033/adding-items-to-listt-using-reflection
+ var objTyp = genericType0;
+ var IListRef = typeof(AasClassMapperRange<>);
+ Type[] IListParam = { objTyp };
+ object rngObj = Activator.CreateInstance(IListRef.MakeGenericType(IListParam));
+
+ // set
+ var rngType = rngObj.GetType();
+ AdminShellUtil.SetFieldLazyValue(rngType.GetField("Min"), rngObj, "" + rng.Min);
+ AdminShellUtil.SetFieldLazyValue(rngType.GetField("Max"), rngObj, "" + rng.Max);
+
+ // ok
+ return rngObj;
+ }
+
+ // TODO (MIHO, 2024-01-04): Move to AdminShellUtil ..
+ private static void SetFieldLazyFromSme(FieldInfo f, object obj, Aas.ISubmodelElement sme)
+ {
+ // access
+ if (f == null || obj == null || sme == null)
return;
+ // identify type
+ var t = AdminShellUtil.GetTypeOrUnderlyingType(f.FieldType);
+
+ if (t.IsGenericType
+ && t.GetGenericTypeDefinition() == typeof(AasClassMapperRange<>)
+ && t.GenericTypeArguments.Length >= 1
+ && sme is Aas.IRange rng)
+ {
+ // create generic instance
+ var rngObj = CreateRangeObjectSpecific(t.GenericTypeArguments[0], sme);
+
+ // set it
+ f.SetValue(obj, rngObj);
+ }
+ else
+ {
+ AdminShellUtil.SetFieldLazyValue(f, obj, sme.ValueAsText());
+ }
+ }
+
+ public static void AddToListLazySme(FieldInfo f, object obj, Aas.ISubmodelElement sme)
+ {
+ // access
+ if (f == null || obj == null || sme == null)
+ return;
+
+ // identify type
+ var t = AdminShellUtil.GetTypeOrUnderlyingType(f.FieldType);
+
+ if (t.IsGenericType
+ && t.GetGenericTypeDefinition() == typeof(AasClassMapperRange<>)
+ && sme is Aas.IRange rng)
+ {
+ // create generic instance
+ var rngObj = CreateRangeObjectSpecific(t.GenericTypeArguments[0], sme);
+
+ // add it
+ var listObj = f.GetValue(obj);
+ listObj.GetType().GetMethod("Add").Invoke(listObj, new[] { rngObj });
+ }
+ else
+ {
+ AdminShellUtil.AddToListLazyValue(obj, sme.ValueAsText());
+ }
+ }
+
+ private static void ParseAasElemFillData(ElemAttrInfo eai, Aas.ISubmodelElement sme)
+ {
+ // access
+ if (eai?.Fi == null || eai.Attr == null || sme == null)
+ return;
+
+ if (sme?.IdShort == "Voltage_L1_N")
+ { ; }
+
// straight?
+ if (!sme.IsStructured())
+ {
+ if (eai.Attr.Card == AasxPredefinedCardinality.One)
+ {
+ // scalar value
+ SetFieldLazyFromSme(eai.Fi, eai.Obj, sme);
+ }
+ else
+ if (eai.Attr.Card == AasxPredefinedCardinality.ZeroToOne)
+ {
+ // sure to have a nullable type
+ SetFieldLazyFromSme(eai.Fi, eai.Obj, sme);
+ }
+ else
+ if ((eai.Attr.Card == AasxPredefinedCardinality.ZeroToMany
+ || eai.Attr.Card == AasxPredefinedCardinality.OneToMany)
+ && eai.Obj.GetType().IsGenericType
+ && eai.Obj.GetType().GetGenericTypeDefinition() == typeof(List<>))
+ {
+ // sure to have a (instantiated) List
+ AddToListLazySme(eai.Fi, eai.Obj, sme);
+ }
+ }
+ else
+ {
+ if (eai.Attr.Card == AasxPredefinedCardinality.One)
+ {
+ // assume a already existing object
+ var childObj = eai.Fi.GetValue(eai.Obj);
+
+ // recurse to fill in
+ ParseAasElemsToObject(sme, childObj);
+ }
+ else
+ if (eai.Attr.Card == AasxPredefinedCardinality.ZeroToOne)
+ {
+ // get value first, shall not be present
+ var childObj = eai.Fi.GetValue(eai.Obj);
+ if (childObj != null)
+ throw new Exception(
+ $"ParseAasElemFillData: [0..1] instance for {eai.Fi.FieldType.Name}> already present!");
+
+ // ok, make new, add
+ childObj = Activator.CreateInstance(eai.Fi.FieldType);
+ eai.Fi.SetValue(eai.Obj, childObj);
+
+ // recurse to fill in
+ ParseAasElemsToObject(sme, childObj);
+ }
+ else
+ if ((eai.Attr.Card == AasxPredefinedCardinality.ZeroToMany
+ || eai.Attr.Card == AasxPredefinedCardinality.OneToMany)
+ && eai.Fi.FieldType.IsGenericType
+ && eai.Fi.FieldType.GetGenericTypeDefinition() == typeof(List<>)
+ && eai.Fi.FieldType.GenericTypeArguments.Length > 0
+ && eai.Fi.FieldType.GenericTypeArguments[0] != null)
+ {
+ // create a new object instance
+ var childObj = Activator.CreateInstance(eai.Fi.FieldType.GenericTypeArguments[0]);
+
+ // add to list
+ var listObj = eai.Fi.GetValue(eai.Obj);
+ listObj.GetType().GetMethod("Add").Invoke(listObj, new [] { childObj });
+ // recurse to fill in
+ ParseAasElemsToObject(sme, childObj);
+ }
+
+ // recurse
+
+ }
}
///
@@ -425,13 +614,22 @@ public static void ParseAasElemsToObject(Aas.IReferable root, object obj)
// find fields for this object
var t = obj.GetType();
- var l = t.GetFields(BindingFlags.Instance | BindingFlags.Public);
+ var l = t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var f in l)
{
+ // special case
+ if (f.FieldType == typeof(AasClassMapperInfo))
+ {
+ var info = new AasClassMapperInfo() { Referable = root };
+ f.SetValue(obj, info);
+ continue;
+ }
+
+ // store for a bit later processing
var a = f.GetCustomAttribute();
if (a != null)
{
- eais.Add(new ElemAttrInfo() { Fi = f, Attr = a });
+ eais.Add(new ElemAttrInfo() { Obj = obj, Fi = f, Attr = a });
}
}
@@ -441,8 +639,20 @@ public static void ParseAasElemsToObject(Aas.IReferable root, object obj)
// try find sme in Rf
foreach (var x in root.DescendOnce())
if (x is Aas.ISubmodelElement sme)
- if (sme?.SemanticId?.MatchesExactlyOneKey(new Aas.Key(Aas.KeyTypes.GlobalReference, eai?.Attr?.Cd)) == true)
- ;
+ {
+ var hit = sme?.SemanticId?.MatchesExactlyOneKey(
+ new Aas.Key(Aas.KeyTypes.GlobalReference, eai?.Attr?.Cd),
+ matchMode: MatchMode.Relaxed) == true;
+
+ if (hit && eai?.Attr?.SupplSemId?.HasContent() == true)
+ hit = hit && sme?.SupplementalSemanticIds?.MatchesAnyWithExactlyOneKey(
+ new Aas.Key(Aas.KeyTypes.GlobalReference, eai?.Attr?.SupplSemId),
+ matchMode: MatchMode.Relaxed) == true;
+
+ if (hit)
+ ParseAasElemFillData(eai, sme);
+ }
+
}
}
}