Application Framework

Grundlagen

Um ein möglichst einfaches Arbeiten mit diesem Projekt zu gewährleisten, wurde ein einfaches Application Framework definiert. Dieses besteht aus einem regulären Java Interface und somit kann schon mit wenigen Zeilen Code eine neue Applikation mit eigenem Code gebaut werden. An jede Applikation wird hierbei jeweils der Pi4J Context übergeben, mit welchem alle Komponenten des CrowPi angesteuert werden können.

Starten einer Applikation

Der integrierte Launcher kann zu jeder Zeit mit Maven gestartet werden. Falls der Code direkt auf dem Raspberry Pi zur Verfügung steht, kann zum Beispiel mit folgenden Befehlen eine Applikation gestartet werden:

# Führt den Launcher ohne Angabe einer Applikation aus, worauf ein Auswahlmenü erscheint.
# Nach Selektion der gewünschten Applikation wird diese schliesslich gestartet.
mvn install

# Führt direkt eine bestimmte Applikation mit dem Launcher aus ohne Umweg über das Auswahlmenü.
# Im Beispiel wird direkt die "BuzzerApp" gestartet.
mvn install -Dcrowpi.launcher.args=BuzzerApp

Neue Applikation anlegen

Um eine neue Applikation anzulegen, welche anschliessend über den integrierten Launcher gestartet werden kann, sind nur wenige
Schritte erforderlich. Die nachfolgende Anleitung führt Schritt für Schritt zur ersten eigenen Applikation.

Zuerst muss eine Java-Klasse unterhalb von src/main/java/com/pi4j/crowpi/applications erstellt werden mit einem beliebigen Namen, welche das Interface Application implementiert. Zum Beispiel könnte diese Klasse ExampleApp heissen und folgenden Code enthalten:

Pfad zum Codebeispiel: src/main/java/com/pi4j/crowpi/applications/ExampleApp.java
Auf GitHub ansehen
package com.pi4j.crowpi.applications;

import com.pi4j.context.Context;
import com.pi4j.crowpi.Application;

public class ExampleApp implements Application {
    @Override
    public void execute(Context pi4j) {
        System.out.println("CrowPi with Pi4J rocks!");
    }
}

Anschliessend muss die Applikation nur noch in der Klasse com.pi4j.crowpi.Launcher zur Liste APPLICATIONS hinzugefügt werden. Die Datei ist unter src/main/java/com/pi4j/crowpi/Launcher.java aufzufinden und muss an dieser Stelle erweitert werden:

public final class Launcher implements Runnable {
    // ...
    private static final List<Application> APPLICATIONS = new ArrayList<>(Arrays.asList(
        new ExampleApp(),   // hier wird die neue Applikation eingefügt
        new BuzzerApp()
    ));
    // ...
}

Nun kann diese neue Applikation beliebig erweitert werden, indem weitere Codes innerhalb der execute() Methode hinzugefügt werden. Die Applikation kann jederzeit durch Starten des Launchers getestet werden und erscheint bei fehlender Angabe der gewünschten Applikation nun dort auch automatisch in der Auswahlliste.

Optional ist es auch möglich, den Namen oder die Beschreibung der Applikation selber anzupassen. Es ist hierbei wichtig, dass der Name unter allen eingehängten Applikationen jeweils eindeutig ist. Um diese Änderungen durchzuführen, können diese Methoden in der eigenen Applikationsklasse verwendet werden:

public class ExampleApp implements Application {
    // ...
    @Override
    public String getName() {
        return "CoolApp";
    }

    @Override
    public String getDescription() {
        return "Meine coole Applikation";
    }
    // ...
}

Der Name entspricht hierbei auch dem Parameter, der an den Launcher übergeben werden muss, um die Applikation direkt zu starten. Im Normalfall ist es aber aufgrund potenzieller Namenskonflikte nicht empfohlen, diesen zu überschreiben.

Das Interface

Zur Vollständigkeit ist hier noch das komplette Application Interface eingebunden. Dieses besteht aus exakt drei Methoden, wobei hiervon nur execute() implementiert werden muss, da die anderen Methoden bereits über eine Standardimplementation verfügen.

Pfad zum Codebeispiel: src/main/java/com/pi4j/crowpi/Application.java
Auf GitHub ansehen
package com.pi4j.crowpi;

import com.pi4j.context.Context;

/**
 * This interface should be implemented by each CrowPi example / application
 */
public interface Application {
    /**
     * Represents the main application entrypoint called by the launcher.
     * This should execute whatever the application is supposed to do.
     *
     * @param pi4j Pi4J context
     */
    void execute(Context pi4j);

    /**
     * Returns a unique name which is used to determine how the application can be called.
     * This uses the simple class name by default, so that the application has the same name as its class.
     *
     * @return Unique application name
     */
    default String getName() {
        return this.getClass().getSimpleName();
    }

    /**
     * Returns a human-readable description what this application is doing.
     * This returns a short explanation together with the class FQDN by default.
     *
     * @return Human-readable application description
     */
    default String getDescription() {
        return this.getClass().getName();
    }

    /**
     * Utility function to sleep for the specified amount of milliseconds.
     * An {@link InterruptedException} will be catched and ignored while setting the interrupt flag again.
     *
     * @param milliseconds Time in milliseconds to sleep
     */
    default void sleep(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}