4.4.3 DeviceExtension

Über diesen ExtensionPoint können neue Geräte hinzugefügt werden. 

Allgemein

Bei der Benutzung des ExtensionPoints empfiehlt es sich, hier von der Klasse "AbstractDeviceExtension" abzuleiten, da diese bereits ein paar wesentliche Funktionen bereitstellt.

Das Plugin bzw. der DeviceExtension-Point stellt lediglich ein Template bereit. Konkrete Geräte werden dann über die GUI hinzugefügt. 

Ein Device-Template hat eine Unique-ID. Diese sollte ähnlich zur Plugin-ID (siehe 4.1. Plugins - Getting Started) über eine „Reverse Domain Name Notation" der Firmen-Domain bestimmt werden und kann auch mit der Plugin-ID übereinstimmen. 

Hier ist die Unique-ID dann z.B. "de.bluebiz.smartenergy". Diese ID wird vom System verwendet, um ein Gerät eindeutig einem Device-Template zuordnen zu können.

Wird ein konkretes Gerät durch ein Device-Template erzeugt, so bekommt es eine UUID - diese UUID ist systemweit einzigartig und identifiziert damit genau das eine, erstellte Device. 

Device-Template

Das Device-Template entspricht in diesem Falle dem ExtensionPoint und dient dazu, alle notwendigen Informationen zum Erstellen von konkreten Device-Instanzen bereitzustellen. Dazu gehören neben der Factory-Methode "createInstance" auch das Definieren von notwendigen Parametern. 

Device-Template-Parameter

Notwendige Parameter werden beim Erstellen eines Device abgefragt, sofern diese vorher für das Template definiert wurden. 

Durch den Aufruf von "createTemplate" können diese hinzugefügt werden. 

Zum Beispiel fügt

addParameter(new StringParameterType("Host"));

einen Parameter mit dem Namen "Host" als String hinzu. In diesem Fall ist der Standardwert "null". Es kann jedoch auch ein vorgegebener Wert hinzugefügt werden:

addParameter(new StringParameterType("Host", "localhost"));

Des Weiteren gibt es Long, Double, Boolean und List-Parameter.

Diese Parameter werden dann beim Anlegen (bzw. ändern) des Device abgefragt:

Die angegeben Parameter werden dann der Factory-Methode "createInstance" übergeben und stehen damit dort zur Verfügung. Diese Parameter werden auch im System gespeichert und beim Neustart werden diese geladen und auch an "createInstance" übergeben, um das Device wieder herzustellen. 

Das heißt, dass die Methode "createInstance" für jedes hinzugefügte Gerät aufgerufen wird. 

Device-Instanz

Eine Device-Instanz entspricht einem tatsächlichen Gerät und wird über "createInstance" des ExtensionPoints erzeugt. Jedes Device hat systemweit eine eigene UUID. 

Um ein entsprechendes Device erzeugen zu können, muss diese von der Klasse 

DeviceInstance

Zum Beispiel:

public class DeviceEnergymeter extends DeviceInstance

Wenn die Parameter eines Gerätes in der GUI geändert werden, dann wird vom System  

deviceSettingsChanged

aufgerufen. Diese kann entsprechend überschrieben werden, um dann auf die Änderungen zu reagieren.

Device-Features

Ein Gerät kann zusätzlich bestimmte Fähigkeiten haben, die dann an entsprechenden Stellen im SmartMES behandelt werden. 

Dieser werden über eine Implementierung des Interfaces angegeben, also für das Feature "MessageReceiver" muss das entsprechende Interface angegeben werden:

public class DeviceSmartwatch extends DeviceInstance implements DeviceMessageReceiver{

Derzeit gibt es folgende Device-Features:

DeviceFileProvider

Das entsprechende Device kann Dateien bereitstellen, die beim Abschluss eines Produktions-Auftrag an die Stückliste gehängt werden, damit sie beim nächsten Auftrag mit derselben Stückliste wieder verfügbar sind.

Die Dateien werden dabei an den Arbeitsplan angehängt. Dies erfolgt nur, wenn das entsprechende Gerät auch der Maschine, an der dieser Auftrag gerade beendet wird, zugeordnet wurde.

DeviceMessageReceiver

Hierbei bekommt das Gerät verschiedene Mitteilungen des Systems übergeben. Zum Beispiel, wenn ein neuer Auftrag eingegangen ist, Produktionsaufträge gestartet wurden oder auch Plugins gestartet bzw. gestoppt wurden. 

DeviceConnector

Dies sind Geräte, die explizit eine Verbindung herstellen bzw. beenden müssen. Dies ist z.B. notwendig, wenn das Gerät nur arbeiten soll, wenn eine Verbindung besteht. 

Beim Starten vom SmartMES wird dann "connect()" und beim Beenden wird entsprechend "disconnect()" für alle diese Geräte aufgerufen. Dies ist aber nicht zwingend für alle Geräte notwendig.

DeviceFileReceiver

Erlaubt das Empfangen von Dateien, wenn ein Produktionsprozess gestartet wird. Es ist damit das Gegenstück zu DeviceFileProvider, 

Die Dateien, die an einem Arbeitsplan hängen (z.B. NC-Daten) werden beim Starten eines Auftrags übergeben. Dabei muss das Gerät jedoch der Maschine zugeordnet sein, an der dieser Auftrag gerade gestartet wird.

DeviceTaskProvider

Erlaubt das Bereitstellen von zusätzlichen Aufgaben, die an bestimmten Stellen (HookPoint) durchgeführt werden. Ein Task ist dabei entweder eine stille Aufgabe, die automatisch durchgeführt wird, oder ein Dialog, das dem Benutzer angezeigt wird. 

Als HookPoints kann dann entsprechend vor bzw. nach dem Starten oder dem Beenden eines Auftrags etwas durchgeführt werden oder der Benutzer kann aufgefordert werden, etwas einzugeben. Dies erlaubt es dann z.B., dass das Gerät dann eine entsprechende Aktion durchführt.

Das SmartUSB-Device fragt beispielsweise vor dem Start und nach dem Beenden eines Fertigungsauftrags den Benutzer. Dazu werden zwei Tasks im Device definiert:

@Override
public List<Task> getTasks() {
    List<Task> tasks = new ArrayList<>();
    tasks.add(new ProductionJobStartTask(this));
    tasks.add(new ProductionJobEndTask(this));
    return tasks;
}

Beim Beenden wird damit dann gefragt, ob die Dateien gespeichert werden sollen oder nicht:

public class ProductionJobEndTask extends AbstractYesNoTask {

    private final DeviceSmartUSB device;

    public ProductionJobEndTask(DeviceSmartUSB deviceSmartUSB){
        this.device = deviceSmartUSB;
    }

    @Override
    public void executeOnYes() {
        device.saveFiles(true);
    }

    @Override
    public void executeOnNo() {
        device.saveFiles(false);
    }

    @Override
    public HookPoint getHookPoint() {
        return HookPoint.beforeProductionJobClose;
    }

    @Override
    public String getQuestion() {
        return "Sollen die Daten jetzt gespeichert werden?";
    }

    @Override
    public String getDescription() {
        return "Die Daten müssen auf das USB-Device gespielt sein!";
    }
}

DeviceStreamDataProvider

Erlaubt dem System sich mit einm Datenstrom zu verbinden. Dies erfordert die Analytics-Engine.

Beispiel

In diesem Beispiel wird ein "SmartEnergy" als Device angelegt. Das konkrete Device ist dann "DeviceEnergymeter", dass durch den Aufruf von "createInstance" erzeugt wird. 

@Extension
public class DeviceEnergymeterExtension extends AbstractDeviceExtension<DeviceEnergymeter> {

    public DeviceEnergymeterExtension() {
        super("SmartEnergy", "de.bluebiz.smartenergy");
    }

    @Override
    protected void createTemplate() {
        addParameter(new StringParameterType("Host"));
        addParameter(new LongParameterType("Port", 17750));
        addParameter(new BooleanParameterType("Active", true));
    }


    @Override
    public DeviceEnergymeter createInstance(ParameterValueContainer parameters) {
        String host = parameters.getParameterValue("host");
        Long port = parameters.getParameterValue("port");
        boolean active = parameters.getParameterValue("active");
        DeviceEnergymeter deviceEnergymeter = new DeviceEnergymeter(host, port.intValue(), active);

        return deviceEnergymeter;
    }
}

Das Device sieht dann entsprechend so aus:

public class DeviceEnergymeter extends DeviceInstance implements DeviceConnector {
	
	private String host;
	private int port;
	private boolean active;
	private boolean connected = false;

	public DeviceEnergymeter(String host, int port, boolean active) {
    	this.host = host;
	    this.port = port;
	    this.active = active;
	}
 
	@Override
	public boolean connect() {
		//... create a stream and connect to this.host on port this.port
		this.connected = true;
	}
 
	@Override
	public boolean disconnect() {
		// disconnect the stream
		this.connected = false;
	}
 
	@Override
	public boolean isConnected() {
		return this.connected;
	}

	@Override
	public void deviceSettingsChanged(ParameterValueContainer parameters) {
    	String host = parameters.getParameterValue("host");
	    Long port = parameters.getParameterValue("port");
	    boolean active = parameters.getParameterValue("active");
	    disconnect();
    	this.host = host;
	    this.active = active;
	    this.port = port.intValue();
    	connect();
	}

    
}