Die Betriebssystem-Version Raspberry Pi OS Full (32-bit) enthält bereits das Java Development Kit (JDK) in der Version 11. Um Java-Anwendungen zu entwickeln, hilft uns jedoch eine IDE dabei, Anwendungen zu schreiben, die einfach zu warten sind. Wie im vorherigen Artikel [1] beschrieben, kann Visual Studio Code auf dem Raspberry Pi verwendet werden. Alternativ können Anwendungen in Visual Studio Code auch auf einem PC entwickelt und dann auf dem Raspberry Pi kompiliert und ausgeführt werden.

Für diesen Artikel werden wir den Code direkt auf dem Raspberry Pi schreiben. Dazu benötigen wir einige zusätzliche Tools, also installieren wir diese zunächst.

Maven

Wir werden Maven verwenden, um die Anwendung auf unserem Raspberry Pi zu erstellen. Maven kompiliert den Code zusammen mit den erforderlichen Abhängigkeiten in eine einzige JAR-Datei. Dies ist dank der Konfigurationsdatei pom.xml möglich, die sich im Stammverzeichnis des Projekts befindet.

Maven wird mit einem einzigen Befehl installiert. Danach überprüfen wir die Installation, indem wir die Version wie folgt abfragen:

$ sudo apt install maven
$ mvn -v
Apache Maven 3.6.0
Maven home: /usr/share/maven

Pi4J

Um die GPIOs und verschiedene daran angeschlossene elektronischen Komponenten zu steuern, verwenden wir die Pi4J-Bibliothek, die eine Brücke zwischen unserem Java-Code und den GPIO-Pins (GPIO = General Purpose Input/Output) des Raspberry Pi schlägt.

Um die volle Unterstützung der Pi4J-Bibliothek auf dem Raspberry Pi zu erhalten, müssen wir eine zusätzliche Software installieren. Auch dazu brauchen wir nur einen einzigen Befehl:

$ curl -sSL https://pi4j.com/install | sudo bash

Update von WiringPi

Ein letzter Schritt der Vorbereitung ist erforderlich. Wenn Sie einen Raspberry Pi◦4 verwenden, müssen Sie die von Pi4J verwendete native Bibliothek WiringPi zur Ansteuerung der GPIOs aktualisieren. Da sich die Architektur des System-on-Chip (SoC) mit der Version 4 geändert hat, wird eine neue Version von WiringPi benötigt. Leider wurde dieses Projekt im letzten Jahr „deprecated“, aber dank der Open-Source-Community ist eine inoffizielle Version verfügbar, die durch ein von Pi4J bereitgestelltes Skript installiert werden kann. Führen Sie dazu den Befehl aus:

sudo pi4j -wiringpi

Der Befehl bezieht das Projekt von GitHub, kompiliert und installiert es auf Ihrem Raspberry Pi in einem Rutsch. Wenn Sie die Version abfragen, werden Sie sehen, dass sie von der Standardversion 2.50 auf 2.60 hochgestuft wurde:

$ gpio -v
gpio version: 2.50
$ sudo pi4j –wiringpi
$ pi4j -v
--------------------------------------------

              THE Pi4J PROJECT
--------------------------------------------

  PI4J.VERSION     : 1.3
  PI4J.TIMESTAMP   : 2021-01-28 04:14:07
----------------------------------------

  WIRINGPI.PATH : /usr/lib/libwiringPi.so /usr/local/lib/libwiringPi.so
  WIRINGPI.VERSION : 2.60
--------------------------------------------

Die Applikation

Der vollständige Code dieser Anwendung ist im GitHub-Repository dieses Artikels [2] im Ordner elektor/2106 verfügbar. Dieses Projekt ist eine Proof-of-Concept-Anwendung, die die GPIOs über einen REST-Webdienst steuert. Es verwendet das Spring-Framework, eine Software, die viele Werkzeuge zum Erstellen leistungsfähiger Anwendungen mit minimalem Code bietet (Bild 1).

Java on the Raspberry Pi
Bild 1. Überblick über die Anwendung, die den Spring-REST-Service und die Pi4J-Bibliothek verwendet.

Der Prozess zum Erstellen der verschiedenen Dateien, aus denen dieses Projekt besteht, wird im Folgenden beschrieben. Wenn dies nicht funktioniert, sollte aber der Repository-Code out-of-the-box funktionieren.

