diff --git a/src/AasxIntegrationBase/AasForms/FormDescription.cs b/src/AasxIntegrationBase/AasForms/FormDescription.cs index 5d5320bdc..accd4d9be 100644 --- a/src/AasxIntegrationBase/AasForms/FormDescription.cs +++ b/src/AasxIntegrationBase/AasForms/FormDescription.cs @@ -86,7 +86,7 @@ public class FormDescReferable : FormDescBase /// Preset for Referable.description /// [JsonProperty(Order = 7)] - public List PresetDescription = null; + public List PresetDescription = new List(); /// /// SemanticId of the SubmodelElement. Always required. @@ -591,6 +591,94 @@ public Aas.Property GenerateDefault() } } + + [DisplayName("FormRange")] + public class FormDescRange : FormDescSubmodelElement + { + [JsonProperty(Order = 20)] + public string[] allowedValueTypes = new string[] { "string" }; + + /// + /// Pre-set the editable Property value with this value. + /// + [JsonProperty(Order = 21)] + public string presetMin = ""; + + [JsonProperty(Order = 22)] + public string presetMax = ""; + + // Constructors + //============= + + public FormDescRange() { } + + public FormDescRange( + string formText, FormMultiplicity multiplicity, Aas.Key smeSemanticId, + string presetIdShort, string formInfo = null, bool isReadOnly = false, string valueType = null, + string presetMin = null, string presetMax = null) + : base(formText, multiplicity, smeSemanticId, presetIdShort, formInfo, isReadOnly) + { + // init + if (valueType != null) + this.allowedValueTypes = new[] { valueType }; + if (presetMin != null) + this.presetMin = presetMin; + if (presetMax != null) + this.presetMax = presetMax; + + } + + public FormDescRange(FormDescRange other) + : base(other) + { + // this part == static, therefore only shallow copy + this.allowedValueTypes = other.allowedValueTypes; + this.presetMin = other.presetMin; + this.presetMax = other.presetMax; + } + +#if !DoNotUseAasxCompatibilityModels + public FormDescRange(AasxCompatibilityModels.AasxIntegrationBase.AasForms.FormDescRangeV20 other) + : base(other) + { + // this part == static, therefore only shallow copy + this.allowedValueTypes = other.allowedValueTypes; + this.presetMin = other.presetMin; + this.presetMax = other.presetMax; + } +#endif + + public override FormDescSubmodelElement Clone() + { + return new FormDescRange(this); + } + + /// + /// Build a new instance, based on the description data + /// + public override FormInstanceSubmodelElement CreateInstance( + FormInstanceListOfSame parentInstance, Aas.ISubmodelElement source = null) + { + return new FormInstanceRange(parentInstance, this, source); + } + + public Aas.Range GenerateDefault() + { + var res = new Aas.Range(Aas.DataTypeDefXsd.String); + this.InitSme(res); + if (this.presetMin != null) + res.Min = this.presetMin; + if (this.presetMax != null) + res.Max = this.presetMax; + if (this.allowedValueTypes.Length == 1) + { + res.ValueType = Aas.Stringification.DataTypeDefXsdFromString(this.allowedValueTypes[0]) + ?? Aas.DataTypeDefXsd.String; + } + return res; + } + } + [DisplayName("FormMultiLangProp")] public class FormDescMultiLangProp : FormDescSubmodelElement { diff --git a/src/AasxIntegrationBase/AasForms/FormInstance.cs b/src/AasxIntegrationBase/AasForms/FormInstance.cs index 0ef43b497..61063ad88 100644 --- a/src/AasxIntegrationBase/AasForms/FormInstance.cs +++ b/src/AasxIntegrationBase/AasForms/FormInstance.cs @@ -1359,7 +1359,6 @@ public override void RenderAnyUi(AnyUiStackPanel view, AnyUiSmallWidgetToolkit u } } } - public class FormInstanceProperty : FormInstanceSubmodelElement { public FormInstanceProperty( @@ -1569,6 +1568,164 @@ public override void RenderAnyUi(AnyUiStackPanel view, AnyUiSmallWidgetToolkit u } } + public class FormInstanceRange : FormInstanceSubmodelElement + { + public FormInstanceRange( + FormInstanceListOfSame parentInstance, FormDescRange parentDesc, + Aas.ISubmodelElement source = null, bool deepCopy = false) + { + // way back to description + this.parentInstance = parentInstance; + this.desc = parentDesc; + + // initialize Referable + var p = new Aas.Range(Aas.DataTypeDefXsd.String); + this.sme = p; + InitReferable(parentDesc, source); + + // check, if a source is present + this.sourceSme = source; + var pSource = this.sourceSme as Aas.Range; + if (pSource != null) + { + // take over + p.ValueType = pSource.ValueType; + p.Min = pSource.Min; + p.Max = pSource.Max; + } + else + { + // some more preferences + if (parentDesc.allowedValueTypes != null && parentDesc.allowedValueTypes.Length >= 1) + p.ValueType = Aas.Stringification.DataTypeDefXsdFromString(parentDesc.allowedValueTypes[0]) + ?? Aas.DataTypeDefXsd.String; + + if (parentDesc.presetMin != null && parentDesc.presetMax != null) + { + p.Min = parentDesc.presetMin; + p.Max = parentDesc.presetMax; + // immediately set touched in order to have this value saved + this.Touch(); + } + } + + // create user control +#if USE_WPF + if (createSubControls) + { + this.subControl = new FormSubControlProperty(); + this.subControl.DataContext = this; + } +#endif + } + + /// + /// Before rendering the SME into a list of new elements, process the SME. + /// If Touched, sourceSme and editSource is set, + /// this function shall write back the new values instead of + /// producing a new element. Returns True, if a new element shall be rendered. + /// + public override bool ProcessSmeForRender( + AdminShellPackageEnv packageEnv = null, bool addFilesToPackage = false, bool editSource = false) + { + // refer to base (SME) function, but not caring about result + base.ProcessSmeForRender(packageEnv, addFilesToPackage, editSource); + + var p = this.sme as Aas.Range; + var pSource = this.sourceSme as Aas.Range; + if (p != null && Touched && pSource != null && editSource) + { + pSource.ValueType = p.ValueType; + pSource.Min = p.Min; + pSource.Max = p.Max; + return false; + } + return true; + } + + /// + /// Event was raised from master because matching slave. + /// + public override void OnSlaveEvent( + FormDescSubmodelElement masterDesc, FormInstanceSubmodelElement masterInst, int index) + { + // access to master + var pMasterInst = masterInst as FormInstanceRange; + var pMaster = pMasterInst?.sme as Aas.Range; + if (pMaster?.Min == null || pMaster.Max == null) + return; + + // accues to this + var pThis = this.sme as Aas.Range; + if (pThis == null) + return; + + // refresh +#if USE_WPF + if (this.subControl != null && this.subControl is FormSubControlRange scr) + scr.UpdateDisplay(); +#endif + if (MainControl is AnyUiTextBox mtb) + { + mtb.Text = pThis.Min + ".." + pThis.Max; + mtb.Touch(); + } + + if (MainControl is AnyUiComboBox mcb && mcb.IsEditable == true) + { + mcb.Text = pThis.Min + ".." + pThis.Max; + mcb.Touch(); + } + } + + /// + /// Render the AnyUI representation of the current instance data structure + /// + public override void RenderAnyUi(AnyUiStackPanel view, AnyUiSmallWidgetToolkit uitk, + PluginOperationContextBase opctx) + { + // access + var prop = sme as Aas.Range; + var pDesc = desc as FormDescRange; + if (prop == null || pDesc == null) + return; + + // Intended layout + // Grid + // Index + // TextBox | ComboBox + + var g = view.Add( + uitk.AddSmallGrid(rows: 2, cols: 3, colWidths: new[] { "2:", "*", "2:" })); + + + MainControl = AnyUiUIElement.RegisterControl( + uitk.AddSmallTextBoxTo(g, 0, 1, + margin: new AnyUiThickness(0, 2, 0, 2), + text: "" + prop.Min), + (o) => + { + if (o is string os) + prop.Min = os; + Touch(); + return new AnyUiLambdaActionNone(); + }); + + + MainControl = AnyUiUIElement.RegisterControl( + uitk.AddSmallTextBoxTo(g, 1, 1, + margin: new AnyUiThickness(0, 2, 0, 2), + text: "" + prop.Max), + (o) => + { + if (o is string os) + prop.Max = os; + Touch(); + return new AnyUiLambdaActionNone(); + }); + } + } + public class FormInstanceMultiLangProp : FormInstanceSubmodelElement { public FormInstanceMultiLangProp( diff --git a/src/AasxIntegrationBase/AasxCompatibilityModels/AasForms/FormDescriptionV20.cs b/src/AasxIntegrationBase/AasxCompatibilityModels/AasForms/FormDescriptionV20.cs index 3e8e430f1..89fb5d5b0 100644 --- a/src/AasxIntegrationBase/AasxCompatibilityModels/AasForms/FormDescriptionV20.cs +++ b/src/AasxIntegrationBase/AasxCompatibilityModels/AasForms/FormDescriptionV20.cs @@ -198,6 +198,28 @@ public class FormDescPropertyV20 : FormDescSubmodelElementV20 } + [DisplayName("FormRange_V20")] + public class FormDescRangeV20 : FormDescSubmodelElementV20 + { + /// + /// Pre-set the Property with this valueType. Right now, only one item (and this shall be "string") is allowed! + /// + [JsonProperty(Order = 20)] + public string[] allowedValueTypes = new string[] { "string" }; + + /// + /// Pre-set the editable Range Min with this value. + /// + [JsonProperty(Order = 21)] + public string presetMin = ""; + + /// + /// Pre-set the editable Range Max with this value. + /// + [JsonProperty(Order = 22)] + public string presetMax = ""; + } + [DisplayName("FormMultiLangProp_V20")] public class FormDescMultiLangPropV20 : FormDescSubmodelElementV20 { diff --git a/src/AasxPackageExplorer.sln b/src/AasxPackageExplorer.sln index 25aa0daf8..774b38674 100644 --- a/src/AasxPackageExplorer.sln +++ b/src/AasxPackageExplorer.sln @@ -160,6 +160,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AasxPluginDigitalNameplate" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AasxPluginContactInformation", "AasxPluginContactInformation\AasxPluginContactInformation.csproj", "{938BB137-DC45-4A84-B0C9-AC46DA321FDB}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AasxPluginAID", "AasxPluginAID\AasxPluginAID.csproj", "{B481FE2E-20B0-49AD-88DE-930A992DF49F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -268,7 +270,6 @@ Global {EBAE658A-3ECE-4C98-89BC-F79809AB4A5E}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU {EBAE658A-3ECE-4C98-89BC-F79809AB4A5E}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU {967E60E3-D668-42A3-AA0B-1A031C20D871}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {967E60E3-D668-42A3-AA0B-1A031C20D871}.Debug|Any CPU.Build.0 = Debug|Any CPU {967E60E3-D668-42A3-AA0B-1A031C20D871}.Debug|x64.ActiveCfg = Debug|Any CPU {967E60E3-D668-42A3-AA0B-1A031C20D871}.Debug|x64.Build.0 = Debug|Any CPU {967E60E3-D668-42A3-AA0B-1A031C20D871}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -298,7 +299,6 @@ Global {967E60E3-D668-42A3-AA0B-1A031C20D871}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU {967E60E3-D668-42A3-AA0B-1A031C20D871}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU {6C45112D-B7F0-4463-BE6D-A8A2B5A547BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6C45112D-B7F0-4463-BE6D-A8A2B5A547BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {6C45112D-B7F0-4463-BE6D-A8A2B5A547BF}.Debug|x64.ActiveCfg = Debug|Any CPU {6C45112D-B7F0-4463-BE6D-A8A2B5A547BF}.Debug|x64.Build.0 = Debug|Any CPU {6C45112D-B7F0-4463-BE6D-A8A2B5A547BF}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -836,7 +836,6 @@ Global {7788AC2B-7F97-4755-B343-C4196FA90198}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU {7788AC2B-7F97-4755-B343-C4196FA90198}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU {2F21FEFF-F0EF-40B5-BA05-09FC9F499AE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2F21FEFF-F0EF-40B5-BA05-09FC9F499AE9}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F21FEFF-F0EF-40B5-BA05-09FC9F499AE9}.Debug|x64.ActiveCfg = Debug|Any CPU {2F21FEFF-F0EF-40B5-BA05-09FC9F499AE9}.Debug|x64.Build.0 = Debug|Any CPU {2F21FEFF-F0EF-40B5-BA05-09FC9F499AE9}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1436,7 +1435,6 @@ Global {E9AC7B0F-58FC-4BD8-A1C9-97BBB34A4E99}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU {E9AC7B0F-58FC-4BD8-A1C9-97BBB34A4E99}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU {BCE9B9F3-35CD-4CEA-8C88-68B0FD48DFD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BCE9B9F3-35CD-4CEA-8C88-68B0FD48DFD5}.Debug|Any CPU.Build.0 = Debug|Any CPU {BCE9B9F3-35CD-4CEA-8C88-68B0FD48DFD5}.Debug|x64.ActiveCfg = Debug|Any CPU {BCE9B9F3-35CD-4CEA-8C88-68B0FD48DFD5}.Debug|x64.Build.0 = Debug|Any CPU {BCE9B9F3-35CD-4CEA-8C88-68B0FD48DFD5}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1760,7 +1758,6 @@ Global {4EB64F40-1A01-46BB-BEED-D1A75313C7F8}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU {4EB64F40-1A01-46BB-BEED-D1A75313C7F8}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU {BE68E42C-28CB-4298-9F34-A18AF92FC4DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BE68E42C-28CB-4298-9F34-A18AF92FC4DE}.Debug|Any CPU.Build.0 = Debug|Any CPU {BE68E42C-28CB-4298-9F34-A18AF92FC4DE}.Debug|x64.ActiveCfg = Debug|Any CPU {BE68E42C-28CB-4298-9F34-A18AF92FC4DE}.Debug|x64.Build.0 = Debug|Any CPU {BE68E42C-28CB-4298-9F34-A18AF92FC4DE}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1939,6 +1936,36 @@ Global {938BB137-DC45-4A84-B0C9-AC46DA321FDB}.ReleaseWithoutCEF|x64.Build.0 = Release|Any CPU {938BB137-DC45-4A84-B0C9-AC46DA321FDB}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU {938BB137-DC45-4A84-B0C9-AC46DA321FDB}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Debug|x64.ActiveCfg = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Debug|x64.Build.0 = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Debug|x86.ActiveCfg = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Debug|x86.Build.0 = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugSlow|Any CPU.ActiveCfg = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugSlow|Any CPU.Build.0 = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugSlow|x64.ActiveCfg = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugSlow|x64.Build.0 = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugSlow|x86.ActiveCfg = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugSlow|x86.Build.0 = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugWithoutCEF|Any CPU.ActiveCfg = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugWithoutCEF|Any CPU.Build.0 = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugWithoutCEF|x64.ActiveCfg = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugWithoutCEF|x64.Build.0 = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugWithoutCEF|x86.ActiveCfg = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.DebugWithoutCEF|x86.Build.0 = Debug|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Release|Any CPU.Build.0 = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Release|x64.ActiveCfg = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Release|x64.Build.0 = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Release|x86.ActiveCfg = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.Release|x86.Build.0 = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.ReleaseWithoutCEF|Any CPU.ActiveCfg = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.ReleaseWithoutCEF|Any CPU.Build.0 = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.ReleaseWithoutCEF|x64.ActiveCfg = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.ReleaseWithoutCEF|x64.Build.0 = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU + {B481FE2E-20B0-49AD-88DE-930A992DF49F}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2002,6 +2029,7 @@ Global {D39BC0A4-64EA-4C7B-B72C-BF0A80FF29FE} = {DDA9C372-F8ED-4099-A53C-01B9333FD985} {DA75828B-E5AC-4E9D-AE1F-398F8FF5AE25} = {66D730EB-B9D7-4C3A-8954-0F86240AD612} {938BB137-DC45-4A84-B0C9-AC46DA321FDB} = {66D730EB-B9D7-4C3A-8954-0F86240AD612} + {B481FE2E-20B0-49AD-88DE-930A992DF49F} = {66D730EB-B9D7-4C3A-8954-0F86240AD612} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1AE21162-9541-4B98-A49C-A63B6AD03998} diff --git a/src/AasxPackageExplorer/options-debug.MIHO.json b/src/AasxPackageExplorer/options-debug.MIHO.json index d4cd79b69..0be962728 100644 --- a/src/AasxPackageExplorer/options-debug.MIHO.json +++ b/src/AasxPackageExplorer/options-debug.MIHO.json @@ -116,6 +116,10 @@ "Path": "..\\..\\..\\..\\..\\..\\AasxPluginDigitalNameplate\\bin\\Debug\\net6.0-windows\\AasxPluginDigitalNameplate.dll", "Args": [] }, + { + "Path": "..\\..\\..\\..\\..\\..\\AasxPluginAID\\bin\\Debug\\net6.0-windows\\AasxPluginAID.dll", + "Args": [] + }, { "Path": "..\\..\\..\\..\\..\\..\\AasxPluginDocumentShelf\\bin\\Debug\\net6.0-windows\\AasxPluginDocumentShelf.dll", "Args": [] diff --git a/src/AasxPackageExplorer/options-debug.json b/src/AasxPackageExplorer/options-debug.json index 55e6b550c..e43202be8 100644 --- a/src/AasxPackageExplorer/options-debug.json +++ b/src/AasxPackageExplorer/options-debug.json @@ -59,8 +59,8 @@ ], "PluginPrefer": "ANYUI", "PluginDll": [ - - { + + { "Path": "..\\..\\..\\..\\..\\..\\AasxPluginUaNetServer\\bin\\Debug\\net6.0-windows\\AasxPluginUaNetServer.dll", "Args": [ "-single-nodeids", @@ -89,6 +89,10 @@ "Path": "..\\..\\..\\..\\..\\..\\AasxPluginDigitalNameplate\\bin\\Debug\\net6.0-windows\\AasxPluginDigitalNameplate.dll", "Args": [] }, + { + "Path": "..\\..\\..\\..\\..\\..\\AasxPluginAID\\bin\\Debug\\net6.0-windows\\AasxPluginAID.dll", + "Args": [] + }, { "Path": "..\\..\\..\\..\\..\\..\\AasxPluginDocumentShelf\\bin\\Debug\\net6.0-windows\\AasxPluginDocumentShelf.dll", "Args": [] diff --git a/src/AasxPluginAID/AIDAnyUiControl.cs b/src/AasxPluginAID/AIDAnyUiControl.cs new file mode 100644 index 000000000..e391d9c26 --- /dev/null +++ b/src/AasxPluginAID/AIDAnyUiControl.cs @@ -0,0 +1,938 @@ +/* +Copyright (c) 2024 Festo SE & Co. KG +Author: Harish Kumar Pakala + +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 AasxIntegrationBase; +using AasxIntegrationBase.AasForms; +using AasxIntegrationBaseGdi; +using AasxPredefinedConcepts; +using AdminShellNS; +using AnyUi; +using Extensions; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Aas = AasCore.Aas3_0; + +// ReSharper disable InconsistentlySynchronizedField +// ReSharper disable AccessToModifiedClosure + +namespace AasxPluginAID +{ + public class AIDAnyUiControl + { + #region Members + //============= + + private LogInstance _log = new LogInstance(); + private AdminShellPackageEnv _package = null; + private Aas.Submodel _submodel = null; + private PluginEventStack _eventStack = null; + private PluginSessionBase _session = null; + private AnyUiStackPanel _panel = null; + private AnyUiContextPlusDialogs _displayContext = null; + private PluginOperationContextBase _opContext = null; + private AasxPluginBase _plugin = null; + + protected AnyUiSmallWidgetToolkit _uitk = new AnyUiSmallWidgetToolkit(); + + private String _selectedProtocolType = "HTTP"; + + private List _renderedInterfaces = new List(); + private List theDocEntitiesToPreview = new List(); + + private System.Timers.Timer _dispatcherTimer = null; + + // members for form editing + + protected AnyUiRenderForm _formDoc = null; + + protected static int InstCounter = 1; + + protected string CurrInst = ""; + + #endregion + + #region Cache for already generated Images + //======================================== + +#if USE_WPF + private static Dictionary referableHashToCachedBitmap = + new Dictionary(); +#else + private static Dictionary referableHashToCachedBitmap = + new Dictionary(); +#endif + #endregion + + #region Constructors, as for WPF control + //============= + + public AIDAnyUiControl() + { +#if JUST_FOR_INFO + // Timer for loading + //System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer(); + //dispatcherTimer.Tick += DispatcherTimer_Tick; + //dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000); + //dispatcherTimer.Start(); + + //var _timer = new System.Threading.Timer((e) => + //{ + // DispatcherTimer_Tick(null, null); + //}, null, TimeSpan.FromMilliseconds(2000), TimeSpan.FromMilliseconds(1000)); + + // see: https://stackoverflow.com/questions/5143599/detecting-whether-on-ui-thread-in-wpf-and-winforms + //var dispatcher = System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread); + //if (dispatcher != null) + //{ + // var dispatcherTimer = new System.Windows.Threading.DispatcherTimer(); + // dispatcherTimer.Tick += DispatcherTimer_Tick; + // dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000); + // dispatcherTimer.Start(); + //} + //else + //{ + // // Note: this timer shall work for all sorts of applications? + // // see: https://stackoverflow.com/questions/21041299/c-sharp-dispatchertimer-in-dll-application-never-triggered + // var _timer2 = new System.Timers.Timer(1000); + // _timer2.Elapsed += DispatcherTimer_Tick; + // _timer2.Enabled = true; + // _timer2.Start(); + //} +#endif +#if USE_WPF + AnyUiHelper.CreatePluginTimer(1000, DispatcherTimer_Tick); +#else + // Note: this timer shall work for all sorts of applications? + // see: https://stackoverflow.com/questions/21041299/c-sharp-dispatchertimer-in-dll-application-never-triggered + _dispatcherTimer = new System.Timers.Timer(1000); + _dispatcherTimer.Elapsed += DispatcherTimer_Tick; + _dispatcherTimer.Enabled = true; + _dispatcherTimer.Start(); +#endif + + CurrInst = "" + InstCounter; + InstCounter++; + + } + + public void Dispose() + { + if (_dispatcherTimer != null) + { + _dispatcherTimer.Stop(); + _dispatcherTimer.Dispose(); + } + } + + public void Start( + LogInstance log, + AdminShellPackageEnv thePackage, + Aas.Submodel theSubmodel, + PluginEventStack eventStack, + PluginSessionBase session, + AnyUiStackPanel panel, + PluginOperationContextBase opContext, + AnyUiContextPlusDialogs cdp, + AasxPluginBase plugin) + { + _log = log; + _package = thePackage; + _submodel = theSubmodel; + _eventStack = eventStack; + _session = session; + _panel = panel; + _opContext = opContext; + _displayContext = cdp; + _plugin = plugin; + + // no form, yet + _formDoc = null; + + // fill given panel + RenderFullShelf(_panel, _uitk); + } + + public static AIDAnyUiControl FillWithAnyUiControls( + LogInstance log, + object opackage, object osm, + PluginEventStack eventStack, + PluginSessionBase session, + object opanel, + PluginOperationContextBase opContext, + AnyUiContextPlusDialogs cdp, + AasxPluginBase plugin) + { + // 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(); + + // do NOT create WPF controls + FormInstanceBase.createSubControls = false; + + // factory this object + var shelfCntl = new AIDAnyUiControl(); + shelfCntl.Start(log, package, sm, eventStack, session, panel, opContext, cdp, plugin); + + // return shelf + return shelfCntl; + } + + #endregion + + #region Display Submodel + //============= + + private void RenderFullShelf(AnyUiStackPanel view, AnyUiSmallWidgetToolkit uitk) + { + // test trivial access + if ( _submodel?.SemanticId == null) + return; + + var found = false; + if (_submodel.SemanticId.GetAsExactlyOneKey().Value.ToString() == "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Submodel") + found = true; + + if (!found) + return; + + // set usage info + string useinf = null; + + // what defaultLanguage + string defaultLang = "en"; + + // make new list box items + _renderedInterfaces = new List(); + // ReSharper disable ExpressionIsAlwaysNull + _renderedInterfaces = ListOfInterfaceEntity.ParseSubmodelAID( + _package, _submodel); + // bring it to the panel + RenderPanelOutside(view, uitk, useinf, defaultLang, _renderedInterfaces); + } + + protected double _lastScrollPosition = 0.0; + + protected void RenderPanelOutside( + AnyUiStackPanel view, AnyUiSmallWidgetToolkit uitk, + string usageInfo, + string defaultLanguage, + List its, + double? initialScrollPos = null) + { + var outer = view.Add(uitk.AddSmallGrid(rows: 4, cols: 1, colWidths: new[] { "*" })); + outer.RowDefinitions[2].Height = new AnyUiGridLength(1.0, AnyUiGridUnitType.Star); + + // at top, make buttons for the general form + var header = uitk.AddSmallGridTo(outer, 0, 0, rows: 2, cols: 5, + colWidths: new[] { "*", "#", "#", "#", "#" }); + + header.Margin = new AnyUiThickness(0); + header.Background = AnyUiBrushes.LightBlue; + + // + // Blue bar + // + + uitk.AddSmallBasicLabelTo(header, 0, 0, margin: new AnyUiThickness(8, 6, 0, 6), + foreground: AnyUiBrushes.DarkBlue, + fontSize: 1.5f, + setBold: true, + content: $"AssetInterfaceDescriptions"); + + if (_opContext?.IsDisplayModeEditOrAdd == true) + AnyUiUIElement.RegisterControl( + uitk.AddSmallButtonTo(header, 0, 2, + margin: new AnyUiThickness(2), setHeight: 21, + padding: new AnyUiThickness(2, 0, 2, 0), + content: "Add Interface Description .."), + setValueAsync: (o) => ButtonTabPanels_Click("ButtonAddInterface")); + // controls + var controls = uitk.AddSmallWrapPanelTo(outer, 1, 0, + background: AnyUiBrushes.MiddleGray, margin: new AnyUiThickness(0, 0, 0, 2)); + + AnyUiButton importButton = null; + + importButton = AnyUiUIElement.RegisterControl(controls.Add(new AnyUiButton() + { + Margin = new AnyUiThickness(2), + MinHeight = 21, + Content = "Import Interface Description .." + }), (o) => + { + ButtonTabPanels_Click("ButtonImportInterface"); + return new AnyUiLambdaActionNone(); + }); + + // + // Scroll area + // + + // small spacer + outer.RowDefinitions[2] = new AnyUiRowDefinition(2.0, AnyUiGridUnitType.Pixel); + uitk.AddSmallBasicLabelTo(outer, 2, 0, + fontSize: 0.3f, + verticalAlignment: AnyUiVerticalAlignment.Top, + content: "", background: AnyUiBrushes.White); + + // add the body, a scroll viewer + outer.RowDefinitions[3] = new AnyUiRowDefinition(1.0, AnyUiGridUnitType.Star); + var scroll = AnyUiUIElement.RegisterControl( + uitk.AddSmallScrollViewerTo(outer, 3, 0, + horizontalScrollBarVisibility: AnyUiScrollBarVisibility.Disabled, + verticalScrollBarVisibility: AnyUiScrollBarVisibility.Visible, + flattenForTarget: AnyUiTargetPlatform.Browser, initialScrollPosition: initialScrollPos), + (o) => + { + if (o is Tuple positions) + { + _lastScrollPosition = positions.Item2; + } + return new AnyUiLambdaActionNone(); + }); + + // need a stack panel to add inside + var inner = new AnyUiStackPanel() { Orientation = AnyUiOrientation.Vertical }; + scroll.Content = inner; + + // render the innerts of the scroll viewer + inner.Background = AnyUiBrushes.LightGray; + + if (its != null) + foreach (var de in its) + { + var rde = RenderAnyUiInterfaceEntity(uitk, de); + if (rde != null) + inner.Add(rde); + } + + // post process + if (its != null) + foreach (var ent in its) + { + // attach events and add + ent.DoubleClick += InterfaceEntity_DoubleClick; + ent.MenuClick += InterfaceEntity_MenuClick; + } + } + + public AnyUiFrameworkElement RenderAnyUiInterfaceEntity( + AnyUiSmallWidgetToolkit uitk, InterfaceEntity de) + { + // access + if (de == null) + return new AnyUiStackPanel(); + + // make a outer grid + var outerG = uitk.AddSmallGrid(1, 1, + colWidths: new[] { "*" }, rowHeights: new[] { "*" }, + margin: new AnyUiThickness(0)); + + // make background border + for (int i = 2; i > 0; i--) + uitk.Set( + uitk.AddSmallBorderTo(outerG, 0, 0, + margin: new AnyUiThickness(3 + 2 * i, 3 + 2 * i, 3 + 4 - 2 * i, 3 + 4 - 2 * i), + background: AnyUiBrushes.White, + borderBrush: AnyUiBrushes.Black, + borderThickness: new AnyUiThickness(1.0)), + skipForTarget: AnyUiTargetPlatform.Browser); + + // make the border, which will get content + var border = uitk.AddSmallBorderTo(outerG, 0, 0, + margin: new AnyUiThickness(3, 3, 3 + 4, 3 + 4), + background: AnyUiBrushes.White, + borderBrush: AnyUiBrushes.Black, + borderThickness: new AnyUiThickness(1.0)); + + // the border emits double clicks + border.EmitEvent = AnyUiEventMask.LeftDouble; + border.setValueLambda = (o) => + { + if (o is AnyUiEventData ed + && ed.Mask == AnyUiEventMask.LeftDouble + && ed.ClickCount == 2) + { + de.RaiseDoubleClick(); + } + return new AnyUiLambdaActionNone(); + }; + + // make a grid + var g = uitk.AddSmallGrid(4, 4, + colWidths: new[] { "*", "5:", "*", "22:" }, + rowHeights: new[] { "*", "5:", "*", "25:" }, + margin: new AnyUiThickness(1), + background: AnyUiBrushes.White); + border.Child = g; + + uitk.AddSmallBasicLabelTo(g, 0, 0, + textIsSelectable: false, + margin: new AnyUiThickness(2), + verticalAlignment: AnyUiVerticalAlignment.Center, + verticalContentAlignment: AnyUiVerticalAlignment.Center, + fontSize: 1.0f, + content: "Title : " + $"{de.Title}"); + + + uitk.AddSmallBasicLabelTo(g, 0, 2, + textIsSelectable: false, + margin: new AnyUiThickness(2), + verticalAlignment: AnyUiVerticalAlignment.Center, + verticalContentAlignment: AnyUiVerticalAlignment.Center, + fontSize: 1.0f, + content: "Created : " + $"{de.Created}"); + + uitk.AddSmallBasicLabelTo(g, 2, 0, + textIsSelectable: false, + margin: new AnyUiThickness(2), + verticalAlignment: AnyUiVerticalAlignment.Center, + verticalContentAlignment: AnyUiVerticalAlignment.Center, + fontSize: 1.0f, + content: "contentType : " + $"{de.ContentType}"); + + + uitk.AddSmallBasicLabelTo(g, 2, 2, + textIsSelectable: false, + margin: new AnyUiThickness(2), + verticalAlignment: AnyUiVerticalAlignment.Center, + verticalContentAlignment: AnyUiVerticalAlignment.Center, + fontSize: 1.0f, + content: "ProtocolType : " + $"{de.ProtocolType}"); + + var hds = new List(); + if (_opContext?.IsDisplayModeEditOrAdd == true) + { + hds.AddRange(new[] { "\u270e", "Edit Interface Data" }); + hds.AddRange(new[] { "\u2702", "Delete Interface Data" }); + } + else + hds.AddRange(new[] { "\u270e", "View Interface Data" }); + + hds.AddRange(new[] { "\U0001F4BE", "Save to thing description file .." }); + + // context menu + uitk.AddSmallContextMenuItemTo(g, 3, 3, + "\u22ee", + hds.ToArray(), + margin: new AnyUiThickness(2, 2, 2, 2), + padding: new AnyUiThickness(5, 0, 5, 0), + fontWeight: AnyUiFontWeight.Bold, + menuItemLambda: null, + menuItemLambdaAsync: async (o) => + { + if (o is int ti && ti >= 0 && ti < hds.Count) + // awkyard, but for compatibility to WPF version + await de?.RaiseMenuClick(hds[2 * ti + 1], null); + return new AnyUiLambdaActionNone(); + }); + + // ok + return outerG; + } + + #endregion + + #region Create entity + //===================== + + protected AnyUiPanelEntity _formEntity = null; + + protected class AnyUiPanelEntity + { + public string IdShort = ""; + + public void RenderAnyUi( + AnyUiStackPanel view, AnyUiSmallWidgetToolkit uitk, + Func> lambdaCancel = null, + Func> lambdaAdd = null) + { + // + // make an outer grid, very simple grid of rows: header, spacer, body + // + + var outer = view.Add(uitk.AddSmallGrid(rows: 3, cols: 1, colWidths: new[] { "*" })); + outer.RowDefinitions[2].Height = new AnyUiGridLength(1.0, AnyUiGridUnitType.Star); + + // at top, make buttons for the general form + var header = uitk.AddSmallGridTo(outer, 0, 0, 1, cols: 5, colWidths: new[] { "*", "#", "#", "#", "#" }); + + header.Margin = new AnyUiThickness(0); + header.Background = AnyUiBrushes.LightBlue; + + // + // Blue bar + // + + uitk.AddSmallBasicLabelTo(header, 0, 0, margin: new AnyUiThickness(8, 6, 0, 6), + foreground: AnyUiBrushes.DarkBlue, + fontSize: 1.5f, + setBold: true, + content: $"Entity"); + + AnyUiUIElement.RegisterControl( + uitk.AddSmallButtonTo(header, 0, 1, + margin: new AnyUiThickness(2), setHeight: 21, + padding: new AnyUiThickness(4, 0, 4, 0), + content: "Cancel"), + setValueAsync: lambdaCancel); + + AnyUiUIElement.RegisterControl( + uitk.AddSmallButtonTo(header, 0, 2, + margin: new AnyUiThickness(2), setHeight: 21, + padding: new AnyUiThickness(4, 0, 4, 0), + content: "Add"), + setValueAsync: lambdaAdd); + + // 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); + + // + // Grid with entries + // + + var body = uitk.AddSmallGridTo(outer, 2, 0, rows: 1, cols: 2, + colWidths: new[] { "#", "*" }, + background: AnyUiBrushes.LightGray); + + uitk.AddSmallBasicLabelTo(body, 0, 0, + verticalAlignment: AnyUiVerticalAlignment.Center, + verticalContentAlignment: AnyUiVerticalAlignment.Center, + margin: new AnyUiThickness(0, 0, 4, 0), + textWrapping: AnyUiTextWrapping.NoWrap, + content: "idShort:"); + + AnyUiUIElement.RegisterControl( + uitk.AddSmallTextBoxTo(body, 0, 1, + margin: new AnyUiThickness(2, 10, 2, 10), + text: "" + IdShort), + (o) => + { + if (o is string os) + IdShort = os; + return new AnyUiLambdaActionNone(); + }); + } + + } + + #endregion + + #region Event handling + //============= + + private Action _menuSubscribeForNextEventReturn = null; + + protected void PushUpdateEvent(AnyUiRenderMode mode = AnyUiRenderMode.All) + { + // bring it to the panel by redrawing the plugin + _eventStack?.PushEvent(new AasxPluginEventReturnUpdateAnyUi() + { + // get the always currentplugin name + PluginName = "AasxPluginAID", + Session = _session, + Mode = mode, + UseInnerGrid = true + }); + } + + protected void PushUpdatenRedrawEvent(AnyUiRenderMode mode = AnyUiRenderMode.All) + { + // bring it to the panel by redrawing the plugin + _eventStack?.PushEvent(new AasxPluginEventReturnUpdateAnyUi() + { + // get the always currentplugin name + PluginName = "AasxPluginAID", + Session = _session, + Mode = mode, + UseInnerGrid = true + }); + + _eventStack?.PushEvent(new AasxPluginResultEventRedrawAllElements() + { + Session = _session, + }); + } + + public void HandleEventReturn(AasxPluginEventReturnBase evtReturn) + { + // demands from shelf + if (_menuSubscribeForNextEventReturn != null) + { + // delete first + var tempLambda = _menuSubscribeForNextEventReturn; + _menuSubscribeForNextEventReturn = null; + + // execute + tempLambda(evtReturn); + + // finish + return; + } + + // check, if a form is active + if (_formDoc != null) + { + _formDoc.HandleEventReturn(evtReturn); + } + } + + #endregion + + #region Update + //============= + + public void Update(params object[] args) + { + // check args + if (args == null || args.Length < 2 + || !(args[0] is AnyUiStackPanel newPanel) + || !(args[1] is AnyUiContextPlusDialogs newCdp)) + return; + + // ok, re-assign panel and re-display + _displayContext = newCdp; + _panel = newPanel; + _panel.Children.Clear(); + + // multiple different views can be renders + if (_formEntity != null) + { + _formEntity.RenderAnyUi(_panel, _uitk, + lambdaCancel: (o) => ButtonTabPanels_Click("ButtonCancelEntity"), + lambdaAdd: (o) => ButtonTabPanels_Click("ButtonAddEntity")); + } + else + if (_formDoc != null) + { + if (_opContext?.IsDisplayModeEditOrAdd == true) + { + _formDoc.RenderFormInst(_panel, _uitk, _opContext, + setLastScrollPos: true, + lambdaFixCds: (o) => ButtonTabPanels_Click("ButtonFixCDs"), + lambdaCancel: (o) => ButtonTabPanels_Click("ButtonCancel"), + lambdaOK: (o) => ButtonTabPanels_Click("ButtonUpdate")); + } + else + { + _formDoc.RenderFormInst(_panel, _uitk, _opContext, + setLastScrollPos: true, + lambdaCancel: (o) => ButtonTabPanels_Click("ButtonCancel")); + } + } + else + { + // the default: the full shelf + RenderFullShelf(_panel, _uitk); + } + } + + #endregion + + #region Callbacks + //=============== + + private List _updateSourceElements = null; + private async Task InterfaceEntity_MenuClick(InterfaceEntity e, string menuItemHeader, object tag) + { + // first check + if (e == null || menuItemHeader == null) + return; + + // what to do? + if (tag == null + && (menuItemHeader == "Edit Interface Data" || menuItemHeader == "View Interface Data")) + { + // lambda + Action lambda = (desc) => + { + var fi = new FormInstanceSubmodelElementCollection(null, desc); + fi.PresetInstancesBasedOnSource(_updateSourceElements); + fi.outerEventStack = _eventStack; + fi.OuterPluginName = _plugin?.GetPluginName(); + fi.OuterPluginSession = _session; + + // initialize form + _formDoc = new AnyUiRenderForm( + fi, + updateMode: true); + PushUpdateEvent(); + }; + + var desc = AIDSemanticConfig.CreateAssetInterfaceDescription(); + _updateSourceElements = e.SourceElementsInterface; + + lambda(desc); + + // OK + return; + } + + if (tag == null && menuItemHeader == "Delete Interface Data" && _submodel?.SubmodelElements != null + && _opContext?.IsDisplayModeEditOrAdd == true) + { + // the source elements need to match a Document + var semConf = IDTAAid.Static.AID_Interface; + var found = false; + foreach (var smcDoc in + _submodel.SubmodelElements.FindAllSemanticIdAs( + semConf, MatchMode.Relaxed)) + if (smcDoc?.Value == e.SourceElementsInterface) + { + // ask back via display context + if (AnyUiMessageBoxResult.Cancel == await _displayContext?.MessageBoxFlyoutShowAsync( + "Delete Interface description? This cannot be reverted!", + "AssetInterfaceDescriptions", + AnyUiMessageBoxButton.OKCancel, + AnyUiMessageBoxImage.Question)) + return; + + // do it + try + { + _submodel.SubmodelElements.Remove(smcDoc); + e.SourceElementsInterface.Remove(smcDoc); + + // re-display also in Explorer + _eventStack?.PushEvent(new AasxPluginResultEventRedrawAllElements() + { Session = _session }); + + // log + _log?.Info("Deleted Interface description."); + } + catch (Exception ex) + { + _log?.Error(ex, "while saveing digital file to user specified loacation"); + } + + // OK + return; + + // ReSharper enable PossibleMultipleEnumeration + } + + if (!found) + _log?.Error("Document element was not found properly!"); + } + + // show digital file + if (tag == null && menuItemHeader == "View file") + InterfaceEntity_DisplaySaveFileAsync(e, true, false); + + // save digital file? + if (tag == null && menuItemHeader == "Save to thing description file ..") + { + InterfaceEntity_DisplaySaveFileAsync(e, true, true); + } + + } + private async Task InterfaceEntity_DisplaySaveFileAsync(InterfaceEntity e, bool display, bool save) + { + try + { + if (e.SourceElementsInterface.Count == 0) + { + return; + } + Aas.ISubmodelElementCollection dmc = e.SourceElementsInterface[0].Parent as Aas.ISubmodelElementCollection; + var uc = await _displayContext.MenuSelectSaveFilenameAsync( + ticket: null, argName: null, + caption: "Select preset JSON file to save ..", + proposeFn: e.InterfaceName + ".json", + filter: "Preset JSON file (*.json)|*.json|All files (*.*)|*.*", + msg: "Not found"); + + + + JObject tdJson = AIDTDExport.ExportInterfacetoTDJson(dmc); + using (var s = new StreamWriter(uc.TargetFileName as string)) + { + string output = Newtonsoft.Json.JsonConvert.SerializeObject(tdJson, + Newtonsoft.Json.Formatting.Indented); + s.WriteLine(output); + } + } + catch (Exception ex) + { + _log?.Error(ex, "when executing file action"); + return; + } + } + private void InterfaceEntity_DoubleClick(InterfaceEntity e) + { + InterfaceEntity_DisplaySaveFileAsync(e, true, false); + } + private async Task ButtonTabPanels_Click(string cmd, string args = null) + { + if (cmd == "ButtonCancel") + { + // re-display (tree & panel) + return new AnyUiLambdaActionRedrawAllElementsBase() { RedrawCurrentEntity = true }; + } + + if (cmd == "ButtonUpdate") + { + // add + if (this._formDoc != null + && _package != null + && _submodel != null) + { + // on this level of the hierarchy, shall a new SMEC be created or shall + // the existing source of elements be used? + List currentElements = null; + if (_formDoc.InUpdateMode) + { + currentElements = _updateSourceElements; + } + else + { + currentElements = new List(); + } + + // create a sequence of SMEs + try + { + if (_formDoc.FormInstance is FormInstanceSubmodelElementCollection fismec) + fismec.AddOrUpdateDifferentElementsToCollection( + currentElements, _package, addFilesToPackage: true); + + _log?.Info("Document elements updated. Do not forget to save, if necessary!"); + } + catch (Exception ex) + { + _log?.Error(ex, "when adding Document"); + } + // the InstSubmodel, which started the process, should have a "fresh" SMEC available + // make it unique in the Documentens Submodel + var newSmc = (_formDoc.FormInstance as FormInstanceSubmodelElementCollection)?.sme + as Aas.SubmodelElementCollection; + + // if not update, put them into the Document's Submodel + if (!_formDoc.InUpdateMode && currentElements != null && newSmc != null) + { + // make newSmc unique in the cotext of the Submodel + FormInstanceHelper.MakeIdShortUnique(_submodel.SubmodelElements, newSmc); + + // add the elements + newSmc.Value = currentElements; + + // add the whole SMC + _submodel.Add(newSmc); + } + } + else + { + _log?.Error("Preconditions for update entities from Document not met."); + } + // re-display (tree & panel) + return new AnyUiLambdaActionRedrawAllElementsBase() { NextFocus = _submodel }; + } + + if (cmd == "ButtonAddInterface") + { + Action lambda = (desc) => + { + var fi = new FormInstanceSubmodelElementCollection(null, desc); + fi.outerEventStack = _eventStack; + fi.OuterPluginName = _plugin?.GetPluginName(); + fi.OuterPluginSession = _session; + + // initialize form + _formDoc = new AnyUiRenderForm( + fi, + updateMode: false); + + // bring it to the panel by redrawing the plugin + PushUpdateEvent(); + }; + + var desc = AIDSemanticConfig.CreateAssetInterfaceDescription(); + _updateSourceElements = null; + lambda(desc); + + return new AnyUiLambdaActionNone(); + } + + if (cmd == "ButtonImportInterface") + { + var uc = await _displayContext.MenuSelectOpenFilenameAsync( + ticket: null, argName: null, + caption: "Select JSON file to import..", + proposeFn: null, filter: "Preset JSON file (*.json)|*.json|All files (*.*)|*.*", + msg: "Not found"); + + + string text = System.IO.File.ReadAllText(uc.TargetFileName); + JObject tdJObject; + using (var tdStringReader = new StringReader(text)) + using (var jsonTextReader = new JsonTextReader(tdStringReader) + { DateParseHandling = DateParseHandling.None }) + { + tdJObject = JObject.FromObject(JToken.ReadFrom(jsonTextReader)); + } + var targetPath = "/aasx/files/"; + var onlyFn = System.IO.Path.GetFileNameWithoutExtension(uc.TargetFileName); + var onlyExt = System.IO.Path.GetExtension(uc.TargetFileName); + var salt = Guid.NewGuid().ToString().Substring(0, 8); + var targetFn = String.Format("{0}_{1}{2}", onlyFn, salt, onlyExt); + + var desc = AIDTDImport.CreateAssetInterfaceDescriptionFromTd(tdJObject, + targetPath + "/"+targetFn,_submodel.Id.ToString(),_submodel.SubmodelElements.Count,"JSONLD"); + _submodel.Add(desc); + PushUpdatenRedrawEvent(); + return new AnyUiLambdaActionRedrawAllElementsBase() { NextFocus = _submodel }; + } + + if (cmd == "ButtonCancelEntity") + { + // reset view + _formEntity = null; + _formDoc = null; + + // redisplay + PushUpdateEvent(); + return new AnyUiLambdaActionNone(); + } + + return new AnyUiLambdaActionNone(); + } + #endregion + + #region Timer + //=========== + + protected int _dispatcherNumException = 0; + + private void DispatcherTimer_Tick(object sender, EventArgs e) + { + + } + #region Utilities + //=============== + + #endregion + } +} +#endregion \ No newline at end of file diff --git a/src/AasxPluginAID/AIDSemanticConfig.cs b/src/AasxPluginAID/AIDSemanticConfig.cs new file mode 100644 index 000000000..837977918 --- /dev/null +++ b/src/AasxPluginAID/AIDSemanticConfig.cs @@ -0,0 +1,118 @@ +/* +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.Text; +using System.Threading.Tasks; +using AasxIntegrationBase; +using AasxIntegrationBase.AasForms; +using AasxPredefinedConcepts; +using Aas = AasCore.Aas3_0; +using AdminShellNS; +using Extensions; +using Newtonsoft.Json; +using AasxPluginAID; +using Microsoft.VisualBasic; +using AnyUi; +using Newtonsoft.Json.Linq; +using System.Windows.Forms; +using AasCore.Aas3_0; +using ImageMagick; +using JetBrains.Annotations; + +namespace AasxPluginAID +{ + public class AIDSemanticConfig + + { + public Aas.Key SemIdReferencedObject = null; + public static AasxPredefinedConcepts.IDTAAid idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + public static FormDescSubmodelElement BuildUIFormElem(JToken formElem) + { + JObject elemJObject = JObject.FromObject(formElem); + + string elem = elemJObject["formtext"].ToString(); + string elemType = elemJObject["AasElementType"].ToString(); + string presetIdShort = elemJObject["presetIdShort"].ToString(); + + FormMultiplicity multiplicity = idtaDef.GetFormMultiplicity(elemJObject["multiplcity"].ToString()); + Aas.Key semanticReferenceKey = idtaDef.ConstructKey(KeyTypes.GlobalReference, elemJObject["semanticReference"].ToString()); + + LangStringTextType description = new Aas.LangStringTextType("en", elemJObject["description"].ToString()); + + if (elemType == "Property") + { + string valueType = elemJObject["valueType"].ToString(); + FormDescProperty _propertyFrom = new FormDescProperty(elem, + multiplicity,semanticReferenceKey, presetIdShort, + valueType: valueType); + _propertyFrom.PresetDescription.Add(description); + + return _propertyFrom; + } + else if (elemJObject["AasElementType"].ToString() == "SubmodelElementCollection") + { + FormDescSubmodelElementCollection _formCollection = new FormDescSubmodelElementCollection(elem, + multiplicity, semanticReferenceKey, presetIdShort + ); + _formCollection.PresetDescription.Add(description); + foreach (var childElem in elemJObject["childs"]) + { + _formCollection.Add(BuildUIFormElem(childElem)); + } + return _formCollection; + } + else if (elemJObject["AasElementType"].ToString() == "Range") + { + string valueType = elemJObject["valueType"].ToString(); + FormDescRange _rangeFrom = new FormDescRange(elem, + multiplicity, semanticReferenceKey, presetIdShort, + valueType: valueType); + _rangeFrom.PresetDescription.Add(new Aas.LangStringTextType("en", elemJObject["description"].ToString())); + + return _rangeFrom; + } + else if (elemJObject["AasElementType"].ToString() == "ReferenceElement") + { + FormDescReferenceElement _referenceElementFrom = new FormDescReferenceElement(elem, + multiplicity, semanticReferenceKey, presetIdShort + ); + _referenceElementFrom.PresetDescription.Add(new Aas.LangStringTextType("en", elemJObject["description"].ToString())); + + return _referenceElementFrom; + } + else if (elemJObject["AasElementType"].ToString() == "File") + { + FormDescFile _fileElementForm = new FormDescFile(elem, + multiplicity, semanticReferenceKey, presetIdShort + ); + + return _fileElementForm; + } + return null; + } + public static FormDescSubmodelElementCollection CreateAssetInterfaceDescription() + { + try + { + FormDescSubmodelElementCollection interfaceDescription = BuildUIFormElem(idtaDef.EndpointMetadataJObject["interface"]) as FormDescSubmodelElementCollection; + + return interfaceDescription; + } + catch(Exception ex) { + Console.WriteLine(ex.ToString()); + return null; + } + } + + } +} \ No newline at end of file diff --git a/src/AasxPluginAID/AIDTDExport.cs b/src/AasxPluginAID/AIDTDExport.cs new file mode 100644 index 000000000..20df8bff0 --- /dev/null +++ b/src/AasxPluginAID/AIDTDExport.cs @@ -0,0 +1,154 @@ +using AasCore.Aas3_0; +using Extensions; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using Aas = AasCore.Aas3_0; + +namespace AasxPluginAID +{ + class AIDTDExport + { + public static AasxPredefinedConcepts.IDTAAid idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + public static JToken TDelemDefinition(ISubmodelElement se, JObject tdSchemaObject, string addParams = null) + { + string semanticReference = se.SemanticId.GetAsExactlyOneKey().Value; + + foreach (var child in tdSchemaObject["childs"]) + { + JObject childElemJObject = JObject.FromObject(child); + if (childElemJObject["semanticReference"].ToString() == semanticReference) + { + return child; + } + } + return null; + } + public static JObject serialize_aid_elem(JToken tdJToken, Aas.ISubmodelElement sme) + { + JObject TDJson = new JObject(); + JObject tdSchemaObject = JObject.FromObject(tdJToken); + string presetIdShort = tdSchemaObject["presetIdShort"].ToString(); + string elemType = tdSchemaObject["AasElementType"].ToString(); + string semanticReference = tdSchemaObject["semanticReference"].ToString(); + string multiplcity = tdSchemaObject["multiplcity"].ToString(); + + if (elemType == "Property") + { + Aas.Property _property = sme as Aas.Property; + TDJson[sme.IdShort] = _property.Value.ToString(); + } + else if (elemType == "Range") + { + Aas.Range _range = sme as Aas.Range; + if (_range.IdShort == "min_max") + { + TDJson["minimum"] = _range.Min; + TDJson["maximum"] = _range.Max; + } + if (_range.IdShort == "lengthRange") + { + TDJson["minLength"] = _range.Min; + TDJson["maxLength"] = _range.Max; + } + if (_range.IdShort == "itemsRange") + { + TDJson["minItems"] = _range.Min; + TDJson["maxItems"] = _range.Max; + } + } + else if (elemType == "SubmodelElementCollection") + { + Aas.ISubmodelElementCollection smc = sme as Aas.SubmodelElementCollection; + if (presetIdShort == "scopes" || presetIdShort == "enum" || presetIdShort == "security") + { + List listElem = new List(); + foreach (var se in smc.Value) + { + if (presetIdShort == "security") + { + Aas.ReferenceElement referenceElem = se as Aas.ReferenceElement; + listElem.Add(referenceElem.Value.Keys.Last().Value.ToString()); + } + else + { + Aas.Property _property = se as Aas.Property; + listElem.Add(_property.Value.ToString()); + } + } + TDJson[presetIdShort] = JToken.FromObject(listElem); + } + else if (presetIdShort == "forms") + { + List forms = new List(); + Aas.ISubmodelElementCollection formsSC = sme as Aas.SubmodelElementCollection; + foreach (var form in formsSC.Value) + { + JToken formSchemadefinition = TDelemDefinition(form, tdSchemaObject); + forms.Add(serialize_aid_elem(formSchemadefinition, form)[form.IdShort]); + } + TDJson["forms"] = JToken.FromObject(forms); + } + else + { + JObject smcJObject = new JObject(); + foreach (var se in smc.Value) + { + JToken childSchemaDefinition = TDelemDefinition(se, tdSchemaObject); + JObject serializeJObject = serialize_aid_elem(childSchemaDefinition, se); + smcJObject.Merge(JToken.FromObject(serializeJObject)); + } + if (semanticReference == "https://admin-shell.io/idta/AssetInterfaceDescription/1/0/PropertyDefinition" + || semanticReference == "https://www.w3.org/2019/wot/json-schema#propertyName") + { + TDJson[smcJObject["key"].ToString()] = JToken.FromObject(smcJObject); + } + else + { + TDJson[sme.IdShort] = JToken.FromObject(smcJObject); + } + } + } + + return TDJson; + } + public static JObject ExportInterfacetoTDJson(Aas.ISubmodelElementCollection smc) + { + JObject TDJson = new JObject(); + TDJson["@context"] = "https://www.w3.org/2019/wot/td/v1"; + TDJson["@type"] = "Thing"; + try + { + foreach (var se in smc.Value) + { + if (se.IdShort == "EndpointMetadata") + { + JToken endpointmetaData = serialize_aid_elem(idtaDef.EndpointMetadataJObject["interface"]["childs"][4], se)["EndpointMetadata"]; + TDJson.Merge(JObject.FromObject(endpointmetaData)); + } + else if (se.IdShort == "ExternalDescriptor") + { + + } + else if (se.IdShort == "InterfaceMetaData") + { + JToken InterfaceMetaData = serialize_aid_elem(idtaDef.EndpointMetadataJObject["interface"]["childs"][6], se)["InterfaceMetaData"]; + TDJson.Merge(JObject.FromObject(InterfaceMetaData)); + } + else + { + Aas.Property _property = se as Aas.Property; + TDJson[se.IdShort] = _property.Value.ToString(); + } + } + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } + return TDJson; + + } + } +} diff --git a/src/AasxPluginAID/AIDTDImport.cs b/src/AasxPluginAID/AIDTDImport.cs new file mode 100644 index 000000000..da716800f --- /dev/null +++ b/src/AasxPluginAID/AIDTDImport.cs @@ -0,0 +1,286 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Aas = AasCore.Aas3_0; +using Extensions; +using AasCore.Aas3_0; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.Xml.Linq; +using System.Security.Policy; +using System.Windows.Forms; +using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox; +using AasxIntegrationBase.AasForms; +using System.Text.RegularExpressions; + +namespace AasxPluginAID +{ + class AIDTDImport + { + public static string submodelId = null; + public static string interfaceId = null; + public static AasxPredefinedConcepts.IDTAAid idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + public static Aas.ISubmodelElement BuildAasElement(JObject tdJObject, JObject tdSchemaObject) + { + Aas.ISubmodelElement submodelElement = null; + Aas.Reference semanticReference = idtaDef.ConstructReference(tdSchemaObject["semanticReference"].ToString()); + FormMultiplicity multiplicity = idtaDef.GetFormMultiplicity(tdSchemaObject["multiplcity"].ToString()); + string presetIdShort = tdSchemaObject["presetIdShort"].ToString(); + string elemType = tdSchemaObject["AasElementType"].ToString(); + string formText = tdSchemaObject["formtext"].ToString(); + LangStringTextType description = new Aas.LangStringTextType("en", tdSchemaObject["description"].ToString()); + + if (elemType == "Property") + { + DataTypeDefXsd valueType = idtaDef.GetValueType( tdSchemaObject["valueType"].ToString()); + submodelElement = new Property(valueType, idShort:presetIdShort, + semanticId : semanticReference, description : new List { description }, + value: tdJObject[formText].ToString()); + return submodelElement; + } + else if (elemType == "SubmodelElementCollection") + { + submodelElement = new SubmodelElementCollection(idShort: presetIdShort, + semanticId: semanticReference, description: new List { description }); + foreach (var childSchemaElem in tdSchemaObject["childs"]) + { + JObject childSchemaElemObject = JObject.FromObject(childSchemaElem); + string celemType = childSchemaElemObject["AasElementType"].ToString(); + string cFormtext = childSchemaElemObject["formtext"].ToString(); + string cpresetIdShort = childSchemaElemObject["presetIdShort"].ToString(); + Aas.Reference csemanticReference = idtaDef.ConstructReference(childSchemaElemObject["semanticReference"].ToString()); + List cdescription = new List { new Aas.LangStringTextType("en", childSchemaElemObject["description"].ToString()) }; + if (tdJObject.ContainsKey(cFormtext)) + { + if (celemType == "SubmodelElementCollection") + { + if (cFormtext == "scopes" || cFormtext == "enum") + { + Aas.SubmodelElementCollection _elems = new SubmodelElementCollection(idShort: cpresetIdShort, + semanticId: csemanticReference, + description: cdescription); + JObject _cSchemaObject = JObject.FromObject(childSchemaElemObject["childs"][0]); + int j = 0; + foreach (var _scope in tdJObject[cFormtext]) + { + _elems.Add(new Property(Aas.DataTypeDefXsd.String, idShort: _cSchemaObject["presetIdShort"].ToString(), + semanticId: csemanticReference, description: new List { new Aas.LangStringTextType("en", "Authorization scope identifier") }, + value: _scope.ToString())); + j++; + } + submodelElement.Add(_elems); + } + else if (cFormtext == "security") + { + Aas.SubmodelElementCollection security = new SubmodelElementCollection(idShort: cpresetIdShort, + semanticId: csemanticReference, + description: cdescription); + int j = 0; + foreach (var _security in tdJObject["security"]) + { + List _keys = new List + { + idtaDef.ConstructKey(KeyTypes.Submodel,submodelId), + idtaDef.ConstructKey(KeyTypes.SubmodelElementCollection,interfaceId), + idtaDef.ConstructKey(KeyTypes.SubmodelElementCollection,"EndpointMetadata"), + idtaDef.ConstructKey(KeyTypes.SubmodelElementCollection,"securityDefinitions"), + idtaDef.ConstructKey(KeyTypes.SubmodelElementCollection,_security.ToString()) + }; + + Aas.ReferenceElement _secRef = new ReferenceElement(idShort: "security" + string.Format("{00:00}", j), + semanticId: csemanticReference, description: new List { new Aas.LangStringTextType("en", "Reference element to security scheme definition") }, + value: new Reference(ReferenceTypes.ModelReference, _keys)); + + security.Add(_secRef); + j++; + } + submodelElement.Add(security); + } + else if (cFormtext == "properties") + { + Aas.SubmodelElementCollection propoerties = new SubmodelElementCollection(idShort: cpresetIdShort, + semanticId: csemanticReference, + description: cdescription); + foreach(JProperty _property in tdJObject["properties"]) + { + string _key = _property.Name; + JObject propertyJObject = JObject.FromObject(_property.Value); + JObject propertySchemaJObject = JObject.FromObject(childSchemaElemObject["childs"][0]); + Aas.SubmodelElementCollection _propertySMC = BuildAasElement(propertyJObject, propertySchemaJObject) as Aas.SubmodelElementCollection; + _propertySMC.Add(new Aas.Property(Aas.DataTypeDefXsd.String, idShort: "key", + semanticId: semanticReference, description: new List { new Aas.LangStringTextType("en", "Optional element when the idShort of {property_name} cannot be used to reflect the desired property name due to the idShort restrictions ") }, + value : _key)); + propoerties.Add(_propertySMC); + } + submodelElement.Add(propoerties); + } + else if (cFormtext == "forms") + { + Aas.SubmodelElementCollection forms = new SubmodelElementCollection(idShort: cpresetIdShort, + semanticId: csemanticReference, + description: cdescription); + foreach (var _form in tdJObject["forms"]) + { + JObject formJObject = JObject.FromObject(_form); + List keys = formJObject.Properties().Select(p => p.Name).ToList(); + if (keys.Contains("htv_methodName")) + { + JObject formSchemaJObject = JObject.FromObject(childSchemaElemObject["childs"][0]); + forms.Add(BuildAasElement(formJObject, formSchemaJObject)); + } + else if (isMQTTForm(keys)) + { + JObject formSchemaJObject = JObject.FromObject(childSchemaElemObject["childs"][1]); + forms.Add(BuildAasElement(formJObject, formSchemaJObject)); + } + else if (isModBusForm(keys)) + { + JObject formSchemaJObject = JObject.FromObject(childSchemaElemObject["childs"][2]); + forms.Add(BuildAasElement(formJObject, formSchemaJObject)); + } + break; + } + submodelElement.Add(forms); + } + else + { + JObject childTDJobject = JObject.FromObject(tdJObject[cFormtext]); + submodelElement.Add(BuildAasElement(childTDJobject, childSchemaElemObject)); + } + } + else if (celemType == "Property") + { + submodelElement.Add(BuildAasElement(tdJObject, childSchemaElemObject)); + } + } + else if (celemType == "Range") + { + DataTypeDefXsd valueType = idtaDef.GetValueType(childSchemaElemObject["valueType"].ToString()); + + Aas.Range _range = new Aas.Range(Aas.DataTypeDefXsd.String, idShort: cpresetIdShort, + semanticId: csemanticReference, description: cdescription); + if (cFormtext == "min_max") + { + if (tdJObject.ContainsKey("minimum")) + { + _range.Min = tdJObject["minimum"].ToString(); + } + if (tdJObject.ContainsKey("maximum")) + { + _range.Max = tdJObject["maximum"].ToString(); + } + } + else if (cFormtext == "itemsRange") + { + if (tdJObject.ContainsKey("minItems")) + { + _range.Min = tdJObject["minItems"].ToString(); + } + if (tdJObject.ContainsKey("maxItems")) + { + _range.Max = tdJObject["maxItems"].ToString(); + } + } + else if (cFormtext == "lengthRange") + { + if (tdJObject.ContainsKey("minLength")) + { + _range.Min = tdJObject["minLength"].ToString(); + } + if (tdJObject.ContainsKey("maxLength")) + { + _range.Max = tdJObject["maxLength"].ToString(); + } + } + submodelElement.Add(_range); + } + } + return submodelElement; + } + return submodelElement; + + } + public static Boolean isMQTTForm(List keysList) + { + foreach (string key in idtaDef.mqttFormElemList) + { + if (keysList.Contains(key)) + return true; + } + return false; + } + public static Boolean isModBusForm(List keysList) + { + foreach (string key in idtaDef.modvFormElemList) + { + if (keysList.Contains(key)) + return true; + } + return false; + } + public static SubmodelElementCollection BuildExternalDescriptor(string filename,JToken externalDescriptionTdObject, string contentType) + { + Aas.SubmodelElementCollection externalDescriptor = new Aas.SubmodelElementCollection(); + externalDescriptor.IdShort = "ExternalDescriptor"; + externalDescriptor.AddDescription("en", externalDescriptionTdObject["description"].ToString()); + externalDescriptor.SemanticId = idtaDef.ConstructReference(externalDescriptionTdObject["semanticReference"].ToString()); + + Aas.File descriptorName = new Aas.File(contentType: contentType, idShort: "fileName", + semanticId: idtaDef.ConstructReference("https://admin-shell.io/idta/AssetInterfacesDescription/1/0/externalDescriptorName") + ); + descriptorName.Value = filename; + + externalDescriptor.Add(descriptorName); + + return externalDescriptor; + } + public static SubmodelElementCollection CreateAssetInterfaceDescriptionFromTd( + JObject tdJObject, string filename, string _submodelId, int interfaceCount, string _contentType) + { + interfaceCount++; + submodelId = _submodelId; + interfaceId = "interface" + string.Format("{00:00}", interfaceCount); + JObject interfaceJObject = JObject.FromObject(idtaDef.EndpointMetadataJObject["interface"]); + Aas.Reference semanticReference = idtaDef.ConstructReference(interfaceJObject["semanticReference"].ToString()); + LangStringTextType description = new Aas.LangStringTextType("en", interfaceJObject["description"].ToString()); + + Aas.SubmodelElementCollection interfaceDescription = new SubmodelElementCollection(idShort: interfaceId, + semanticId: semanticReference, description: new List { description }); + try + { + foreach (var childElem in interfaceJObject["childs"]) + { + JObject childSchemaObject = JObject.FromObject(childElem); + if (childElem["formtext"].ToString() == "ExternalDescriptor") + { + interfaceDescription.Add(BuildExternalDescriptor(filename, childSchemaObject, _contentType)); + } + else + { + interfaceDescription.Add(BuildAasElement(tdJObject, childSchemaObject)); + } + } + + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + + /* + + interfaceDescription.Add(BuildEndPointMetaData(tdJObject, submodelId, interfaceDescription.IdShort)); + interfaceDescription.Add(BuildInterfaceMetaData(tdJObject)); + interfaceDescription.Add(BuildExternalDescriptor(filename)); + + interfaceDescription.SemanticId = idtaDef.AID_Interface; + + */ + return interfaceDescription; + + } + + } +} diff --git a/src/AasxPluginAID/AasxPluginAID.csproj b/src/AasxPluginAID/AasxPluginAID.csproj new file mode 100644 index 000000000..c6530f749 --- /dev/null +++ b/src/AasxPluginAID/AasxPluginAID.csproj @@ -0,0 +1,40 @@ + + + net6.0-windows + Library + false + true + false + false + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + + PreserveNewest + + + + + + + + diff --git a/src/AasxPluginAID/AasxPluginAID.options.json b/src/AasxPluginAID/AasxPluginAID.options.json new file mode 100644 index 000000000..daf4912bf --- /dev/null +++ b/src/AasxPluginAID/AasxPluginAID.options.json @@ -0,0 +1 @@ +null /* by intention NO JSON data. Built in options are used. */ \ No newline at end of file diff --git a/src/AasxPluginAID/AasxPluginAID.plugin b/src/AasxPluginAID/AasxPluginAID.plugin new file mode 100644 index 000000000..3beebdf2d --- /dev/null +++ b/src/AasxPluginAID/AasxPluginAID.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/AasxPluginAID/InterfaceEntity.cs b/src/AasxPluginAID/InterfaceEntity.cs new file mode 100644 index 000000000..e922e8c9c --- /dev/null +++ b/src/AasxPluginAID/InterfaceEntity.cs @@ -0,0 +1,249 @@ +/* +Copyright (c) 2024 Festo SE & Co. KG +Author: Harish Kumar Pakala + +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 AasxIntegrationBase; +using AasxIntegrationBaseGdi; +using AasxPredefinedConcepts; +using Aas = AasCore.Aas3_0; +using AdminShellNS; +using Extensions; +using AnyUi; +using System.Threading.Tasks; +using System.Net.Mime; +using System.Net.Sockets; + +namespace AasxPluginAID +{ + public class InterfaceEntity + { + public delegate void InterfaceEntityEvent(InterfaceEntity e); + public event InterfaceEntityEvent DoubleClick = null; + + public delegate Task MenuClickDelegate(InterfaceEntity e, string menuItemHeader, object tag); + public event MenuClickDelegate MenuClick = null; + + public event InterfaceEntityEvent DragStart = null; + + public string Title = ""; + public string Created = ""; + public string ContentType = ""; + public string ProtocolType = ""; + public string InterfaceName = ""; + +#if USE_WPF + public System.Windows.Controls.Viewbox ImgContainerWpf = null; +#endif + public AnyUiImage ImgContainerAnyUi = null; + public string ReferableHash = null; + + public List SourceElementsInterface = null; + public List SourceElementsDocumentVersion = null; + + public string ImageReadyToBeLoaded = null; // adding Image to ImgContainer needs to be done by the GUI thread!! + public string[] DeleteFilesAfterLoading = null; + + public enum DocRelationType { DocumentedEntity, RefersTo, BasedOn, Affecting, TranslationOf }; + public List> Relations = + new List>(); + + /// + /// The parsing might add a dedicated, version-specific action to add. + /// + public delegate bool AddPreviewFileDelegate(InterfaceEntity e, string path, string contentType); + + public AddPreviewFileDelegate AddPreviewFile; + + public class FileInfo + { + public string Path = ""; + public string MimeType = ""; + + public FileInfo() { } + + public FileInfo(Aas.File file) + { + Path = file?.Value; + MimeType = file?.ContentType; + } + } + + public InterfaceEntity() { } + + public InterfaceEntity(string Title, string Created, string ContentType, string ProtocolType, + string interfaceName) + { + this.Title = Title; + this.Created = Created; + this.ContentType = ContentType; + this.ProtocolType = ProtocolType; + InterfaceName = interfaceName; + } + + public void RaiseDoubleClick() + { + if (DoubleClick != null) + DoubleClick(this); + } + + public async Task RaiseMenuClick(string menuItemHeader, object tag) + { + await MenuClick?.Invoke(this, menuItemHeader, tag); + } + + public void RaiseDragStart() + { + DragStart?.Invoke(this); + } + + /// + /// This function needs to be called as part of tick-Thread in STA / UI thread + /// + public AnyUiBitmapInfo LoadImageFromPath(string fn) + { + // be a bit suspicous .. + if (!System.IO.File.Exists(fn)) + return null; + + // convert here, as the tick-Thread in STA / UI thread + try + { +#if USE_WPF + var bi = new BitmapImage(new Uri(fn, UriKind.RelativeOrAbsolute)); + + if (ImgContainerWpf != null) + { + var img = new Image(); + img.Source = bi; + ImgContainerWpf.Child = img; + } + + if (ImgContainerAnyUi != null) + { + ImgContainerAnyUi.BitmapInfo = AnyUiHelper.CreateAnyUiBitmapInfo(bi); + } + return bi; +#else + ImgContainerAnyUi.BitmapInfo = AnyUiGdiHelper.CreateAnyUiBitmapInfo(fn); +#endif + } + catch (Exception ex) + { + LogInternally.That.SilentlyIgnoredError(ex); + } + return null; + } + } + + public class ListOfInterfaceEntity : List + { + public static AasxPredefinedConcepts.IDTAAid idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + + public static InterfaceEntity ParseSCInterfaceDescription(Aas.SubmodelElementCollection smcInterface, + string referableHash) + { + string title = "", created = "", contentype = "", protocolType = ""; + + foreach (var elem in smcInterface.Value) + { + if (elem.IdShort == "title") + { + title = (elem as Aas.Property).Value.ToString(); + } + else if (elem.IdShort == "created") + { + created = (elem as Aas.Property).Value.ToString(); + } + else if (elem.IdShort == "InterfaceMetaData") + { + Aas.SubmodelElementCollection InterfaceMetaData = (elem as Aas.SubmodelElementCollection); + foreach (var imdElem in InterfaceMetaData.Value) + { + if (imdElem.IdShort == "properties") + { + Aas.SubmodelElementCollection properties = (imdElem as Aas.SubmodelElementCollection); + foreach (var property in properties.Value) + { + Aas.SubmodelElementCollection propertySMC = (property as Aas.SubmodelElementCollection); + foreach (var propertyElem in propertySMC.Value) + { + if (propertyElem.IdShort == "forms") + { + Aas.SubmodelElementCollection formsSMC = (propertyElem as Aas.SubmodelElementCollection); + foreach(var form in formsSMC.Value) + { + Aas.SubmodelElementCollection formSMC = (form as Aas.SubmodelElementCollection); + foreach (var formElem in formSMC.Value) + { + if (formElem.IdShort == "htv_methodName") + { + protocolType = "HTTP"; + break; + } + else if (idtaDef.mqttFormElemList.Contains(formElem.IdShort)) + { + protocolType = "MQTT"; + break; + } + else if (idtaDef.modvFormElemList.Contains(formElem.IdShort)) + { + protocolType = "MODBUS"; + break; + } + } + foreach (var formElem in formSMC.Value) + { + if (formElem.IdShort == "contentType") + { + contentype = (formElem as Aas.Property).Value.ToString(); + } + } + break; + } + } + } + } + } + } + } + } + var InterfaceName = smcInterface.IdShort; + var ent = new InterfaceEntity(title, created, contentype, protocolType, InterfaceName); + ent.SourceElementsInterface = smcInterface.Value; + ent.ReferableHash = referableHash; + + return ent; + } + + public static ListOfInterfaceEntity ParseSubmodelAID(AdminShellPackageEnv thePackage, + Aas.Submodel subModel) + { + var interfaceEntities = new ListOfInterfaceEntity(); + var defs1 = AasxPredefinedConcepts.IDTAAid.Static; + + if (thePackage == null || subModel == null) + return interfaceEntities; + + // look for Interfaces + if (subModel.SubmodelElements != null) + foreach (var smcInterface in + subModel.SubmodelElements.FindAllSemanticIdAs( + defs1.AID_Interface, MatchMode.Relaxed)) + { + if (smcInterface == null || smcInterface.Value == null) + continue; + string referableHash = String.Format( + "{0:X14} {1:X14}", thePackage.GetHashCode(), smcInterface.GetHashCode()); + interfaceEntities.Add(ParseSCInterfaceDescription(smcInterface, referableHash)); + } + return interfaceEntities; + } + } +} \ No newline at end of file diff --git a/src/AasxPluginAID/InterfaceShelfOptions.cs b/src/AasxPluginAID/InterfaceShelfOptions.cs new file mode 100644 index 000000000..160634e38 --- /dev/null +++ b/src/AasxPluginAID/InterfaceShelfOptions.cs @@ -0,0 +1,56 @@ +/* +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.Text; +using System.Threading.Tasks; +using AasxIntegrationBase; +using AasxIntegrationBase.AasForms; +using AasxPredefinedConcepts; +using Aas = AasCore.Aas3_0; +using AdminShellNS; +using Extensions; +using Newtonsoft.Json; + +namespace AasxPluginAID +{ + public class IntefaceShelfOptionsRecord : AasxPluginOptionsLookupRecordBase + { + public string UsageInfo = null; + } + + public class InterfaceShelfOptions : AasxPluginLookupOptionsBase + { + public List Records = new List(); + public static AasxPredefinedConcepts.IDTAAid idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + + /// + /// Create a set of minimal options + /// + public static InterfaceShelfOptions CreateDefault() + { + var opt = new InterfaceShelfOptions(); + + // + // basic record + // + + var rec = new IntefaceShelfOptionsRecord(); + opt.Records.Add(rec); + + rec.AllowSubmodelSemanticId.Add(idtaDef.SM_AssetInterfaceDescription.GetSemanticKey()); + + return opt; + } + } + +} diff --git a/src/AasxPluginAID/LICENSE.txt b/src/AasxPluginAID/LICENSE.txt new file mode 100644 index 000000000..e41b57159 --- /dev/null +++ b/src/AasxPluginAID/LICENSE.txt @@ -0,0 +1 @@ +Please see LICENSE.txt of the AASX Package Explorer main application. \ No newline at end of file diff --git a/src/AasxPluginAID/Plugin.cs b/src/AasxPluginAID/Plugin.cs new file mode 100644 index 000000000..3786c23de --- /dev/null +++ b/src/AasxPluginAID/Plugin.cs @@ -0,0 +1,227 @@ +/* +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 AasxPluginAID; +using Aas = AasCore.Aas3_0; +using AdminShellNS; +using Extensions; +using JetBrains.Annotations; +using AnyUi; +using AasxPredefinedConcepts; + +namespace AasxIntegrationBase // the namespace has to be: AasxIntegrationBase +{ + [UsedImplicitlyAttribute] + // the class names has to be: AasxPlugin and subclassing IAasxPluginInterface + public class AasxPlugin : AasxPluginBase + { + InterfaceShelfOptions _options = new InterfaceShelfOptions(); + public class Session : PluginSessionBase + { + public AasxPluginAID.AIDAnyUiControl AnyUiControl = null; + } + + public new void InitPlugin(string[] args) + { + // start .. + PluginName = "AasxPluginAID"; + _log.Info("InitPlugin() called with args = {0}", (args == null) ? "" : string.Join(", ", args)); + } + + public new AasxPluginActionDescriptionBase[] ListActions() + { + var res = ListActionsBasicHelper( + enableCheckVisualExt: true, + enableOptions: true, + enableLicenses: true, + enableEventsGet: true, + enableEventReturn: true, + enableNewSubmodel: 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 + var found = false; + // ReSharper disable once UnusedVariable + if (sm.SemanticId.GetAsExactlyOneKey().Value.ToString() == "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Submodel") + found = true; + if (!found) + return null; + + // success prepare record + var cve = new AasxPluginResultVisualExtension("AID", "Asset Interface Descriptions"); + + // ok + return cve; + } + + // can basic helper help to reduce lines of code? + var help = ActivateActionBasicHelper(action, ref _options, args, + disableDefaultLicense: true, + enableGetCheckVisuExt: true); + if (help != null) + return help; + + // rest follows + + if (action == "get-licenses") + { + var lic = new AasxPluginResultLicense(); + lic.shortLicense = "The CountryFlag library (NuGet) is licensed under the MIT license (MIT)."; + + lic.isStandardLicense = true; + lic.longLicense = AasxPluginHelper.LoadLicenseTxtFromAssemblyDir( + "LICENSE.txt", Assembly.GetExecutingAssembly()); + + return lic; + } + + if (action == "event-return" && args != null + && args.Length >= 1 && args[0] is AasxPluginEventReturnBase erb) + { + // arguments (event return, session-id) + if (args.Length >= 2 + && _sessions.AccessSession(args[1], out Session session) + && session.AnyUiControl != null) + { + session.AnyUiControl.HandleEventReturn(erb); + } + } + + if (action == "get-check-visual-extension") + { + var cve = new AasxPluginResultBaseObject(); + cve.strType = "True"; + cve.obj = true; + return cve; + } + + if (action == "fill-anyui-visual-extension") + { + // arguments (package, submodel, panel, display-context, session-id, operation-context) + if (args == null || args.Length < 6) + return null; + + // create session and call + var session = _sessions.CreateNewSession(args[4]); + var opContext = args[5] as PluginOperationContextBase; + session.AnyUiControl = AasxPluginAID.AIDAnyUiControl.FillWithAnyUiControls( + _log, args[0], args[1], _eventStack, session, args[2], opContext, + args[3] as AnyUiContextPlusDialogs, this); + + // 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 + session.AnyUiControl.Dispose(); + + // remove + _sessions.Remove(args[0]); + } + // ReSharper enable UnusedVariable + } + + if (action == "get-list-new-submodel") + { + // prepare list + var list = new List(); + list.Add("Asset Interface Description V1.0"); + + // make result + var res = new AasxPluginResultBaseObject(); + res.obj = list; + return res; + } + + if (action == "generate-submodel" && args != null && args.Length >= 1 && args[0] is string) + { + try + { + // get arguments + var smName = args[0] as string; + if (smName == null) + return null; + + // generate (by hand) + var sm = new Aas.Submodel(""); + sm.SemanticId = IDTAAid.Static.AID_Submodel; + sm.IdShort = "AssetInterfacesDescription"; + + // make result + var res = new AasxPluginResultBaseObject(); + res.strType = "OK"; + res.obj = sm; + return res; + } + catch (Exception ex) { + Console.WriteLine(ex.ToString()); + return null; + } + } + + // default + return null; + } + + } +} diff --git a/src/AasxPluginAID/app.config b/src/AasxPluginAID/app.config new file mode 100644 index 000000000..e936cc132 --- /dev/null +++ b/src/AasxPluginAID/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/AasxPluginAID/packages.config b/src/AasxPluginAID/packages.config new file mode 100644 index 000000000..635271e7b --- /dev/null +++ b/src/AasxPluginAID/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/AasxPredefinedConcepts/AIDResources.cs b/src/AasxPredefinedConcepts/AIDResources.cs new file mode 100644 index 000000000..976ee229f --- /dev/null +++ b/src/AasxPredefinedConcepts/AIDResources.cs @@ -0,0 +1,1256 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AasxPredefinedConcepts +{ + class AIDResources + { public static JObject EndpointMetadataJObject = JObject.Parse( + @" + { + 'interface': { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'An abstraction of a physical or a virtual entity whose metadata and interfaces are described by a WoT Thing Description, whereas a virtual entity is the composition of one or more Things.', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface', + 'formtext': 'interface', + 'presetIdShort': 'interface{00:00}', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'title', + 'presetIdShort': 'title', + 'multiplcity': '1', + 'description': 'Provides a human-readable title', + 'semanticReference': 'https://www.w3.org/2019/wot/td#title' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'created', + 'presetIdShort': 'created', + 'multiplcity': '0..1', + 'description': 'Provides information when the TD instance was created.', + 'semanticReference': 'http://purl.org/dc/terms/created' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'modified', + 'presetIdShort': 'modified', + 'multiplcity': '0..1', + 'description': 'Provides information when the TD instance was last modified.', + 'semanticReference': 'http://purl.org/dc/terms/modified' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'support', + 'presetIdShort': 'support', + 'multiplcity': '0..1', + 'description': 'Provides information about the TD maintainer as URI scheme (e.g., mailto [RFC6068], tel [RFC3966], https [RFC9112]).', + 'semanticReference': 'https://www.w3.org/2019/wot/td#supportContact' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Provides the metadata of the asset’s endpoint (base, content type that is used for interaction, etc)', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/EndpointMetadata', + 'formtext': 'EndpointMetadata', + 'presetIdShort': 'EndpointMetadata', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'base', + 'presetIdShort': 'base', + 'multiplcity': '0..1', + 'description': 'Define the base URI that is used for all relative URI references throughout a TD document. In TD instances: all relative URIs are resolved relative to the base URI using the algorithm defined in [RFC3986].', + 'semanticReference': 'https://www.w3.org/2019/wot/td#baseURI' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'contentType', + 'presetIdShort': 'contentType', + 'multiplcity': '0..1', + 'description': 'Assign a content type based on a media type (e.g.: text/plain) and potential parameters (e.g.: charset=utf-8) for the media type [RFC2046].', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#forContentType' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Defines the security scheme according to W3C', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#securityDefinitions', + 'formtext': 'securityDefinitions', + 'presetIdShort': 'securityDefinitions', + 'childs': [ + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Bearer Security Definition', + 'semanticReference': 'https://www.w3.org/2019/wot/security#BearerSecurityScheme', + 'formtext': 'bearer_sc', + 'presetIdShort': 'bearer_sc', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:anyURI', + 'formtext': 'proxy', + 'presetIdShort': 'proxy', + 'multiplcity': '0..1', + 'description': 'Identification of the security mechanism being configured.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#proxy' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'scheme', + 'presetIdShort': 'scheme', + 'multiplcity': '1', + 'description': 'URI of the proxy server this security configuration provides access to. If not given, the corresponding security configuration is for the endpoint.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#SecurityScheme' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:anyURI', + 'formtext': 'authorization', + 'presetIdShort': 'authorization', + 'multiplcity': '0..1', + 'description': 'URI of the authorization server.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#authorization' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'name', + 'presetIdShort': 'name', + 'multiplcity': '0..1', + 'description': 'Name for query: header: cookie: or uri parameters.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#name' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'alg', + 'presetIdShort': 'alg', + 'multiplcity': '0..1', + 'description': 'Encoding: encryption: or digest algorithm.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#alg' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'format', + 'presetIdShort': 'format', + 'multiplcity': '0..1', + 'description': 'Specifies format of security authentication information.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#format' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'in', + 'presetIdShort': 'in', + 'multiplcity': '0..1', + 'description': 'Specifies the location of security authentication information.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#in' + } + ] + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Digest Security Definition', + 'semanticReference': 'https://www.w3.org/2019/wot/security#DigestSecurityScheme', + 'formtext': 'digest_sc', + 'presetIdShort': 'digest_sc', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:anyURI', + 'formtext': 'proxy', + 'presetIdShort': 'proxy', + 'multiplcity': '0..1', + 'description': 'Identification of the security mechanism being configured.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#proxy' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'scheme', + 'presetIdShort': 'scheme', + 'multiplcity': '1', + 'description': 'URI of the proxy server this security configuration provides access to. If not given, the corresponding security configuration is for the endpoint.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#SecurityScheme' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'name', + 'presetIdShort': 'name', + 'multiplcity': '0..1', + 'description': 'Name for query: header: cookie: or uri parameters.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#name' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'in', + 'presetIdShort': 'in', + 'multiplcity': '0..1', + 'description': 'Specifies the location of security authentication information.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#in' + } + ] + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Api Key Security Definition', + 'semanticReference': 'https://www.w3.org/2019/wot/security#APIKeySecurityScheme', + 'formtext': 'apikey_sc', + 'presetIdShort': 'apikey_sc', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:anyURI', + 'formtext': 'proxy', + 'presetIdShort': 'proxy', + 'multiplcity': '0..1', + 'description': 'Identification of the security mechanism being configured.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#proxy' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'scheme', + 'presetIdShort': 'scheme', + 'multiplcity': '1', + 'description': 'URI of the proxy server this security configuration provides access to. If not given, the corresponding security configuration is for the endpoint.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#SecurityScheme' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'name', + 'presetIdShort': 'name', + 'multiplcity': '0..1', + 'description': 'Name for query: header: cookie: or uri parameters.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#name' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'in', + 'presetIdShort': 'in', + 'multiplcity': '0..1', + 'description': 'Specifies the location of security authentication information.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#in' + } + ] + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'PSK Security Definition', + 'semanticReference': 'https://www.w3.org/2019/wot/security#PSKSecurityScheme', + 'formtext': 'psk_sc', + 'presetIdShort': 'psk_sc', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:anyURI', + 'formtext': 'proxy', + 'presetIdShort': 'proxy', + 'multiplcity': '0..1', + 'description': 'Identification of the security mechanism being configured.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#proxy' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'scheme', + 'presetIdShort': 'scheme', + 'multiplcity': '1', + 'description': 'URI of the proxy server this security configuration provides access to. If not given, the corresponding security configuration is for the endpoint.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#SecurityScheme' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'identity', + 'presetIdShort': 'identity', + 'multiplcity': '0..1', + 'description': 'Identifier providing information which can be used for selection or confirmation.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#identity' + } + ] + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Basic Security Definition', + 'semanticReference': 'https://www.w3.org/2019/wot/security#BasicSecurityScheme', + 'formtext': 'basic_sc', + 'presetIdShort': 'basic_sc', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:anyURI', + 'formtext': 'proxy', + 'presetIdShort': 'proxy', + 'multiplcity': '0..1', + 'description': 'Identification of the security mechanism being configured.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#proxy' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'scheme', + 'presetIdShort': 'scheme', + 'multiplcity': '1', + 'description': 'URI of the proxy server this security configuration provides access to. If not given, the corresponding security configuration is for the endpoint.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#SecurityScheme' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'name', + 'presetIdShort': 'name', + 'multiplcity': '0..1', + 'description': 'Name for query: header: cookie: or uri parameters.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#name' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'in', + 'presetIdShort': 'in', + 'multiplcity': '0..1', + 'description': 'Name for query, header, cookie, or uri parameters', + 'semanticReference': 'https://www.w3.org/2019/wot/security#name' + } + ] + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'OAuth2 Security Definition', + 'semanticReference': 'https://www.w3.org/2019/wot/security#OAuth2SecurityScheme', + 'formtext': 'oauth2_sc', + 'presetIdShort': 'oauth2_sc', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:anyURI', + 'formtext': 'proxy', + 'presetIdShort': 'proxy', + 'multiplcity': '0..1', + 'description': 'Identification of the security mechanism being configured.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#proxy' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'scheme', + 'presetIdShort': 'scheme', + 'multiplcity': '1', + 'description': 'URI of the proxy server this security configuration provides access to. If not given, the corresponding security configuration is for the endpoint.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#SecurityScheme' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:anyURI', + 'formtext': 'authorization', + 'presetIdShort': 'authorization', + 'multiplcity': '0..1', + 'description': 'URI of the authorization server.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#authorization' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:anyURI', + 'formtext': 'token', + 'presetIdShort': 'token', + 'multiplcity': '0..1', + 'description': 'URI of the token server.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#token' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:anyURI', + 'formtext': 'refresh', + 'presetIdShort': 'refresh', + 'multiplcity': '0..1', + 'description': 'URI of the refresh server.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#refresh' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'format', + 'presetIdShort': 'format', + 'multiplcity': '0..1', + 'description': 'Specifies format of security authentication information.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#format' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'flow', + 'presetIdShort': 'flow', + 'multiplcity': '0..1', + 'description': 'Defines authorization flow such as code or client', + 'semanticReference': 'https://www.w3.org/2019/wot/security#flow' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'formtext': 'scopes', + 'presetIdShort': 'scopes', + 'multiplcity': '0..1', + 'description': 'Set of authorization scope identifiers provided as an array. These are provided in tokens returned by an authorization server and associated with forms in order to identify what resources a client may access and how.', + 'semanticReference': 'https://www.w3.org/2019/wot/security#scopes', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'scope', + 'presetIdShort': 'scope{00:00}', + 'multiplcity': '0..*', + 'description': 'Authorization scope identifier', + 'semanticReference': 'https://www.w3.org/2019/wot/security#scopes' + } + ] + } + ] + } + ] + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '1', + 'description': 'Selects one or more of the security scheme(s) that can be applied at runtime from the collection of security schemes defines in securityDefinitions', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasSecurityConfiguration', + 'formtext': 'security', + 'presetIdShort': 'security', + 'childs': [ + { + 'AasElementType': 'ReferenceElement', + 'multiplcity': '0..*', + 'description': 'Reference element to security scheme definition', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasSecurityConfiguration', + 'formtext': 'security', + 'presetIdShort': '' + } + ] + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'modv_mostSignificantByte', + 'presetIdShort': 'modv_mostSignificantByte', + 'multiplcity': '0..1', + 'description': 'Define the base URI that is used for all relative URI references throughout a TD document. In TD instances: all relative URIs are resolved relative to the base URI using the algorithm defined in [RFC3986].', + 'semanticReference': 'https://www.w3.org/2019/wot/modbus#hasMostSignificByte' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'modv_mostSignificantWord', + 'presetIdShort': 'modv_mostSignificantWord', + 'multiplcity': '0..1', + 'description': 'When true: it describes that the word order of the data in the Modbus message is the most significant word first (i.e.: no word swapping). When false: it describes the least significant word first (i.e. word swapping) ', + 'semanticReference': 'https://www.w3.org/2019/wot/modbus#hasMostSignificantWord' + } + ] + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Provides an place for existing description files (e.g., Thing Description, GSDML, etc,).', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/ExternalDescriptor', + 'formtext': 'ExternalDescriptor', + 'presetIdShort': 'ExternalDescriptor', + 'childs': [ + { + 'AasElementType': 'File', + 'formtext': 'descriptorName', + 'presetIdShort': 'descriptorName', + 'multiplcity': '1..*', + 'description': 'File reference (local in AASX or outside) to an external descriptor description (e.g., Thing Description, GSDML, etc,).', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/externalDescriptorName' + } + ] + }, +{ + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'An abstraction of a physical or a virtual entity whose metadata and interfaces are described by a WoT Thing Description, whereas a virtual entity is the composition of one or more Things.', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/InteractionMetadata', + 'formtext': 'InteractionMetaData', + 'presetIdShort': 'InteractionMetaData', + 'childs': [ + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'All Property-based Interaction Affordances of the Thing.', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasPropertyAffordance', + 'formtext': 'properties', + 'presetIdShort': 'properties', + 'childs': [ + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'An Interaction Affordance that exposes state of the Thing', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfaceDescription/1/0/PropertyDefinition', + 'formtext': 'property', + 'presetIdShort': 'property{00:00}', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'key', + 'presetIdShort': 'key', + 'multiplcity': '0..1', + 'description': 'Optional element when the idShort of {property_name} cannot be used to reflect the desired property name due to the idShort restrictions', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/key' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'title', + 'presetIdShort': 'title', + 'multiplcity': '0..1', + 'description': 'Provides a human-readable title (e.g., display a text for UI representation) based on a default language.', + 'semanticReference': 'https://www.w3.org/2019/wot/td#title' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'observable', + 'presetIdShort': 'observable', + 'multiplcity': '0..1', + 'description': 'An indicator that tells that the interaction datapoint can be observed with a, e.g., subscription mechanism by an underlying protocol.', + 'semanticReference': 'https://www.w3.org/2019/wot/td#isObservable' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '1', + 'description': 'Provides a list of restricted set of values that the asset can provide as datapoint value.', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasForm', + 'formtext': 'forms', + 'presetIdShort': 'forms', + 'childs': [ + { + 'AasElementType': 'SubmodelElementCollection', + 'formtext': 'HTTP Form', + 'presetIdShort': 'form{00:00}', + 'multiplcity': '0..1', + 'description': 'HTTP form', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasHTTPForm', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'contentType', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#forContentType', + 'presetIdShort': 'contentType', + 'description': 'Indicates the datapoint media type specified by IANA.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'subprotocol', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#forSubProtocol', + 'presetIdShort': 'subprotocol', + 'description': 'Indicates the exact mechanism by which an interaction will be accomplished for a given protocol when there are multiple options.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'href', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#hasTarget', + 'presetIdShort': 'href', + 'description': 'Target IRI relative path or full IRI of assets datapoint.The relative endpoint definition in href is always relative to base defined in EndpointMetadata' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'formtext': 'security', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasSecurityConfiguration', + 'presetIdShort': 'security', + 'description': 'Selects one or more of the security scheme(s) that can be applied at runtime from the collection of security schemes defines in securityDefinitions', + 'childs': [ + { + 'AasElementType': 'ReferenceElement', + 'formtext': 'security', + 'multiplcity': '0..*', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasSecurityConfiguration', + 'presetIdShort': '', + 'description': 'Reference element to security scheme definition' + } + ] + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'htv_methodName', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2011/http#methodName', + 'presetIdShort': 'htv_methodName', + 'description': '' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'formtext': 'htv_header', + 'multiplcity': '0..*', + 'semanticReference': 'https://www.w3.org/2011/http#headers', + 'presetIdShort': '', + 'description': ' Information for http message header definition', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'htv_fieldName', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2011/http#fieldName', + 'presetIdShort': 'htv_fieldName', + 'description': '' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'htv_fieldValue', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2011/http#fieldValue', + 'presetIdShort': 'htv_fieldValue', + 'description': '' + } + ] + } + ] + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'formtext': 'MQTT Form', + 'presetIdShort': 'form{00:00}', + 'multiplcity': '0..1', + 'description': 'MQTT form', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasMQTTForm', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'contentType', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#forContentType', + 'presetIdShort': 'contentType', + 'description': 'Indicates the datapoint media type specified by IANA.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'subprotocol', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#forSubProtocol', + 'presetIdShort': 'subprotocol', + 'description': 'Indicates the exact mechanism by which an interaction will be accomplished for a given protocol when there are multiple options.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'href', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#hasTarget', + 'presetIdShort': 'href', + 'description': 'Target IRI relative path or full IRI of assets datapoint.The relative endpoint definition in href is always relative to base defined in EndpointMetadata' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'formtext': 'security', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasSecurityConfiguration', + 'presetIdShort': 'security', + 'description': 'Selects one or more of the security scheme(s) that can be applied at runtime from the collection of security schemes defines in securityDefinitions', + 'childs': [ + { + 'AasElementType': 'ReferenceElement', + 'formtext': 'security', + 'multiplcity': '0..*', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasSecurityConfiguration', + 'presetIdShort': '', + 'description': 'Reference element to security scheme definition' + } + ] + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'mqv_retain', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/mqtt#hasRetainFlag', + 'presetIdShort': 'mqv_retain', + 'description': 'It is an indicator that tells the broker to always retain last published payload.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'mqv_controlPacket', + 'multiplcity': '1', + 'semanticReference': 'https://www.w3.org/2019/wot/mqtt#ControlPacket', + 'presetIdShort': 'mqv_controlPacket', + 'description': 'Defines the method associated to the datapoint in relation to the broker.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'mqv_qos', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/mqtt#hasQoSFlag', + 'presetIdShort': 'mqv_qos', + 'description': 'Defined the level of guarantee for message delivery between clients.' + } + ] + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'formtext': 'MODBUS Form', + 'presetIdShort': 'form{00:00}', + 'multiplcity': '0..1', + 'description': 'MODBUS form', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasMODBUSForm', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'contentType', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#forContentType', + 'presetIdShort': 'contentType', + 'description': 'Indicates the datapoint media type specified by IANA.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'subprotocol', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#forSubProtocol', + 'presetIdShort': 'subprotocol', + 'description': 'Indicates the exact mechanism by which an interaction will be accomplished for a given protocol when there are multiple options.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'href', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/hypermedia#hasTarget', + 'presetIdShort': 'href', + 'description': 'Target IRI relative path or full IRI of assets datapoint.The relative endpoint definition in href is always relative to base defined in EndpointMetadata' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'formtext': 'security', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasSecurityConfiguration', + 'presetIdShort': 'security', + 'description': 'Selects one or more of the security scheme(s) that can be applied at runtime from the collection of security schemes defines in securityDefinitions', + 'childs': [ + { + 'AasElementType': 'ReferenceElement', + 'formtext': 'security', + 'multiplcity': '0..*', + 'semanticReference': 'https://www.w3.org/2019/wot/td#hasSecurityConfiguration', + 'presetIdShort': '', + 'description': 'Reference element to security scheme definition' + } + ] + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'modv_function', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/modbus#hasFunction', + 'presetIdShort': 'modv_function', + 'description': 'Abstraction of the Modbus function code sent during a request. A function value can be either readCoil, readDeviceIdentification, readDiscreteInput, readHoldingRegisters, readInputRegisters, writeMultipleCoils, writeMultipleHoldingRegisters, writeSingleCoil, or writeSingleHoldingRegister' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'modv_entity', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/modbus#hasEntity', + 'presetIdShort': 'modv_entity', + 'description': 'A registry type to let the runtime automatically detect the right function code. An entity value can be Coil, DiscreteInput, HoldingRegister, or InputRegister ' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'modv_zeroBasedAddressing', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/modbus#hasZeroBasedAddressingFlag', + 'presetIdShort': 'modv_zeroBasedAddressing', + 'description': 'Modbus implementations can differ in the way addressing works, as the first coil/register can be either referred to as True or False.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:integer', + 'formtext': 'modv_timeout', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/modbus#hasTimeout', + 'presetIdShort': 'modv_timeout', + 'description': 'Modbus response maximum waiting time. Defines how much time in milliseconds the runtime should wait until it receives a reply from the device.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:integer', + 'formtext': 'modv_pollingTime', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/modbus#hasPollingTime', + 'presetIdShort': 'modv_pollingTime', + 'description': 'Modbus TCP maximum polling rate. The Modbus specification does not define a maximum or minimum allowed polling rate, however specific implementations might introduce such limits. Defined as integer of milliseconds.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'modv_type', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/modbus#hasPayloadDataType', + 'presetIdShort': 'modv_type', + 'description': 'Defines the data type of the modbus asset payload. type in terms of possible sign, base type. the modv_type offers a set a types defined in XML schema' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'modv_mostSignificantByte', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/modbus#hasMostSignificantByte', + 'presetIdShort': 'modv_mostSignificantByte', + 'description': 'Define the base URI that is used for all relative URI references throughout a TD document. In TD instances, all relative URIs are resolved relative to the base URI using the algorithm defined in [RFC3986].' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'modv_mostSignificantWord', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/modbus#hasMostSignificantWord', + 'presetIdShort': 'modv_mostSignificantWord', + 'description': 'When true, it describes that the word order of the data in the Modbus message is the most significant word first (i.e., no word swapping). When false, it describes the least significant word first (i.e. word swapping) ' + } + ] + } + ] + }, + { + 'AasElementType': 'ReferenceElement', + 'formtext': 'valueSemantics', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/valueSemantics', + 'presetIdShort': 'valueSemantics', + 'description': 'Provides additional semantic information of the value that is read/subscribed at runtime.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'type', + 'presetIdShort': 'type', + 'multiplcity': '0..1', + 'description': 'Assignment of JSON-based data types compatible with JSON Schema (one of boolean, integer, number, string, object, array, or null).', + 'semanticReference': 'https://www.w3.org/1999/02/22-rdf-syntax-ns#type' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'const', + 'presetIdShort': 'const', + 'multiplcity': '0..1', + 'description': 'Provides a constant value.', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#const' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Provides a list of restricted set of values that the asset can provide as datapoint value.', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#enum', + 'formtext': 'enum', + 'presetIdShort': 'enum', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'enum', + 'presetIdShort': 'enum{00:00}', + 'multiplcity': '0..*', + 'description': 'Data Point Value', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#enum' + } + ] + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'default', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#default', + 'presetIdShort': 'default', + 'description': 'Supply a default value. The value SHOULD validate against the data schema in which it resides.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'unit', + 'multiplcity': '0..1', + 'semanticReference': 'https://schema.org/unitCode', + 'presetIdShort': 'unit', + 'description': 'Provides unit information that is used, e.g., in international science, engineering, and business. To preserve uniqueness, it is recommended that the value of the unit points to a semantic definition' + }, + { + 'AasElementType': 'Range', + 'valueType' : 'xs:integer', + 'formtext': 'min_max', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/minMaxRange', + 'presetIdShort': 'min_max', + 'description': 'Specifies a minimum and/or maximum numeric value for the datapoint.' + }, + { + 'AasElementType': 'Range', + 'valueType' : 'xs:unsignedInt', + 'formtext': 'lengthRange', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/lengthRange', + 'presetIdShort': 'lengthRange', + 'description': 'Specifies the minimum and maximum length of a string.' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '1', + 'description': 'Used to define the data schema characteristics of an array payload.', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#items', + 'formtext': 'items', + 'presetIdShort': 'items', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'type', + 'presetIdShort': 'type', + 'multiplcity': '0..1', + 'description': 'Assignment of JSON-based data types compatible with JSON Schema (one of boolean, integer, number, string, object, array, or null).', + 'semanticReference': 'https://www.w3.org/1999/02/22-rdf-syntax-ns#type' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'const', + 'presetIdShort': 'const', + 'multiplcity': '0..1', + 'description': 'Provides a constant value.', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#const' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Provides a list of restricted set of values that the asset can provide as datapoint value.', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#enum', + 'formtext': 'enum', + 'presetIdShort': 'enum', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'enum{00:00}', + 'presetIdShort': 'enum{00:00}', + 'multiplcity': '0..*', + 'description': 'Data Point Value', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#enum' + } + ] + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'default', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#default', + 'presetIdShort': 'default', + 'description': 'Supply a default value. The value SHOULD validate against the data schema in which it resides.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'unit', + 'multiplcity': '0..1', + 'semanticReference': 'https://schema.org/unitCode', + 'presetIdShort': 'unit', + 'description': 'Provides unit information that is used, e.g., in international science, engineering, and business. To preserve uniqueness, it is recommended that the value of the unit points to a semantic definition' + }, + { + 'AasElementType': 'Range', + 'valueType' : 'xs:integer', + 'formtext': 'min_max', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/minMaxRange', + 'presetIdShort': 'min_max', + 'description': 'Specifies a minimum and/or maximum numeric value for the datapoint.' + }, + { + 'AasElementType': 'Range', + 'valueType' : 'xs:unsignedInt', + 'formtext': 'lengthRange', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/lengthRange', + 'presetIdShort': 'lengthRange', + 'description': 'Specifies the minimum and maximum length of a string.' + } + ] + }, + { + 'AasElementType': 'Range', + 'valueType' : 'xs:unsignedInt', + 'formtext': 'itemsRange', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/itemsRange', + 'presetIdShort': 'itemsRange', + 'description': 'Defines the minimum and maximum number of items that have to be in an array payload.' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Nested definitions of a datapoint. Only applicable if type=object', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#properties', + 'formtext': 'properties', + 'presetIdShort': 'properties', + 'childs': [ + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'An Interaction Affordance that exposes state of the Thing', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#propertyName', + 'formtext': 'property', + 'presetIdShort': 'property{00:00}', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'key', + 'presetIdShort': 'key', + 'multiplcity': '0..1', + 'description': 'Optional element when the idShort of {property_name} cannot be used to reflect the desired property name due to the idShort restrictions', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/key' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'title', + 'presetIdShort': 'title', + 'multiplcity': '0..1', + 'description': 'Provides a human-readable title (e.g., display a text for UI representation) based on a default language.', + 'semanticReference': 'https://www.w3.org/2019/wot/td#title' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'observable', + 'presetIdShort': 'observable', + 'multiplcity': '0..1', + 'description': 'An indicator that tells that the interaction datapoint can be observed with a, e.g., subscription mechanism by an underlying protocol.', + 'semanticReference': 'https://www.w3.org/2019/wot/td#isObservable' + }, + { + 'AasElementType': 'ReferenceElement', + 'formtext': 'valueSemantics', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/valueSemantics', + 'presetIdShort': 'valueSemantics', + 'description': 'Provides additional semantic information of the value that is read/subscribed at runtime.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'type', + 'presetIdShort': 'type', + 'multiplcity': '0..1', + 'description': 'Assignment of JSON-based data types compatible with JSON Schema (one of boolean, integer, number, string, object, array, or null).', + 'semanticReference': 'https://www.w3.org/1999/02/22-rdf-syntax-ns#type' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'const', + 'presetIdShort': 'const', + 'multiplcity': '0..1', + 'description': 'Provides a constant value.', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#const' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Provides a list of restricted set of values that the asset can provide as datapoint value.', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#enum', + 'formtext': 'enum', + 'presetIdShort': 'enum', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'enum', + 'presetIdShort': 'enum{00:00}', + 'multiplcity': '0..*', + 'description': 'Data Point Value', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#enum' + } + ] + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'default', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#default', + 'presetIdShort': 'default', + 'description': 'Supply a default value. The value SHOULD validate against the data schema in which it resides.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'unit', + 'multiplcity': '0..1', + 'semanticReference': 'https://schema.org/unitCode', + 'presetIdShort': 'unit', + 'description': 'Provides unit information that is used, e.g., in international science, engineering, and business. To preserve uniqueness, it is recommended that the value of the unit points to a semantic definition' + }, + { + 'AasElementType': 'Range', + 'valueType' : 'xs:integer', + 'formtext': 'min_max', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/minMaxRange', + 'presetIdShort': 'min_max', + 'description': 'Specifies a minimum and/or maximum numeric value for the datapoint.' + }, + { + 'AasElementType': 'Range', + 'valueType' : 'xs:unsignedInt', + 'formtext': 'lengthRange', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/lengthRange', + 'presetIdShort': 'lengthRange', + 'description': 'Specifies the minimum and maximum length of a string.' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Used to define the data schema characteristics of an array payload.', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#items', + 'formtext': 'items', + 'presetIdShort': 'items', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'type', + 'presetIdShort': 'type', + 'multiplcity': '0..1', + 'description': 'Assignment of JSON-based data types compatible with JSON Schema (one of boolean, integer, number, string, object, array, or null).', + 'semanticReference': 'https://www.w3.org/1999/02/22-rdf-syntax-ns#type' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'const', + 'presetIdShort': 'const', + 'multiplcity': '0..1', + 'description': 'Provides a constant value.', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#const' + }, + { + 'AasElementType': 'SubmodelElementCollection', + 'multiplcity': '0..1', + 'description': 'Provides a list of restricted set of values that the asset can provide as datapoint value.', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#enum', + 'formtext': 'enum', + 'presetIdShort': 'enum', + 'childs': [ + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'enum{00:00}', + 'presetIdShort': 'enum{00:00}', + 'multiplcity': '0..*', + 'description': 'Data Point Value', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#enum' + } + ] + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:boolean', + 'formtext': 'default', + 'multiplcity': '0..1', + 'semanticReference': 'https://www.w3.org/2019/wot/json-schema#default', + 'presetIdShort': 'default', + 'description': 'Supply a default value. The value SHOULD validate against the data schema in which it resides.' + }, + { + 'AasElementType': 'Property', + 'valueType' : 'xs:string', + 'formtext': 'unit', + 'multiplcity': '0..1', + 'semanticReference': 'https://schema.org/unitCode', + 'presetIdShort': 'unit', + 'description': 'Provides unit information that is used, e.g., in international science, engineering, and business. To preserve uniqueness, it is recommended that the value of the unit points to a semantic definition' + }, + { + 'AasElementType': 'Range', + 'valueType' : 'xs:integer', + 'formtext': 'min_max', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/minMaxRange', + 'presetIdShort': 'min_max', + 'description': 'Specifies a minimum and/or maximum numeric value for the datapoint.' + }, + { + 'AasElementType': 'Range', + 'valueType' : 'xs:unsignedInt', + 'formtext': 'lengthRange', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/lengthRange', + 'presetIdShort': 'lengthRange', + 'description': 'Specifies the minimum and maximum length of a string.' + } + ] + }, + { + 'AasElementType': 'Range', + 'valueType' : 'xs:unsignedInt', + 'formtext': 'itemsRange', + 'multiplcity': '0..1', + 'semanticReference': 'https://admin-shell.io/idta/AssetInterfacesDescription/1/0/itemsRange', + 'presetIdShort': 'itemsRange', + 'description': 'Defines the minimum and maximum number of items that have to be in an array payload.' + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + }"); + + } +} diff --git a/src/AasxPredefinedConcepts/DefinitionsAID.cs b/src/AasxPredefinedConcepts/DefinitionsAID.cs new file mode 100644 index 000000000..c69129573 --- /dev/null +++ b/src/AasxPredefinedConcepts/DefinitionsAID.cs @@ -0,0 +1,91 @@ +/* +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 Newtonsoft.Json.Linq; +using System.Reflection; +using AdminShellNS; +using AasCore.Aas3_0; +using System.Collections.Generic; +using JetBrains.Annotations; +using Microsoft.VisualBasic; +using System.Security.Cryptography; +using AasxIntegrationBase.AasForms; +// ReSharper disable UnassignedField.Global +// (working by reflection) + +namespace AasxPredefinedConcepts +{ + /// + /// Definitions of Submodel VDI2770 according to new alignment with VDI + /// + public class IDTAAid : AasxDefinitionBase + { + public static IDTAAid Static = new IDTAAid(); + public Submodel + SM_AssetInterfaceDescription; + + public JObject EndpointMetadataJObject = AIDResources.EndpointMetadataJObject; + public List mqttFormElemList = new List() { "mqv_retain", + "mqv_controlPacket","mqv_qos"}; + public List modvFormElemList = new List() { "modv_function", + "modv_entity","modv_zeroBasedAddressing","modv_pollingTime", + "modv_type","modv_mostSignificantByte","modv_mostSignificantWord" + }; + + public Reference AID_Submodel = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Submodel") }); + public Reference AID_Interface = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface") }); + + public Reference ConstructReference(string value) + { + Reference _ref = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, value) }); + return _ref; + } + public Key ConstructKey(KeyTypes _keyType, string value) { + + Key _key = new Key(_keyType, value); + return _key; + } + public FormMultiplicity GetFormMultiplicity(string multipli) + { + if (multipli == "1") + { + return FormMultiplicity.One; + } + else if (multipli == "0..1") + { + return FormMultiplicity.ZeroToOne; + } + else if (multipli == "0..*") + { + return FormMultiplicity.ZeroToMany; + } + else if (multipli == "1..*") + { + return FormMultiplicity.OneToMany; + } + return FormMultiplicity.ZeroToOne; + } + public DataTypeDefXsd GetValueType(string valueType) + { + return Stringification.DataTypeDefXsdFromString(valueType) + ?? DataTypeDefXsd.String; + } + public IDTAAid() + { + // info + this.DomainInfo = "IDTA Asset Interface Description"; + + // IReferable + this.ReadLibrary( + Assembly.GetExecutingAssembly(), "AasxPredefinedConcepts.Resources." + "IdtaAssetInterfaceDescription.json"); + this.RetrieveEntriesFromLibraryByReflection(typeof(IDTAAid), useFieldNames: true); + } + } + +}