Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update to API specification v3.0 #105

Merged
merged 86 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
201fa26
Memory: separate AAS und Submodel Registry
tbischoff2 Oct 25, 2023
ce5c4be
first version: separate storage for standalone submodels
tbischoff2 Oct 26, 2023
3a4a486
second version: separate storage for standalone submodels
tbischoff2 Oct 27, 2023
3234eec
Merge remote-tracking branch 'remotes/origin/main' into feature/separ…
tbischoff2 Oct 27, 2023
ddf7a7b
Merge remote-tracking branch 'remotes/origin/main' into feature/separ…
tbischoff2 Oct 27, 2023
9e77c3f
cleanup
tbischoff2 Oct 27, 2023
3ce80d8
fix error in addSubmodel
tbischoff2 Oct 27, 2023
25d35b5
remove comments
tbischoff2 Oct 30, 2023
3534364
refactor JPA submodels
tbischoff2 Oct 30, 2023
bc48161
remove sonar warning
tbischoff2 Oct 30, 2023
c027b9d
Merge remote-tracking branch 'remotes/origin/main' into feature/separ…
tbischoff2 Dec 11, 2023
c68a95c
Merge remote-tracking branch 'remotes/origin/main' into feature/separ…
tbischoff2 Dec 11, 2023
8894a4d
Merge remote-tracking branch 'remotes/origin/main' into feature/separ…
tbischoff2 Dec 20, 2023
11954d3
Merge remote-tracking branch 'remotes/origin/main' into feature/separ…
tbischoff2 Jan 24, 2024
74cc27e
Merge branch 'main' into feature/separate_storage
tbischoff2 Feb 20, 2024
4deeab2
Merge remote-tracking branch 'remotes/origin/main' into feature/separ…
tbischoff2 Feb 20, 2024
3016dcc
adapt to v3.0 model
tbischoff2 Feb 21, 2024
126fc2b
update libs
tbischoff2 Feb 26, 2024
49c2513
adapt ORM to changed model
tbischoff2 Feb 26, 2024
f1535ca
fix version incompatibilities
tbischoff2 Feb 26, 2024
3be9a8f
add more properties
tbischoff2 Feb 26, 2024
ab79fe0
add extensions
tbischoff2 Feb 27, 2024
8746e77
Add SupplementalSemanticId to SubmodelDescriptor
tbischoff2 Feb 27, 2024
65c661d
Extension: avoid reserved names
tbischoff2 Feb 27, 2024
69ee860
change API URL
tbischoff2 Feb 27, 2024
6211144
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Feb 27, 2024
f82233a
Merge remote-tracking branch 'remotes/origin/main' into feature/separ…
tbischoff2 Feb 27, 2024
6fa9410
add Location Header
tbischoff2 Feb 27, 2024
3160388
change Enum handling
tbischoff2 Feb 28, 2024
ac09dc6
start adding request parameter
tbischoff2 Feb 28, 2024
7d56d44
code analysis
tbischoff2 Feb 29, 2024
4479786
Merge remote-tracking branch 'remotes/origin/main' into feature/separ…
tbischoff2 Feb 29, 2024
1bcc915
Merge remote-tracking branch 'remotes/origin/feature/separate_storage…
tbischoff2 Feb 29, 2024
8f6e04f
start integrating constraints
tbischoff2 Mar 1, 2024
9b94b54
implement endpoint constraints
tbischoff2 Mar 5, 2024
4c7e45e
add SpecificAssetId constraint
tbischoff2 Mar 6, 2024
5f4fc13
check submodel constraints
tbischoff2 Mar 6, 2024
f0f1515
refactoring
tbischoff2 Mar 6, 2024
de33a0c
Merge branch 'main' into feature/v3.0
tbischoff2 Mar 20, 2024
ffda6d7
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Mar 21, 2024
40e3ca6
add paging support
tbischoff2 Mar 21, 2024
c0fe156
cleanup pom.xml
tbischoff2 Mar 21, 2024
ef9c424
check constraints
tbischoff2 Mar 22, 2024
d44c1f5
update libs
tbischoff2 Mar 25, 2024
510ec15
use HTTPS
tbischoff2 Mar 26, 2024
5dfa6a9
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Mar 27, 2024
900fe47
change date format
tbischoff2 Apr 2, 2024
28e2f2d
generate correct exception message
tbischoff2 Apr 2, 2024
59a98fd
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Apr 3, 2024
a77e56b
use Fa3st Service Release 1.0.1
tbischoff2 Apr 4, 2024
497ce2e
add data specification
tbischoff2 Apr 5, 2024
9e9e8f2
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Apr 10, 2024
2000292
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Apr 12, 2024
9f28563
fix errors in JPA transformation
tbischoff2 Apr 12, 2024
b08b52b
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Apr 15, 2024
8a46780
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Apr 18, 2024
9fc218c
add missing members
tbischoff2 Apr 19, 2024
0f1d7f8
rename columns (prevent reserved keywords)
tbischoff2 Apr 19, 2024
896e2df
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Apr 23, 2024
3576b0c
JPA: filter getAllAas
tbischoff2 Apr 23, 2024
c7d011a
JPA fixes; cleanup
tbischoff2 Apr 24, 2024
5b01e4c
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Apr 24, 2024
5e3353c
Submodel must have at least one endpoint
tbischoff2 Apr 24, 2024
ceccf32
switch to in-memory
tbischoff2 Apr 25, 2024
af4a78c
update documentation
tbischoff2 Apr 26, 2024
8c65c84
remove unnecessary constructor
tbischoff2 Apr 29, 2024
fcfd66b
fix package name
tbischoff2 Apr 29, 2024
ad99bd3
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Apr 29, 2024
4560177
pom.xml: add sonar properties
tbischoff2 Apr 29, 2024
c6462d9
use Fa3st 1.1.0-SNAPSHOT;
tbischoff2 Apr 29, 2024
525b120
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 Apr 29, 2024
ce27209
remove sonar warnings
tbischoff2 Apr 29, 2024
196220a
add owaspSuppressions
tbischoff2 Apr 29, 2024
7df02d8
remove sonar warning
tbischoff2 Apr 29, 2024
f99ee1f
update documentation
tbischoff2 Apr 29, 2024
3fee362
remove sonar warning
tbischoff2 May 6, 2024
f61c870
remove sonar warning
tbischoff2 May 6, 2024
daa7a54
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 May 6, 2024
a789a90
update documentation
tbischoff2 May 7, 2024
ae71f07
Docker configuration
tbischoff2 May 8, 2024
af0ca07
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 May 8, 2024
001f1c0
docker-compose: remove version (deprecated)
tbischoff2 May 8, 2024
cb40dbf
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 May 17, 2024
47532e0
change docker-compose.yml
tbischoff2 May 24, 2024
79b1f82
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 May 24, 2024
70489df
Merge remote-tracking branch 'remotes/origin/main' into feature/v3.0
tbischoff2 May 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM eclipse-temurin:17-jdk-alpine
COPY service/target/service-0.1.0-SNAPSHOT.jar service-0.1.0-SNAPSHOT.jar
ENTRYPOINT ["java","-jar","/service-0.1.0-SNAPSHOT.jar"]
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import de.fraunhofer.iosb.ilt.faaast.service.model.descriptor.AssetAdministrationShellDescriptor;
import de.fraunhofer.iosb.ilt.faaast.service.model.descriptor.SubmodelDescriptor;
import java.util.List;
import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind;


