blob: a2e88d11be258435720513a0c7b94fe0195c2c23 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2021 the Eclipse BaSyx Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
******************************************************************************/
package org.eclipse.basyx.examples.mockup.device;
import java.util.Map;
import org.eclipse.basyx.aas.aggregator.restapi.AASAggregatorProvider;
import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell;
import org.eclipse.basyx.aas.metamodel.map.descriptor.AASDescriptor;
import org.eclipse.basyx.aas.metamodel.map.descriptor.ModelUrn;
import org.eclipse.basyx.aas.metamodel.map.descriptor.SubmodelDescriptor;
import org.eclipse.basyx.aas.registration.proxy.AASRegistryProxy;
import org.eclipse.basyx.components.device.BaseSmartDevice;
import org.eclipse.basyx.examples.contexts.BaSyxExamplesContext;
import org.eclipse.basyx.examples.support.directory.ExamplesPreconfiguredDirectory;
import org.eclipse.basyx.models.controlcomponent.ExecutionState;
import org.eclipse.basyx.submodel.metamodel.map.Submodel;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property;
import org.eclipse.basyx.submodel.restapi.MultiSubmodelElementProvider;
import org.eclipse.basyx.vab.manager.VABConnectionManager;
import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
import org.eclipse.basyx.vab.modelprovider.map.VABMapProvider;
import org.eclipse.basyx.vab.protocol.basyx.server.BaSyxTCPServer;
import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorProvider;
/**
* This class implements a mockup of a smart manufacturing device
*
* The device pushes its AAS to an external asset administration shell server -
* The sub model "statusSM" is pushed to the external asset administration shell
* server as well - The sub model "controllerSM" is provided by an BaSyx/TCP
* server of the smart device
*
* @author kuhn
*
*/
public class SmartBaSyxTCPDeviceMockup extends BaseSmartDevice {
/**
* Server port
*/
protected int serverPort = -1;
/**
* BaSyx/TCP Server that exports the control component
*/
protected BaSyxTCPServer<VABMapProvider> server = null;
/**
* AAS server connection
*/
protected VABElementProxy aasServerConnection = null;
protected String aasPath;
/**
* Constructor
*/
public SmartBaSyxTCPDeviceMockup(int port) {
// Invoke base constructor
super();
// Store server port
serverPort = port;
// Register URNs of managed VAB objects
addShortcut("AAS", new ModelUrn("urn:de.FHG:devices.es.iese:aas:1.0:3:x-509#001"));
addShortcut("Status", new ModelUrn("urn:de.FHG:devices.es.iese:statusSM:1.0:3:x-509#001"));
// Configure BaSyx service - registry and connection manager
setRegistry(new AASRegistryProxy("http://localhost:8080/" + BaSyxExamplesContext.REGISTRYURL));
setConnectionManager(new VABConnectionManager(new ExamplesPreconfiguredDirectory(), new HTTPConnectorProvider()));
}
/**
* Indicate a service invocation
*/
@SuppressWarnings("unchecked")
@Override
protected void onServiceInvocation() {
// Base implementation
super.onServiceInvocation();
// Implement the device invocation counter - read and increment invocation counter
Map<String, Object> property = (Map<String, Object>) aasServerConnection
.getValue(aasPath + "/submodels/Status/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/invocations");
int invocations = (int) property.get("value");
aasServerConnection.setValue(aasPath + "/submodels/Status/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/invocations/value", ++invocations);
}
/**
* Smart device control component indicates an execution state change
*/
@Override
public void onChangedExecutionState(ExecutionState newExecutionState) {
// Invoke base implementation
super.onChangedExecutionState(newExecutionState);
// Update property "properties/status" in external AAS
aasServerConnection.setValue(aasPath + "/submodels/Status/submodel/" + MultiSubmodelElementProvider.ELEMENTS + "/status/value",
newExecutionState.getValue());
}
/**
* Start smart device
*/
@Override
public void start() {
// Invoke base implementation
super.start();
// Connect to AAS server
aasServerConnection = this.getConnectionManager().connectToVABElement("AASServer");
// Create device AAS
// - Create device AAS
AssetAdministrationShell aas = new AssetAdministrationShell();
aas.setIdShort("DeviceIDShort");
aas.setIdentification(lookupURN("AAS"));
// - Transfer device AAS to server
aasServerConnection.setValue(VABPathTools.append(AASAggregatorProvider.PREFIX, VABPathTools.encodePathElement(aas.getIdentification().getId())), aas);
aasPath = VABPathTools.concatenatePaths(AASAggregatorProvider.PREFIX, lookupURN("AAS").getEncodedURN(), "aas");
// The device also brings a sub model structure with an own ID that is being pushed on the server
// - Create generic sub model and add properties
Submodel statusSM = new Submodel();
statusSM.setIdShort("Status");
// - Property status: indicate device status
Property statusProp = new Property("offline");
statusProp.setIdShort("status");
statusSM.addSubmodelElement(statusProp);
// - Property statistics: export invocation statistics for every service
// - invocations: indicate total service invocations. Properties are not persisted in this example,
// therefore we start counting always at 0.
Property invocationsProp = new Property(0);
invocationsProp.setIdShort("invocations");
statusSM.addSubmodelElement(invocationsProp);
// - Transfer device sub model to server
aasServerConnection.setValue(aasPath + "/submodels/" + statusSM.getIdShort(), statusSM);
// Register control component as local sub model
// - This sub model will stay with the device
server = new BaSyxTCPServer<>(new VABMapProvider(controlComponent), serverPort);
// - Start local BaSyx/TCP server
server.start();
// Register AAS and sub models in directory (push AAS descriptor to server)
// - AAS repository server URL
String aasRepoURL = "http://localhost:8080" + BaSyxExamplesContext.AASSERVERURL + "/" + AASAggregatorProvider.PREFIX + "/" + lookupURN("AAS").getEncodedURN() + "/aas";
// - Build an AAS descriptor, add sub model descriptors
AASDescriptor deviceAASDescriptor = new AASDescriptor(lookupURN("AAS"), aasRepoURL);
// Create sub model descriptors
SubmodelDescriptor statusSMDescriptor = new SubmodelDescriptor("Status", lookupURN("Status"),
aasRepoURL + "/submodels/Status/submodel");
// Add sub model descriptor to AAS descriptor
deviceAASDescriptor.addSubmodelDescriptor(statusSMDescriptor);
// - Push AAS descriptor to server
getRegistry().register(deviceAASDescriptor);
}
/**
* Stop smart device
*/
@Override
public void stop() {
// Stop local BaSyx/TCP server
server.stop();
}
/**
* Wait for completion of all threads
*/
@Override
public void waitFor() {
// Wait for server end
server.waitFor();
}
}