Das fertige Projekt wird wie folgt von GitHub heruntergeladen:

pi@raspberrypi:~ $ git clone https://github.com/FDelporte/elektor
Cloning into 'elektor'...
remote: Enumerating objects: 34, done.
remote: Counting objects: 100% (34/34), done.
remote: Compressing objects: 100% (24/24), done.
remote: Total 34 (delta 2), reused 34 (delta 2), pack-reused 0
Unpacking objects: 100% (34/34), done.
pi@raspberrypi:~ $ cd elektor/2106
pi@raspberrypi:~/elektor/2106 $ ls -l
total 8
-rw-r--r-- 1 pi pi 1720 Feb 15 14:23 pom.xml
drwxr-xr-x 3 pi pi 4096 Feb 15 14:23 src

Was sind Spring und seine Werkzeuge?

Spring ist ein Framework, das die Entwicklung von (Business-) Java-Anwendungen vereinfacht und beschleunigt. Spring Boot ist eine Schicht, die auf Spring aufsetzt und „fertige“ Pakete bereitstellt, die es ermöglichen, eigenständige Spring-basierte Anwendungen zu erstellen, die man „einfach ausführen“ kann. Dies wird durch ein Prinzip „Convention over Convention“ erreicht, was bedeutet, dass standardmäßig alles nach einer vordefinierten Konvention funktioniert. Wenn Sie etwas anders machen wollen, können Sie Ihren eigenen Weg konfigurieren.

Als wichtigste Fähigkeiten nennt die Spring-Boot-Website [3]:

  • Einfache Erstellung von eigenständigen Spring-Anwendungen.
  • Ermöglicht die Einbettung eines Webservers in Ihre Anwendung (Tomcat, Jetty oder Undertow).
  • Stellt „Starter“-Abhängigkeiten zur Verfügung, um Ihre Build-Konfiguration zu vereinfachen.
  • Konfiguriert Spring und Bibliotheken von Drittanbietern automatisch, wann immer dies möglich ist.
  • Bietet produktionsreife Funktionen wie Metrics, Health Checks und externalisierte Konfiguration.
  • Keine Notwendigkeit für Code-Generierung oder XML-Konfiguration.

Schließlich gibt es noch Spring Initializr [4], ein Online-Tool zur schnellen Erstellung einer Starter-Anwendung, die alle erforderlichen Spring-Boot-Pakete enthält.

Erste Schritte

Um dieses Projekt von Grund auf zu erstellen, verwenden wir zunächst Spring Initializr, ein webbasiertes Konfigurationsformular zur Erstellung eines Einstiegspaket. Folgen Sie dem Link in [4] und geben Sie im Formular die in Bild 2 gezeigten Informationen an.
 
Configuration settings
Bild 2. Erforderliche Konfigurationseinstellungen für Spring Initializr.

Achten Sie darauf, dass Sie auf der rechten Seite auch die Schaltfläche Dependencies anklicken. In dem sich öffnenden Fenster müssen wir die Abhängigkeit Spring Web hinzufügen, die sich über das Suchfeld schnell finden lässt. Mit einem Klick auf diesen Eintrag wird die Abhängigkeit dem Projekt hinzugefügt. Sollte versehentlich eine unerwünschte Abhängigkeit hinzugefügt worden sein, kann diese durch einen Klick auf den roten Button (ganz rechts) wieder entfernt werden.

Das Hinzufügen der Abhängigkeit Spring Web ermöglicht es, eine REST-Anwendung [5] zu erstellen, die es ermöglicht, uns über Webseiten im Browser mit der Anwendung zu verbinden.

Ein Klick auf die Schaltfläche Generate liefert eine ZIP-Datei mit einem fertigen Maven-Projekt. Nachdem es in ein geeignetes Verzeichnis entpackt wurde, kann es in Visual Studio Code [6] sowohl auf dem Raspberry Pi als auch auf einem PC geöffnet werden. Verwenden Sie einfach File -> Open folder… und wählen Sie den entpackten Ordner. Als nächstes suchen Sie die Datei JavaSpringRestApplication.java (unter src/main/java). Im Kontextmenü dieses Dateinamens wählen Sie die Option Run, so dass die Anwendung gestartet wird (Bild 3).

