diff --git a/src/AasxPackageExplorer.sln b/src/AasxPackageExplorer.sln index 25aa0daf..59a361eb 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", "{9D2684FD-5992-4434-940C-351D90459E77}" +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 @@ -1166,7 +1165,6 @@ Global {8D09D103-1B97-4D54-BAA9-841B2F93FF36}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU {8D09D103-1B97-4D54-BAA9-841B2F93FF36}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU {B649731D-C961-4A0E-9A20-3DF20D941E83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B649731D-C961-4A0E-9A20-3DF20D941E83}.Debug|Any CPU.Build.0 = Debug|Any CPU {B649731D-C961-4A0E-9A20-3DF20D941E83}.Debug|x64.ActiveCfg = Debug|Any CPU {B649731D-C961-4A0E-9A20-3DF20D941E83}.Debug|x64.Build.0 = Debug|Any CPU {B649731D-C961-4A0E-9A20-3DF20D941E83}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1436,7 +1434,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 +1757,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 +1935,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 + {9D2684FD-5992-4434-940C-351D90459E77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Debug|x64.ActiveCfg = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Debug|x64.Build.0 = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Debug|x86.ActiveCfg = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Debug|x86.Build.0 = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugSlow|Any CPU.ActiveCfg = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugSlow|Any CPU.Build.0 = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugSlow|x64.ActiveCfg = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugSlow|x64.Build.0 = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugSlow|x86.ActiveCfg = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugSlow|x86.Build.0 = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugWithoutCEF|Any CPU.ActiveCfg = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugWithoutCEF|Any CPU.Build.0 = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugWithoutCEF|x64.ActiveCfg = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugWithoutCEF|x64.Build.0 = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugWithoutCEF|x86.ActiveCfg = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.DebugWithoutCEF|x86.Build.0 = Debug|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Release|Any CPU.Build.0 = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Release|x64.ActiveCfg = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Release|x64.Build.0 = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Release|x86.ActiveCfg = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.Release|x86.Build.0 = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.ReleaseWithoutCEF|Any CPU.ActiveCfg = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.ReleaseWithoutCEF|Any CPU.Build.0 = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.ReleaseWithoutCEF|x64.ActiveCfg = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.ReleaseWithoutCEF|x64.Build.0 = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.ReleaseWithoutCEF|x86.ActiveCfg = Release|Any CPU + {9D2684FD-5992-4434-940C-351D90459E77}.ReleaseWithoutCEF|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2002,6 +2028,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} + {9D2684FD-5992-4434-940C-351D90459E77} = {66D730EB-B9D7-4C3A-8954-0F86240AD612} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1AE21162-9541-4B98-A49C-A63B6AD03998} diff --git a/src/AasxPackageExplorer/options-debug.json b/src/AasxPackageExplorer/options-debug.json index 55e6b550..e43202be 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 00000000..4eafeab4 --- /dev/null +++ b/src/AasxPluginAID/AIDAnyUiControl.cs @@ -0,0 +1,1399 @@ +/* +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 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 == IDTAAid.Static.AID_Submodel.GetAsExactlyOneKey().Value) + 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, "HTTP"); + // 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("ButtonAddDocument")); + + + List protocolTypes = new List { "HTTP", "MQTT", "MODBUS" }; + // 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("ButtonImportDocument"); + 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 = RenderAnyUiDocumentEntity(uitk, de); + if (rde != null) + inner.Add(rde); + } + + // post process + if (its != null) + foreach (var ent in its) + { + // if a preview file exists, try load directly, but not interfere + // we delayed load logic, as these images might get more detailed + if (ent.PreviewFile?.Path?.HasContent() == true) + { + var inputFn = ent.PreviewFile.Path; + + try + { + // from package? + if (CheckIfPackageFile(inputFn)) + inputFn = _package?.MakePackageFileAvailableAsTempFile(ent.PreviewFile.Path); + + ent.LoadImageFromPath(inputFn); + } + catch (Exception ex) + { + // do not show any error message, as it might appear + // frequently + LogInternally.That.SilentlyIgnoredError(ex); + } + } + + // delayed load logic + // can already put a generated image into the viewbox? + if (referableHashToCachedBitmap != null && + referableHashToCachedBitmap.ContainsKey(ent.ReferableHash)) + { +#if USE_WPF + ent.ImgContainerAnyUi.BitmapInfo = AnyUiHelper.CreateAnyUiBitmapInfo( + referableHashToCachedBitmap[ent.ReferableHash]); +#else + ent.ImgContainerAnyUi.BitmapInfo = referableHashToCachedBitmap[ent.ReferableHash]; +#endif + } + else + { + // trigger generation of image + + // check if already in list + InterfaceEntity foundDe = null; + foreach (var de in theDocEntitiesToPreview) + if (ent.ReferableHash == de.ReferableHash) + foundDe = de; + + lock (theDocEntitiesToPreview) + { + if (foundDe != null) + theDocEntitiesToPreview.Remove(foundDe); + theDocEntitiesToPreview.Add(ent); + } + } + + // attach events and add + ent.DoubleClick += DocumentEntity_DoubleClick; + ent.MenuClick += DocumentEntity_MenuClick; + ent.DragStart += DocumentEntity_DragStart; + } + } + + public AnyUiFrameworkElement RenderAnyUiDocumentEntity( + 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 GetFormDescForV12( + List sourceElems, + Action lambda) + { + // ask the plugin generic forms for information via event stack + _eventStack?.PushEvent(new AasxIntegrationBase.AasxPluginResultEventInvokeOtherPlugin() + { + Session = _session, + PluginName = "AasxPluginGenericForms", + Action = "find-form-desc", + UseAsync = false, + Args = new object[] { + AasxPredefinedConcepts.IdtaHandoverDocumentationV12.Static + .SM_HandoverDocumentation.GetSemanticRef() } + }); + + // .. and receive incoming event .. + _menuSubscribeForNextEventReturn = (revt) => + { + if (revt is AasxPluginEventReturnInvokeOther rinv + && rinv.ResultData is AasxPluginResultBaseObject rbo + && rbo.obj is List fdb + && fdb.Count == 1 + && fdb[0] is FormDescSubmodel descSm) + { + _updateSourceElements = sourceElems; + + // need to identify the form for single document BELOW the Submodel + FormDescSubmodelElementCollection descSmc = null; + if (descSm.SubmodelElements != null) + foreach (var desc in descSm.SubmodelElements) + if (desc is FormDescSubmodelElementCollection desc2 + && AasxPredefinedConcepts.IdtaHandoverDocumentationV12.Static + .CD_Document.GetReference()?.MatchesExactlyOneKey( + desc2?.KeySemanticId, matchMode: MatchMode.Relaxed) == true) + { + descSmc = desc2; + } + + if (descSmc == null) + return; + + lambda?.Invoke(descSmc); + } + }; + } + + private async Task DocumentEntity_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.SourceElementsDocument; + + 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.SourceElementsDocument) + { + // 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.SourceElementsDocument.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") + DocumentEntity_DisplaySaveFileAsync(e, true, false); + + // save digital file? + if (tag == null && menuItemHeader == "Save to thing description file ..") + { + DocumentEntity_DisplaySaveFileAsync(e, true, true); + } + + // show digital file + if (tag == null && menuItemHeader == "Make preview permanent" + && e?.ReferableHash != null + && referableHashToCachedBitmap.ContainsKey(e?.ReferableHash) + && e.AddPreviewFile != null) + { + // make sure its empty + if (e.PreviewFile != null) + { + _log?.Error("For this entity, the PreviewFile seems to be already defined. Aborting."); + return; + } + + if (AnyUiMessageBoxResult.Cancel == await _displayContext?.MessageBoxFlyoutShowAsync( + "Add a PreviewFile information to the current DocumentEntity?", + "AssetInterfaceDescriptions", + AnyUiMessageBoxButton.OKCancel, + AnyUiMessageBoxImage.Question)) + return; + + // try turn the bitmap into a physical file + try + { + var bi = referableHashToCachedBitmap[e.ReferableHash]; + + // go the easy route first + if (bi.PngData != null) + { + // create a writeable temp png file name + var tmpfn = System.IO.Path.GetTempFileName(); + var pngfn = tmpfn.Replace(".tmp", ".png"); + + // write it + System.IO.File.WriteAllBytes(pngfn, bi.PngData); + + // prepare upload data + var ptd = "/aasx/"; + var ptfn = System.IO.Path.GetFileName(pngfn); + _package.PrepareSupplementaryFileParameters(ref ptd, ref ptfn); + + // get content type + var mimeType = AdminShellPackageEnv.GuessMimeType(ptfn); + + // call "add" + var targetPath = _package.AddSupplementaryFileToStore( + pngfn, ptd, ptfn, + embedAsThumb: false, useMimeType: mimeType); + + if (targetPath == null) + { + _log?.Error( + $"Error adding file {pngfn} to package"); + } + else + { + // add + _log?.Info(StoredPrint.Color.Blue, + $"Added {ptfn} to pending package items. A save-operation is required."); + + var res = e.AddPreviewFile( + e, + path: System.IO.Path.Combine(ptd, ptfn), + contentType: mimeType); + + // re-display also in Explorer + _eventStack?.PushEvent(new AasxPluginResultEventRedrawAllElements() + { Session = _session }); + } + } + } + catch (Exception ex) + { + _log?.Error(ex, "Creating physical file for PreviewFile"); + } + } + } + + private async Task DocumentEntity_DisplaySaveFileAsync(InterfaceEntity e, bool display, bool save) + { + try + { + if (e.SourceElementsDocument.Count == 0) + { + return; + } + Aas.ISubmodelElementCollection dmc = e.SourceElementsDocument[0].Parent as Aas.ISubmodelElementCollection; + var uc = await _displayContext.MenuSelectSaveFilenameAsync( + ticket: null, argName: null, + caption: "Select preset JSON file to save ..", + proposeFn: "new.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 DocumentEntity_DoubleClick(InterfaceEntity e) + { + DocumentEntity_DisplaySaveFileAsync(e, true, false); + } + + protected bool _inDragStart = false; + + private void DocumentEntity_DragStart(InterfaceEntity e) + { + // first check + if (e == null || e.DigitalFile?.Path == null || e.DigitalFile.Path.Trim().Length < 1 || _inDragStart) + { + _inDragStart = false; + return; + } + + // lock + _inDragStart = true; + + // hastily prepare data + try + { + // make a file available + var inputFn = e.DigitalFile.Path; + + // check if it an address in the package only + if (!inputFn.Trim().StartsWith("/")) + { + _log?.Error("Can only drag package local files!"); + _inDragStart = false; + return; + } + + // now should make available + if (CheckIfPackageFile(inputFn)) + inputFn = _package?.MakePackageFileAvailableAsTempFile(e.DigitalFile.Path, keepFilename: true); + + if (!inputFn.HasContent()) + { + _log?.Error("Error making digital file available. Aborting!"); + return; + } + + // start the operation + e.ImgContainerAnyUi?.DisplayData?.DoDragDropFiles(e.ImgContainerAnyUi, new[] { inputFn }); + } + catch (Exception ex) + { + _log?.Error(ex, "when initiate file dragging"); + _inDragStart = false; + return; + } + + // unlock + _inDragStart = 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 == "ButtonAddDocument") + { + 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 == "ButtonImportDocument") + { + 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.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(); + } + + public static InterfaceEntity ParseSCInterfaceDescription(Aas.SubmodelElementCollection smcDoc, + string referableHash) + { + var defs1 = AasxPredefinedConcepts.IDTAAid.Static; + + var title = + "" + + smcDoc.Value.FindFirstSemanticIdAs(defs1.AID_title, + MatchMode.Relaxed)?.Value; + + var Created = + "" + + smcDoc.Value.FindFirstSemanticIdAs( + defs1.AID_created, MatchMode.Relaxed)? + .Value; + + var ContentType = + "" + + smcDoc.Value.FindFirstSemanticIdAs( + defs1.AID_contentType, MatchMode.Relaxed)? + .Value; + + var ProtocolType = "HTTP"; + var ent = new InterfaceEntity(title, Created, ContentType, ProtocolType); + + // add + ent.SourceElementsDocument = smcDoc.Value; + ent.ReferableHash = referableHash; + + return ent; + } + #endregion + + #region Timer + //=========== + + private object mutexDocEntitiesInPreview = new object(); + private int numDocEntitiesInPreview = 0; + private const int maxDocEntitiesInPreview = 3; + + private bool _inDispatcherTimer = false; + + protected int _dispatcherNumException = 0; + + private void DispatcherTimer_Tick(object sender, EventArgs e) + { + // access + if (_renderedInterfaces == null || theDocEntitiesToPreview == null || _inDispatcherTimer) + if (_renderedInterfaces == null || theDocEntitiesToPreview == null || _inDispatcherTimer) + return; + + _inDispatcherTimer = true; + var updateDisplay = false; + + // each tick check for one image, if a preview shall be done + if (theDocEntitiesToPreview != null && theDocEntitiesToPreview.Count > 0 && + numDocEntitiesInPreview < maxDocEntitiesInPreview) + { + // pop + InterfaceEntity ent = null; + lock (theDocEntitiesToPreview) + { + ent = theDocEntitiesToPreview[0]; + theDocEntitiesToPreview.RemoveAt(0); + } + + try + { + // temp input + var inputFn = ent?.DigitalFile?.Path; + if (inputFn != null) + { + // try check if Magick.NET library is available + var thumbBI = AnyUiGdiHelper.MakePreviewFromPackageOrUrl(_package, inputFn); + if (thumbBI != null) + { + // directly add this + if (referableHashToCachedBitmap != null + && !referableHashToCachedBitmap.ContainsKey(ent.ReferableHash)) + { + if (ent.ImgContainerAnyUi != null) + ent.ImgContainerAnyUi.BitmapInfo = thumbBI; + referableHashToCachedBitmap[ent.ReferableHash] = thumbBI; + updateDisplay = true; + } + } + else + { + // + // OLD way: use external program to convert + // + + // makes only sense under Windows + if (OperatingSystemHelper.IsWindows()) + { + // from package? + if (CheckIfPackageFile(inputFn)) + inputFn = _package?.MakePackageFileAvailableAsTempFile(ent.DigitalFile.Path); + + // temp output + string outputFn = System.IO.Path.GetTempFileName().Replace(".tmp", ".png"); + + // remember these for later deletion + ent.DeleteFilesAfterLoading = new[] { inputFn, outputFn }; + + // start process + string arguments = string.Format( + "-flatten -density 75 \"{0}\"[0] \"{1}\"", inputFn, outputFn); + string exeFn = System.IO.Path.Combine( + System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), + "convert.exe"); + + var startInfo = new ProcessStartInfo(exeFn, arguments) + { + WindowStyle = ProcessWindowStyle.Hidden + }; + + var process = new Process { StartInfo = startInfo, EnableRaisingEvents = true }; + + InterfaceEntity lambdaEntity = ent; + string outputFnBuffer = outputFn; + process.Exited += (sender2, args) => + { + // release number of parallel processes + lock (mutexDocEntitiesInPreview) + { + numDocEntitiesInPreview--; + } + + // take over data? + if (lambdaEntity.ImgContainerAnyUi != null) + { + // trigger display image + lambdaEntity.ImageReadyToBeLoaded = outputFnBuffer; + } + }; + + try + { + process.Start(); + } + catch (Exception ex) + { + AdminShellNS.LogInternally.That.Error( + ex, $"Failed to start the process: {startInfo.FileName} " + + $"with arguments {string.Join(" ", startInfo.Arguments)}"); + } + + // limit the number of parallel executions + lock (mutexDocEntitiesInPreview) + { + numDocEntitiesInPreview++; + } + } + } + } + } + catch (Exception ex) + { + AdminShellNS.LogInternally.That.SilentlyIgnoredError(ex); + + if (_dispatcherNumException < 3) + _log?.Error(ex, "AasxPluginAID / converting previews"); + else if (_dispatcherNumException == 3) + _log?.Info("AasxPluginAID / stopping logging exceptions."); + _dispatcherNumException++; + } + } + + // over all items in order to check, if a prepared image shall be displayed + foreach (var de in _renderedInterfaces) + { + if (de == null) + continue; + + if (de.ImageReadyToBeLoaded != null) + { + // never again + var tempFn = de.ImageReadyToBeLoaded; + de.ImageReadyToBeLoaded = null; + + // try load + try + { + // convert here, as the tick-Thread in STA / UI thread + var bi = de.LoadImageFromPath(tempFn); + updateDisplay = true; + + // now delete the associated files file! + if (de.DeleteFilesAfterLoading != null) + foreach (var fn in de.DeleteFilesAfterLoading) + // it is quite likely (e.g. http:// files) that the delete fails! + try + { + System.IO.File.Delete(fn); + } + catch (Exception ex) + { + AdminShellNS.LogInternally.That.SilentlyIgnoredError(ex); + } + + // remember in the cache + if (bi != null + && referableHashToCachedBitmap != null + && !referableHashToCachedBitmap.ContainsKey(de.ReferableHash)) + referableHashToCachedBitmap[de.ReferableHash] = bi; + } + catch (Exception ex) + { + AdminShellNS.LogInternally.That.SilentlyIgnoredError(ex); + + if (_dispatcherNumException < 3) + _log?.Error(ex, "AasxPluginAID / displaying previews"); + else if (_dispatcherNumException == 3) + _log?.Info("AasxPluginAID / stopping logging exceptions."); + _dispatcherNumException++; + } + } + } + + if (_eventStack != null && updateDisplay) + _eventStack.PushEvent(new AasxPluginEventReturnUpdateAnyUi() + { + Session = _session, + PluginName = null, // do NOT call the plugin before rendering + Mode = AnyUiRenderMode.StatusToUi, + UseInnerGrid = true + }); + + _inDispatcherTimer = false; + } + + #endregion + + #region Utilities + //=============== + + private bool CheckIfPackageFile(string fn) + { + return fn.StartsWith(@"/"); + } + + #endregion + } +} diff --git a/src/AasxPluginAID/AIDSemanticConfig.cs b/src/AasxPluginAID/AIDSemanticConfig.cs new file mode 100644 index 00000000..5ec3d1c0 --- /dev/null +++ b/src/AasxPluginAID/AIDSemanticConfig.cs @@ -0,0 +1,555 @@ +/* +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; + +namespace AasxPluginAID +{ + /// + /// Starting from Dec 2021, move these information into a separate class. + /// These were for V1.0 only; no case is known, that these were redefined. + /// Therefore, make then more static + /// + public class AIDSemanticConfig + + { + public Aas.Key SemIdReferencedObject = null; + public static AasxPredefinedConcepts.IDTAAid idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + public FormDescSubmodelElementCollection FormVdi2770 = null; + + public static FormDescSubmodelElementCollection AddCommonSecurityProperty(FormDescSubmodelElementCollection secDef) + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + + secDef.Add(new FormDescProperty( + "proxy", FormMultiplicity.One, idtaDef.AID_proxy.GetAsExactlyOneKey(), + "proxy", + "URI of the proxy server this security configuration provides access to. If not given, " + + "the corresponding security configuration is for the endpoint." + )); + + secDef.Add(new FormDescProperty( + "scheme", FormMultiplicity.One, idtaDef.AID_scheme.GetAsExactlyOneKey(), + "scheme", + "Identification of the security mechanism being configured." + )); + + return secDef; + } + + public static FormDescSubmodelElementCollection AddNoSecScheme(string[] elements = null) + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + var nosecDefinition = new FormDescSubmodelElementCollection( + "nosec", FormMultiplicity.ZeroToMany, idtaDef.AID_nosec_sc.GetAsExactlyOneKey(), + "securityDefinition{0:00}", + ""); + return AddCommonSecurityProperty(nosecDefinition); + } + public static FormDescSubmodelElementCollection AddBearerScheme() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + + var bearerDefinition = new FormDescSubmodelElementCollection( + "bearer", FormMultiplicity.ZeroToMany, idtaDef.AID_bearer_sc.GetAsExactlyOneKey(), + "securityDefinition{0:00}", + ""); + + bearerDefinition.Add(new FormDescProperty( + "authorization", FormMultiplicity.One, idtaDef.AID_authorization.GetAsExactlyOneKey(), + "authorization", + "URI of the authorization server.")); + + bearerDefinition.Add(new FormDescProperty( + "name", FormMultiplicity.One, idtaDef.AID_name.GetAsExactlyOneKey(), + "name", + "Name for query, header, cookie, or uri parameters.")); + + bearerDefinition.Add(new FormDescProperty( + "alg", FormMultiplicity.One, idtaDef.AID_alg.GetAsExactlyOneKey(), + "alg", + "Encoding, encryption, or digest algorithm.")); + + bearerDefinition.Add(new FormDescProperty( + "format", FormMultiplicity.One, idtaDef.AID_format.GetAsExactlyOneKey(), + "format", + "Specifies format of security authentication information.")); + + bearerDefinition.Add(new FormDescProperty( + "in", FormMultiplicity.One, idtaDef.AID_in.GetAsExactlyOneKey(), + "in", + "Specifies the location of security authentication information.")); + + return AddCommonSecurityProperty(bearerDefinition); + } + public static FormDescSubmodelElementCollection AddBasicScheme() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + var basicDefinition = new FormDescSubmodelElementCollection( + "basic", FormMultiplicity.ZeroToMany, idtaDef.AID_basic_sc.GetAsExactlyOneKey(), + "securityDefinition{0:00}", + ""); + + basicDefinition.Add(new FormDescProperty( + "name", FormMultiplicity.One, idtaDef.AID_name.GetAsExactlyOneKey(), + "name", + "Name for query, header, cookie, or uri parameters.")); + + basicDefinition.Add(new FormDescProperty( + "in", FormMultiplicity.One, idtaDef.AID_in.GetAsExactlyOneKey(), + "in", + "Specifies the location of security authentication information.")); + + return AddCommonSecurityProperty(basicDefinition); + + } + public static FormDescSubmodelElementCollection AddDigestScheme() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + var digestDefinition = new FormDescSubmodelElementCollection( + "digest", FormMultiplicity.ZeroToMany, idtaDef.AID_digest_sc.GetAsExactlyOneKey(), + "securityDefinition{0:00}", + ""); + + digestDefinition.Add(new FormDescProperty( + "name", FormMultiplicity.One, idtaDef.AID_name.GetAsExactlyOneKey(), + "name", + "Name for query, header, cookie, or uri parameters.")); + + digestDefinition.Add(new FormDescProperty( + "in", FormMultiplicity.One, idtaDef.AID_in.GetAsExactlyOneKey(), + "in", + "Specifies the location of security authentication information.")); + + digestDefinition.Add(new FormDescProperty( + "qop", FormMultiplicity.One, idtaDef.AID_qop.GetAsExactlyOneKey(), + "qop", + "Quality of protection.")); + + return AddCommonSecurityProperty(digestDefinition); + + } + public static FormDescSubmodelElementCollection AddPskScheme() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + var pskDefinition = new FormDescSubmodelElementCollection( + "psk", FormMultiplicity.ZeroToMany, idtaDef.AID_psk_sc.GetAsExactlyOneKey(), + "securityDefinition{0:00}", + ""); + + pskDefinition.Add(new FormDescProperty( + "identity", FormMultiplicity.One, idtaDef.AID_qop.GetAsExactlyOneKey(), + "identity", + "Identifier providing information which can be used for selection or confirmation")); + + return AddCommonSecurityProperty(pskDefinition); + } + public static FormDescSubmodelElementCollection AddOauth2Scheme() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + + var oauth2Definition = new FormDescSubmodelElementCollection( + "oauth2", FormMultiplicity.ZeroToMany, idtaDef.AID_oauth2_sc.GetAsExactlyOneKey(), + "securityDefinition{0:00}", + ""); + + oauth2Definition.Add(new FormDescProperty( + "authorization", FormMultiplicity.One, idtaDef.AID_authorization.GetAsExactlyOneKey(), + "authorization", + "URI of the authorization server.")); + + oauth2Definition.Add(new FormDescProperty( + "token", FormMultiplicity.One, idtaDef.AID_token.GetAsExactlyOneKey(), + "token", + "URI of the token server.")); + + oauth2Definition.Add(new FormDescProperty( + "refresh", FormMultiplicity.One, idtaDef.AID_alg.GetAsExactlyOneKey(), + "refresh", + "URI of the refresh server.")); + + oauth2Definition.Add(new FormDescProperty( + "scopes", FormMultiplicity.One, idtaDef.AID_format.GetAsExactlyOneKey(), + "scopes", + "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. The values associated with a form SHOULD be chosen from " + + "those defined in an OAuth2SecurityScheme active on that form.")); + + oauth2Definition.Add(new FormDescProperty( + "flow", FormMultiplicity.One, idtaDef.AID_alg.GetAsExactlyOneKey(), + "flow", + "Authorization flow.")); + + return AddCommonSecurityProperty(oauth2Definition); + } + public static FormDescSubmodelElementCollection AddApiKeyScheme() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + var apikeyDefinition = new FormDescSubmodelElementCollection( + "apikey", FormMultiplicity.ZeroToMany, idtaDef.AID_apikey_sc.GetAsExactlyOneKey(), + "securityDefinition{0:00}", + ""); + + apikeyDefinition.Add(new FormDescProperty( + "name", FormMultiplicity.One, idtaDef.AID_name.GetAsExactlyOneKey(), + "name", + "Name for query, header, cookie, or uri parameters.")); + + apikeyDefinition.Add(new FormDescProperty( + "in", FormMultiplicity.One, idtaDef.AID_in.GetAsExactlyOneKey(), + "in", + "Specifies the location of security authentication information.")); + + return AddCommonSecurityProperty(apikeyDefinition); + + } + public static FormDescSubmodelElementCollection AddautoScheme() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + var autoDefinition = new FormDescSubmodelElementCollection( + "auto", FormMultiplicity.ZeroToMany, null, + "securityDefinition{0:00}", + ""); + + return AddCommonSecurityProperty(autoDefinition); + } + public static FormDescSubmodelElementCollection CreateSecurityDefinitions() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + + var securityDefinitions = new FormDescSubmodelElementCollection( + "securityDefinitions", FormMultiplicity.ZeroToOne, idtaDef.AID_securityDefinitions.GetAsExactlyOneKey(), + "securityDefinitions", + ""); + securityDefinitions.Add(AddNoSecScheme()); + securityDefinitions.Add(AddBearerScheme()); + securityDefinitions.Add(AddBasicScheme()); + securityDefinitions.Add(AddDigestScheme()); + securityDefinitions.Add(AddPskScheme()); + securityDefinitions.Add(AddOauth2Scheme()); + securityDefinitions.Add(AddApiKeyScheme()); + securityDefinitions.Add(AddautoScheme()); + + return securityDefinitions; + } + public static FormDescSubmodelElementCollection CreateFormCommomElements(string title, string presetIdShort, string formInfo) + { + var form = new FormDescSubmodelElementCollection( + title, FormMultiplicity.ZeroToOne, null, + presetIdShort,formInfo); + + return form; + } + public static FormDescSubmodelElementCollection CreateHTTPForm() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + FormDescSubmodelElementCollection form = CreateFormCommomElements("HTTP form","forms","HTTP form"); + + form.Add(new FormDescProperty( + "htv:methodName", FormMultiplicity.One, idtaDef.AID_htv_methodName.GetAsExactlyOneKey(), + "htv:methodName", + "")); + + var htvHeaders = new FormDescSubmodelElementCollection( + "htv:headers", FormMultiplicity.One, idtaDef.AID_htv_headers.GetAsExactlyOneKey(), + "htv:headers", + ""); + + htvHeaders.Add(new FormDescProperty( + "htv:fieldName", FormMultiplicity.One, idtaDef.AID_htv_fieldName.GetAsExactlyOneKey(), + "htv:fieldName", + "")); + + htvHeaders.Add(new FormDescProperty( + "htv:fieldValue", FormMultiplicity.One, idtaDef.AID_htv_fieldValue.GetAsExactlyOneKey(), + "htv:fieldValue", + "")); + + form.Add(htvHeaders); + form.KeySemanticId = idtaDef.AID_httpforms.GetAsExactlyOneKey(); + + return form; + } + public static FormDescSubmodelElementCollection CreateModbusForm() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + FormDescSubmodelElementCollection form = CreateFormCommomElements("Modbus form", "forms", "Modbus form"); + + + form.Add(new FormDescProperty( + "modbus:function", FormMultiplicity.One, idtaDef.AID_modbus_function.GetAsExactlyOneKey(), + "modbus:function", + "")); + + form.Add(new FormDescProperty( + "modbus:entity", FormMultiplicity.One, idtaDef.AID_modbus_entity.GetAsExactlyOneKey(), + "modbus:entity", + "")); + + form.Add(new FormDescProperty( + "modbus:zeroBasedAddressing", FormMultiplicity.One, idtaDef.AID_modbus_zeroBasedAddressing.GetAsExactlyOneKey(), + "modbus:zeroBasedAddressing", + "")); + + form.Add(new FormDescProperty( + "modbus:timeout", FormMultiplicity.One, idtaDef.AID_modbus_timeout.GetAsExactlyOneKey(), + "modbus:timeout", + "")); + + form.Add(new FormDescProperty( + "modbus:pollingTime", FormMultiplicity.One, idtaDef.AID_modbus_pollingTime.GetAsExactlyOneKey(), + "modbus:pollingTime", + "")); + form.KeySemanticId = idtaDef.AID_modbusforms.GetAsExactlyOneKey(); + return form; + } + public static FormDescSubmodelElementCollection CreateMQTTForm() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + FormDescSubmodelElementCollection form = CreateFormCommomElements("MQTT form", "forms", "MQTT form"); + + + form.Add(new FormDescProperty( + "mqv:retain", FormMultiplicity.One, idtaDef.AID_mqv_retain.GetAsExactlyOneKey(), + "mqv:retain", + "")); + + form.Add(new FormDescProperty( + "mqv:controlPacket", FormMultiplicity.One, idtaDef.AID_mqv_controlPacket.GetAsExactlyOneKey(), + "mqv:controlPacket", + "")); + + form.Add(new FormDescProperty( + "mqv:qos", FormMultiplicity.One, idtaDef.AID_mqv_qos.GetAsExactlyOneKey(), + "mqv: qos", + "")); + form.KeySemanticId = idtaDef.AID_mqttforms.GetAsExactlyOneKey(); + return form; + } + public static FormDescSubmodelElementCollection CreateProperty() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + + var property = new FormDescSubmodelElementCollection( + "property", FormMultiplicity.ZeroToMany, idtaDef.AID_propertyName.GetAsExactlyOneKey(), + "property{0:00}", + ""); + + property.Add(new FormDescProperty( + "title", FormMultiplicity.One, idtaDef.AID_title.GetAsExactlyOneKey(), + "title", + "Provides a human-readable title " + + "(e.g., display a text for UI representation) based on a default language.")); + + + property.Add(new FormDescProperty( + "observable", FormMultiplicity.One, idtaDef.AID_observable.GetAsExactlyOneKey(), + "observable", + "A hint that indicates whether Servients hosting the Thing and Intermediaries " + + "should provide a Protocol Binding that supports the observeproperty and unobserveproperty operations for this Property.")); + + property.Add(new FormDescProperty( + "description", FormMultiplicity.One, idtaDef.AID_description.GetAsExactlyOneKey(), + "description", + "Provides additional (human-readable) information based on a default language.")); + + property.Add(new FormDescProperty( + "type", FormMultiplicity.One, idtaDef.AID_type.GetAsExactlyOneKey(), + "type", + "Assignment of JSON-based data types compatible with JSON Schema" + + " (one of boolean, integer, number, string, object, array, or null).")); + + property.Add(new FormDescProperty( + "min_max", FormMultiplicity.One, idtaDef.AID_min_max.GetAsExactlyOneKey(), + "min_max", + "")); + + property.Add(new FormDescProperty( + "itemsRange", FormMultiplicity.One, idtaDef.AID_itemsRange.GetAsExactlyOneKey(), + "itemsRange", + "")); + + property.Add(new FormDescProperty( + "lengthRange", FormMultiplicity.One, idtaDef.AID_lengthRange.GetAsExactlyOneKey(), + "lengthRange", + "")); + + property.Add(new FormDescProperty( + "contentMediaType", FormMultiplicity.One, idtaDef.AID_contentType.GetAsExactlyOneKey(), + "contentMediaType", + "Specifies the MIME type of the contents of a string value," + + " as described in [RFC2046].")); + + property.Add(new FormDescProperty( + "const", FormMultiplicity.One, idtaDef.AID_const.GetAsExactlyOneKey(), + "const", + "Provides a constant value.")); + + property.Add(new FormDescProperty( + "default", FormMultiplicity.One, idtaDef.AID_default.GetAsExactlyOneKey(), + "default", + "Supply a default value. The value SHOULD validate against the data schema" + + " in which it resides.")); + + property.Add(new FormDescProperty( + "unit", FormMultiplicity.One, null, + "unit", + "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")); + + property.Add(CreateHTTPForm()); + property.Add(CreateMQTTForm()); + property.Add(CreateModbusForm()); + + return property; + } + + + public static FormDescSubmodelElementCollection CreateAssetInterfaceDescription() + { + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + // DocumentItem + + var interfaceDescription = new FormDescSubmodelElementCollection( + "Interface", FormMultiplicity.ZeroToMany,idtaDef.AID_Interface.GetAsExactlyOneKey(), + "Interface{0:00}", + "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."); + + + interfaceDescription.Add(new FormDescProperty( + "title", FormMultiplicity.One, idtaDef.AID_title.GetAsExactlyOneKey(), + "title", + "Provides a human-readable title")); + + interfaceDescription.Add(new FormDescProperty( + "description", FormMultiplicity.One, idtaDef.AID_description.GetAsExactlyOneKey(), + "description", + "Provides additional (human-readable) information based on a default language.")); + + interfaceDescription.Add(new FormDescProperty( + "created", FormMultiplicity.One, idtaDef.AID_created.GetAsExactlyOneKey(), + "created", + "Provides information when the TD instance was created.")); + + interfaceDescription.Add(new FormDescProperty( + "modified", FormMultiplicity.One, idtaDef.AID_modified.GetAsExactlyOneKey(), + "modified", + "Provides information when the TD instance was last modified.")); + + interfaceDescription.Add(new FormDescProperty( + "support", FormMultiplicity.One, idtaDef.AID_support.GetAsExactlyOneKey(), + "support", + "Provides information about the TD maintainer as URI scheme (e.g., mailto [RFC6068], tel [RFC3966], https [RFC9112]).")); + + var endPointMetaData = new FormDescSubmodelElementCollection( + "EndpointMetadata", FormMultiplicity.One, idtaDef.AID_EndpointMetadata.GetAsExactlyOneKey(), + "EndpointMetadata", + ""); + + endPointMetaData.Add(new FormDescProperty( + "base", FormMultiplicity.One, idtaDef.AID_base.GetAsExactlyOneKey(), + "base", + "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].")); + + endPointMetaData.Add(new FormDescProperty( + "contentType", FormMultiplicity.One, idtaDef.AID_contentType.GetAsExactlyOneKey(), + "contentType", + "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].")); + + endPointMetaData.Add(CreateSecurityDefinitions()); + + interfaceDescription.Add(endPointMetaData); + + var interfaceMetaData = new FormDescSubmodelElementCollection( + "InterfaceMetaData", FormMultiplicity.One, idtaDef.AID_InterfaceMetadata.GetAsExactlyOneKey(), + "InterfaceMetaData", + ""); + + var properties = new FormDescSubmodelElementCollection( + "properties", FormMultiplicity.ZeroToOne, idtaDef.AID_properties.GetAsExactlyOneKey(), + "properties", + ""); + + var externalDescriptor = new FormDescSubmodelElementCollection( + "ExternalDescriptor", FormMultiplicity.ZeroToOne, idtaDef.AID_ExternalDescriptor.GetAsExactlyOneKey(), + "ExternalDescriptor", + ""); + + externalDescriptor.Add(new FormDescFile( + "descriptorName", FormMultiplicity.One, idtaDef.AID_fileName.GetAsExactlyOneKey(), + "descriptorName")); + + properties.Add(CreateProperty()); + + interfaceMetaData.Add(properties); + + interfaceDescription.Add(interfaceMetaData); + interfaceDescription.Add(externalDescriptor); + + return interfaceDescription; + } + + public static InterfaceEntity ParseSCInterfaceDescription(Aas.SubmodelElementCollection smcDoc, + string referableHash) + { + var defs1 = AasxPredefinedConcepts.IDTAAid.Static; + + var title = + "" + + smcDoc.Value.FindFirstSemanticIdAs(defs1.AID_title, + MatchMode.Relaxed)?.Value; + + var Created = + "" + + smcDoc.Value.FindFirstSemanticIdAs( + defs1.AID_created, MatchMode.Relaxed)? + .Value; + + var ContentType = + "" + + smcDoc.Value.FindFirstSemanticIdAs( + defs1.AID_contentType, MatchMode.Relaxed)? + .Value; + + var ProtocolType = "HTTP"; + var ent = new InterfaceEntity(title, Created, ContentType, ProtocolType); + + // add + ent.SourceElementsDocument = smcDoc.Value; + ent.ReferableHash = referableHash; + + return ent; + } + + } +} \ No newline at end of file diff --git a/src/AasxPluginAID/AIDTDExport.cs b/src/AasxPluginAID/AIDTDExport.cs new file mode 100644 index 00000000..58429f27 --- /dev/null +++ b/src/AasxPluginAID/AIDTDExport.cs @@ -0,0 +1,200 @@ +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; + +namespace AasxPluginAID +{ + class AIDTDExport + { + public static JObject serialize_ds(Aas.ISubmodelElementCollection dsc) + { + JObject dsJO = new JObject(); + string[] stringidShorts = { "type", "title", "description" , "contentMediaType", "const", + "default", "unit"}; + string[] unsignedIdShorts = { "minimum", "maximum" }; + string[] floatIdShorts = { "minItems", "maxItems", "minLength", "maxLength" }; + + foreach (var dsce in dsc.Value) + { + if (stringidShorts.Contains(dsce.IdShort)) { dsJO[dsce.IdShort] = dsce.ValueAsText(); } + if (unsignedIdShorts.Contains(dsce.IdShort)) { dsJO[dsce.IdShort] = dsce.ValueAsText(); } + if (floatIdShorts.Contains(dsce.IdShort)) { dsJO[dsce.IdShort] = dsce.ValueAsText(); } + if (dsce.IdShort == "enum") + { + Aas.ISubmodelElementCollection _enum = dsce as Aas.SubmodelElementCollection; + List enumsList = new List(); + foreach (var enume in _enum.Value) + { + enumsList.Add(enume.ValueAsText()); + } + dsJO["enum"] = JToken.FromObject(_enum); + } + else if (dsce.IdShort == "items") + { + Aas.ISubmodelElementCollection itemsSC = dsce as Aas.SubmodelElementCollection; + if (itemsSC.Value.Count == 1) + { + List itemsList = new List(); + foreach (var item in itemsSC.Value) + { + Aas.ISubmodelElementCollection _item = item as Aas.SubmodelElementCollection; + itemsList.Add(serialize_ds(_item)); + } + dsJO["items"] = JToken.FromObject(itemsList); + } + else + { + Aas.ISubmodelElementCollection _item = itemsSC.Value[0] as Aas.SubmodelElementCollection; + dsJO["items"] = JToken.FromObject(serialize_ds(_item)); + } + + } + + } + return dsJO; + } + public static JObject serialize_io(Aas.ISubmodelElementCollection dsc) + { + JObject ioJB = new JObject(); + string[] stringidShorts = { "title", "description" }; + foreach (var dsce in dsc.Value) + { + if (stringidShorts.Contains(dsce.IdShort)) { ioJB[dsce.IdShort] = dsce.ValueAsText(); } + if (dsce.IdShort == "forms") + { + Aas.ISubmodelElementCollection forms = dsce as Aas.SubmodelElementCollection; + List formsJD = new List(); + JObject formJD = new JObject(); + foreach (var fe in forms.Value) + { + if (fe.IdShort == "href") { formJD["href"] = fe.ValueAsText(); } + else if (fe.IdShort == "contentType") { formJD["contentType"] = fe.ValueAsText(); } + else if (fe.IdShort == "subprotocol") { formJD["subprotocol"] = fe.ValueAsText(); } + else if (fe.IdShort.Split(":")[0] == "htv") + { + if (fe.IdShort.Split(":")[0] == "htv:headers") + { + Aas.ISubmodelElementCollection htv_headerSC = fe as Aas.SubmodelElementCollection; + foreach (var headerElem in htv_headerSC.Value) + { + if (headerElem.IdShort == "htv:fieldName") { formJD["htv:fieldName"] = fe.ValueAsText(); } + else if (headerElem.IdShort == "htv:fieldValue") { formJD["htv:fieldValue"] = fe.ValueAsText(); } + } + } + else { formJD[fe.IdShort] = fe.ValueAsText(); } + } + else if (fe.IdShort.Split(":")[0] == "modbus") { formJD[fe.IdShort] = fe.ValueAsText(); } + else if (fe.IdShort.Split(":")[0] == "mqv") { formJD[fe.IdShort] = fe.ValueAsText(); } + } + formsJD.Add(formJD); + ioJB["forms"] = JToken.FromObject(formsJD); + + } + } + return ioJB; + } + public static JObject serialize_p(Aas.ISubmodelElementCollection posc) + { + JObject propertyJD = serialize_io(posc); + propertyJD.Merge(serialize_ds(posc)); + + foreach (var pe in posc.Value) + { + if (pe.IdShort == "observable") + { + propertyJD[pe.IdShort] = pe.ValueAsText(); + } + } + return propertyJD; + } + public static JObject EndpointMetadata(Aas.ISubmodelElement enm,JObject TDJson) + { + Aas.ISubmodelElementCollection epm = enm as Aas.SubmodelElementCollection; + + foreach (var _epm in epm.Value){ + if (_epm.IdShort == "base") + { + TDJson["base"] = _epm.ValueAsText(); + } + else if (_epm.IdShort == "contentType") + { + TDJson["contentType"] = _epm.ValueAsText(); + } + else if (_epm.IdShort == "securityDefinitions") + { + Aas.ISubmodelElementCollection securityDefinitions = _epm as Aas.SubmodelElementCollection; + JObject securityDefinitionsList = new JObject(); + foreach (var securityDefinition in securityDefinitions.Value) + { + Aas.ISubmodelElementCollection _securityDefinition = securityDefinition as Aas.SubmodelElementCollection; + JObject securityDefinitionJD = new JObject(); + foreach (var _sde in _securityDefinition.Value) + { + securityDefinitionJD[_sde.IdShort] = _sde.ValueAsText(); + } + securityDefinitionsList[_securityDefinition.IdShort] = securityDefinitionJD; + } + TDJson["securityDefinitions"] = JToken.FromObject(securityDefinitionsList); + } + } + 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 sme in smc.Value) + { + if (sme.IdShort == "EndpointMetadata") + { + TDJson = EndpointMetadata(sme, TDJson); + } + else if (sme.IdShort == "InterfaceMetaData") + { + Aas.ISubmodelElementCollection imd = sme as Aas.SubmodelElementCollection; + JObject imdJson = new JObject(); + foreach (var imde in imd.Value) + { + if (imde.IdShort == "properties") + { + Aas.ISubmodelElementCollection properties = imde as Aas.SubmodelElementCollection; + JObject propertiesJO = new JObject(); + foreach (var _property in properties.Value) + { + JObject _propetyJO = new JObject(); + Aas.ISubmodelElementCollection _propertysmc = _property as Aas.SubmodelElementCollection; + propertiesJO[_propertysmc.IdShort] = serialize_p(_propertysmc); + } + TDJson["properties"] = propertiesJO; + } + else + { + TDJson[imde.IdShort] = imde.ValueAsText(); + } + } + } + else + { + TDJson[sme.IdShort] = sme.ValueAsText(); + } + + } + } + catch (Exception ex) + { + + } + return TDJson; + } + } +} diff --git a/src/AasxPluginAID/AIDTDImport.cs b/src/AasxPluginAID/AIDTDImport.cs new file mode 100644 index 00000000..bba6bea6 --- /dev/null +++ b/src/AasxPluginAID/AIDTDImport.cs @@ -0,0 +1,588 @@ +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; + +namespace AasxPluginAID +{ + class AIDTDImport + { + public static AasxPredefinedConcepts.IDTAAid idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + public static Aas.Property BuildAASProperty(string idShort, string value, string description = "", Aas.Reference _semanticId = null) + { + Aas.Property _property = new Aas.Property(valueType: Aas.DataTypeDefXsd.String, idShort: idShort, value: value); + _property.IdShort = idShort; + _property.Category = "PARAMETER"; + _property.AddDescription("en", description); + _property.SemanticId = _semanticId; + + return _property; + } + public static Aas.Range BuildAASRange(string idShort, string description = "", Aas.Reference _semanticId = null) + { + Aas.Range _range = new Aas.Range(valueType: Aas.DataTypeDefXsd.String, idShort: idShort); + _range.IdShort = idShort; + _range.Category = "PARAMETER"; + _range.AddDescription("en", description); + _range.SemanticId = _semanticId; + + return _range; + } + public static Aas.SubmodelElementCollection BuildCommonSecurityProperties(JObject secJObject, string _name) + { + Aas.SubmodelElementCollection securityScheme = new Aas.SubmodelElementCollection(); + securityScheme.IdShort = _name; + if (secJObject.ContainsKey("proxy")) + { + securityScheme.Add(BuildAASProperty(idShort: "proxy", value: secJObject["proxy"].ToString(), + description: "", idtaDef.AID_proxy)); + } + if (secJObject.ContainsKey("scheme")) + { + securityScheme.Add(BuildAASProperty(idShort: "scheme", value: secJObject["scheme"].ToString(), + description: "", idtaDef.AID_scheme)); + } + + return securityScheme; + } + public static Aas.SubmodelElementCollection BuildNosecScheme(JObject nosecJObject, string _name) + { + Aas.SubmodelElementCollection nosec = BuildCommonSecurityProperties(nosecJObject, _name); + nosec.SemanticId = idtaDef.AID_nosec_sc; + return nosec; + } + public static Aas.SubmodelElementCollection BuildBearerScheme(JObject bearerJObject, string _name) + { + Aas.SubmodelElementCollection bearersec = BuildCommonSecurityProperties(bearerJObject, _name); + bearersec.SemanticId = idtaDef.AID_bearer_sc; + if (bearerJObject.ContainsKey("name")) + { + bearersec.Add(BuildAASProperty(idShort: "name", value: bearerJObject["name"].ToString(), + description: "", idtaDef.AID_name)); + } + if (bearerJObject.ContainsKey("in")) + { + bearersec.Add(BuildAASProperty(idShort: "in", value: bearerJObject["in"].ToString(), + description: "", idtaDef.AID_in)); + } + if (bearerJObject.ContainsKey("qop")) + { + bearersec.Add(BuildAASProperty(idShort: "qop", value: bearerJObject["qop"].ToString(), + description: "", idtaDef.AID_qop)); + } + if (bearerJObject.ContainsKey("authorization")) + { + bearersec.Add(BuildAASProperty(idShort: "authorization", value: bearerJObject["authorization"].ToString(), + description: "", idtaDef.AID_scheme)); + } + if (bearerJObject.ContainsKey("alg")) + { + bearersec.Add(BuildAASProperty(idShort: "alg", value: bearerJObject["alg"].ToString(), + description: "", idtaDef.AID_alg)); + } + if (bearerJObject.ContainsKey("format")) + { + bearersec.Add(BuildAASProperty(idShort: "format", value: bearerJObject["format"].ToString(), + description: "", idtaDef.AID_format)); + } + return bearersec; + } + public static Aas.SubmodelElementCollection BuildBasicScheme(JObject basicJObject, string _name) + { + Aas.SubmodelElementCollection basicsec = BuildCommonSecurityProperties(basicJObject, _name); + basicsec.SemanticId = idtaDef.AID_basic_sc; + if (basicJObject.ContainsKey("name")) + { + basicsec.Add(BuildAASProperty(idShort: "name", value: basicJObject["name"].ToString(), + description: "", idtaDef.AID_name)); + } + if (basicJObject.ContainsKey("in")) + { + basicsec.Add(BuildAASProperty(idShort: "in", value: basicJObject["in"].ToString(), + description: "", idtaDef.AID_in)); + } + return basicsec; + } + public static Aas.SubmodelElementCollection BuildDigestScheme(JObject digestJObject, string _name) + { + Aas.SubmodelElementCollection digestsec = BuildCommonSecurityProperties(digestJObject, _name); + digestsec.SemanticId = idtaDef.AID_digest_sc; + if (digestJObject.ContainsKey("name")) + { + digestsec.Add(BuildAASProperty(idShort: "name", value: digestJObject["name"].ToString(), + description: "", idtaDef.AID_name)); + } + if (digestJObject.ContainsKey("in")) + { + digestsec.Add(BuildAASProperty(idShort: "in", value: digestJObject["in"].ToString(), + description: "", idtaDef.AID_in)); + } + if (digestJObject.ContainsKey("qop")) + { + digestsec.Add(BuildAASProperty(idShort: "qop", value: digestJObject["qop"].ToString(), + description: "", idtaDef.AID_qop)); + } + return digestsec; + } + public static Aas.SubmodelElementCollection BuildPskScheme(JObject pskJObject, string _name) + { + Aas.SubmodelElementCollection psksec = BuildCommonSecurityProperties(pskJObject, _name); + psksec.SemanticId = idtaDef.AID_psk_sc; + if (pskJObject.ContainsKey("identity")) + { + psksec.Add(BuildAASProperty(idShort: "name", value: pskJObject["identity"].ToString(), + description: "", idtaDef.AID_name)); + } + return psksec; + } + public static Aas.SubmodelElementCollection BuildOauth2Scheme(JObject oauth2JObject, string _name) + { + Aas.SubmodelElementCollection oauth2sec = BuildCommonSecurityProperties(oauth2JObject, _name); + oauth2sec.SemanticId = idtaDef.AID_oauth2_sc; + if (oauth2JObject.ContainsKey("authorization")) + { + oauth2sec.Add(BuildAASProperty(idShort: "authorization", value: oauth2JObject["authorization"].ToString(), + description: "", idtaDef.AID_authorization)); + } + if (oauth2JObject.ContainsKey("token")) + { + oauth2sec.Add(BuildAASProperty(idShort: "token", value: oauth2JObject["token"].ToString(), + description: "", idtaDef.AID_token)); + } + if (oauth2JObject.ContainsKey("refresh")) + { + oauth2sec.Add(BuildAASProperty(idShort: "refresh", value: oauth2JObject["refresh"].ToString(), + description: "", idtaDef.AID_refresh)); + } + if (oauth2JObject.ContainsKey("scopes")) + { + oauth2sec.Add(BuildAASProperty(idShort: "scopes", value: oauth2JObject["scopes"].ToString(), + description: "", idtaDef.AID_scopes)); + } + if (oauth2JObject.ContainsKey("alg")) + { + oauth2sec.Add(BuildAASProperty(idShort: "flow", value: oauth2JObject["flow"].ToString(), + description: "", idtaDef.AID_flow)); + } + return oauth2sec; + } + public static Aas.SubmodelElementCollection BuildApiKeyScheme(JObject apiKeyJObject, string _name) + { + Aas.SubmodelElementCollection apikeysec = BuildCommonSecurityProperties(apiKeyJObject, _name); + apikeysec.SemanticId = idtaDef.AID_digest_sc; + if (apiKeyJObject.ContainsKey("name")) + { + apikeysec.Add(BuildAASProperty(idShort: "name", value: apiKeyJObject["name"].ToString(), + description: "", idtaDef.AID_name)); + } + if (apiKeyJObject.ContainsKey("in")) + { + apikeysec.Add(BuildAASProperty(idShort: "in", value: apiKeyJObject["in"].ToString(), + description: "", idtaDef.AID_in)); + } + return apikeysec; + } + public static Aas.SubmodelElementCollection BuildSecurityDefinitions(JObject sdJObject) + { + Aas.SubmodelElementCollection sds = new Aas.SubmodelElementCollection(); + sds.IdShort = "securityDefinitions"; + sds.SemanticId = idtaDef.AID_securityDefinitions; + foreach (var temp in sdJObject["securityDefinitions"]) + { + JProperty x1 = (JProperty)temp; + JObject _jObject = JObject.Parse((x1.Value).ToString()); + string _name = x1.Name.ToString(); + string scheme = _jObject["scheme"].ToString(); + + if (scheme == "nosec") + { + Aas.SubmodelElementCollection nosec = BuildCommonSecurityProperties(_jObject, _name); + nosec.SemanticId = idtaDef.AID_nosec_sc; + sds.Add(nosec); + } + else if (scheme == "bearer") + { + sds.Add(BuildBearerScheme(_jObject, _name)); + } + else if (scheme == "basic") + { + sds.Add(BuildBasicScheme(_jObject, _name)); + } + else if (scheme == "digest") + { + sds.Add(BuildDigestScheme(_jObject, _name)); + } + else if (scheme == "psk") + { + sds.Add(BuildPskScheme(_jObject, _name)); + } + else if (scheme == "oauth2") + { + sds.Add(BuildOauth2Scheme(_jObject, _name)); + } + else if (scheme == "apikey") + { + sds.Add(BuildApiKeyScheme(_jObject, _name)); + } + else if (scheme == "auto") + { + Aas.SubmodelElementCollection autosec = BuildCommonSecurityProperties(_jObject, _name); + autosec.SemanticId = idtaDef.AID_auto_sc; + sds.Add(autosec); + } + } + return sds; + } + public static Aas.SubmodelElementCollection BuildEndPointMetaData(JObject tdJObject) + { + Aas.SubmodelElementCollection EndpointMetadata = new Aas.SubmodelElementCollection(); + EndpointMetadata.IdShort = "EndpointMetadata"; + EndpointMetadata.AddDescription("en", ""); + EndpointMetadata.SemanticId = idtaDef.AID_EndpointMetadata; + if (tdJObject.ContainsKey("base")) + { + EndpointMetadata.Add(BuildAASProperty(idShort: "base", value: tdJObject["base"].ToString(), + description: "", idtaDef.AID_base)); + } + if (tdJObject.ContainsKey("contentType")) + { + EndpointMetadata.Add(BuildAASProperty(idShort: "contentType", value: tdJObject["contentType"].ToString(), + description: "", idtaDef.AID_contentType)); + } + if (tdJObject.ContainsKey("securityDefinitions")) + { + EndpointMetadata.Add(BuildSecurityDefinitions(tdJObject)); + } + return EndpointMetadata; + } + public static Aas.SubmodelElementCollection BuildDataSchema(JObject dsJObject) + { + Aas.SubmodelElementCollection _dataschema = new Aas.SubmodelElementCollection(); + if (dsJObject.ContainsKey("const")) + { + _dataschema.Add(BuildAASProperty("const", dsJObject["const"].ToString(), "", idtaDef.AID_const)); + } + if (dsJObject.ContainsKey("default")) + { + _dataschema.Add(BuildAASProperty("default", dsJObject["default"].ToString(), "", idtaDef.AID_default)); + } + if (dsJObject.ContainsKey("unit")) + { + _dataschema.Add(BuildAASProperty("unit", dsJObject["unit"].ToString(), "", idtaDef.AID_unit)); + } + if (dsJObject.ContainsKey("title")) + { + _dataschema.Add(BuildAASProperty("title", dsJObject["title"].ToString(), "", idtaDef.AID_title)); + } + if (dsJObject.ContainsKey("description")) + { + _dataschema.Add(BuildAASProperty("description", dsJObject["description"].ToString(), "", idtaDef.AID_description)); + } + if (dsJObject.ContainsKey("type")) + { + _dataschema.Add(BuildAASProperty("type", dsJObject["type"].ToString(), "", idtaDef.AID_type)); + } + if (dsJObject.ContainsKey("minimum")) + { + Aas.Range min_max = BuildAASRange("min_max", "", idtaDef.AID_min_max); + min_max.Min = dsJObject["minimum"].ToString(); + if (dsJObject.ContainsKey("maximum")) + { + min_max.Max = dsJObject["maximum"].ToString(); + } + _dataschema.Add(min_max); + } + if (dsJObject.ContainsKey("maximum") && !dsJObject.ContainsKey("minimum")) + { + Aas.Range min_max = BuildAASRange("min_max", "", idtaDef.AID_min_max); + min_max.Max = dsJObject["maximum"].ToString(); + _dataschema.Add(min_max); + } + if (dsJObject.ContainsKey("minItems")) + { + Aas.Range itemsRange = BuildAASRange("itemsRange", "", idtaDef.AID_itemsRange); + itemsRange.Min = dsJObject["minItems"].ToString(); + if (dsJObject.ContainsKey("maxItems")) + { + itemsRange.Max = dsJObject["maxItems"].ToString(); + } + _dataschema.Add(itemsRange); + } + if (dsJObject.ContainsKey("maxItems") && !dsJObject.ContainsKey("minItems")) + { + Aas.Range itemsRange = BuildAASRange("itemsRange", "", idtaDef.AID_itemsRange); + itemsRange.Max = dsJObject["maxItems"].ToString(); + _dataschema.Add(itemsRange); + } + if (dsJObject.ContainsKey("minLength")) + { + Aas.Range itemsRange = BuildAASRange("itemsRange", "", idtaDef.AID_itemsRange); + itemsRange.Min = dsJObject["minLength"].ToString(); + if (dsJObject.ContainsKey("maxLength")) + { + itemsRange.Max = dsJObject["maxLength"].ToString(); + } + _dataschema.Add(itemsRange); + } + if (dsJObject.ContainsKey("maxLength") && !dsJObject.ContainsKey("minLength")) + { + Aas.Range itemsRange = BuildAASRange("itemsRange", "", idtaDef.AID_itemsRange); + itemsRange.Max = dsJObject["maxLength"].ToString(); + _dataschema.Add(itemsRange); + } + if (dsJObject.ContainsKey("contentMediaType")) + { + _dataschema.Add(BuildAASProperty("contentMediaType", dsJObject["contentMediaType"].ToString(), "", idtaDef.AID_contentType)); + } + return _dataschema; + } + public static Aas.SubmodelElementCollection BuildHTTPBindings(JObject httpJObject, Aas.SubmodelElementCollection _form) + { + bool formfound = false; + if (httpJObject.ContainsKey("htv:methodName")) + { + _form.Add(BuildAASProperty("htv:methodName", httpJObject["htv:methodName"].ToString(), "", idtaDef.AID_htv_methodName)); + formfound = true; + } + if (httpJObject.ContainsKey("htv:headers")) + { + Aas.SubmodelElementCollection httpHeaders = new Aas.SubmodelElementCollection(); + httpHeaders.IdShort = "htv:headers"; + httpHeaders.SemanticId = idtaDef.AID_htv_headers; + foreach (var temp in httpJObject["htv:headers"]) + { + JProperty x1 = (JProperty)temp; + JObject _jObject = JObject.Parse((x1.Value).ToString()); + + if (_jObject.ContainsKey("htv:fieldName")) + { + httpHeaders.Add(BuildAASProperty("htv_fieldName", httpJObject["htv:fieldName"].ToString(), "", idtaDef.AID_htv_fieldName)); + } + if (_jObject.ContainsKey("htv:fieldValue")) + { + httpHeaders.Add(BuildAASProperty("htv_fieldValue", httpJObject["htv:fieldValue"].ToString(), "", idtaDef.AID_htv_fieldValue)); + } + } + _form.Add(httpHeaders); + formfound = true; + } + if(formfound) + { + _form.SemanticId = idtaDef.AID_httpforms; + } + return _form; + } + public static Aas.SubmodelElementCollection BuildMQTTBindings(JObject mqttJObject, Aas.SubmodelElementCollection _form) + { + bool formfound = false; + if (mqttJObject.ContainsKey("mqv:retain")) + { + _form.Add(BuildAASProperty("mqv_retain", mqttJObject["mqv:retain"].ToString(), "", idtaDef.AID_mqv_retain)); + formfound = true; + } + if (mqttJObject.ContainsKey("mqv:controlPacket")) + { + _form.Add(BuildAASProperty("mqv_controlPacket", mqttJObject["mqv:controlPacket"].ToString(), "", idtaDef.AID_mqv_controlPacket)); + formfound = true; + } + if (mqttJObject.ContainsKey("mqv:qos")) + { + _form.Add(BuildAASProperty("mqv_qos", mqttJObject["mqv:qos"].ToString(), "", idtaDef.AID_mqv_qos)); + formfound = true; + } + if (formfound) + { + _form.SemanticId = idtaDef.AID_mqttforms; + } + return _form; + } + public static Aas.SubmodelElementCollection BuildModBusBindings(JObject mqttJObject, Aas.SubmodelElementCollection _form) + { + bool formfound = false; + if (mqttJObject.ContainsKey("modbus:function")) + { + _form.Add(BuildAASProperty("modbus_function", mqttJObject["modbus:function"].ToString(), "", idtaDef.AID_modbus_function)); + formfound = true; + } + if (mqttJObject.ContainsKey("modbus:entity")) + { + _form.Add(BuildAASProperty("modbus_entity", mqttJObject["modbus:entity"].ToString(), "", idtaDef.AID_modbus_entity)); + formfound = true; + } + if (mqttJObject.ContainsKey("modbus:zeroBasedAddressing")) + { + _form.Add(BuildAASProperty("modbus_zeroBasedAddressing", mqttJObject["modbus:zeroBasedAddressing"].ToString(), "", idtaDef.AID_modbus_zeroBasedAddressing)); + formfound = true; + } + if (mqttJObject.ContainsKey("modbus:timeout")) + { + _form.Add(BuildAASProperty("modbus:timeout", mqttJObject["modbus:timeout"].ToString(), "", idtaDef.AID_modbus_timeout)); + formfound = true; + } + if (mqttJObject.ContainsKey("modbus_pollingTime")) + { + _form.Add(BuildAASProperty("modbus_pollingTime", mqttJObject["modbus:pollingTime"].ToString(), "", idtaDef.AID_modbus_pollingTime)); + formfound = true; + } + if (mqttJObject.ContainsKey("modbus:endian")) + { + _form.Add(BuildAASProperty("modbus_type", mqttJObject["modbus:type"].ToString(), "", idtaDef.AID_modbus_type)); + formfound = true; + } + if (formfound) + { + _form.SemanticId = idtaDef.AID_modbusforms; + } + return _form; + } + public static Aas.SubmodelElementCollection BuildForm(JObject formJObject) + { + Aas.SubmodelElementCollection _form = new Aas.SubmodelElementCollection(); + _form.IdShort = "forms"; + _form.SemanticId = idtaDef.AID_forms; + + if (formJObject.ContainsKey("href")) + { + _form.Add(BuildAASProperty("href", formJObject["href"].ToString(), "", idtaDef.AID_href)); + } + if (formJObject.ContainsKey("contentType")) + { + _form.Add(BuildAASProperty("contentType", formJObject["contentType"].ToString(), "", idtaDef.AID_contentType)); + } + if (formJObject.ContainsKey("subprotocol")) + { + _form.Add(BuildAASProperty("subprotocol", formJObject["subprotocol"].ToString(), "", idtaDef.AID_subprotocol)); + } + _form = BuildHTTPBindings(formJObject, _form); + _form = BuildMQTTBindings(formJObject, _form); + _form = BuildModBusBindings(formJObject, _form); + return _form; + } + public static Aas.SubmodelElementCollection BuildTDProperty(JObject pJObject, string name) + { + Aas.SubmodelElementCollection _property = BuildDataSchema(pJObject); + _property.IdShort = name; + _property.AddDescription("en", ""); + _property.SemanticId = idtaDef.AID_propertyName; + + if (pJObject.ContainsKey("observable")) + { + _property.Add(BuildAASProperty("observable", pJObject["observable"].ToString(),"" ,idtaDef.AID_observable)); + } + if (pJObject.ContainsKey("forms")) + { + _property.Add(BuildForm((JObject)pJObject["forms"][0])); + } + return _property; + } + public static Aas.SubmodelElementCollection BuildInterfaceMetaData(JObject tdJObject) + { + Aas.SubmodelElementCollection InterfaceMetaData = new Aas.SubmodelElementCollection(); + InterfaceMetaData.IdShort = "InterfaceMetaData"; + InterfaceMetaData.AddDescription("en", ""); + InterfaceMetaData.SemanticId = idtaDef.AID_InterfaceMetadata; + + if (tdJObject.ContainsKey("properties")) + { + Aas.SubmodelElementCollection properties = new Aas.SubmodelElementCollection(); + properties.IdShort = "properties"; + properties.AddDescription("en", ""); + properties.SemanticId = idtaDef.AID_properties; + int i = 0; + foreach (var temp in tdJObject["properties"]) + { + try + { + JProperty x1 = (JProperty)temp; + JObject _jObject = JObject.Parse((x1.Value).ToString()); + properties.Add(BuildTDProperty(_jObject, x1.Name.ToString())); + i++; + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } + + } + InterfaceMetaData.Add(properties); + } + + return InterfaceMetaData; + } + public static SubmodelElementCollection BuildExternalDescriptor(string filename) + { + Aas.SubmodelElementCollection externalDescriptor = new Aas.SubmodelElementCollection(); + externalDescriptor.IdShort = "ExternalDescriptor"; + externalDescriptor.AddDescription("en",""); + externalDescriptor .SemanticId = idtaDef.AID_ExternalDescriptor; + + Aas.File descriptorName = new Aas.File(contentType : "json", idShort : "fileName", + semanticId: idtaDef.AID_fileName); + descriptorName.Value = filename; + + externalDescriptor.Add(descriptorName); + + return externalDescriptor; + } + public static SubmodelElementCollection CreateAssetInterfaceDescriptionFromTd( + JObject tdJObject, string filename) + { + // shortcut + var idtaDef = AasxPredefinedConcepts.IDTAAid.Static; + // DocumentItem + + Aas.SubmodelElementCollection interfaceDescription = new Aas.SubmodelElementCollection(); + interfaceDescription.IdShort = "interface01"; + interfaceDescription.AddDescription("en", "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."); + interfaceDescription.SemanticId = idtaDef.AID_Interface; + + if (tdJObject.ContainsKey("title")) + { + interfaceDescription.Add(BuildAASProperty(idShort: "title", value: tdJObject["title"].ToString(), + description: "Provides a human-readable title", idtaDef.AID_title)); + } + if (tdJObject.ContainsKey("description")) + { + interfaceDescription.Add(BuildAASProperty(idShort: "description", value: tdJObject["description"].ToString(), + description: "Provides additional (human-readable) information based on a default language.", idtaDef.AID_title)); + } + if (tdJObject.ContainsKey("created")) + { + interfaceDescription.Add(BuildAASProperty(idShort: "created", value: tdJObject["created"].ToString(), + description: "Provides information when the TD instance was created.", idtaDef.AID_created)); + } + if (tdJObject.ContainsKey("modified")) + { + interfaceDescription.Add(BuildAASProperty(idShort: "modified", value: tdJObject["modified"].ToString(), + description: "Provides information when the TD instance was last modified.", idtaDef.AID_modified)); + } + if (tdJObject.ContainsKey("support")) + { + interfaceDescription.Add(BuildAASProperty(idShort: "support", value: tdJObject["support"].ToString(), + description: "Provides information about the TD maintainer as URI scheme", idtaDef.AID_support)); + } + + interfaceDescription.Add(BuildEndPointMetaData(tdJObject)); + 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 00000000..4fc90673 --- /dev/null +++ b/src/AasxPluginAID/AasxPluginAID.csproj @@ -0,0 +1,39 @@ + + + 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 00000000..daf4912b --- /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 00000000..3beebdf2 --- /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/EnumBooleanConverter.cs b/src/AasxPluginAID/EnumBooleanConverter.cs new file mode 100644 index 00000000..c41f8a27 --- /dev/null +++ b/src/AasxPluginAID/EnumBooleanConverter.cs @@ -0,0 +1,47 @@ +/* +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). +*/ + +// ReSharper disable EmptyNamespace + +namespace AasxPluginDocumentShelf +{ + // see: https://stackoverflow.com/questions/397556/how-to-bind-radiobuttons-to-an-enum + +#if USE_WPF + public class EnumBooleanConverter : IValueConverter + { + #region IValueConverter Members + public object Convert( + object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + string parameterString = parameter as string; + if (value == null || parameterString == null) + return DependencyProperty.UnsetValue; + + if (Enum.IsDefined(value.GetType(), value) == false) + return DependencyProperty.UnsetValue; + + object parameterValue = Enum.Parse(value.GetType(), parameterString); + + return parameterValue.Equals(value); + } + + public object ConvertBack( + object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + string parameterString = parameter as string; + if (parameterString == null) + return DependencyProperty.UnsetValue; + + return Enum.Parse(targetType, parameterString); + } + #endregion + } +#endif +} diff --git a/src/AasxPluginAID/InterfaceEntity.cs b/src/AasxPluginAID/InterfaceEntity.cs new file mode 100644 index 00000000..4a806bc1 --- /dev/null +++ b/src/AasxPluginAID/InterfaceEntity.cs @@ -0,0 +1,227 @@ +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 DocumentEntityEvent(InterfaceEntity e); + public event DocumentEntityEvent DoubleClick = null; + + public delegate Task MenuClickDelegate(InterfaceEntity e, string menuItemHeader, object tag); + public event MenuClickDelegate MenuClick = null; + + public event DocumentEntityEvent DragStart = null; + + public string Title = ""; + public string Created = ""; + public string ContentType = ""; + public string ProtocolType = ""; + + public FileInfo DigitalFile, PreviewFile; + +#if USE_WPF + public System.Windows.Controls.Viewbox ImgContainerWpf = null; +#endif + public AnyUiImage ImgContainerAnyUi = null; + public string ReferableHash = null; + + public List SourceElementsDocument = 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) + { + this.Title = Title; + this.Created = Created; + this.ContentType = ContentType; + this.ProtocolType = ProtocolType; + } + + 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 + { + + + private static void SearchForRelations( + List smwc, + InterfaceEntity.DocRelationType drt, + Aas.IReference semId, + InterfaceEntity intoDoc) + { + // access + if (smwc == null || semId == null || intoDoc == null) + return; + + foreach (var re in smwc.FindAllSemanticIdAs(semId, + MatchMode.Relaxed)) + { + // access + if (re.Value == null || re.Value.Count() < 1) + continue; + + // be a bit picky + if (re.Value.Last().Type != Aas.KeyTypes.Entity) + continue; + + // add + intoDoc.Relations.Add(new Tuple( + drt, re.Value)); + } + } + + public static InterfaceEntity ParseSCInterfaceDescription(Aas.SubmodelElementCollection smcDoc, + string referableHash) + { + var defs1 = AasxPredefinedConcepts.IDTAAid.Static; + + var title = + "" + + smcDoc.Value.FindFirstSemanticIdAs(defs1.AID_title, + MatchMode.Relaxed)?.Value; + + var Created = + "" + + smcDoc.Value.FindFirstSemanticIdAs( + defs1.AID_created, MatchMode.Relaxed)? + .Value; + + var ContentType = + "" + + smcDoc.Value.FindFirstSemanticIdAs( + defs1.AID_contentType, MatchMode.Relaxed)? + .Value; + + var ProtocolType = "HTTP"; + var ent = new InterfaceEntity(title, Created, ContentType, ProtocolType); + ent.SourceElementsDocument = smcDoc.Value; + ent.ReferableHash = referableHash; + + return ent; + } + + public static ListOfInterfaceEntity ParseSubmodelAID( + AdminShellPackageEnv thePackage, + Aas.Submodel subModel, + string selectedProtocol) + { + // set a new list + + var its = new ListOfInterfaceEntity(); + var defs1 = AasxPredefinedConcepts.IDTAAid.Static; + + if (thePackage == null || subModel == null ) + return its; + + // look for Documents + if (subModel.SubmodelElements != null) + foreach (var smcDoc in + subModel.SubmodelElements.FindAllSemanticIdAs( + defs1.AID_Interface, MatchMode.Relaxed)) + { + // access + if (smcDoc == null || smcDoc.Value == null) + continue; + string referableHash = String.Format( + "{0:X14} {1:X14}", thePackage.GetHashCode(), smcDoc.GetHashCode()); + its.Add(ParseSCInterfaceDescription(smcDoc, referableHash)); + } + + // ok + return its; + } + } +} diff --git a/src/AasxPluginAID/InterfaceShelfOptions.cs b/src/AasxPluginAID/InterfaceShelfOptions.cs new file mode 100644 index 00000000..c9aaf62c --- /dev/null +++ b/src/AasxPluginAID/InterfaceShelfOptions.cs @@ -0,0 +1,83 @@ +/* +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(); + + /// + /// Create a set of minimal options + /// + public static InterfaceShelfOptions CreateDefault() + { + var opt = new InterfaceShelfOptions(); + + // + // basic record + // + + var rec = new IntefaceShelfOptionsRecord(); + opt.Records.Add(rec); + + // V1.0 + var preDefs = new AasxPredefinedConcepts.DefinitionsVDI2770.SetOfDefsVDI2770( + new AasxPredefinedConcepts.DefinitionsVDI2770()); + var semIdDocumentation = preDefs.SM_VDI2770_Documentation?.SemanticId?.GetAsExactlyOneKey(); + if (semIdDocumentation != null) + rec.AllowSubmodelSemanticId.Add(semIdDocumentation); + + // V1.1 + rec.AllowSubmodelSemanticId.Add( + AasxPredefinedConcepts.VDI2770v11.Static + .SM_ManufacturerDocumentation.GetSemanticKey()); + + // V1.2 + rec.AllowSubmodelSemanticId.Add( + AasxPredefinedConcepts.IdtaHandoverDocumentationV12.Static + .SM_HandoverDocumentation.GetSemanticKey()); + + // + // further models for CAD + // (for the time being still V11!) + // + + rec = new IntefaceShelfOptionsRecord() + { + UsageInfo = "Some manufacturers use manufacturer documentation to provide models for " + + "Computer Aided Design (CAD) and further engineering tools.", + }; + opt.Records.Add(rec); + + return opt; + } + } + +} diff --git a/src/AasxPluginAID/LICENSE.txt b/src/AasxPluginAID/LICENSE.txt new file mode 100644 index 00000000..e41b5715 --- /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 00000000..53d2cba5 --- /dev/null +++ b/src/AasxPluginAID/Plugin.cs @@ -0,0 +1,220 @@ +/* +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 == IDTAAid.Static.AID_Submodel.GetAsExactlyOneKey().Value) + 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) + { + // 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; + } + + // default + return null; + } + + } +} diff --git a/src/AasxPluginAID/TDSemanticID.cs b/src/AasxPluginAID/TDSemanticID.cs new file mode 100644 index 00000000..6ca43f45 --- /dev/null +++ b/src/AasxPluginAID/TDSemanticID.cs @@ -0,0 +1,273 @@ +/* +Copyright (c) 2021-2022 Otto-von-Guericke-Universität Magdeburg, Lehrstuhl Integrierte Automation +harish.pakala@ovgu.de, 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 System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Xml; +using AdminShellNS; +using Microsoft.VisualBasic.FileIO; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Schema; + +namespace AasxPackageExplorer +{ + public static class TDSemanticId + { + public static JObject semanticIDJObject = new JObject + { + // td Schema + ["Thing"] = "https://www.w3.org/2019/wot/td#Thing", + ["@type"] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", + ["@id"] = "tbd", + ["id"] = "tbd", + ["@context"] = "https://www.w3.org/2019/wot/td/v1", + ["title"] = "https://dublincore.org/specifications/dublin-core/dcmi-terms/#title", + ["titles"] = "https://dublincore.org/specifications/dublin-core/dcmi-terms/#title", + ["description"] = "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description", + ["descriptions"] = "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description", + + ["created"] = "https://dublincore.org/specifications/dublin-core/dcmi-terms/#created", + ["modified"] = "https://dublincore.org/specifications/dublin-core/dcmi-terms/#modified", + ["support"] = "https://www.w3.org/2019/wot/td#supportContact", + ["base"] = "https://www.w3.org/2019/wot/td#baseURI", + + //Property + ["properties"] = "https://www.w3.org/2019/wot/json-schema#properties", + ["property"] = "https://www.w3.org/2019/wot/td#PropertyAffordance",// Property Affordance + ["observable"] = "https://www.w3.org/2019/wot/td#isObservable", + + //action + ["actions"] = "https://www.w3.org/2019/wot/td#hasActionAffordance", + ["action"] = "https://www.w3.org/2019/wot/td#ActionAffordance", + ["input"] = "https://www.w3.org/2019/wot/td#hasInputSchema", + ["output"] = "https://www.w3.org/2019/wot/td#hasOutputSchema", + ["safe"] = "https://www.w3.org/2019/wot/td#isSafe", + ["idempotent"] = "https://www.w3.org/2019/wot/td#isIdempotent", + + //event + ["events"] = "https://www.w3.org/2019/wot/td#hasEventAffordance", + ["event"] = "https://www.w3.org/2019/wot/td#EventAffordance", + ["subscription"] = "https://www.w3.org/2019/wot/td#hasSubscriptionSchema", + ["data"] = "https://www.w3.org/2019/wot/td#hasNotificationSchema", + ["cancellation"] = "https://www.w3.org/2019/wot/td#hasCancellationSchema", + + //links + ["links"] = "https://www.w3.org/2019/wot/td#hasLink", + ["link"] = "https://www.w3.org/2019/wot/hypermedia#Link", + + //forms + ["forms"] = "https://www.w3.org/2019/wot/td#hasForm", + ["form"] = "https://www.w3.org/2019/wot/hypermedia#Form", + + ["security"] = "https://www.w3.org/2019/wot/td#hasSecurityConfiguration", + + //securityDefinitions + + + ["allOf"] = "https://www.w3.org/2019/wot/security#allOf", + ["authorization"] = "https://www.w3.org/2019/wot/security#authorization", + ["oneOf"] = "https://www.w3.org/2019/wot/security#oneOf", + ["proxy"] = "https://www.w3.org/2019/wot/security#proxy", + ["refresh"] = "https://www.w3.org/2019/wot/security#refresh", + ["token"] = "https://www.w3.org/2019/wot/security#token", + ["alg"] = "https://www.w3.org/2019/wot/security#alg", + ["flow"] = "https://www.w3.org/2019/wot/security#flow", + ["format"] = "https://www.w3.org/2019/wot/security#format", + ["identity"] = "https://www.w3.org/2019/wot/security#identity", + ["in"] = "https://www.w3.org/2019/wot/security#in", + ["name"] = "https://www.w3.org/2019/wot/security#name", + ["qop"] = "https://www.w3.org/2019/wot/security#qop", + ["scopes"] = "https://www.w3.org/2019/wot/security#scopes", + + //DataSchema + ["const"] = "https://www.w3.org/2019/wot/json-schema#const", + ["default"] = "https://www.w3.org/2019/wot/json-schema#default", + ["oneOf"] = "https://www.w3.org/2019/wot/json-schema#oneOf", + ["enum"] = "https://www.w3.org/2019/wot/json-schema#enum", + ["readOnly"] = "https://www.w3.org/2019/wot/json-schema#readOnly", + ["writeOnly"] = "https://www.w3.org/2019/wot/json-schema#writeOnly", + ["format"] = "https://www.w3.org/2019/wot/json-schema#format", + ["type"] = "tbd", + + //ArraySchema + ["items"] = "https://www.w3.org/2019/wot/json-schema#items", + ["item"] = "https://www.w3.org/2019/wot/json-schema#items", + ["minItems"] = "https://www.w3.org/2019/wot/json-schema#minItems", + ["maxItems"] = "https://www.w3.org/2019/wot/json-schema#maxItems", + + //NumberSchema and Integer + ["minimum"] = "https://www.w3.org/2019/wot/json-schema#minimum", + ["exclusiveMinimum"] = "https://www.w3.org/2019/wot/json-schema#exclusiveMinimum", + ["maximum"] = "https://www.w3.org/2019/wot/json-schema#maximum", + ["exclusiveMaximum"] = "https://www.w3.org/2019/wot/json-schema#exclusiveMaximum", + ["multipleOf"] = "https://www.w3.org/2019/wot/json-schema#multipleOf", + + //ObjectSchema + ["required"] = "https://www.w3.org/2019/wot/json-schema#required", + + //StringSchema + ["minLength"] = "https://www.w3.org/2019/wot/json-schema#minLength", + ["maxLength"] = "https://www.w3.org/2019/wot/json-schema#maxLength", + ["pattern"] = "https://www.w3.org/2019/wot/json-schema#pattern", + ["contentEncoding"] = "https://www.w3.org/2019/wot/json-schema#contentEncoding", + ["contentMediaType"] = "https://www.w3.org/2019/wot/json-schema#contentMediaType", + + ["profile"] = "https://www.w3.org/2019/wot/td#hasProfile", + + + ["op"] = "https://www.w3.org/2019/wot/td#OperationType", + + ["success"] = "https://www.w3.org/2019/wot/hypermedia#isSuccess", + ["ContentType"] = "https://www.w3.org/2019/wot/hypermedia#forContentType", + + ["version"] = "https://www.w3.org/2019/wot/td#versionInfo", + ["VersionInfo"] = "https://www.w3.org/2019/wot/td#versionInfo", + + ["invokeAction"] = "https://www.w3.org/2019/wot/td#invokeAction", + ["observeAllProperties"] = "https://www.w3.org/2019/wot/td#observeAllProperties", + ["observeProperty"] = "https://www.w3.org/2019/wot/td#observeProperty", + ["readAllProperties"] = "https://www.w3.org/2019/wot/td#readAllProperties", + ["readMultipleProperties"] = "https://www.w3.org/2019/wot/td#readMultipleProperties", + ["readProperty"] = "https://www.w3.org/2019/wot/td#readProperty", + ["subscribeAllEvents"] = "https://www.w3.org/2019/wot/td#subscribeAllEvents", + ["subscribeEvent"] = "https://www.w3.org/2019/wot/td#subscribeEvent", + ["unobserveAllProperties"] = "https://www.w3.org/2019/wot/td#unobserveAllProperties", + ["unobserveProperty"] = "https://www.w3.org/2019/wot/td#unobserveProperty", + ["unsubscribeAllEvents"] = "https://www.w3.org/2019/wot/td#unsubscribeAllEvents", + ["unsubscribeEvent"] = "https://www.w3.org/2019/wot/td#unsubscribeEvent", + ["writeAllProperties"] = "https://www.w3.org/2019/wot/td#writeAllProperties", + ["writeMultipleProperties"] = "https://www.w3.org/2019/wot/td#writeMultipleProperties", + ["writeProperty"] = "https://www.w3.org/2019/wot/td#writeProperty", + + // json-schema + ["allOf"] = "https://www.w3.org/2019/wot/json-schema#allOf", + ["anyOf"] = "https://www.w3.org/2019/wot/json-schema#anyOf", + ["contentType"] = "https://www.w3.org/2019/wot/hypermedia#forContentType", + + ["href"] = "https://www.w3.org/2019/wot/hypermedia#hasTarget", + + ["scope"] = "https://www.w3.org/2019/wot/td#scope", + + ["uriVariables"] = "", + + + + ["propertyName"] = "https://www.w3.org/2019/wot/json-schema#propertyName", + + //hypermedia + + ["AdditionalExpectedResponse"] = "https://www.w3.org/2019/wot/hypermedia#AdditionalExpectedResponse", + ["ExpectedResponse"] = "https://www.w3.org/2019/wot/hypermedia#ExpectedResponse", + + ["InterfaceDescription"] = "https://admin-shell.io/1/0/InterfaceDescription", + ["EndpointMetadata"] = "https://admin-shell.io/1/0/EndpointMetadata", + ["InterfaceMetaData"] = "https://admin-shell.io/1/0/InterfaceMetaData", + + ["securityDefinitions"] = "https://www.w3.org/2019/wot/td#definesSecurityScheme", + ["apikey"] = "https://www.w3.org/2019/wot/security#APIKeySecurityScheme", + ["basic"] = "https://www.w3.org/2019/wot/security#BasicSecurityScheme", + ["bearer"] = "https://www.w3.org/2019/wot/security#BearerSecurityScheme", + ["combo"] = "https://www.w3.org/2019/wot/security#ComboSecurityScheme", + ["digest"] = "https://www.w3.org/2019/wot/security#DigestSecurityScheme", + ["nosec"] = "https://www.w3.org/2019/wot/security#NoSecurityScheme", + ["oauth2"] = "https://www.w3.org/2019/wot/security#OAuth2SecurityScheme", + ["psk"] = "https://www.w3.org/2019/wot/security#PSKSecurityScheme", + ["scheme"] = "https://www.w3.org/2019/wot/td#scheme", + + }; + + public static JObject arrayListDescription = new JObject + { + ["security"] = "Set of security definition names, chosen from those defined in securityDefinitions." + + "These must all be satisfied for access to resources.", + ["scopes"] = " 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. The values associated with a" + + "form should be chosen from those defined in an OAuth2SecurityScheme active on that form.", + ["op"] = "Indicates the semantic intention of performing the operation(s) described by" + + "the form. For example, the Property interaction allows get and set operations." + + "The protocol binding may contain a form for the get operation and a different form for the" + + "set operation. The op attribute indicates which form is for which and allows the client to select" + + "the correct form for the operation required. op can be assigned one or more interaction verb(s) " + + "representing a semantic intention of an operation." + }; + public static JObject arrayListDesc = new JObject + { + ["enum"] = "Restricted set of values provided as an array.", + ["@type"] = "JSON-LD keyword to label the object with semantic tags (or types)." + }; + public static string getarrayListDescription(string tdType) + { + try + { + foreach (var temp in (JToken)arrayListDescription) + { + JProperty x = (JProperty)temp; + if (x.Name.ToString() == tdType) + { + return x.Value.ToString(); + } + } + return ""; + } + catch + { + return ""; + } + + } + public static string getarrayListDesc(string tdType) + { + try + { + foreach (var temp in (JToken)arrayListDesc) + { + JProperty x = (JProperty)temp; + if (x.Name.ToString() == tdType) + { + return x.Value.ToString(); + } + } + return ""; + } + catch + { + return ""; + } + + } + public static string getSemanticID(string tdType) + { + try + { + foreach (var temp in (JToken)semanticIDJObject) + { + JProperty x = (JProperty)temp; + if (x.Name.ToString() == tdType) + { + return x.Value.ToString(); + } + } + return ""; + } + catch + { + return ""; + } + + } + } +} \ No newline at end of file diff --git a/src/AasxPluginAID/ThingDescDef.cs b/src/AasxPluginAID/ThingDescDef.cs new file mode 100644 index 00000000..851cdc7a --- /dev/null +++ b/src/AasxPluginAID/ThingDescDef.cs @@ -0,0 +1,256 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AasxPluginAID +{ + class ThingDescDef + { + public static JObject semanticIDJObject = new JObject + { + // td Schema + ["Thing"] = "https://www.w3.org/2019/wot/td#Thing", + ["@type"] = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", + ["@id"] = "tbd", + ["id"] = "tbd", + ["@context"] = "https://www.w3.org/2019/wot/td/v1", + ["title"] = "https://dublincore.org/specifications/dublin-core/dcmi-terms/#title", + ["titles"] = "https://dublincore.org/specifications/dublin-core/dcmi-terms/#title", + ["description"] = "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description", + ["descriptions"] = "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description", + + ["created"] = "https://dublincore.org/specifications/dublin-core/dcmi-terms/#created", + ["modified"] = "https://dublincore.org/specifications/dublin-core/dcmi-terms/#modified", + ["support"] = "https://www.w3.org/2019/wot/td#supportContact", + ["base"] = "https://www.w3.org/2019/wot/td#baseURI", + + //Property + ["properties"] = "https://www.w3.org/2019/wot/json-schema#properties", + ["property"] = "https://www.w3.org/2019/wot/td#PropertyAffordance",// Property Affordance + ["observable"] = "https://www.w3.org/2019/wot/td#isObservable", + + //action + ["actions"] = "https://www.w3.org/2019/wot/td#hasActionAffordance", + ["action"] = "https://www.w3.org/2019/wot/td#ActionAffordance", + ["input"] = "https://www.w3.org/2019/wot/td#hasInputSchema", + ["output"] = "https://www.w3.org/2019/wot/td#hasOutputSchema", + ["safe"] = "https://www.w3.org/2019/wot/td#isSafe", + ["idempotent"] = "https://www.w3.org/2019/wot/td#isIdempotent", + + //event + ["events"] = "https://www.w3.org/2019/wot/td#hasEventAffordance", + ["event"] = "https://www.w3.org/2019/wot/td#EventAffordance", + ["subscription"] = "https://www.w3.org/2019/wot/td#hasSubscriptionSchema", + ["data"] = "https://www.w3.org/2019/wot/td#hasNotificationSchema", + ["cancellation"] = "https://www.w3.org/2019/wot/td#hasCancellationSchema", + + //links + ["links"] = "https://www.w3.org/2019/wot/td#hasLink", + ["link"] = "https://www.w3.org/2019/wot/hypermedia#Link", + + //forms + ["forms"] = "https://www.w3.org/2019/wot/td#hasForm", + ["form"] = "https://www.w3.org/2019/wot/hypermedia#Form", + + ["security"] = "https://www.w3.org/2019/wot/td#hasSecurityConfiguration", + + //securityDefinitions + + + ["allOf"] = "https://www.w3.org/2019/wot/security#allOf", + ["authorization"] = "https://www.w3.org/2019/wot/security#authorization", + ["oneOf"] = "https://www.w3.org/2019/wot/security#oneOf", + ["proxy"] = "https://www.w3.org/2019/wot/security#proxy", + ["refresh"] = "https://www.w3.org/2019/wot/security#refresh", + ["token"] = "https://www.w3.org/2019/wot/security#token", + ["alg"] = "https://www.w3.org/2019/wot/security#alg", + ["flow"] = "https://www.w3.org/2019/wot/security#flow", + ["format"] = "https://www.w3.org/2019/wot/security#format", + ["identity"] = "https://www.w3.org/2019/wot/security#identity", + ["in"] = "https://www.w3.org/2019/wot/security#in", + ["name"] = "https://www.w3.org/2019/wot/security#name", + ["qop"] = "https://www.w3.org/2019/wot/security#qop", + ["scopes"] = "https://www.w3.org/2019/wot/security#scopes", + + //DataSchema + ["const"] = "https://www.w3.org/2019/wot/json-schema#const", + ["default"] = "https://www.w3.org/2019/wot/json-schema#default", + ["oneOf"] = "https://www.w3.org/2019/wot/json-schema#oneOf", + ["enum"] = "https://www.w3.org/2019/wot/json-schema#enum", + ["readOnly"] = "https://www.w3.org/2019/wot/json-schema#readOnly", + ["writeOnly"] = "https://www.w3.org/2019/wot/json-schema#writeOnly", + ["format"] = "https://www.w3.org/2019/wot/json-schema#format", + ["type"] = "tbd", + + //ArraySchema + ["items"] = "https://www.w3.org/2019/wot/json-schema#items", + ["item"] = "https://www.w3.org/2019/wot/json-schema#items", + ["minItems"] = "https://www.w3.org/2019/wot/json-schema#minItems", + ["maxItems"] = "https://www.w3.org/2019/wot/json-schema#maxItems", + + //NumberSchema and Integer + ["minimum"] = "https://www.w3.org/2019/wot/json-schema#minimum", + ["exclusiveMinimum"] = "https://www.w3.org/2019/wot/json-schema#exclusiveMinimum", + ["maximum"] = "https://www.w3.org/2019/wot/json-schema#maximum", + ["exclusiveMaximum"] = "https://www.w3.org/2019/wot/json-schema#exclusiveMaximum", + ["multipleOf"] = "https://www.w3.org/2019/wot/json-schema#multipleOf", + + //ObjectSchema + ["required"] = "https://www.w3.org/2019/wot/json-schema#required", + + //StringSchema + ["minLength"] = "https://www.w3.org/2019/wot/json-schema#minLength", + ["maxLength"] = "https://www.w3.org/2019/wot/json-schema#maxLength", + ["pattern"] = "https://www.w3.org/2019/wot/json-schema#pattern", + ["contentEncoding"] = "https://www.w3.org/2019/wot/json-schema#contentEncoding", + ["contentMediaType"] = "https://www.w3.org/2019/wot/json-schema#contentMediaType", + + ["profile"] = "https://www.w3.org/2019/wot/td#hasProfile", + + + ["op"] = "https://www.w3.org/2019/wot/td#OperationType", + + ["success"] = "https://www.w3.org/2019/wot/hypermedia#isSuccess", + ["ContentType"] = "https://www.w3.org/2019/wot/hypermedia#forContentType", + + ["version"] = "https://www.w3.org/2019/wot/td#versionInfo", + ["VersionInfo"] = "https://www.w3.org/2019/wot/td#versionInfo", + + ["invokeAction"] = "https://www.w3.org/2019/wot/td#invokeAction", + ["observeAllProperties"] = "https://www.w3.org/2019/wot/td#observeAllProperties", + ["observeProperty"] = "https://www.w3.org/2019/wot/td#observeProperty", + ["readAllProperties"] = "https://www.w3.org/2019/wot/td#readAllProperties", + ["readMultipleProperties"] = "https://www.w3.org/2019/wot/td#readMultipleProperties", + ["readProperty"] = "https://www.w3.org/2019/wot/td#readProperty", + ["subscribeAllEvents"] = "https://www.w3.org/2019/wot/td#subscribeAllEvents", + ["subscribeEvent"] = "https://www.w3.org/2019/wot/td#subscribeEvent", + ["unobserveAllProperties"] = "https://www.w3.org/2019/wot/td#unobserveAllProperties", + ["unobserveProperty"] = "https://www.w3.org/2019/wot/td#unobserveProperty", + ["unsubscribeAllEvents"] = "https://www.w3.org/2019/wot/td#unsubscribeAllEvents", + ["unsubscribeEvent"] = "https://www.w3.org/2019/wot/td#unsubscribeEvent", + ["writeAllProperties"] = "https://www.w3.org/2019/wot/td#writeAllProperties", + ["writeMultipleProperties"] = "https://www.w3.org/2019/wot/td#writeMultipleProperties", + ["writeProperty"] = "https://www.w3.org/2019/wot/td#writeProperty", + + // json-schema + ["allOf"] = "https://www.w3.org/2019/wot/json-schema#allOf", + ["anyOf"] = "https://www.w3.org/2019/wot/json-schema#anyOf", + ["contentType"] = "https://www.w3.org/2019/wot/hypermedia#forContentType", + + ["href"] = "https://www.w3.org/2019/wot/hypermedia#hasTarget", + + ["scope"] = "https://www.w3.org/2019/wot/td#scope", + + ["uriVariables"] = "", + + + + ["propertyName"] = "https://www.w3.org/2019/wot/json-schema#propertyName", + + //hypermedia + + ["AdditionalExpectedResponse"] = "https://www.w3.org/2019/wot/hypermedia#AdditionalExpectedResponse", + ["ExpectedResponse"] = "https://www.w3.org/2019/wot/hypermedia#ExpectedResponse", + + ["InterfaceDescription"] = "https://admin-shell.io/1/0/InterfaceDescription", + ["EndpointMetadata"] = "https://admin-shell.io/1/0/EndpointMetadata", + ["InterfaceMetaData"] = "https://admin-shell.io/1/0/InterfaceMetaData", + + ["securityDefinitions"] = "https://www.w3.org/2019/wot/td#definesSecurityScheme", + ["apikey"] = "https://www.w3.org/2019/wot/security#APIKeySecurityScheme", + ["basic"] = "https://www.w3.org/2019/wot/security#BasicSecurityScheme", + ["bearer"] = "https://www.w3.org/2019/wot/security#BearerSecurityScheme", + ["combo"] = "https://www.w3.org/2019/wot/security#ComboSecurityScheme", + ["digest"] = "https://www.w3.org/2019/wot/security#DigestSecurityScheme", + ["nosec"] = "https://www.w3.org/2019/wot/security#NoSecurityScheme", + ["oauth2"] = "https://www.w3.org/2019/wot/security#OAuth2SecurityScheme", + ["psk"] = "https://www.w3.org/2019/wot/security#PSKSecurityScheme", + ["scheme"] = "https://www.w3.org/2019/wot/td#scheme", + + }; + + public static JObject arrayListDescription = new JObject + { + ["security"] = "Set of security definition names, chosen from those defined in securityDefinitions." + + "These must all be satisfied for access to resources.", + ["scopes"] = " 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. The values associated with a" + + "form should be chosen from those defined in an OAuth2SecurityScheme active on that form.", + ["op"] = "Indicates the semantic intention of performing the operation(s) described by" + + "the form. For example, the Property interaction allows get and set operations." + + "The protocol binding may contain a form for the get operation and a different form for the" + + "set operation. The op attribute indicates which form is for which and allows the client to select" + + "the correct form for the operation required. op can be assigned one or more interaction verb(s) " + + "representing a semantic intention of an operation." + }; + public static JObject arrayListDesc = new JObject + { + ["enum"] = "Restricted set of values provided as an array.", + ["@type"] = "JSON-LD keyword to label the object with semantic tags (or types)." + }; + public static string getarrayListDescription(string tdType) + { + try + { + foreach (var temp in (JToken)arrayListDescription) + { + JProperty x = (JProperty)temp; + if (x.Name.ToString() == tdType) + { + return x.Value.ToString(); + } + } + return ""; + } + catch + { + return ""; + } + + } + public static string getarrayListDesc(string tdType) + { + try + { + foreach (var temp in (JToken)arrayListDesc) + { + JProperty x = (JProperty)temp; + if (x.Name.ToString() == tdType) + { + return x.Value.ToString(); + } + } + return ""; + } + catch + { + return ""; + } + + } + public static string getSemanticID(string tdType) + { + try + { + foreach (var temp in (JToken)semanticIDJObject) + { + JProperty x = (JProperty)temp; + if (x.Name.ToString() == tdType) + { + return x.Value.ToString(); + } + } + return ""; + } + catch + { + return ""; + } + + } + } +} diff --git a/src/AasxPluginAID/app.config b/src/AasxPluginAID/app.config new file mode 100644 index 00000000..e936cc13 --- /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 00000000..635271e7 --- /dev/null +++ b/src/AasxPluginAID/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/AasxPredefinedConcepts/DefinitionsAID.cs b/src/AasxPredefinedConcepts/DefinitionsAID.cs new file mode 100644 index 00000000..27040f19 --- /dev/null +++ b/src/AasxPredefinedConcepts/DefinitionsAID.cs @@ -0,0 +1,124 @@ +/* +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; +// 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 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 AID_title = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#title") }); + public Reference AID_description = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/#description") }); + public Reference AID_created = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#created") }); + public Reference AID_modified = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#modified") }); + public Reference AID_support = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#support") }); + public Reference AID_EndpointMetadata = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/EndpointMetadata") }); + public Reference AID_base = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#base") }); + public Reference AID_contentType = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/hypermedia#forContentType") }); + public Reference AID_security = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#hasSecurityConfiguration") }); + public Reference AID_securityDefinitions = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#definesSecurityScheme") }); + public Reference AID_nosec_sc = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#NoSecurityScheme") }); + public Reference AID_scheme = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#definesSecurityScheme") }); + public Reference AID_auto_sc = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#AutoSecurityScheme") }); + public Reference AID_proxy = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#proxy") }); + public Reference AID_basic_sc = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#BasicSecurityScheme") }); + public Reference AID_name = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#name") }); + public Reference AID_in = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#in") }); + public Reference AID_combo_sc = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#ComboSecurityScheme") }); + public Reference AID_oneOf = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/json-schema#oneOf") }); + public Reference AID_allOf = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/json-schema#allOf") }); + public Reference AID_apikey_sc = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#APIKeySecurityScheme") }); + public Reference AID_psk_sc = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#PSKSecurityScheme") }); + public Reference AID_identity = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#identity") }); + public Reference AID_digest_sc = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#DigestSecurityScheme") }); + public Reference AID_qop = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#qop") }); + public Reference AID_bearer_sc = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#BearerSecurityScheme") }); + public Reference AID_authorization = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#authorization") }); + public Reference AID_alg = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#alg") }); + public Reference AID_format = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#format") }); + public Reference AID_oauth2_sc = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#OAuth2SecurityScheme") }); + public Reference AID_token = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#token") }); + public Reference AID_refresh = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#refresh") }); + public Reference AID_scopes = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#scopes") }); + public Reference AID_flow = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/security#flow") }); + public Reference AID_InterfaceMetadata = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/InterfaceMetadata") }); + public Reference AID_properties = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#PropertyAffordance") }); + public Reference AID_propertyName = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfaceDescription/1/0/PropertyDefinition") }); + public Reference AID_key = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/key") }); + public Reference AID_type = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/1999/02/22-rdf-syntax-ns#type") }); + public Reference AID_observable = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#isObservable") }); + public Reference AID_const = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/json-schema#const") }); + public Reference AID_default = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/json-schema#default") }); + public Reference AID_unit = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://schema.org/unitCode") }); + public Reference AID_min_max = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/minMaxRange") }); + public Reference AID_lengthRange = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/lengthRange") }); + public Reference AID_items = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/json-schema#items") }); + public Reference AID_valueSemantics = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/valueSemantics") }); + public Reference AID_itemsRange = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/itemsRange") }); + + public Reference AID_forms = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#hasForm") }); + public Reference AID_httpforms = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#hasHTTPForm") }); + public Reference AID_mqttforms = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#hasMQTTForm") }); + public Reference AID_modbusforms = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#hasMODBUSForm") }); + + public Reference AID_href = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/hypermedia#hasTarget") }); + public Reference AID_htv_methodName = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2011/http#methodName") }); + public Reference AID_htv_headers = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2011/http#headers") }); + public Reference AID_htv_fieldName = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2011/http#fieldName") }); + public Reference AID_htv_fieldValue = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2011/http#fieldValue") }); + + public Reference AID_actions = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#ActionAffordance") }); + public Reference AID_events = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/td#EventAffordance") }); + public Reference AID_ExternalDescriptor = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/ExternalDescriptor") }); + public Reference AID_fileName = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/externalDescriptorName") }); + public Reference AID_InterfaceMODBUS = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface") }); + public Reference AID_modbus_function = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/modbus#Function") }); + public Reference AID_modbus_entity = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/modbus#Entity") }); + public Reference AID_modbus_zeroBasedAddressing = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/modbus#hasZeroBasedAddressingFlag") }); + public Reference AID_modbus_pollingTime = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/modbus#pollingTime") }); + public Reference AID_modbus_timeout = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/mqtt#hasQoSFlag") }); + public Reference AID_modbus_type = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/modbus#type") }); + public Reference AID_InterfaceMQTT = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://admin-shell.io/idta/AssetInterfacesDescription/1/0/Interface") }); + public Reference AID_mqv_retain = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/mqtt#hasRetainFlag") }); + public Reference AID_mqv_controlPacket = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/mqtt#ControlPacket") }); + public Reference AID_mqv_qos = new Reference(ReferenceTypes.ExternalReference, new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/mqtt#hasQoSFlag") }); + public Reference AID_subprotocol = new Reference(ReferenceTypes.ExternalReference,new List { new Key(KeyTypes.GlobalReference, "https://www.w3.org/2019/wot/hypermedia#forSubProtocol") }); + + + public IDTAAid() + { + // info + this.DomainInfo = "IDTA Asset Interface Description"; + + // IReferable + this.ReadLibrary( + Assembly.GetExecutingAssembly(), "AasxPredefinedConcepts.Resources." + "IdtaAssetInterfaceDescription.json"); + this.RetrieveEntriesFromLibraryByReflection(typeof(IDTAAid), useFieldNames: true); + } + } + +}