Written by José Pereda
In this chapter, you will learn about how to get started with a Raspberry Pi device and about the required steps to run Java and JavaFX 11 applications, discussing the ways to do local or remote development and how to do remote deployment.
You will be presented different samples, starting from the very basic Java and JavaFX applications, and finally you will be shown a more complex project that tries to create a homemade in-car navigation system, with the help of a GPS device.
Intro to Raspberry Pi
Raspberry Pi and Arduino are the cornerstones of the Maker movement that has been going on for more than 10 years. But these are also the foundation of the Internet of Things (IoT) that has been taking off for years not only for hobbyists but in many industrial sectors. And they even reach more relevance in the STEAM initiative (for Science, Technology, Engineering, Art, and Mathematics), which targets directly the education of our children.
Our mission is to put the power of computing and digital making into the hands of people all over the world.
As proof of that, the usual distributions for Raspberry Pi come with Scratch, Python, or Java preinstalled. By 2017, in only 6 years, more than 17 million units have been sold, where 5 million of these correspond to the Raspberry Pi 3 Model B, only in 2017.
Whether you are a hobbyist, you work on professional IoT projects, or you have children who want to learn computing, there are many reasons why you should consider doing a very small investment in a Raspberry Pi.
This chapter will give you a brief introduction on getting started with it and programming and running Java and JavaFX applications on this embedded device.
Getting Started with a Raspberry Pi
You can follow www.raspberrypi.org/documentation/ on how to get started.
Initial Kit
There, you will find what components are required, depending on your budget. The following are the minimum requirements to get started and complete the samples of this chapter.
Raspberry Pi
SoC: Broadcom BCM2837B0, Cortex-A53 (ARMv8), 64-bit SoC at 1.4 GHz
GPU: Broadcom Videocore-IV
RAM: 1 GB LPDDR2 SDRAM
Bluetooth: 2.4 GHz and 5 GHz IEEE 802.11.b/g/n/ac wireless LAN, Bluetooth 4.2
Networking: Gigabit Ethernet over USB 2.0
Graphics: H.264 MPEG-4 decode (1080P30); H.264 encode (1080P30); OpenGL ES 1.1,2.0 graphics
General-Purpose Input/Output (GPIO): Extended 40-pin GPIO header
Ports: 4 USB 2.0 ports and full-size HDMI; CSI camera port for connecting a Pi camera; DSI display port for connecting a Pi touchscreen display; 4-pole stereo output and composite video port
PoE: Power-over-Ethernet (PoE) support
Power Adaptor
You may buy it with a complete starting kit or select just the required accessories, including at least a 5 V micro-USB power adaptor supplying at least 2 A and an SD Card.
SD Card
Choose an SD card of 8 or 16 GB. I’ll choose a SanDisk Ultra microSDHC 16 GB Class 10.
There are SD cards with NOOBS preinstalled, but the images can be easily downloaded and installed as well.
Keyboard and mouse are optional. Both will require USB connection.
Monitor
It is a 7″ LCD display which connects to the Raspberry Pi through the DSI connector:
Resolution: The full color display outputs up to 800 × 480 (not that good compared to an HDMI connection) and features a capacitive touch sensing capable of detecting ten fingers.
It requires external power supply (using another micro-USB power supply is more convenient than connecting through the same Pi board).
A good case to mount both Raspberry Pi and display is convenient.
It requires to rotate the display 180° (see later in this chapter).
Install SD
Follow www.raspberrypi.org/documentation/installation/installing-images/README.md.
I’ll choose Raspbian Stretch2 with desktop image from www.raspberrypi.org/downloads/raspbian/. You can choose Lite or any other distribution of course.
Download zip (or the latest version available): http://director.downloads.raspberrypi.org/raspbian/images/raspbian-2018-11-15/2018-11-13-raspbian-stretch.zip.
Unzip the file to get the .img file (it might be over 4 GB so Zip64 format is required).
Write the file into the SD card. You might need an SD card reader. A USB SD card reader is simple and very convenient.
- For Mac: www.raspberrypi.org/documentation/installation/installing-images/mac.md
Plug the card and run on a terminal: diskutil list.
- Identify the disk, and unmount it. For instance, as in Figure 12-1, if the SD card is the disk3, we’ll run
Copy the .img file:
$ sudo dd if=/Users/JosePereda/Downloads/2018-11-13-raspbian-stretch.img of=/dev/rdisk3 bs=1m
It will take a few minutes, depending on the image file size. You can check the progress by sending a SIGINFO signal (press Ctrl-T).
- When finished, unmount the SD card from your Mac and mount it on the Pi.
Download the Win32DiskImager utility from the SourceForge Project page: http://sourceforge.net/projects/win32diskimager/ as an installer file, and run it to install the software.
Run the Win32DiskImager utility from your desktop or menu.
Select the image file you extracted earlier.
In the device box, select the drive letter of the SD card. Be careful to select the correct drive: if you choose the wrong drive, you could destroy the data on your computer's hard disk! If you are using an SD card slot in your computer and can't see the drive in the Win32DiskImager window, try using an external SD adapter.
Click “Write” and wait for the write to complete.
- Exit the imager and eject the SD card.
For Linux: www.raspberrypi.org/documentation/installation/installing-images/linux.md
These are similar to Mac’s instructions. Use lsblk to discover the SDcard, unmount it with umount, and run dd.
Raspberry Pi Configuration
See www.raspberrypi.org/documentation/configuration/.
Raspi-config
See www.raspberrypi.org/documentation/configuration/raspi-config.md.
- Change user password:
The default user on Raspbian is pi with the password raspberry. You can change that here. For convenience, I’ll set the same password: pi, which comes handy. But it is quite the opposite of a secure password, of course.
- Network options:
Hostname is the visible name for this Pi on a network. Change the default raspberrypi, if required, for instance, if you have more than one device.
Wi-Fi: Enter SSID and passphrase. It allows connecting to a wireless network using the Raspberry Pi 3's built-in wireless connectivity and will let you work remotely on it from your usual development machine, using SSH.
- Boot options:
Desktop/CLI: Use this option to change your boot preference to command line or desktop. We’ll choose command line, but desktop can be used too. You can choose autologin.
- Localization options:
Choose from keyboard layout, time zone, locale, and Wi-Fi country code. All options on these menus default to British or GB until you change them.
- Interfacing options:
Camera, if you have one.
SSH: Enable it; this is required to access remotely.
- Advanced options:
Memory split: Set at least 256–512 MB for GPU if you are going to run JavaFX.
Update: Recommended, but it takes a while (only with the Pi connected to the network).
When finished, reboot.
Note that you can find directly the applied settings in the /boot/config.txt file.
to find the available networks at any given location.
to configure your eth0 or wlan0 static IP addresses.
Then, save (Ctrl-O), and exit (Ctrl-X).
Then wait a bit, and disconnect power.
Remote Connection via SSH
Most of the time, we will connect to the Raspberry Pi through SSH to run headlessly (i.e., without a dedicated monitor and keyboard on the Pi), having direct access from our developing machine (including copy/paste and file transfer options between both of them).
SSH is built into Linux distributions and Mac OS. For Windows and mobile devices, third-party SSH clients are available. On Linux and Mac OS, you can use SSH to connect to your Raspberry Pi from a Linux computer, a Mac, or another Raspberry Pi, without installing additional software. On Windows, the most commonly used client is called PuTTY and can be downloaded from greenend.org.uk. See www.raspberrypi.org/documentation/remote-access/ssh/windows.md.
where you need to supply the IP of the device. You can use hostname –I to find this IP if you are already connected to it, but if that’s not the case, you can try to find the device’s IP in the local network using nmap, or a mobile app, like Fing.
Since Mac OS and Linux use Bonjour, both support mDNS. On Windows, you can install Bonjour from here, https://support.apple.com/kb/DL999, for instance.
After you enter the password, you will have access to the Raspberry Pi (Figure 12-4). The first time you will see a security/authenticity warning. Type yes to continue.
Installing Java 11
We are going to install and use Java 11.
Java 11 for ARM
There are a number of options if you want to run Java on your Raspberry Pi. If you want to run a Java 11 distribution, completely based on OpenJDK, with integrated JIT (hotspot), you can use a build from https://adoptopenjdk.net.
Testing Java 11
Sample0
Congratulations on running your first Java 11 application on your brand-new Raspberry Pi! Now that Java has been installed successfully, you can move to the next step: installing JavaFX.
Installing JavaFX 11
JavaFX 11 builds for ARM 32 can be downloaded from https://gluonhq.com/products/javafx. This is 100% the same JavaFX sources that are used on desktop platforms (Windows, Mac OS, Linux), but with specific drivers for ARM and 32 bits. Note the regular JavaFX distribution for Linux won’t work, as it is built for x86_64 with 64 bits.
If you look at the list of files under the lib folder, you will find the jars for the different JavaFX modules, as long as the native libraries for ARM.
Note
While you will find the media and web JavaFX modules, these are not supported yet on ARM. Neither is Swing.
Running JavaFX Applications Locally
We can now try to run a HelloFX sample from https://github.com/modernclientjava/mcj-samples/tree/master/ch12-RaspberryPi/Sample1, which is based on the https://openjfx.io/openjfx-docs/ samples.
Sample1
The javafx-gradle-plugin only works on Desktop, and it defaults to Linux x86_64, so the native libraries are not compatible, as the Pi will require Linux ARM 32.
Sample2 build.gradle file
Running JavaFX Applications Remotely
While these projects are compiled and built locally on the Raspberry Pi, it is quite slower compared to building on your machine, and the lack of IDE or the inconveniences of development over SSH invite to look for a different approach: develop on your regular machine and then deploy and run on the Pi.
On the other hand, development on our machine is way faster, but then we still have the deployment issue: we’ll need to copy the related files of our application to the Raspberry Pi, before we can run on it.
There are a few options to copy the required files, like the classic FTP or even SCP (a command for sending files over SSH). This means you can copy files between computers, either from your Raspberry Pi to your desktop or laptop or the other way around.
While this works, it is a tedious error-prone manual process, and it would be better if we could have this step integrated within our IDE, or we could have a plugin for our build tool.
Let’s examine some options.
Java Remote Platform
NetBeans created a while ago the concept of remote platform. You can define the settings of a JVM on another machine and use an Ant task to deploy and run over SSH on that machine.
This comes very handy of course in the case of the Raspberry Pi.
To install Apache NetBeans 11.1, go to https://netbeans.apache.org/download/nb111/nb111.html and choose the installer for you platform.
Once installed, go to Tools ➤ Java Platforms. Click Add Platform... and select Remote Java Standard Edition.
When the remote platform has been created, make sure you add sudo to the exec prefix, as in Figure 12-9.
Finally, with the Raspberry Pi available, click Test Platform and see that the test is successful. Otherwise, make sure all the fields are correctly set.
Let’s try the remote platform with an example. Follow the instructions here, https://openjfx.io/openjfx-docs/#IDE-NetBeans, to create a new Java application without build tools, or download Sample4 from https://github.com/modernclientjava/mcj-samples/tree/master/ch12-RaspberryPi/Sample4.
First of all, make sure the app runs fine on your machine.
Configure window size based on platform
You will see your app running nicely on the Pi’s display, while you can see the output from the process in the NetBeans output window. And you can even debug the application.
However, this approach has a few problems: it only works on NetBeans, and it is not valid for Maven or Gradle projects.
Gradle SSH Plugin
Another option is the SSH Gradle plugin from https://gradle-ssh-plugin.github.io. It will work on Gradle projects from terminal or any IDE with Gradle support.
Let’s run now this sample, https://github.com/modernclientjava/mcj-samples/tree/master/ch12-RaspberryPi/Sample5, from IntelliJ (or any IDE of your choosing).
Gradle build file for Sample5
Note For convenience, the task sets allowAnyHosts, and host key checking is turned off. It will print a warning message that the process is vulnerable to man-in-the-middle attacks and it is not recommended for production.
With this plugin, hitting Ctrl-C from the terminal just kills the Gradle process, but not the application. To solve this issue, make sure you add an Exit button to the UI.
Working with Dependencies
So far, we have seen very simple use cases that were helpful to getting us started and setting everything properly.
Time now to have a look at a more complex example.
The DIY In-Car Navigation System
The following project is a Proof of Concept of a Do It Yourself homemade in-car navigation system. For that, we are going to install a GPS to the Raspberry Pi. A JavaFX application will display a map, and the GPS readings will be used to center the map in our current location.
Bill of Materials
Raspberry Pi 3 Model B+
7″ display 800 × 480; cage is optional but recommended.
5 V power adaptor for Raspberry Pi and display. Power bank is optional but recommended for field testing.
GPS: Universal Asynchronous Receiver-Transmitter (UART) Serial GPS Neo-7M (micro-USB is optional) (Figure 12-12), for instance, this one: http://wiki.keyestudio.com/index.php/KS0319_keyestudio_GPS_Module.
Four female-female jumper wires for GPIO connection.
Micro-USB: USB adaptor (in case the GPS breakout mounts micro-USB) is optional.
Setup for GPIO
We are going to use the General-Purpose Input/Output (GPIO) pins to get serial readings from the GPS.
Select Interfacing options and now select Serial.
Now you have to select No, to disable the login shell access to serial, and then select Yes to enable the hardware serial port (or UART for Universal Asynchronous Receiver-Transmitter). Accept and reboot your Raspberry Pi.
GPIO Connections
VCC pin connected to pin 2 (power 5 V), red jumper
GND pin connected to pin 6 (ground), yellow jumper
Rx pin connected to pin 8 (TxD UART, GPIO 15), blue jumper
Tx pin connected to pin 10 (RxD UART, GPIO 16), green jumper
Note that a breakout board and pin ribbon cable can be used instead, extending the GPIO pins to a breadboard, where the connection to the GPS can be done more easily.
Required GPS Software
If you are indoors, it is probably that the GPS won’t be able to connect to any satellite, and you won’t receive any value. But you will still get some readings.
NMEA Readings
To find out about all the possible sentences and how to parse them, you can see this link: http://aprs.gids.nl/nmea/.
GPSPosition class
NMEAParser class
GPIO and Java
It is a friendly object-oriented I/O API and implementation libraries for Java Programmers to access the full I/O capabilities of the Raspberry Pi platform. This project abstracts the low-level native integration and interrupt monitoring to enable Java programmers to focus on implementing their application business logic.
Then we can add a listener to it so we can react to any incoming serial events, and we can configure the serial based on the usual settings.
Note that the library only works on the Raspberry Pi, but it can be used and compiled on your machine.
GPSService class
While reading from a serial port, we have to be aware that we have a continuous flow of bytes, so we have to take care of converting them properly to string and taking out each sentence. That’s what the processReading method does, with the help of a single StringBuilder.
Also, notice that this thread runs in the background, so whenever there is a new sentence, we’ll use Platform::runLater to use it with the JavaFX properties, on the JavaFX application thread.
For every sentence, we’ll call the NMEA parser and update the GPSPosition object with the new values.
The UI
Let’s define now the JavaFX interface: we are going to display a map that will be centered into the latitude and longitude coordinates retrieved from the GPS reading.
Gluon Maps
Gluon Maps (https://gluonhq.com/labs/maps/) is an open source JavaFX 11 library that provides a map viewer component, rendering tile-based maps from OpenStreetMap. The project is available here: https://github.com/gluonhq/maps.
We can add a MapView container to the center of our view and use a MapLayer to render our position. On mobile devices with built-in GPS sensor, we could use the Gluon Attach position service, but on the Raspberry Pi (or any desktop machine with a connected GPS sensor), we can use the GPSService listed in the preceding text.
PoiLayer class
Afterburner
Scene Builder
Finally, we’ll use Scene Builder 11.0.0 from https://gluonhq.com/products/scene-builder/ to design the UI with FXML on our machine.
Note that with Afterburner, we will create the following files:
org.modernclients.raspberrypi.gps.view.ui.fxml (Listing 12-11)
org.modernclients.raspberrypi.gps.view.ui.css (Listing 12-12)
org.modernclients.raspberrypi.gps.view.ui.properties (Listing 12-13)
UIView class
ui.fxml file
ui.css file
ui.properties file
UIPresenter class
The GPSPosition and the GPSService objects are injected into the presenter, and the text properties of the different labels are bound to the JavaFX properties. Note that it is important to stop the service when the application is closed. This will close the serial port and release the GPIO controller.
The Application Class
MainApp class
module-info.java descriptor
build.gradle file
The complete project can be found here: https://github.com/modernclientjava/mcj-samples/tree/master/ch12-RaspberryPi/Sample6 .
Deploy and Test
Download the project, build it, and run it, to verify it works on your machine. Even if you don’t have GPS, it should display the UI with a map at a fixed location.
Next Challenge
If you were able to make it work, now the next challenge for you is to get your Raspberry Pi and display powered from a power bank, so you can run the app while moving, either walking or with a vehicle. It will be convenient to use tethering, creating a hotspot with your mobile device so the required maps can be downloaded from OpenStreetMap. You can add the SSID of your device to the wpa_supplicant.conf file as discussed at the beginning of this chapter.
Conclusions
In this chapter, you learned about how to configure a Raspberry Pi 3 Model B+ to work with Java 11 and JavaFX 11. With the help of basic samples, you saw how to run applications locally and how it was more convenient to use SSH and remote deployment while doing the development on your regular desktop machine.
Once the basics for running JavaFX applications were covered, you had the chance to learn about a more complex project involving a GPS sensor connected via GPIO pins, parsing NMEA readings, and using Gluon Scene Builder with the Afterburner framework to create the UI, which included Gluon Maps, to track your location.
While the Raspberry Pi is an embedded device, and it can’t be really compared with your regular machine, the actual Model B+ is a very capable device to run UI applications in places where a desktop machine wouldn’t fit.