Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [basyx-dev] Interact with multiple submodels

Dear BaSyx development team,

To precise my use case, I have 22 machines connected with one AAS and 2 submodels each, the dashboard connects on request, and list all AAS, submodels and their dataElements/operations, in a simplified JSON format. (machines can plug in/out so the dashboard don't have expectation on the AAS/submodels connected)
The source code for my dashboard application is in the attachment (ignore the PerformanceTimer and its calls in the source, only used to measure time spent on each call).
The method called by the servlet is buildJsonSnapshot(), it takes about 30s to complete.
Can you tell me which calls or methods do you think are inefficient, and how should I change them?

To be also more precise about starting/stopping all connected machines quickly, I mean the calls should take a couple of seconds or less, I don't expect 1ms response time.

On another note, does BaSyx intend to add other communication patterns in the future? Like publisher/subscriber to use for example to advertise the connection of a new AAS/submodel, or changes of dataElements values?

Best regards,


Nicolas Duminy

----- Mail original -----
De: "Frank Schnicke" <Frank.Schnicke@xxxxxxxxxxxxxxxxxx>
À: "basyx-dev" <basyx-dev@xxxxxxxxxxx>
Envoyé: Jeudi 12 Décembre 2019 08:26:18
Objet: Re: [basyx-dev] Interact with multiple submodels

Dear Nicolas,

> Can you tell me what is the fastest way to get all registered data elements of all submodels? (HTTP-REST calls? VAB crud calls? Using the ConnectedAdministrationShell calls?) I need, for a dashboard 
> application, to request all data elements from every submodels, but it is really slow.

The VAB crud calls/the Connected* classes have little overhead in comparison to http-REST calls, so any option should be fine. What exactly is slow? Retrieving the AAS, retrieving their submodels or retrieving the data elements? There are explicit API calls for data element retrieval (https://wiki.eclipse.org/BaSyx_/_Documentation_/_API_/_Submodel). Are you using these?


> I am trying to build a manager application for a complete factory, which can start or stop all machines connected in the factory (the operations must be quickly applied).

What exactly are you aiming at with this start/stop of machines and why does it need to be applied quickly? If there's any real-time requirement involved here, maybe a dashboard is not the best solution. 


> Is there a built-in way in BaSyx to get all submodels of a specific type? (e.g. get all control component submodels).

Currently, there's no built-in way to do this. What we are planning to do is to implement a tagged directory where it will be possible to retrieve all AAS or submodels with a certain tag (e.g. "ControlComponentContaining", "Device"). 


> How do we differentiate and describe submodel types and instances for this purpose?

The meta-model of the AAS and submodels defines the "HasKind" qualifier. This qualifier allows to define if the current entity is a type or an instance. 

Best regards,
Frank

----------------------------------------------------------------------------------
M.Sc. Frank Schnicke
Abteilung ESW
Fraunhofer IESE 
Fraunhofer-Platz 1 | 67663 Kaiserslautern 
Tel: +49 631 / 6800-2259 | Fax: +49 631 / 6800-9-2259
www.iese.fraunhofer.de 
Mail: frank.schnicke@xxxxxxxxxxxxxxxxxx

-----Ursprüngliche Nachricht-----
Von: basyx-dev-bounces@xxxxxxxxxxx <basyx-dev-bounces@xxxxxxxxxxx> Im Auftrag von Nicolas DUMINY
Gesendet: Mittwoch, 11. Dezember 2019 19:22
An: basyx-dev <basyx-dev@xxxxxxxxxxx>
Betreff: [basyx-dev] Interact with multiple submodels

Dear BaSyx development team,

Can you tell me what is the fastest way to get all registered data elements of all submodels? (HTTP-REST calls? VAB crud calls? Using the ConnectedAdministrationShell calls?) I need, for a dashboard application, to request all data elements from every submodels, but it is really slow.

I am trying to build a manager application for a complete factory, which can start or stop all machines connected in the factory (the operations must be quickly applied).
Is there a built-in way in BaSyx to get all submodels of a specific type? (e.g. get all control component submodels) How do we differentiate and describe submodel types and instances for this purpose?

Best regards,


Nicolas Duminy
_______________________________________________
basyx-dev mailing list
basyx-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/basyx-dev
_______________________________________________
basyx-dev mailing list
basyx-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/basyx-dev
package org.ddpaas.basyx.services;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.ddpaas.utils.PerformanceTimer;
import org.eclipse.basyx.aas.manager.ConnectedAssetAdministrationShellManager;
import org.eclipse.basyx.aas.metamodel.connected.ConnectedAssetAdministrationShell;
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.devicemanager.DeviceManagerComponent;
import org.eclipse.basyx.components.service.BaseBaSyxService;
import org.eclipse.basyx.submodel.metamodel.api.ISubModel;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.IDataElement;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.property.ISingleProperty;
import org.eclipse.basyx.tools.webserviceclient.WebServiceJSONClient;
import org.eclipse.basyx.vab.coder.json.serialization.DefaultTypeFactory;
import org.eclipse.basyx.vab.coder.json.serialization.GSONTools;
import org.eclipse.basyx.vab.manager.VABConnectionManager;
import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorProvider;


public class Dashboard extends BaseBaSyxService {

	public static String registryUrl = "http://localhost:8080/basys.ddpaas/Components/Directory/SQL";;
	
	private WebServiceJSONClient jsonClient;
	private GSONTools serializer;
	private ConnectedAssetAdministrationShellManager aasManager;
	
	// Performance computations
	public PerformanceTimer pTimer;
	
	public Dashboard() {
		// Set registry proxy
		setRegistry(new AASRegistryProxy(registryUrl));
		
		// Set service connection manager and create AAS server connection
		setConnectionManager(new VABConnectionManager(new AASRegistryProxy(registryUrl), new HTTPConnectorProvider()));
	
		// Set objects to recover all AAS from registry & parse them
		jsonClient = new WebServiceJSONClient();
		serializer = new GSONTools(new DefaultTypeFactory());
		aasManager = new ConnectedAssetAdministrationShellManager(getRegistry(), new HTTPConnectorProvider());
		
		// Performance computations
		pTimer = new PerformanceTimer();
	}
	
	/**
	 * Initialize the device, and register it with the backend
	 */
	public void start() {
		// Base implementation
		super.start();
	}
	
	//TODO really really really slow
	public Collection<Object> buildJsonSnapshot() {
		pTimer.start();
		Collection<Object> res = new ArrayList<Object>();
		pTimer.step("create-collection");
		
		Object sql = ((Map<String, Object>) jsonClient.get(registryUrl+"/api/v1/registry")).get("entity");
		pTimer.step("get-all-aas");
		ArrayList<AASDescriptor> allAAS = dirtyParseSQLGetAllAAS((String) sql);
		pTimer.step("parse-all-aas");
		
		for(AASDescriptor aas : allAAS) {
			try {
				res.add(buildJsonSnapshotAAS(aas.getIdentifier()));
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		pTimer.step("overhead");
		
		res.add(pTimer.getAllTotals());
		res.add(pTimer.getAllNb());
		
		return res;
	}
	
	public Map<String, Object> buildJsonSnapshotAAS(IIdentifier aasId) throws Exception {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("Type", "AdministrationShell");
		
		pTimer.step("overhead");
		
		ConnectedAssetAdministrationShell cas = aasManager.retrieveAAS(aasId);
		pTimer.step("get-aas");
		
		map.put("idShort", cas.getIdShort());
		map.put("id", cas.getIdentification().getId());
		
		HashMap<String, Object> submodels = new HashMap<String, Object>();
		// Not working for all remote submodels (which means all submodels in our case) !!!
		//Map<String, ISubModel> sub = cas.getSubModels();
		//for(String key : sub.keySet())
		//	submodels.put(key, buildJsonSnapshotSubmodel(aasId, sub.get(key).getIdentification()));
		for (SubmodelDescriptor sd : cas.getSubModelDescriptors())
			submodels.put((String) sd.get("idShort"), buildJsonSnapshotSubmodel(aasId, sd.getIdentifier()));
		map.put("submodels", submodels);
		
		return map;
	}
	
	public Map<String, Object> buildJsonSnapshotSubmodel(IIdentifier aasId, IIdentifier smId) throws Exception {
		HashMap<String, Object> map = new HashMap<String, Object>();
		pTimer.step("overhead");
		
		ISubModel sm = aasManager.retrieveSubModel(aasId, smId);
		pTimer.step("get-submodel");
		
		map.put("Type", "SubModel");
		map.put("idShort", sm.getIdShort());
		map.put("id", sm.getIdentification().getId());
		HashMap<String, Object> dataElements = new HashMap<String, Object>();
		pTimer.step("overhead");
		for(IDataElement de : sm.getDataElements().values()) {
			dataElements.put(de.getIdShort(), ((ISingleProperty) de).get());
		}
		pTimer.step("get-dataElements");
		map.put("dataElements", dataElements);
		HashMap<String, Object> operations = new HashMap<String, Object>();
		pTimer.step("overhead");
		for (IOperation op : sm.getOperations().values()) {
			operations.put(op.getIdShort(), op.getIdShort());
		}
		pTimer.step("get-operations");
		map.put("operations", operations);
		
		return map;
	}
	
	//TODO Dirty hack!! To be replaced as soon as BaSyx fixes the problem!!
	public ArrayList<AASDescriptor> dirtyParseSQLGetAllAAS(String res) {
		ArrayList<AASDescriptor> list = new ArrayList<AASDescriptor>();
		
		String separator = "\\}\\{";
		String[] slist = res.split(separator);
		for (int i = 0; i < slist.length; i++) {
			String s = slist[i];
			if (i > 0)
				s = "{" + s;
			if (slist.length > 1 && i < slist.length-1)
				s += "}";
			//System.out.println(s);
			//System.out.println(new AASDescriptor((Map<String, Object>) serializer.deserialize(s)).getClass().getName());
			list.add(new AASDescriptor((Map<String, Object>) serializer.deserialize(s)));
		}
		
		return list;
	}
	
}

Back to the top