Deutsche Beschreibung ist hier.
This repository should not be cloned directly. This is a template project and one should create their own project by using the Use this template
Button.
Use the CrowPi image from Pi4J-Team
- Download CrowPi Image
- Extract the ZIP file
- Use the Raspberry Pi Imager to write the image to an SD-Card
- Start the Raspberry Pi with this SD-Card
The CrowPi image contains all the necessary packages and software for JavaFX/Pi4j applications.
-
Java 17. The CrowPi image uses JDK17, thus the developer computer should use the same. Note for Linux and Mac users: The usage of SDKMAN is recommended for the management of JDKs.
-
Using the latest version is important. Installing via JetBrains Toolbox is recommended. The Ultimate Edition is also recommended.
-
Git. The source code repository is a git repository
-
ssh
. The connection to the Raspberry Pi is done usingssh
. Most computers have SSH preinstalled. -
VNC Viewer. A VNC Viewer allows for comfortable access to the Raspberry Pi's desktop, without the need of physically connecting monitor, keyboard and mouse to the Raspberry Pi.
SDKMAN is an ideal tool for managing JDK versions and other development tools on Linux and MacOS.
Enter the following command in a terminal:
export SDKMAN_DIR="$HOME/sdkman" && curl -s "https://get.sdkman.io" | bash
If SDKMAN has already been installed, it can be updated with the following command:
sdk update
Note: After installing it might be necessary to close and open the terminal for the SDKMAN command sdk
to be accessible.
In a new terminal window, enter the following command:
sdk install java 17.0.1-tem
This installs the JDK in your home directory sdkman/candidates/java
. It can then be used from this directory in IntelliJ.
The following command lists which JDKs are available for installation:
sdk ls java
Enter the following command in a new terminal:
java -version
The resulting output should be similar to the following:
openjdk version "17.0.1" 2021-10-19
OpenJDK Runtime Environment Temurin-17.0.1+12 (build 17.0.1+12)
OpenJDK 64-Bit Server VM Temurin-17.0.1+12 (build 17.0.1+12, mixed mode, sharing)
Should JDK 17.x not be the default, then it can be changed with the following command:
sdk default java 17.0.1-tem
The developer computer and the Raspberry Pi must be on the same WLAN.
A simple solution for this is to create a Hotspot with a smartphone. For instance with these parameters:
- SSID:
Pi4J-Spot
- Password:
MayTheSourceBeWithYou!
The CrowPi image is configured to automatically connect to this Hotspot and shows its IP address in the background image.
Connect your developer PC also to the hotspot Pi4J-Spot
.
Enter the following in a terminal of the developer computer:
ssh pi@<ip.number>
Passwort: 'crowpi'
e.g.:
ssh pi@192.168.183.86
Passwort: 'crowpi'
Using the same IP address a VNC connection to the Raspberry Pi can be made. The VNC client shows a window which gives access to the entire desktop of the Raspberry Pi.
The following shows an example session with the started ExampleApp:
This project uses Apache Maven for building the projects. Building can be done either locally on your developer computer or on the Raspberry Pi.
During a local build, the resulting artifacts are copied to the Raspberry Pi and then started there. Development can be done on the Raspberry Pi, but is not recommended. It is far more comfortable to do development on your local development computer and then run the application on the Raspberry Pi.
To build locally and run on the Raspberry Pi, a few configuration changes are needed.
launcher.class
(required): defines which application to start. Thepom.xml
already contains a lists of candidates, simply uncomment the desired application, commenting out the rest.pi.ipnumber
(optional): The current IP of the Raspberry Pi, e.g.192.168.1.2
, is used for SCP/SSH.
With these changes the application can be started through a Maven command on the Raspberry Pi. A more comfortable method is using IntelliJ run configurations.
Four run configurations are already predefined. Two for starting the project, either locally or remote, and two for debugging the application on the Raspberry Pi.
Run Local
starts the program defined inlauncher.class
on the developer computer. This is used especially for GUI development, thus without access to the sensors and actuators attached to the Raspberry Pi.Run on Pi
starts the program on the Raspberry Pi.Debug on Pi
starts the program on the Raspberry Pi im debug mode.Attach to Pi Debugger
connects IntelliJ on the developer computer with the application already running throughDebug on Pi
.
For Run on Pi
and Debug on Pi
the IP address of the Raspberry Pi must be configured. To configure the IP, open Edit Configurations
.
For both run configurations set pi.ipnumber
under Properties
If the Raspberry Pi is the only device connected to the designated WLAN, then one can use crowpi.local
.
Also change the IP address in Attach to Pi Debugger
under Host
.
Used only to test if the JavaFX libraries are installed correctly. Should not be used as a template for one's own JavaFX applications.
To start:
- Set
launcher.class
inpom.xml
:<launcher.class>com.pi4j.mvc/com.pi4j.setup.HelloFX</launcher.class>
- With
Run local
starts locally on the developer computer - With
Run on Pi
starts remotely on the Raspberry Pi
Once the JavaFX setup has been tested, HelloFX can be deleted.
The two other example applications use an LED and a button. These must be wired as is shown in the following diagram:
The MinimalPi4j application is a Pi4j only application without a GUI. This application is also only used to test the setup and can be deleted after testing.
To start:
- Set
launcher.class
inpom.xml
:<launcher.class>com.pi4j.mvc/com.pi4j.setup.MinimalPi4J</launcher.class>
Run local
does not make sense for this example, as no LEDs or buttons are connected to the local development computer.- With
Run on Pi
starts remotely on the Raspberry Pi
Pressing the button should generate a message in the console.
Once the Pi4J setup has been tested, MinimalPi4J can be deleted.
This application shows the interaction between a JavaFX based Graphical User Interface (GUI) and the Raspberry Pi connected sensors and actuators, the Physical User Interface (PUI).
This application is to be used as a template for one's own applications. This includes the existing test cases.
You should first get to know and understand the example. For your own applications you should then copy the TemplateApp
and modify it for your project, however without violating the rules of the MVC concept, which is described below.
To start:
- Set
launcher.class
inpom.xml
:<launcher.class>com.pi4j.mvc/com.pi4j.mvc.templateapp.AppStarter</launcher.class>
- With
Run local
(or directly from the IDE) starts locally on the development computer. Useful for the GUI development. The PUI is not available on the local computer. The GUI can largely be developed without the need for a Raspberry Pi.- in
AppStarter
a simplePuiEmulator
can be started, so that the interaction between GUI and PUI can also be tested on the local development computer.
- in
- With
Run on Pi
starts remotely on the Raspberry Pi (now including the PUI)
The MVC concept should also be used for applications without a GUI.
When developing PUI only applications, or when adding the GUI later, then one should use the TemplatePUIApp
as template.
To start:
- Set
launcher.class
inpom.xml
:<launcher.class>com.pi4j.mvc/com.pi4j.mvc.templatepuiapp.AppStarter</launcher.class>
Run local
makes no sense for PUI only applications- With
Run on Pi
starts remotely on the Raspberry Pi
To start the application on the Raspberry Pi in debug mode the two run configurations Debug on Pi
and Attach to Pi Debugger
are required.
The sequence of starting the run configurations is critical:
- Start
Debug on Pi
using the Run button - Wait till the console contains the following message:
Listening for transport dt_socket at address: 5005 (Attach debugger)
- Start
Attach to Pi Debugger
using the Debug button - Only now will the GUI be shown on the Raspberry Pi screen
Now one can use the debugger from IntelliJ IDEA, setting breakpoints and stepping through the application.
The classic Model-View-Controller concept contains in addition to the starter class at least 3 more classes. The interaction is clearly defined:
-
Model classes
- contain the complete state which is to be visualized, thus these classes are called Presentation-Model
- are completely separate to the Controller and View classes, i.e. they may not interact with those classes
-
Controller classes
- define the entire functionality, i.e. the so-called actions, in the form of methods
- manage the model classes by definition of the business logic
- have no access to the view classes
-
View classes
- only calls methods on the controller, i.e. triggering actions
- are notified of the model of state changes
- observes the state of the model
- never change the model directly
-
Starter class.
- Is a subclass of
javafx.application.Application
. Instantiates the three other classes and starts the application.
- Is a subclass of
In our case at least two view classes exist:
- GUI class. The Graphical-User-Interface. JavaFX based implementation of the visualisation of the UI on the screen.
- PUI class. The Physical-User-Interface. Pi4J based implementation of the sensors and actors. Uses
Component
classes, as is used in CrowPi-Example.
GUI and PUI are completely separated from each other, i.e a GUI button to turn an LED on has no direct access to the LED component of the PUI. Instead the GUI button triggers a corresponding action in the controller which then sets the on state property in the model. The PUI listening on this state then turns the actual LED on or off.
GUI and PUI work with the same identical controller and thus also the same identical model.
It is important that one understands this concept and then apply the concepts to one's own project. Should you have questions, contact the Pi4j team.
In the MVC concept, every user interaction traverses the exact same cycle:
The view classes, i.e. GUI and PUI, implement the Projector-Pattern published by Prof. Dierk König Projector Pattern.
The basic tasks of the GUI and PUI are the same. When looking at the code, this is visible:
they implement the common interface Projector
and can thus be used in the same way.
Consequences of this design:
- Additional UIs can be added, without having to change existing classes, except for the starter class
- An example for this is the
PuiEmulator
, which can be started when necessary.
- An example for this is the
- This architecture is also useful for
- GUI only applications and
- PUI only applications (see
TemplatePUIApp
).
The base classes, required by the MVC concept, are in the package com.pi4j.mvc.util.mvcbase
. The classes have extensive documentation.
An more advanced example is the MultiControllerApp
. It shows the usage and relevancy of multiple controllers in an application.
For any controller the following is imperative:
- each action is asynchronous and follows the sequence of actions explicitly
- for this each controller uses its own
ConcurrentTaskQueue
- the UI is thus never blocked by an action
- if a UI triggers additional actions when an action is in execution, there this action is stored in the
ConcurrentTaskQueue
and executed after the current action has completed.
For simple applications, a single controller will suffice.
There are situations where actions are to be executed in parallel.
The MultiControllerApp
shows such an example. It should be possible to change the counter, while an LED is blinking.
- With a single controller this would not be accomplishable. The controller would execute the
Decrease-Action
only after theBlink-Action
is complete. - With two controllers this is simple:
LedController
andCounterController
each have aConcurrentTaskQueue
. Actions which concern the LED are thus executed independent of actions which modify the counter. - An
ApplicationController
is implemented to coordinate the other controllers, thus giving the UI only a singly visible API.
To start:
- Set
launcher.class
inpom.xml
:<launcher.class>com.pi4j.mvc/com.pi4j.mvc.multicontrollerapp.AppStarter</launcher.class>
- With
Run local
(or directly from the IDE) starts locally on the development computer- A rudimentary
PuiEmulator
can be started inAppStarter
, to test the interaction of the GUI and PUI.
- A rudimentary
- With
Run on Pi
starts remotely on the Raspberry Pi
Through the clear separation in model, view and controller, testing of large parts of the application can be automated. These tests are usually executed on the local development computer, i.e. not on the Raspberry Pi.
The controller implements the entirety of the base functionality. It should be validated with extensive test cases.
It should be pointed out, that all changes to the model are performed asynchronously, thus validation can only be done after the asynchronous Tasks are completed.
An example can be seen in ExampleControllerTest
.
The model is simply a collection of ObservableValues
and doesn't offer any additional functionality, thus it does not require any additional test cases.
The individual PUI-components can be tested easily using the Pi4J integrated MockPlatform
. These tests can be executed locally on the development computer. A Raspberry Pi is not needed.
Examples for such component tests can be seen in the CrowPi-Tutorial and in the package com.pi4j.mvc.templateapp.view.pui.components
.
The PUI can also be tested quite well with JUnit tests.
It should be pointed out, that the actions are again executed asynchronously.
An example is the ExamplePUITest
.
This repository is licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.