/**
Expand All @@ -34,6 +35,16 @@ public interface AasRepository {
public List<AssetAdministrationShellDescriptor> getAASs();


/**
* Retrieves a list of all registered Asset Administration Shells which meet the given conditions.
*
* @param assetType The desired Asset Type.
* @param assetKind The desired Asset Kind.
* @return The list of all registered Asset Administration Shells.
*/
public List<AssetAdministrationShellDescriptor> getAASs(String assetType, AssetKind assetKind);


/**
* Retrieves the Asset Administration Shell with the given ID.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ public abstract class AbstractAasRepository implements AasRepository {
protected AbstractAasRepository() {}


@Override
public List<AssetAdministrationShellDescriptor> getAASs() {
return getAASs(null, null);
}


/**
* Creates a new {@link ResourceNotFoundException} for the AAS.
*
Expand Down Expand Up @@ -96,8 +102,7 @@ protected static ResourceNotFoundException buildSubmodelNotFoundInAASException(S
*/
protected static void ensureDescriptorId(AssetAdministrationShellDescriptor descriptor) {
Ensure.requireNonNull(descriptor, "descriptor must be non-null");
Ensure.requireNonNull(descriptor.getIdentification(), "descriptor.identification must be non-null");
Ensure.requireNonNull(descriptor.getIdentification().getIdentifier(), "descriptor id must be non-null");
Ensure.requireNonNull(descriptor.getId(), "descriptor id must be non-null");
}