Project in  Visual Code Studio.
Bild 3. Ausführbares Projekt in Visual Code Studio.

Installation von Visual Studio Code nicht über die erforderliche Java-Unterstützung verfügt, erscheint ein Popup-Fenster, das zur Installation auffordert.

Im Terminal-Fenster erhalten wir die Ausgabe in Listing◦1 (hier ohne Zeitmarken). Was sagt uns diese Ausgabe?

Starter app output
Listing 1: Output of a Starter Application.
  • Die JVM (Java Virtual Machine) ist sieben Sekunden lang gelaufen, wovon 4,5◦s zum Starten der Anwendung benötigt wurden.
  • Tomcat (der Webserver) ist in die Anwendung eingebettet und läuft auf Port 8080.

Öffnen wir also einen Browser und gehen auf http://localhost:8080/ (Bild 4).
Default error webpage
Bild 4. Die Standard-Fehlerwebseite beweist, dass der Webserver funktionsfähig ist.

Große Enttäuschung! Wir erhalten eine Fehlerseite. Doch das liegt nur daran, dass wir noch nichts erstellt haben, was auf dieser Seite angezeigt werden könnte! Gleichzeitig beweist diese Fehlerseite aber, dass unsere Anwendung funktioniert und als Webserver arbeitet. Sie weiß nur noch nicht, was sie uns mitteilen soll.

Wir bauen unsere eigene Anwendung

