Java ist die mit am häufigsten verwendete Programmiersprache weltweit. Auch auf dem Raspberry Pi läuft Java problemlos. Mittels einer Erweiterung können wir ebenfalls die GPIOs steuern und auslesen. Dazu nutzen wir noch Spring-Boot. So ist es uns möglich, mit sehr wenig Aufwand einen kompletten Webserver mit API’s zu erstellen, der unseren Pi quasi fernsteuert.
Wir werden in diesem Tutorial zunächst Java 11 mit Maven einrichten. Anschließend schauen wir uns die IDE’s Visual Studio Code sowie IntelliJ IDEA an. Danach erstellen wir zunächst eine einfache Web-API, welche wir anschließend so erweitern, dass wir über den Webserver auch GPIOs steuern können. Dafür haben wir einen kleinen Testaufbau vorbereitet.
Zubehör
Um dem Tutorial folgen zu können, brauchen wir folgendes Zubehör:
- einen Raspberry Pi mit mindestens 4GB RAM
- 32GB+ SD Karte
- eine LED
- 330Ω Vorwiderstände
- optional: Breadboard
Dieser Kurz ersetzt keine grundlegenden Java oder Spring Boot Kenntnisse. Daher eignet sich ein Online Java Kurs zum Anfang sehr gut, sowie der Einstieg in Spring Boot.
Der Raspberry Pi sollte bereits mit Raspbian OS laufen, welches wir einfach auf die SD-Karte flashen können. Falls du am Raspberry Pi remote arbeiten willst, kannst du eine Remotedesktopverbindung aufbauen.
Aufbau
Um GPIOs schalten zu können bzw. auszulesen, erstellen wir einen kleinen Testaufbau. Du kannst aber im Prinzip jeden anderen GPIO nehmen. Dazu passt du später einfach den Code mit den GPIO Nummern an.
Zunächst einmal erstellen wir eine folgende Schaltung auf unseren Breadboard:
An GPIO 17 wird das längere Ende einer LED angeschlossen. Das andere Ende kommt über einen 330 Ω Widerstand an GND (Pin 6). Den Taster schließen wir an 3.3V (Pin 1 oder Pin 17) sowie GPIO 22 an. Welche Richtung ist dabei egal.
Auf dem Raspberry Pi Java 11 installieren
Fangen wir mit der Installation von Java 11 und Maven an, die nicht auf allen Betriebssystemen vorinstalliert sind. Dazu updaten wir vorher die Paketquellen. Öffne ein Terminal (oder logge dich per SSH ein) und gib folgendes ein:
sudo apt update sudo apt install default-jdk maven --yes
Danach prüfen wir, ob Java richtig installiert wurde und ob es auch Version 11 ist:
java -version
Hier sollte so etwas stehen wie:
openjdk version "11.0.13" 2021-10-19 OpenJDK Runtime Environment (build 11.0.13+8-post-Raspbian-1deb11u1) OpenJDK Server VM (build 11.0.13+8-post-Raspbian-1deb11u1, mixed mode)
Die pigpio Bibliothek ist auf den neueren Raspberry Pi OS Versionen bereits enthalten und muss nicht manuell installiert werden.
Optional: Visual Studio Code für Java nutzen
Um unsere Anwendung zu bearbeiten, können wir prinzipiell jeden Editor nehmen. Eine IDE vereinfacht allerdings viele Aufgaben. Die Installation von VS Code ist denkbar einfach. Nach der Installation öffnen wir auf der linken Seite den Extensions Tab und suchen nach „Extensions Pack for Java„:
Das Java Extension Pack enthält einige gebündelte Erweiterungen, die für die Java Entwicklung nützlich sind. Microsoft empfiehlt außerdem noch das Spring Boot Extension Pack.
Gehe anschließend zurück in den Explorer Tab. Hier werden wir gleich unser Projekt öffnen.
Optional: IntelliJ IDE verwenden
Neben Visual Studio ist IntelliJ IDEA die beliebteste und beste IDE für Java Anwendungen. In der Community Edition kostet sie zudem nichts. Zudem gibt es IntelliJ sowohl für Windows, als auch für Mac und Linux. Daher können wir IntelliJ auch auf dem Raspberry Pi installieren und benutzen. Allerdings ist die Leistung nicht besonders gut, da IntelliJ IDEA relativ viele Ressourcen verbraucht. Daher empfehle ich einen anderen Editor auf dem Raspberry Pi.
Falls du dennoch IntelliJ nutzen willst, öffne die Website auf dem Raspberry Pi und lade das Community-Paket herunter: https://www.jetbrains.com/idea/download/
Das heruntergeladene Archiv (.tag.gz) entpacken wir (2x Rechtsklick -> Extract Here, alternativ mit tar -xvzf
) und öffnen den extrahierten Ordner. Darin ist ein Ordner mit dem Namen bin
, in dem sich die idea.sh
Datei befindet. Diese öffnen wir per Doppelklick, wodurch sich IntelliJ öffnet. Nachdem du die AGB akzeptierst hast, dauert es einen Moment, bis sich die IDE öffnet. Danach kannst du ein neues Projekt starten oder ein existierendes Projekt importieren. Damit fahren wir fort.
Tipp: Sollte sich nichts, hilft es, die Anwendung per Terminal zu starten und die Fehlermeldung anzusehen. Bei „Out of Memory“ Fehlern, hilft unter Umständen bereits ein Reboot des Raspberry Pi’s. Alternativ kann auch der verfügbare RAM Speicher für die JVM erhöht werden.
Erstes Java Spring Boot Projekt erstellen
Wir können unser Projekt einerseits von Grund auf aufbauen, was etwas mehr Aufwand ist. Oder wir nutzen den Spring Initializr, der uns ein fertiges Beispielprojekt erstellt, welches wir dann anpassen können. Gehe dazu am Raspberry Pi auf https://start.spring.io/
Hier geben wir dem Maven-Projekt einen Namen und stellen die Version etc. ein. Hier ein Beispiel:
Ein Klick auf Generate wird eine demo.zip herunterladen. Entpacke die Datei z.B. in das Home-Verzeichnis. Anschließend können wir den Ordner in unserer IDE auswählen und den Projektordner öffnen (Trust Project).
Zunächst führen wir ein maven compile
aus (unten links in VS Code):
Nun können wir die Anwendung auch bereits starten. Per Rechtsklick auf die DemoApplication.java Datei -> Run Java startet das Projekt. Allerdings macht das Programm noch nicht viel. Im Log sehen wir aber, dass die Spring Boot Anwendung erfolgreich gestartet ist:
[INFO] Attaching agents: [] . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.6.2) ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 17.952 s
Alternativ kannst du über den Run-Tab eine launch.json
Datei erstellen und dort deine Konfiguration und Debugging-Einstellungen hinterlegen.
Viel macht die Java Anwendung aber bisher nicht. Das werden wir in den nächsten Schritten ändern.
Java Anwendung am Raspberry Pi per Kommandozeile starten
Solltest du keine IDE verwenden oder aus anderen Gründen das Terminal bevorzugen, kannst du die Anwendungen auch so kompilieren. Dazu kannst du im Projekt auch folgendes zum Installieren der Maven Pakete und starten der Anwendung aufrufen:
mvn compile mvn spring-boot:run
Falls deine Anwendung später vollständig ist, kannst du auch eine .jar
Datei daraus erstellen. Diese befindet sich anschließend im target
Ordner,
mvn package
Diese kann dann mittels java -jar
gestartet werden.
Projekt kompilieren und als Webserver API nutzen
Wir fangen damit an, einen öffentlichen REST Endpunkt zu erstellen. Bevor wir aber eine Datei erstellen und die Anwendung starten können, fehlen uns noch Abhängigkeiten. Um diese zu installieren, öffnen wir die pom.xml
Datei und fügen innerhalb der <dependencies> ... </dependencies>
Folgendes am Ende hinzu:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
Anschließend müssen wir diese Abhängigkeit noch importieren. Dies geht wieder in der Sidebar unter Maven -> install.
Jetzt fügen wir unserer Raspberry Pi Java Anwendung einen Controller hinzu. Erstelle einen neuen Ordner controller
und darin eine Datei mit dem Namen GpioController.java
Die Datei bekommt folgenden Inhalt:
package com.example.demo.controller; import org.springframework.web.bind.annotation.*; @RestController public class GpioController { @GetMapping("/read/{number}") public Integer readGPIO(@PathVariable Integer number){ return number; } }
Nun kannst du die DemoApplication.java
Datei wieder ausführen. In der Konsole siehst du jetzt die Logs, allerdings läuft die Anwendung weiter. Denn nun wartet unser Server auf eingehende Verbindungen. Öffne den Browser auf dem Raspberry Pi und rufe folgende URL auf:
http://localhost:8080/read/25
Die Zahl 25 kannst du natürlich durch eine beliebige Nummer ersetzen. Als Ergebnis bekommen wir unsere Zahl angezeigt.
Übrigens: Wenn du den Standardport (8080) ändern willst, kannst du dies in der resources/application.properties
Datei: server.port=8081
GPIOs per Java Code am Raspberry Pi steuern
Nun aber zum eigentlich interessanten Teil: Wir wollen die GPIO Pins des Raspberry Pi’s steuern. Dazu brauchen wir eine externe Bibliothek. Wir nutzen hierfür Pi4J. Die Version v2 ist mit Java 11 und kann als Maven Dependency eingebunden werden.
Dazu bearbeiten wir wieder die pom.xml
und ändern sie wie folgt. Anschließend führen wir noch mvn clean install
aus.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> <pi4j.version>2.1.1</pi4j.version> <!-- BUILD PLUGIN VERSIONS --> <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version> <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- include Pi4J Core --> <dependency> <groupId>com.pi4j</groupId> <artifactId>pi4j-core</artifactId> <version>${pi4j.version}</version> </dependency> <!-- include Pi4J Plugins (Platforms and I/O Providers) --> <dependency> <groupId>com.pi4j</groupId> <artifactId>pi4j-plugin-raspberrypi</artifactId> <version>${pi4j.version}</version> </dependency> <dependency> <groupId>com.pi4j</groupId> <artifactId>pi4j-plugin-pigpio</artifactId> <version>${pi4j.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <!-- JAVA COMPILER --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler-plugin.version}</version> <configuration> <release>${java.version}</release> <showDeprecation>true</showDeprecation> <showWarnings>true</showWarnings> <verbose>false</verbose> </configuration> </plugin> <!-- DEFAULT JAR EXECUTABLE CLASS --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>${exec-maven-plugin.version}</version> <executions> <execution> <goals> <goal>java</goal> </goals> </execution> </executions> <configuration> <executable>java</executable> <arguments> <argument>--module-path</argument> <argument>${project.build.directory}/distribution</argument> <argument>--module</argument> <argument>com.pi4j.example/com.pi4j.example.MinimalExample</argument> </arguments> </configuration> </plugin> <!-- BUILD THE FINAL JAR FILE IN THE /target/distribution PATH --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.1.2</version> <configuration> <outputDirectory>${project.build.directory}/distribution</outputDirectory> </configuration> </plugin> <!-- COPY ANY RUNTIME SCRIPTS TO THE /target/distribution PATH --> <plugin> <artifactId>maven-antrun-plugin</artifactId> <version>1.8</version> <executions> <execution> <id>copy</id> <phase>package</phase> <configuration> <target> <!-- <copy todir="${project.build.directory}/distribution" overwrite="true" flatten="true"> <fileset dir="assets" includes="*.sh" ></fileset> </copy> --> <chmod dir="${project.build.directory}/distribution" perm="ugo+rx" includes="**/*.sh"/> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> <!-- DOWNLOAD RUNTIME DEPENDENCIES --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy-dependencies</id> <phase>process-sources</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/distribution</outputDirectory> <includeScope>runtime</includeScope> <excludeTransitive>false</excludeTransitive> <overWriteReleases>false</overWriteReleases> <overWriteSnapshots>true</overWriteSnapshots> <overWriteIfNewer>true</overWriteIfNewer> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> |
Für den Start benötigen wir Root-Rechte, was behoben werden soll. Daher funktioniert der Aufruf über das VS Code UI nicht und wir müssen die Anwendung per Terminal starten:
sudo mvn spring-boot:run
Die Beispiele kannst du übrigens hier nachsehen.
Das war’s! Drücke nun den Taster und rufe die URL auf:
http://localhost:8080/read/22
Falls du die LED anschalten willst, so ist das die URL:
http://localhost:8080/set/17/true
Und zum Ausschalten:
http://localhost:8080/set/17/false
Fazit und Alternativen
Java mit Spring Boot ist einer einfache und starke Methode um API’s zu erstellen. Da wir Java Anwendungen auch auf dem Raspberry Pi laufen lassen können, liegt es nahe, dass wir auch die GPIO’s steuern wollen. Das ist mittels Pi4J möglich und funktioniert auch sehr gut. Allerdings gibt es definitiv einfachere und schlankere Möglichkeiten ein Webinterface für die Raspberry Pi Pins bereitzustellen. Hier bieten sich z.B. Python (mit FastAPI) oder auch Node.JS an. Welche Programmiersprache man bevorzugt liegt natürlich beim Anwender.
Persönlich entwickle ich lieber an einem PC und schiebe dann die JAR Datei auf den Pi, aber das ist Geschmackssache. In diesem Fall wird es am PC auch schwierig, sobald wir die GPIOs testen möchten.