| @page |
| @model BaSyx.AAS.Server.Http.Pages.MultiIndexModel |
| @using BaSyx.API.Components; |
| @using BaSyx.Models.Core.AssetAdministrationShell.Generics; |
| @using BaSyx.Models.Core.AssetAdministrationShell.Generics.SubmodelElementTypes; |
| @using BaSyx.Models.Core.AssetAdministrationShell.Identification; |
| @using BaSyx.Models.Core.AssetAdministrationShell.References; |
| @using BaSyx.Models.Core.Common; |
| @using BaSyx.Models.Extensions; |
| @using BaSyx.Models.Core.AssetAdministrationShell.Semantics; |
| @using Microsoft.AspNetCore.Html; |
| |
| @{ |
| ViewData["Title"] = "MultiIndex"; |
| IAssetAdministrationShellAggregatorServiceProvider sp = Model.ServiceProvider; |
| |
| string eClassLink = "https://www.eclasscontent.com/index.php?action=cc2prdet&language=en&version=10.1&id=&pridatt="; |
| |
| Func<Identifier, IHtmlContent> ShowIdentification = @<text>@{ |
| var identifier = item; |
| @if (identifier != null) |
| { |
| |
| <div class="panel-body"> |
| <div class="row"> |
| <div class="col-sm-2"><b>Identifier (@identifier.IdType.ToString())</b></div> |
| <div class="col-sm-10">@identifier.Id</div> |
| </div> |
| </div> |
| } |
| }</text>; |
| |
| Func<string, IHtmlContent> ShowIdShort = @<text>@{ |
| var idShort = item; |
| @if (!string.IsNullOrEmpty(idShort)) |
| { |
| |
| <div class="panel-body"> |
| <div class="row"> |
| <div class="col-sm-2"><b>IdShort</b></div> |
| <div class="col-sm-10">@idShort</div> |
| </div> |
| </div> |
| } |
| }</text>; |
| |
| Func<IReference, IHtmlContent> ShowSemanticId = @<text>@{ |
| var reference = item; |
| @if (reference?.First?.Value != null) |
| { |
| |
| <div class="panel-body"> |
| <div class="row"> |
| <div class="col-sm-2"><b>SemanticId</b></div> |
| @if (reference.First.IdType == KeyType.IRDI) |
| { |
| { |
| string link = eClassLink + Uri.EscapeDataString(reference.First.Value); |
| <div class="col-sm-10"><a target="_blank" href="@link">@reference.First.Value (eCl@ss)</a></div> |
| } |
| } |
| else |
| { |
| <div class="col-sm-10">@reference.First.Value</div> |
| } |
| </div> |
| </div> |
| } |
| }</text>; |
| |
| |
| Func<LangStringSet, IHtmlContent> ShowDescription = @<text>@{ |
| var langStringCollection = item; |
| @if (langStringCollection?.Count > 0) |
| { |
| string description = string.Empty; |
| for (int i = 0; i < langStringCollection.Count; i++) |
| { |
| description = langStringCollection[i].Language + ":" + langStringCollection[i].Text + (i != langStringCollection.Count - 1 ? ";" : ""); |
| } |
| |
| <div class="panel-body"> |
| <div class="row"> |
| <div class="col-sm-2"><b>Description</b></div> |
| <div class="col-sm-10">@description</div> |
| </div> |
| </div> |
| } |
| }</text>; |
| |
| Func<IValue, IHtmlContent> ShowValue = @<text>@{ |
| var value = item; |
| if (value.ValueType == null) |
| { |
| var serialized = Json.Serialize(value.Value).ToString(); |
| @serialized |
| } |
| else |
| { |
| @value.Value?.ToString() |
| } |
| }</text>; |
| |
| Func<string, IHtmlContent> ShowSubmodelElementHeader = @<text>@{ |
| var idShort = item; |
| if (string.IsNullOrEmpty(idShort)) |
| { |
| return; |
| } |
| else |
| { |
| <div class="panel-heading"> |
| <h4 class="panel-title"> |
| <a data-toggle="collapse" href="#@idShort">@idShort</a> |
| </h4> |
| </div> |
| } |
| }</text>; |
| |
| Func<string, IProperty, IHtmlContent> ShowPropertyFooter = (submodelIdShort, property) => new Func<object, Microsoft.AspNetCore.Mvc.Razor.HelperResult>(@<text>@{ |
| |
| if (string.IsNullOrEmpty(submodelIdShort) || property == null) |
| { |
| return; |
| } |
| else |
| { |
| <div class="panel-footer"> |
| <div class="row"> |
| <div class="col-sm-8"> |
| |
| <div class="input-group"> |
| <span class="input-group-addon"><i class="glyphicon glyphicon-pencil"></i></span> |
| <input id="Input_@submodelIdShort@property.IdShort" type="text" class="form-control" placeholder="Value" value="@ShowValue(property)" /> |
| </div> |
| |
| </div> |
| <div class="col-sm-1"><button onclick="@("GetPropertyValue('" + submodelIdShort + "', '" + property.IdShort + "')")" id="@property.IdShort;Retrieve" type="button" class="btn btn-primary">Retrieve</button></div> |
| <div class="col-sm-1"><button onclick="@("SetPropertyValue('" + submodelIdShort + "', '" + property.IdShort + "', '" + property.ValueType?.ToString() + "', $('#Input_" + submodelIdShort + property.IdShort + "').val() )")" id="@property.IdShort;Update" type="button" class="btn btn-success">Update</button></div> |
| |
| </div> |
| </div> |
| } |
| }</text>)(null); |
| |
| Func<ISubmodelElement, IHtmlContent> ShowModelElementSpecificAttributes = @<text>@{ |
| var submodelElement = item; |
| |
| if (!Enum.TryParse<KeyElements>(submodelElement.ModelType.Name, out KeyElements keyElements)) |
| { |
| return; |
| } |
| |
| switch (keyElements) |
| { |
| case KeyElements.GlobalReference: |
| break; |
| case KeyElements.FragmentReference: |
| break; |
| case KeyElements.AccessPermissionRule: |
| break; |
| case KeyElements.AnnotatedRelationshipElement: |
| break; |
| case KeyElements.BasicEvent: |
| break; |
| case KeyElements.Blob: |
| break; |
| case KeyElements.Capability: |
| break; |
| case KeyElements.ConceptDictionary: |
| break; |
| case KeyElements.DataElement: |
| break; |
| case KeyElements.File: |
| { |
| IFile file = submodelElement?.ToModelElement<IFile>(); |
| if (file == null) |
| { |
| return; |
| } |
| |
| string path = GetPath(file); |
| |
| <div class="panel-body"> |
| <div class="row"> |
| <div class="col-sm-2"><b>MimeType</b></div> |
| <div class="col-sm-10">@file.MimeType</div> |
| </div> |
| </div> |
| <div class="panel-body"> |
| <div class="row"> |
| <div class="col-sm-2"><b>Path</b></div> |
| <div class="col-sm-10">@path</div> |
| </div> |
| </div> |
| string contentRoot = System.IO.Path.Combine(AppContext.BaseDirectory, Model.Settings.ServerConfig.Hosting.ContentPath); |
| var contentFileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(contentRoot); |
| @if (contentFileProvider.GetFileInfo(path).Exists) |
| { |
| <embed src="@path#navpanes=0&scrollbar=0" width="100%" /> |
| } |
| } |
| return; |
| case KeyElements.Entity: |
| break; |
| case KeyElements.Event: |
| { |
| IEvent eventable = submodelElement?.ToModelElement<IEvent>(); |
| if (eventable == null) |
| { |
| return; |
| } |
| |
| @foreach (var element in eventable.DataElements) |
| { |
| <div class="row"> |
| @{ string valueTypeName = element.ToModelElement<IProperty>()?.ValueType?.ToString() ?? "ANY"; } |
| <div class="col-sm-10"><b>@element.IdShort (@valueTypeName)</b></div> |
| </div> |
| } |
| } |
| return; |
| case KeyElements.MultiLanguageProperty: |
| break; |
| case KeyElements.Operation: |
| break; |
| case KeyElements.Property: |
| IProperty property = submodelElement?.ToModelElement<IProperty>(); |
| if (property == null) |
| { |
| return; |
| } |
| |
| string dataTypeName = property.ValueType?.ToString()?.ToUpper(); |
| if (string.IsNullOrEmpty(dataTypeName)) |
| { |
| dataTypeName = property?.ModelType?.Name; |
| } |
| |
| <div class="panel-body"> |
| <div class="row"> |
| <div class="col-sm-2"><b>ValueType</b></div> |
| <div class="col-sm-10">@dataTypeName</div> |
| </div> |
| </div> |
| return; |
| case KeyElements.Range: |
| break; |
| case KeyElements.ReferenceElement: |
| break; |
| case KeyElements.RelationshipElement: |
| break; |
| case KeyElements.SubmodelElement: |
| break; |
| case KeyElements.SubmodelElementCollection: |
| break; |
| case KeyElements.View: |
| break; |
| case KeyElements.AssetAdministrationShell: |
| break; |
| case KeyElements.ConceptDescription: |
| break; |
| default: |
| break; |
| } |
| |
| }</text>; |
| |
| Func<ISubmodelElement, IHtmlContent> ShowValueType = @<text>@{ |
| var submodelElement = item; |
| if (submodelElement.GetType().GetInterfaces().Where(i => i.Name == "ISubmodelElement") == null) |
| { |
| return; |
| } |
| else |
| { |
| var property = (IProperty)submodelElement; |
| var dataTypeName = property.ValueType?.DataObjectType?.Name?.ToUpper(); |
| if (string.IsNullOrEmpty(dataTypeName)) |
| { |
| dataTypeName = property.ModelType?.Name; |
| } |
| <div class="panel-body"> |
| <div class="row"> |
| <div class="col-sm-2"><b>ValueType</b></div> |
| <div class="col-sm-10">@dataTypeName</div> |
| </div> |
| </div> |
| } |
| }</text>; |
| |
| Func<IEnumerable<IEmbeddedDataSpecification>, IHtmlContent> ShowDataSpecifications = @<text>@{ |
| var embeddedDataSpecifications = item; |
| if (embeddedDataSpecifications?.Count() > 0) |
| { |
| @foreach (var dataSpecification in embeddedDataSpecifications) |
| { |
| <div class="list-group-item" style="background:#88b8d9; color:white"> |
| <div class="row"> |
| <div class="col-sm-2"><b>Data-Specification</b></div> |
| <div class="col-sm-10">@dataSpecification.HasDataSpecification.First.Value</div> |
| </div> |
| </div> |
| |
| @foreach (var property in dataSpecification.DataSpecificationContent.GetType().GetProperties()) |
| { |
| |
| @if (property.PropertyType.IsGenericType && (property.PropertyType.GetGenericTypeDefinition() == typeof(List<>))) |
| { |
| var values = property.GetValue(dataSpecification.DataSpecificationContent) as IEnumerable<object>; |
| if (values?.Count() > 0) |
| { |
| foreach (var element in values) |
| { |
| foreach (var subProperty in property.PropertyType.GenericTypeArguments[0].GetProperties()) |
| { |
| var value = subProperty.GetValue(element)?.ToString(); |
| if (value != null) |
| { |
| <div class="list-group-item" style="background:#88b8d9; color:white"> |
| <div class="row"> |
| <div class="col-sm-2"><b>@subProperty.Name</b></div> |
| <div class="col-sm-10">@value</div> |
| </div> |
| </div> |
| } |
| } |
| } |
| } |
| } |
| else |
| { |
| var value = property.GetValue(dataSpecification.DataSpecificationContent); |
| if (value != null) |
| { |
| if (value is IReference reference) |
| { |
| value = reference.First.Value; |
| } |
| else |
| { |
| value = value.ToString(); |
| } |
| |
| <div class="list-group-item" style="background:#88b8d9; color:white"> |
| <div class="row"> |
| <div class="col-sm-2"><b>@property.Name</b></div> |
| <div class="col-sm-10">@value</div> |
| </div> |
| </div> |
| } |
| } |
| |
| } |
| } |
| } |
| }</text>; |
| |
| Func<List<object>, IHtmlContent> ShowSubmodelElement = null; |
| |
| ShowSubmodelElement = @<text>@{ |
| var submodelwithElement = item; |
| if (submodelwithElement?.Count < 2) |
| { |
| return; |
| } |
| else |
| { |
| ISubmodel submodel = submodelwithElement[0] as ISubmodel; |
| ISubmodelElement submodelElement = submodelwithElement[1] as ISubmodelElement; |
| |
| <div class="panel panel-warning"> |
| <div class="panel-heading"> |
| <h4 class="panel-title"> |
| <a data-toggle="collapse" href="#@submodelElement.IdShort">@submodelElement.IdShort</a> |
| </h4> |
| </div> |
| <div id="@submodelElement.IdShort" class="panel-collapse collapse"> |
| @ShowDataSpecifications(submodelElement.EmbeddedDataSpecifications) |
| @ShowDescription(submodelElement.Description) |
| @ShowSemanticId(submodelElement.SemanticId) |
| @ShowModelElementSpecificAttributes(submodelElement) |
| |
| @if (submodelElement is IProperty property) |
| { |
| @ShowPropertyFooter(submodel.IdShort, property) |
| } |
| else if (submodelElement is IOperation operation) |
| { |
| if (operation.InputVariables?.Count > 0) |
| { |
| foreach (var argument in operation.InputVariables.ToElementContainer()) |
| { |
| <div class="panel-body" style="background:#88b8d9"> |
| <div class="row"> |
| <div class="col-sm-2 argInName @submodel.IdShort @operation.IdShort"><b>@argument.IdShort</b></div> |
| <div class="col-sm-2 argInType @submodel.IdShort @operation.IdShort">@GetValueOrModelType(argument)</div> |
| <div class="col-sm-8"> |
| <div class="input-group"> |
| <span class="input-group-addon"><i class="glyphicon glyphicon-pencil"></i></span> |
| <input id="msg" type="text" class="form-control argInValue @submodel.IdShort @operation.IdShort" name="msg" placeholder="Argument Value"> |
| </div> |
| </div> |
| </div> |
| </div> |
| } |
| } |
| if (operation.OutputVariables?.Count > 0) |
| { |
| foreach (var argument in operation.OutputVariables.ToElementContainer()) |
| { |
| <div class="panel-body" style="background:#d68dbc"> |
| <div class="row"> |
| <div class="col-sm-2 argOutName @submodel.IdShort @operation.IdShort"><b>@argument.IdShort</b></div> |
| <div class="col-sm-2 argOutType @submodel.IdShort @operation.IdShort">@GetValueOrModelType(argument)</div> |
| <div class="col-sm-8"> |
| <div class="input-group"> |
| <span class="input-group-addon"><i class="glyphicon glyphicon-pencil"></i></span> |
| <input id="argOutValue_@submodel.IdShort@operation.IdShort@argument.IdShort" type="text" class="form-control argOutValue @submodel.IdShort @operation.IdShort" name="msg" placeholder="Return Value"> |
| </div> |
| </div> |
| </div> |
| </div> |
| } |
| } |
| <div class="panel-footer"><button onclick="@("ExecuteOperation('" + submodel.IdShort + "', '" + operation.IdShort + "')")" type="button" class="btn btn-success">Execute</button></div> |
| } |
| else if (submodelElement is ISubmodelElementCollection collection) |
| { |
| if (collection.Value?.Count > 0) |
| { |
| @foreach (var value in collection.Value) |
| { |
| <div class="panel-body"> |
| @ShowSubmodelElement(new List<object>() { submodel, value }) |
| </div> |
| } |
| } |
| } |
| </div> |
| </div> |
| } |
| }</text>; |
| } |
| |
| @functions |
| { |
| public string GetPath(IFile file) |
| { |
| string content = file.Value; |
| if (string.IsNullOrEmpty(content)) |
| return string.Empty; |
| |
| content = content.Replace('\\', '/'); |
| return content; |
| } |
| |
| public string GetValueOrModelType(ISubmodelElement submodelElement) |
| { |
| if (submodelElement is IProperty property) |
| { |
| return property.ValueType?.ToString(); |
| } |
| else |
| { |
| return submodelElement.ModelType.Name; |
| } |
| } |
| } |
| |
| <!doctype html> |
| <html> |
| <head> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <link rel="stylesheet" href="~/scripts/bootstrap.min.css"> |
| <title>BaSys Multi Asset Administration Shell UI</title> |
| <script src="~/scripts/jquery-3.3.1.min.js"></script> |
| <script src="~/scripts/popper.min.js"></script> |
| <script src="~/scripts/bootstrap.min.js"></script> |
| |
| <style> |
| .bd-placeholder-img { |
| font-size: 1.125rem; |
| text-anchor: middle; |
| } |
| |
| @@media (min-width: 768px) { |
| .bd-placeholder-img-lg { |
| font-size: 3.5rem; |
| } |
| } |
| </style> |
| |
| </head> |
| <body> |
| |
| <nav class="navbar navbar-inverse"> |
| <div class="container-fluid"> |
| <div class="navbar-header"> |
| <img src="~/images/basyxlogo.png" width="160" height="64" /> |
| </div> |
| <ul class="nav navbar-nav"> |
| <li><a href="#" style="margin-top:15px">Main</a></li> |
| </ul> |
| <div class="navbar-right"><img src="~/images/Bosch.gif" width="103" height="30" style="margin-top:25px; margin-right:15px" /></div> |
| </div> |
| </nav> |
| |
| <main role="main" class="container"> |
| |
| <div class="starter-template"> |
| <h1>Multi Asset Administration Shell UI</h1> |
| <p class="lead">Generic UI to display many Asset Administration Shells</p> |
| </div> |
| </main> |
| |
| |
| @if (sp.AssetAdministrationShells?.Count() > 0) |
| { |
| foreach (var aas in sp.AssetAdministrationShells) |
| { |
| <div class="container"> |
| <div class="panel panel-default"> |
| <div class="panel-heading" style="background:#7ca1ce"> |
| <h4> |
| <a style="color:white" data-toggle="collapse" href="#@aas.IdShort">@aas.IdShort</a> |
| </h4> |
| </div> |
| <div id="@aas.IdShort" class="panel-collapse collapse"> |
| <div class="panel-body"> |
| <div class="panel panel-default"> |
| <div class="panel-heading" style="background:#7ca1ce"><h4 style="color:white">Asset Administration Shell</h4></div> |
| @ShowIdShort(aas.IdShort) |
| @ShowIdentification(aas.Identification) |
| @ShowDescription(aas.Description) |
| </div> |
| @{ |
| var asset = aas.Asset; |
| if (asset != null) |
| { |
| |
| <div class="panel panel-default"> |
| <div class="panel-heading" style="background:#b90276"><h4 style="color:white">Asset</h4></div> |
| @ShowIdShort(asset.IdShort) |
| @ShowIdentification(asset.Identification) |
| @ShowDescription(asset.Description) |
| </div> |
| |
| } |
| } |
| @if (aas.Submodels?.Count > 0) |
| { |
| foreach (var submodel in aas.Submodels) |
| { |
| <div class="panel panel-default"> |
| <div class="panel-heading" style="background:darkgreen"> |
| <h4> |
| <a style="color:white" data-toggle="collapse" href="#@submodel.IdShort">@submodel.IdShort</a> |
| </h4> |
| </div> |
| <div id="@submodel.IdShort" class="panel-collapse collapse"> |
| @ShowIdShort(submodel.IdShort) |
| @ShowIdentification(submodel.Identification) |
| @ShowDescription(submodel.Description) |
| @ShowSemanticId(submodel.SemanticId) |
| <div class="panel-body"> |
| <div class="panel-group"> |
| @if (submodel.SubmodelElements?.Count > 0) |
| { |
| <div class="panel panel-default"> |
| <div class="panel-heading" style="background:#005691"><h4 style="color:white">Submodel-Elements</h4></div> |
| <div class="panel-body"> |
| <div class="panel-group"> |
| @for (int i = 0; i < submodel.SubmodelElements.Count; i++) |
| { |
| var submodelElement = submodel.SubmodelElements[i]; |
| if (submodelElement == null) |
| { continue; } |
| |
| @ShowSubmodelElement(new List<object>() { submodel, submodelElement }); |
| |
| } |
| </div> |
| </div> |
| </div> |
| } |
| </div> |
| </div> |
| </div> |
| </div> |
| } |
| } |
| </div> |
| </div> |
| </div> |
| </div> |
| } |
| } |
| |
| |
| </body> |
| </html> |