Wir werden nun dieses Spring-Starterpaket um die Funktionalität erweitern, die wir in unserer Anwendung haben wollen, nämlich die Steuerung der GPIOs über Java-Code. Dazu müssen wir die Pi4J-Bibliothek in unser Projekt einbinden. Da wir den vollen Satz an Java-Methoden dieser Bibliothek nutzen können, müssen wir die Hardware nicht selbst ansteuern. Es ist jedoch zu bedenken, dass wir aufgrund der Abhängigkeit dieser Bibliothek vom Raspberry Pi diese Anwendung nicht vollständig auf dem PC ausführen oder testen können. Dazu muss die erzeugte JAR-Datei auf dem Raspberry Pi ausgeführt werden. In den Code-Beispielen, die hier zur Verfügung gestellt werden, ist jede Variable und Methode im JavaDoc-Stil (beginnend mit /**) kommentiert, um ihren Zweck zu erklären.

Hinzufügen der Abhängigkeiten

Dem mit Spring Initializr erstellten Projekt fügen wir die pi4j-core-Abhängigkeit zur pom.xml-Datei hinzu, um auf die pi4j-Methoden zugreifen zu können:

<dependency>
<groupId>com.pi4j</groupId>
<artifactId>pi4j-core</artifactId>
<version>1.3</version>
<scope>compile</scope>
</dependency>

Und wenn wir schon dabei sind, können wir gleich auch die OpenAPI-Abhängigkeit (springdoc-openapi-ui) hinzufügen, die wir später zum Testen der REST-Dienste verwenden:

<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.1</version>
</dependency>

Hinzufügen eines Information-REST-Controllers

Das erste, was wir mit dieser Anwendung zeigen werden, sind die von der Pi4J-Bibliothek bereitgestellten Informationen über unseren Raspberry Pi. Wir erstellen zunächst ein Paket controller mit einer Datei InfoRestController.java. In Visual Studio Code klicken Sie einfach mit der rechten Maustaste auf den Eintrag java\be\webtechie\javaspringrestgpio und wählen New Folder. Sie taufen den neuen Ordner controller, klicken mit der rechten Maustaste auf den Ordner und wählen New File. Nennen Sie die Datei InfoRestController.java.

In den Material zu dem Artíkel finden Sie den vollständigen Code, aber Listing 2 zeigt schon einmal einen kurzen Ausschnitt. Jede Methode ist ein REST-Mapping, das einen bestimmten Satz von Schlüssel-Wert-Paaren mit Informationen über den Raspberry Pi zurückgibt.

InfoRestController.java file.
Listing 2: Section of the InfoRestController.java file.

Hinzufügen des GPIO-Managers

Bevor wir den GPIO-REST-Controller erstellen können, müssen wir eine Datei namens GpioManager.java hinzufügen, um die Pi4J-Aufrufe zu verarbeiten. Diese wird in einem manager-Paket abgelegt, das wie zuvor beschieben als New Folder und New File angelegt wurde. Dieser Manager soll die initialisierten GPIO-Pins speichern und die Pi4J-Methoden aufrufen, die mit den GPIOs interagieren. Auch hier ist ein kurzer Ausschnitt des Codes in Listing◦3 zu sehen, während der vollständige Code für diese Klasse im Repository zu finden ist. In dieser Klasse wird @Service verwendet, das das Spring-Framework anweist, eine einzelne Instanz dieses Objekts im Speicher zu halten. Damit haben wir jederzeit eine Liste der bereitgestellten GPIOs zur Verfügung.

GpioManager.java file.
Listing 3a: Section of the GpioManager.java file.
Listing 3b for "Java on the Raspberry Pi"
Listing 3b
Listing 3c for "Java on the Raspberry Pi"
Listing 3c

Hinzufügen des GPIO-REST-Controllers

Abschließend fügen wir dem controller-Paket (Ordner) einen GPIO-Controller mit einer REST-Schnittstelle hinzu. Diese Datei heißt GpioRestController.java und stellt die Pi4J-GPIO-Methoden zur Verfügung, die wir in der Klasse GpioManager.java definiert haben. Auch hier ist ein Ausschnitt des Codes in Listing◦4 gezeigt, während der vollständige Code im Repository verfügbar ist.

Listing 4a: Section of the GpioRestController.java file.
Listing 4b for "Java on the Raspberry Pi"
Listing 4b

Ausführen der Anwendung

Dieser Schritt kann sowohl auf dem PC als auch auf dem Raspberry Pi durchgeführt werden. Im ersten Fall ist es am besten, die Anwendung aus Visual Studio Code heraus zu starten, denn es macht die Installation von Maven auf dem PC überflüssig.

Da wir die springdoc-openapi-ui-Abhängigkeit der pom.xml-Datei hinzugefügt haben, stellt die Anwendung eine sehr nützliche Swagger-Webseite zum Testen der REST-Dienste zur Verfügung. Swagger ist ein weiteres Open-Source-Projekt, das eine einfache Webpage-Oberfläche zum Testen unseres Java-Codes generiert, indem es die von uns erstellten Controller automatisch visualisiert.

Es gibt zwei Möglichkeiten, die Anwendung zu starten. In Visual Studio Code kann sie mit Run (Raspberry Pi oder PC) gestartet werden. Eine Alternative für den Raspberry Pi ist es, die Anwendung mit mvn package in eine jar-Datei zu überführen. Ist dies geschehen, wird die Datei wie folgt von der Kommandozeile aus gestartet:

java -jar target/javaspringrestgpio-0.0.1-SNAPSHOT.jar

Öffnen Sie in einem Browser auf dem Raspberry Pi die Swagger-Seite mit http://localhost:8080/swagger-ui.html. Alternativ können Sie auf einem beliebigen PC im gleichen Netzwerk http://<IP_ADDRESS_RASPBERRY_PI>:8080/swagger-ui.html verwenden. Die beiden Controller mit ihren Methoden werden wie in Bild 5 dargestellt.

Bild 5a: Die Swagger-Seite bietet Zugriff auf die Info- und GPIO-REST-Controller-APIs.
Fig 5b for "Java on the Raspberry Pi"
Bild 5b: Die Swagger-Seite bietet Zugriff auf die GPIO-REST-Controller-APIs.

Testen des Information-REST-Controllers

Wir können auf die Schaltflächen der Swagger-Seite klicken und die verfügbaren Optionen ausführen, zum Beispiel im Abschnitt info-rest-controller neben der Methode info/hardware auf GET klicken. Klicken Sie dann auf Try it out und auf Execute, so dass im Abschnitt Response body die Antwort angezeigt wird.

Alle diese Methoden können auch direkt aus dem Browser heraus aufgerufen werden. Hängen Sie einfach den Methodennamen an die URL: Für info/hardware geben Sie einfach http://localhost:8080/info/hardware ein, und für info/java wäre es http://localhost:8080/info/java. Die Daten aus dem Aufruf dieser Methoden werden im JSON-Format angezeigt, wie in Bild 6 zu sehen.

Acquiring JSON data
Bild 6. Die JSON-Daten können direkt durch Anhängen des Methodennamens an die URL abgerufen werden.

Test des GPIO-REST-Controllers mit LED und Taster

Um zu demonstrieren, wie die Anwendung mit den GPIOs interagieren kann, verwenden wir einen sehr einfachen Breadboard-Aufbau wie in Bild 7 gezeigt:

Wiring diagram to connect the switch and LED
Bild 7. Schaltplan zum Anschluss des Schalters und der LED an den Raspberry Pi.
  • LED an GPIO-Pin 15, BCM-Controller Pin 22, WiringPi Nr. 3
  • Taster an GPIO-Pin 18, BCM-Controller Pin 24, WiringPi Nr. 5

Um die angeschlossene LED ansteuern und den Tasterzustand auslesen zu können, müssen wir zunächst die GPIOs initialisieren. Zur Konfiguration des Ausgangs wird die Methode /gpio/provision/digital/output verwendet. Kehren Sie auf die Seite http://localhost:8080/swagger-ui.html zurück, klicken bei dieser Methode auf GET, Try it out und tragen dann 3 in address sowie LED in string ein. Bestätigen Sie die Konfiguration durch Execute (Bild 8 links).

 Initialization of the GPIOs
Bild 8. Initialisierung der GPIOs mit den Methoden /gpio/provision/digital/.

Der Eingang wird mit der Methode /gpio/provision/digital/input konfiguriert. Klicken Sie bei dieser Methode auf GET, Try it out und tragen dann 5 in address sowie Button in string ein. Bestätigen Sie die Konfiguration durch Execute (Bild 8 rechts).

Sobald die GPIOs initialisiert sind, können wir mit der Methode /gpio/provision/list eine Liste der GPIOs erhalten. Verwenden Sie einfach GET, Try it out und Execute oder geben Sie die URL http://localhost:8080/gpio/provision/list direkt im Browser an (Bild 9).

Requesting the GPIO configuration
Bild 9. Abfrage der GPIO-Konfiguration mit der Methode /gpio/provision/list.

Nachdem wir nun überprüft haben, dass die GPIOs einsatzbereit sind, können wir die LED mit der Methode /gpio/digital/toggle ein- und ausschalten, indem wir wiederholt auf die Schaltfläche Execute klicken (Bild◦10).

Toggle the LED
Bild 10. Verwendung der Schaltfläche Execute in der Swagger-Schnittstelle zum Umschalten der LED.

Es gibt eine weitere Methode, die die LED für eine bestimmte Zeit einschalten kann, zum Beispiel für 2s (Bild 11). Die Dauer muss in Millisekunden angegeben werden

The LED can be pulsed
Bild 11. Die LED kann auch für eine bestimmte Dauer gepulst werden.

Die Abfrage des Zustands der Taste kann über die Swagger-Schnittstelle erfolgen, ist aber auch direkt über die URL http://localhost:8080/gpio/state/5 verfügbar. Im Fall von Bild 12 ist die Taste gedrückt und gibt eine 1 zurück.

The URL together with the gpio/state/5 method
Bild 12. Die URL zusammen mit der Methode gpio/state/5 erfasst den Zustand des Button-Eingangs.

Wer rastet, der rostet, wer RESTet, forscht weiter!

In dieser Anwendung wurden nur einige der Pi4J-Methoden als REST-Services gezeigt, um die Möglichkeiten und die Leistungsfähigkeit dieses Ansatzes zu zeigen. Abhängig von dem Projekt, das Sie bauen wollen, können Sie dieses Beispiel erweitern oder überarbeiten, um es Ihren Bedürfnissen auf den Leib zu schneidern.

Die Pi4J-Bibliothek wird derzeit neu geschrieben, um eine noch bessere Unterstützung für den Raspberry Pi 4 und zukünftige Versionen zu bieten. Dadurch wird sie auch mit den neusten Versionen von Java auf den neuesten Stand gebracht. In der Zwischenzeit können Sie mit der aktuellen Version loslegen und Anwendungen erstellen, bei denen Sie die Steuerung der Hardware über eine REST-API integrieren möchten.


Fragen zu diesem Artikel, Java oder Raspberry Pi?
Haben Sie technische Fragen oder Kommentare zu diesem Artikel? Dann kontaktieren Sie den Autor direkt über javaonraspberrypi@webtechie.be oder die Redaktion über editor@elektor.com.

Übersetzung: Rolf Gerstendorf