Expand All @@ -109,8 +114,7 @@ protected static void ensureDescriptorId(AssetAdministrationShellDescriptor desc
*/
protected static void ensureDescriptorId(SubmodelDescriptor descriptor) {
Ensure.requireNonNull(descriptor, "descriptor must be non-null");
Ensure.requireNonNull(descriptor.getIdentification(), "descriptor.identification must be non-null");
Ensure.requireNonNull(descriptor.getIdentification().getIdentifier(), "descriptor id must be non-null");
Ensure.requireNonNull(descriptor.getId(), "descriptor id must be non-null");
}


Expand Down Expand Up @@ -145,11 +149,9 @@ protected static void ensureSubmodelId(String submodelId) {
*/
protected static Optional<SubmodelDescriptor> getSubmodelInternal(List<SubmodelDescriptor> submodels, String submodelId) {
return submodels.stream()
.filter(x -> Objects.nonNull(x.getIdentification())
&& Objects.nonNull(x.getIdentification().getIdentifier())
&& Objects.equals(x.getIdentification().getIdentifier(), submodelId))
.filter(x -> Objects.nonNull(x.getId())
&& Objects.equals(x.getId(), submodelId))
.findAny();

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,17 @@
import de.fraunhofer.iosb.ilt.faaast.service.model.descriptor.impl.DefaultEndpoint;
import de.fraunhofer.iosb.ilt.faaast.service.model.descriptor.impl.DefaultProtocolInformation;
import de.fraunhofer.iosb.ilt.faaast.service.model.descriptor.impl.DefaultSubmodelDescriptor;
import io.adminshell.aas.v3.model.IdentifierType;
import io.adminshell.aas.v3.model.KeyElements;
import io.adminshell.aas.v3.model.KeyType;
import io.adminshell.aas.v3.model.LangString;
import io.adminshell.aas.v3.model.impl.DefaultAdministrativeInformation;
import io.adminshell.aas.v3.model.impl.DefaultIdentifier;
import io.adminshell.aas.v3.model.impl.DefaultIdentifierKeyValuePair;
import io.adminshell.aas.v3.model.impl.DefaultKey;
import io.adminshell.aas.v3.model.impl.DefaultReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.digitaltwin.aas4j.v3.model.KeyTypes;
import org.eclipse.digitaltwin.aas4j.v3.model.ReferenceTypes;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAdministrativeInformation;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultKey;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultLangStringNameType;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultLangStringTextType;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultReference;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSpecificAssetId;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
Expand All @@ -51,18 +50,15 @@ public void clearDatastore() {}
protected DefaultSubmodelDescriptor getSubmodel() {
return DefaultSubmodelDescriptor.builder()
.idShort("Submodel2")
.identification(new DefaultIdentifier.Builder()
.idType(IdentifierType.CUSTOM)
.identifier("TestSubmodel2")
.build())
.description(new LangString("some submodel", "en-US"))
.displayName(new LangString("Submodel 2 Name", "de-DE"))
.id("TestSubmodel2")
.description(new DefaultLangStringTextType.Builder().text("some submodel").language("en-US").build())
.displayName(new DefaultLangStringNameType.Builder().text("Submodel 2 Name").language("de-DE").build())
.semanticId(new DefaultReference.Builder()
.key(new DefaultKey.Builder()
.idType(KeyType.IRI)
.type(KeyElements.SUBMODEL)
.keys(new DefaultKey.Builder()
.type(KeyTypes.SUBMODEL)
.value("http://example.org/smTest2")
.build())
.type(ReferenceTypes.EXTERNAL_REFERENCE)
.build())
.administration(new DefaultAdministrativeInformation.Builder()
.revision("1")
Expand All @@ -71,7 +67,7 @@ protected DefaultSubmodelDescriptor getSubmodel() {
.endpoint(DefaultEndpoint.builder()
.interfaceInformation("http")
.protocolInformation(DefaultProtocolInformation.builder()
.endpointAddress("localhost:8080/factory1/submodel2")
.href("localhost:8080/factory1/submodel2")
.endpointProtocol("http")
.build())
.build())
Expand All @@ -82,64 +78,52 @@ protected DefaultSubmodelDescriptor getSubmodel() {
protected AssetAdministrationShellDescriptor getAASWithSubmodel() {
AssetAdministrationShellDescriptor aas = DefaultAssetAdministrationShellDescriptor.builder()
.idShort("Test1")
.identification(new DefaultIdentifier.Builder()
.idType(IdentifierType.CUSTOM)
.identifier("TestAAS1")
.build())
.description(new LangString("some aas", "en-US"))
.displayName(new LangString("Test 1 AAS", "en-US"))
.id("TestAAS1")
.description(new DefaultLangStringTextType.Builder().text("some aas").language("en-US").build())
.displayName(new DefaultLangStringNameType.Builder().text("Test 1 AAS").language("en-US").build())
.administration(new DefaultAdministrativeInformation.Builder()
.revision("1")
.version("1.1")
.build())
.specificAssetIds(new ArrayList<>(Arrays.asList(new DefaultIdentifierKeyValuePair.Builder()
.specificAssetIds(new ArrayList<>(Arrays.asList(new DefaultSpecificAssetId.Builder()
.name("TestKey")
.value("ValueTest")
.externalSubjectId(new DefaultReference.Builder()
.key(new DefaultKey.Builder()
.idType(KeyType.IRI)
.type(KeyElements.ASSET)
.keys(new DefaultKey.Builder()
.type(KeyTypes.GLOBAL_REFERENCE)
.value("http://example.org/aasTest1")
.build())
.type(ReferenceTypes.EXTERNAL_REFERENCE)
.build())
.semanticId(new DefaultReference.Builder()
.key(new DefaultKey.Builder()
.idType(KeyType.IRI)
.type(KeyElements.ASSET)
.keys(new DefaultKey.Builder()
.type(KeyTypes.GLOBAL_REFERENCE)
.value("http://example.org/aasTest1")
.build())
.type(ReferenceTypes.EXTERNAL_REFERENCE)
.build())
.key("TestKey")
.value("ValueTest")
.build())))
.globalAssetId(new DefaultReference.Builder()
.key(new DefaultKey.Builder()
.idType(KeyType.IRI)
.type(KeyElements.ASSET)
.value("http://example.org/aasTest1")
.build())
.build())
.globalAssetId("http://example.org/aasTest1")
.endpoint(DefaultEndpoint.builder()
.interfaceInformation("http")
.protocolInformation(DefaultProtocolInformation.builder()
.endpointAddress("localhost:8080/factory1")
.href("localhost:8080/factory1")
.endpointProtocol("http")
.build())
.build())
.build();
List<SubmodelDescriptor> submodels = new ArrayList<>();
submodels.add(DefaultSubmodelDescriptor.builder()
.idShort("Submodel1")
.identification(new DefaultIdentifier.Builder()
.idType(IdentifierType.CUSTOM)
.identifier("TestSubmodel1")
.build())
.description(new LangString("some submodel", "en-US"))
.displayName(new LangString("Submodel 1 Name", "en-US"))
.id("TestSubmodel1")
.description(new DefaultLangStringTextType.Builder().text("some submodel").language("en-US").build())
.displayName(new DefaultLangStringNameType.Builder().text("Submodel 1 Name").language("en-US").build())
.semanticId(new DefaultReference.Builder()
.key(new DefaultKey.Builder()
.idType(KeyType.IRI)
.type(KeyElements.SUBMODEL)
.keys(new DefaultKey.Builder()
.type(KeyTypes.SUBMODEL)
.value("http://example.org/smTest1")
.build())
.type(ReferenceTypes.EXTERNAL_REFERENCE)
.build())
.administration(new DefaultAdministrativeInformation.Builder()
.revision("1")
Expand All @@ -148,7 +132,7 @@ protected AssetAdministrationShellDescriptor getAASWithSubmodel() {
.endpoint(DefaultEndpoint.builder()
.interfaceInformation("http")
.protocolInformation(DefaultProtocolInformation.builder()
.endpointAddress("localhost:8080/factory1/submodel")
.href("localhost:8080/factory1/submodel")
.endpointProtocol("http")
.build())
.build())
Expand Down Expand Up @@ -189,7 +173,7 @@ public void updateAAS() throws Exception {
aas.setIdShort("NewIdShort");
aas.getSubmodels().get(0).setIdShort("NewSubmodelIdShort");
repository.update(aasId, aas);
aas = repository.getAAS(aas.getIdentification().getIdentifier());
aas = repository.getAAS(aas.getId());
Assert.assertEquals("NewIdShort", aas.getIdShort());
Assert.assertEquals("NewSubmodelIdShort", aas.getSubmodels().get(0).getIdShort());
}
Expand Down Expand Up @@ -217,8 +201,8 @@ public void createSubmodelToAAS() throws Exception {
SubmodelDescriptor submodel = getSubmodel();
AssetAdministrationShellDescriptor aas = getAASWithSubmodel();
repository.create(aas);
repository.addSubmodel(aas.getIdentification().getIdentifier(), submodel);
compareSubmodel(submodel, repository.getSubmodel(aas.getIdentification().getIdentifier(), submodel.getIdentification().getIdentifier()));
repository.addSubmodel(aas.getId(), submodel);
compareSubmodel(submodel, repository.getSubmodel(aas.getId(), submodel.getId()));
}


Expand All @@ -240,8 +224,8 @@ public void findStandAloneSubmodelById() throws Exception {

SubmodelDescriptor findSubmodel;
// Ensure, submodel of the AAS is not registered
Assert.assertThrows(ResourceNotFoundException.class, () -> repository.getSubmodel(aas.getSubmodels().get(0).getIdentification().getIdentifier()));
findSubmodel = repository.getSubmodel(submodel.getIdentification().getIdentifier());
Assert.assertThrows(ResourceNotFoundException.class, () -> repository.getSubmodel(aas.getSubmodels().get(0).getId()));
findSubmodel = repository.getSubmodel(submodel.getId());
Assert.assertNotNull(findSubmodel);
}

Expand All @@ -251,9 +235,9 @@ public void findAASSubmodelById() throws Exception {
AssetAdministrationShellDescriptor aas = getAASWithSubmodel();
SubmodelDescriptor submodel = getSubmodel();
repository.create(getAASWithSubmodel());
repository.addSubmodel(aas.getIdentification().getIdentifier(), submodel);
repository.addSubmodel(aas.getId(), submodel);

SubmodelDescriptor findSubmodel = repository.getSubmodel(aas.getIdentification().getIdentifier(), submodel.getIdentification().getIdentifier());
SubmodelDescriptor findSubmodel = repository.getSubmodel(aas.getId(), submodel.getId());
Assert.assertNotNull(findSubmodel);
}

Expand All @@ -262,10 +246,10 @@ public void findAASSubmodelById() throws Exception {
public void deleteStandAloneSubmodel() throws Exception {
SubmodelDescriptor submodel = getSubmodel();
repository.addSubmodel(submodel);
compareSubmodel(submodel, repository.getSubmodel(submodel.getIdentification().getIdentifier()));
compareSubmodel(submodel, repository.getSubmodel(submodel.getId()));

repository.deleteSubmodel(submodel.getIdentification().getIdentifier());
Assert.assertThrows(ResourceNotFoundException.class, () -> repository.getSubmodel(submodel.getIdentification().getIdentifier()));
repository.deleteSubmodel(submodel.getId());
Assert.assertThrows(ResourceNotFoundException.class, () -> repository.getSubmodel(submodel.getId()));
}


Expand All @@ -274,12 +258,12 @@ public void deleteAASSubmodel() throws Exception {
SubmodelDescriptor submodel = getSubmodel();
AssetAdministrationShellDescriptor aas = getAASWithSubmodel();
repository.create(aas);
repository.addSubmodel(aas.getIdentification().getIdentifier(), submodel);
compareSubmodel(submodel, repository.getSubmodel(aas.getIdentification().getIdentifier(), submodel.getIdentification().getIdentifier()));
repository.addSubmodel(aas.getId(), submodel);
compareSubmodel(submodel, repository.getSubmodel(aas.getId(), submodel.getId()));

repository.deleteSubmodel(aas.getIdentification().getIdentifier(), submodel.getIdentification().getIdentifier());
repository.deleteSubmodel(aas.getId(), submodel.getId());

Assert.assertThrows(ResourceNotFoundException.class, () -> repository.getSubmodel(aas.getIdentification().getIdentifier(), submodel.getIdentification().getIdentifier()));
Assert.assertThrows(ResourceNotFoundException.class, () -> repository.getSubmodel(aas.getId(), submodel.getId()));
}


Expand Down
2 changes: 1 addition & 1 deletion docs/source/about/about.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# About the Project

This project provides an implemetation of the Registry for the [Asset Administration Shell (AAS)](https://www.plattform-i40.de/SiteGlobals/IP/Forms/Listen/Downloads/EN/Downloads_Formular.html?cl2Categories_TechnologieAnwendungsbereich_name=Verwaltungsschale).
This project provides an implemetation of the Registry for the [Asset Administration Shell (AAS)](https://industrialdigitaltwin.org/content-hub/downloads).
The Registry provides information about registered AASs, including the endpoint of the AASs.

## Contact
Expand Down
3 changes: 2 additions & 1 deletion docs/source/about/recommended.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

- [Asset Administration Shell Specifications](https://industrialdigitaltwin.org/en/content-hub)
Quicklinks To Different Versions & Reading Guide
- [Details of the Asset Administration Shell - Part 2](https://www.plattform-i40.de/IP/Redaktion/EN/Downloads/Publikation/Details_of_the_Asset_Administration_Shell_Part2_V1.html), Nov 2021
- [Details of the Asset Administration Shell - Part 2](https://industrialdigitaltwin.org/wp-content/uploads/2023/06/IDTA-01002-3-0_SpecificationAssetAdministrationShell_Part2_API_.pdf), June 20237LTS#cjt#+

This part of the AAS specification provides information about the Registry, the descriptors and the available APIs.
Loading
Loading