diff --git a/examples/BaSyxHelloWorld/README.md b/examples/BaSyxHelloWorld/README.md new file mode 100644 index 000000000..7a62d9aee --- /dev/null +++ b/examples/BaSyxHelloWorld/README.md @@ -0,0 +1,341 @@ +# HelloWorld BaSyx Java Example + +This tutorial demonstrates how to use **Eclipse BaSyx** to create and manage an **Asset Administration Shell (AAS)** in Java. + +## Overview + +In this tutorial you will learn how to: + +1. Connect to a BaSyx environment +2. Create an AAS +3. Create a Submodel +4. Add Submodel Elements +5. Create Operations +6. Update and read data +7. Delete elements +8. Remove the full AAS + +## Lifecycle Summary + +>Create AAS +>↓ +>Create Submodel +>↓ +>Add Elements +>↓ +>Add Operations +>↓ +>Interact / Update +>↓ +>Invoke Operations +>↓ +>Delete Elements +>↓ +>Delete Submodel +>↓ +>Delete AAS + + +## Running BaSyx Services + +Make sure the following services are running: + +- AAS Repository +- Submodel Repository +- AAS Registry +- Submodel Registry + +Default endpoints used: + +```java +String aasRegistryBaseUrl = "http://localhost:8082"; +String aasRepositoryBaseUrl = "http://localhost:8081"; +String submodelRegistryBaseUrl = "http://localhost:8083"; +String submodelRepositoryBaseUrl = "http://localhost:8081"; +``` + +BaSyx provides Docker images for quick setup. + + + +## Step 1 – BaSyx Docker Setup + +Before starting the implementation, make sure your BaSyx environment is running via Docker. + +>You can follow the official Quick Installation Guide here: +>https://wiki.basyx.org/en/latest/content/introduction/quickstart.html + + + +## Step 2 – Configure BaSyx Environment + +Configure BaSyx by editing the file: + +`basyx/aas-env.properties` + +Use the following configuration: + +```properties +server.port=8081 +basyx.backend=InMemory +basyx.environment=file:aas +basyx.cors.allowed-origins=* +basyx.cors.allowed-methods=GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD +spring.servlet.multipart.max-file-size=500MB +spring.servlet.multipart.max-request-size=500MB +``` + + + +# Step 3 – BaSyx Library Imports + +Add the required BaSyx and AAS4J dependencies: + +```java +import org.eclipse.digitaltwin.aas4j.v3.model.*; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.*; +import org.eclipse.digitaltwin.basyx.aasenvironment.client.ConnectedAasManager; +import org.eclipse.digitaltwin.basyx.aasservice.client.ConnectedAasService; +import org.eclipse.digitaltwin.basyx.operation.InvokableOperation; +import org.eclipse.digitaltwin.basyx.submodelservice.client.ConnectedSubmodelService; +``` +Edit your `pom.xml` to have this (or newer version) dependencies : + +```xml + + + org.eclipse.digitaltwin.basyx + basyx.aasenvironment-client + 2.0.0-milestone-04 + + + org.eclipse.digitaltwin.basyx + basyx.aasrepository-client + 2.0.0-milestone-08 + + + org.eclipse.digitaltwin.basyx + basyx.submodelrepository-client + 2.0.0-milestone-08 + + + org.eclipse.digitaltwin.basyx + basyx.aasservice-client + 2.0.0-milestone-08 + + + org.eclipse.digitaltwin.basyx + basyx.submodelservice-client + 2.0.0-milestone-08 + + + org.eclipse.digitaltwin.aas4j + aas4j-dataformat-aasx + 2.0.1 + + +``` + + + +## Step 4 – Connect to BaSyx + +```java +ConnectedAasManager helloManager = + new ConnectedAasManager( + aasRegistryBaseUrl, + aasRepositoryBaseUrl, + submodelRegistryBaseUrl, + submodelRepositoryBaseUrl + ); +``` + +This manager allows you to: + +- Create AAS +- Create Submodels +- Delete resources +- Access services + + + +## Step 5 – Create an AAS + +```java +AssetAdministrationShell helloAAS = + new DefaultAssetAdministrationShell.Builder() + .id("http://example.com/aas/helloWorld") + .idShort("HelloWorldAAS") + .build(); +``` + + + +## Step 6 – Create a Submodel + +### Semantic Reference + +```java +DefaultKey key = new DefaultKey.Builder() + .type(KeyTypes.SUBMODEL) + .value("http://example.com/aas/helloWorld/submodel") + .build(); + +DefaultReference ref = new DefaultReference.Builder() + .type(ReferenceTypes.EXTERNAL_REFERENCE) + .keys(key) + .build(); +``` + +### Submodel + +```java +Submodel helloSubmodel = + new DefaultSubmodel.Builder() + .id("http://example.com/aas/helloWorld/submodel") + .idShort("helloSubmodel") + .semanticId(ref) + .build(); +``` + + + +## Step 7 – Deploy AAS and Submodel + +```java +helloManager.createAas(helloAAS); + +helloManager.createSubmodelInAas( + helloAAS.getId(), + helloSubmodel +); +``` + + + +## Step 8 – Get Service Access + +```java +ConnectedAasService helloAASService = + helloManager.getAasService(helloAAS.getId()); + +ConnectedSubmodelService helloSMService = + helloManager.getSubmodelService(helloSubmodel.getId()); +``` + + + +## Step 9 – Create Submodel Collection + +```java +SubmodelElementCollection helloCollection = + new DefaultSubmodelElementCollection.Builder() + .idShort("helloSMCollection") + .value(List.of()) + .build(); + +helloSMService.createSubmodelElement(helloCollection); +``` + + + +## Step 10 – Create Operation (Pythagoras Example) + +```java +Operation helloOperation = + new InvokableOperation.Builder() + .idShort("pythagorasOperation") + .inputVariables(input_A) + .inputVariables(input_B) + .outputVariables(result_C) + .invokable(Main::pythagoras) + .build(); +``` + + + +## Step 11 – Add Elements to Submodel + +```java +SubmodelElementCollection helloSMC = + (SubmodelElementCollection) + helloSMService.getSubmodelElement("helloSMCollection"); + +helloSMC.getValue().add( + new DefaultProperty.Builder() + .idShort("helloProperty") + .valueType(DataTypeDefXsd.STRING) + .value("h3ll0World!") + .build() +); + +helloSMC.getValue().add(helloOperation); + +helloSMService.updateSubmodelElement( + "helloSMCollection", + helloSMC +); +``` + + + +## Step 12 – Definition of Invoked Operation (Pythagoras) + +>The operation calculates: +> `C = sqrt(A² + B²)` + +```java +private static OperationVariable[] pythagoras(OperationVariable[] inputs) { + Property A = (Property) inputs[0].getValue(); + Property B = (Property) inputs[1].getValue(); + + Integer iA = Integer.valueOf(A.getValue()); + Integer iB = Integer.valueOf(B.getValue()); + + Integer C_out = (int) Math.sqrt(iA*iA + iB*iB); + + Property C = new DefaultProperty.Builder() + .idShort("C") + .value(String.valueOf(C_out)) + .build(); + + return new OperationVariable[] { + new DefaultOperationVariable.Builder().value(C).build() + }; +} +``` + + + +## Step 13 – Delete Property / Submodel / AAS + +### Delete Property +```java +helloSMService.deleteSubmodelElement( + "helloSMCollection.helloProperty" +); +``` + + + +### Delete Submodel + +```java +helloManager.deleteSubmodelOfAas( + helloAAS.getId(), + helloSubmodel.getId() +); +``` + + + +### Delete AAS + +```java +helloManager.deleteAas( + helloAAS.getId() +); +``` + + + diff --git a/examples/BaSyxHelloWorld/pom.xml b/examples/BaSyxHelloWorld/pom.xml new file mode 100644 index 000000000..88a703e22 --- /dev/null +++ b/examples/BaSyxHelloWorld/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + + + sonatype.snapshots + Sonatype Snapshot Repository + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + org.example + BaSyx_HelloWorld + 1.0-SNAPSHOT + + + 25 + 25 + UTF-8 + + + + + org.eclipse.digitaltwin.basyx + basyx.aasenvironment-client + 2.0.0-milestone-04 + + + org.eclipse.digitaltwin.basyx + basyx.aasrepository-client + 2.0.0-milestone-08 + + + org.eclipse.digitaltwin.basyx + basyx.submodelrepository-client + 2.0.0-milestone-08 + + + org.eclipse.digitaltwin.basyx + basyx.aasservice-client + 2.0.0-milestone-08 + + + org.eclipse.digitaltwin.basyx + basyx.submodelservice-client + 2.0.0-milestone-08 + + + org.eclipse.digitaltwin.aas4j + aas4j-dataformat-aasx + 2.0.1 + + + + \ No newline at end of file diff --git a/examples/BaSyxHelloWorld/src/main/java/org/example/Main.java b/examples/BaSyxHelloWorld/src/main/java/org/example/Main.java new file mode 100644 index 000000000..81fecf437 --- /dev/null +++ b/examples/BaSyxHelloWorld/src/main/java/org/example/Main.java @@ -0,0 +1,112 @@ +package org.example; + +import org.eclipse.digitaltwin.aas4j.v3.model.*; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.*; +import org.eclipse.digitaltwin.basyx.aasenvironment.client.ConnectedAasManager; +import org.eclipse.digitaltwin.basyx.aasservice.client.ConnectedAasService; +import org.eclipse.digitaltwin.basyx.operation.InvokableOperation; +import org.eclipse.digitaltwin.basyx.submodelservice.client.ConnectedSubmodelService; + +import java.util.List; + +public class Main { + static void main() { + + //SEE POM.XML FOR NECESSARY DEPENDENCY BASYX LIBRARIES AND AAS4J OBJECT MODEL + //THIS CODE NEEDS BASYX [AAS REPOSITORY] , [SUBMODEL REPOSITORY] , [AAS REGISTRY] and [SUBMODEL REGISTRY] RUNNING + //SEE basyx.org FOR BASYX OFF THE SHELF DOCKER CONTAINER DOWNLOADS + + //Connect to AAS Environment (BaSyx Servers) + String aasRegistryBaseUrl = "http://localhost:8082"; + String aasRepositoryBaseUrl = "http://localhost:8081"; + String submodelRegistryBaseUrl = "http://localhost:8083"; + String submodelRepositoryBaseUrl = "http://localhost:8081"; + ConnectedAasManager helloManager = new ConnectedAasManager(aasRegistryBaseUrl, aasRepositoryBaseUrl, submodelRegistryBaseUrl, submodelRepositoryBaseUrl); + + //Create AAS in Java Object Model + AssetAdministrationShell helloAAS= new DefaultAssetAdministrationShell.Builder() + .id("http://example.com/aas/helloWorld") + .idShort("HelloWorldAAS") + .build(); + + //Create SemanticId for Submodel + DefaultKey key = new DefaultKey.Builder().type(KeyTypes.SUBMODEL).value("http://example.com/aas/helloWorld/submodel").build(); + DefaultReference ref = new DefaultReference.Builder().type(ReferenceTypes.EXTERNAL_REFERENCE).keys(key).build(); + + //Create empty Submodel in Java Object Model + Submodel helloSubmodel = new DefaultSubmodel.Builder() + .id("http://example.com/aas/helloWorld/submodel") + .idShort("helloSubmodel") + .semanticId(ref) + .build(); + + helloManager.createAas(helloAAS); + helloManager.createSubmodelInAas(helloAAS.getId(), helloSubmodel); + + //Initialize Service Managers + ConnectedAasService helloAASService = helloManager.getAasService(helloAAS.getId()); + ConnectedSubmodelService helloSMService = helloManager.getSubmodelService(helloSubmodel.getId()); + + //Create new SubmodelElementCollection (SMC) in Java Object Model + SubmodelElementCollection helloCollection = new DefaultSubmodelElementCollection.Builder() + .idShort("helloSMCollection") + .value(List.of()) + .build(); + + //Add SubmodelElementCollection (SMC) from Java Object to Submodel + helloSMService.createSubmodelElement(helloCollection); + + //Create Invokable Operation + DefaultOperationVariable input_A = new DefaultOperationVariable.Builder().value(new DefaultProperty.Builder().idShort("A").valueType(DataTypeDefXsd.INT).build()).build(); + DefaultOperationVariable input_B = new DefaultOperationVariable.Builder().value(new DefaultProperty.Builder().idShort("B").valueType(DataTypeDefXsd.INT).build()).build(); + DefaultOperationVariable result_C = new DefaultOperationVariable.Builder().value(new DefaultProperty.Builder().idShort("C").valueType(DataTypeDefXsd.INT).build()).build(); + + Operation helloOperation = new InvokableOperation.Builder() + .idShort("pythagorasOperation") + .inputVariables(input_A) + .inputVariables(input_B) + .outputVariables(result_C) + .invokable(Main::pythagoras) + .build(); + + //Get Submodel Element from Submodel Service (Submodel Server) and add a Property to the SMC (Update), then re-push it to the Server + SubmodelElementCollection helloSMC = (SubmodelElementCollection) helloSMService.getSubmodelElement("helloSMCollection"); + helloSMC.getValue().add(new DefaultProperty.Builder().idShort("helloProperty").valueType(DataTypeDefXsd.STRING).value("h3ll0World!").build()); + helloSMC.getValue().add(helloOperation); + helloSMService.updateSubmodelElement("helloSMCollection", helloSMC); + + //STOP EXECUTION HERE TO SEE RESULTS + Integer addBreakpointHere = 42; + //REST OF EXAMPLE CODE WILL DELETE EVERYTHING CREATED + + //Delete the Property + helloSMService.deleteSubmodelElement("helloSMCollection.helloProperty"); + + //Delete whole Submodel + helloManager.deleteSubmodelOfAas(helloAAS.getId(),helloSubmodel.getId()); + + //Delete whole AAS + helloManager.deleteAas(helloAAS.getId()); + } + + //Invokable Operation: Pythagoras + private static OperationVariable[] pythagoras(OperationVariable[] inputs) { + Property A = (Property) inputs[0].getValue(); + Property B = (Property) inputs[1].getValue(); + Property C = (Property) inputs[2].getValue(); + Integer iA = Integer.valueOf(A.getValue()); + Integer iB = Integer.valueOf(B.getValue()); + + Integer A_squared = iA * iA; + Integer B_squared = iB * iB; + Integer C_squared = A_squared + B_squared; + Integer C_out = (int) Math.sqrt(C_squared); + + C.setValue(C_out.toString()); + C.setIdShort("C"); + + OperationVariable result = new DefaultOperationVariable.Builder().value(C).build(); + + return new OperationVariable[] { result }; + } +}