17 | * onUpdate() will be called 120 times per second on a 120hz monitor (provided the CPU/GPU are fast enough),
18 | * but the value of tpf won't be 0.0166(6), it will be 0.00833(3) since tpf = 1 / fps.
19 | * Hence if you take tpf into account in your calculation, the result will be the same regardless of the refresh rate.
20 | *
21 | * For example,
22 | * start x = 0,
23 | * update x += 2 * tpf.
24 | *
25 | * After 1 second (at 60fps), x is ~2, because x = 2 * 0.0167 * 60
26 | * After 1 second (at 120fps), x is also ~2, because x = 2 * 0.00833 * 120
27 | *
28 | * Whilst the actual values may not be identical (they won't be identical even if two machines run at 60fps,
29 | * or even if running two instances of the game on the same machine), they will be very close.
30 | */
31 | @Override
32 | public void onUpdate(double tpf) {
33 | // We want the clouds to move faster than the player
34 | entity.translate(direction.multiply(tpf * 100));
35 | checkForBounds();
36 | }
37 |
38 | private void checkForBounds() {
39 | if (entity.getX() < 0) {
40 | remove();
41 | }
42 | if (entity.getX() >= getAppWidth()) {
43 | remove();
44 | }
45 | if (entity.getY() < 0) {
46 | remove();
47 | }
48 | if (entity.getY() >= getAppHeight()) {
49 | remove();
50 | }
51 | }
52 |
53 | public void remove() {
54 | entity.removeFromWorld();
55 | }
56 | }
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/fxgl-game/src/main/java/be/webtechie/fxgl/component/PlayerComponent.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.fxgl.component;
2 |
3 | import com.almasb.fxgl.entity.SpawnData;
4 | import com.almasb.fxgl.entity.component.Component;
5 | import javafx.geometry.Point2D;
6 |
7 | import static com.almasb.fxgl.dsl.FXGL.*;
8 |
9 | public class PlayerComponent extends Component {
10 |
11 | private static final double ROTATION_CHANGE = 0.5;
12 |
13 | private Point2D direction = new Point2D(1, 1);
14 |
15 | @Override
16 | public void onUpdate(double tpf) {
17 | entity.translate(direction.multiply(tpf * 30));
18 | checkForBounds();
19 | }
20 |
21 | private void checkForBounds() {
22 | if (entity.getX() < 0) {
23 | die();
24 | }
25 | if (entity.getX() >= getAppWidth()) {
26 | die();
27 | }
28 | if (entity.getY() < 0) {
29 | die();
30 | }
31 | if (entity.getY() >= getAppHeight()) {
32 | die();
33 | }
34 | }
35 |
36 | public void shoot() {
37 | spawn("bullet", new SpawnData(
38 | getEntity().getPosition().getX() + 20,
39 | getEntity().getPosition().getY() - 5)
40 | .put("direction", direction));
41 | }
42 |
43 | public void die() {
44 | inc("lives", -1);
45 |
46 | if (geti("lives") <= 0) {
47 | getDialogService().showMessageBox("Game Over",
48 | () -> getGameController().startNewGame());
49 | return;
50 | }
51 |
52 | entity.setPosition(0, 0);
53 | direction = new Point2D(1, 1);
54 | right();
55 | }
56 |
57 | public void up() {
58 | if (direction.getY() > -1) {
59 | direction = new Point2D(direction.getX(), direction.getY() - ROTATION_CHANGE);
60 | }
61 | }
62 |
63 | public void down() {
64 | if (direction.getY() < 1) {
65 | direction = new Point2D(direction.getX(), direction.getY() + ROTATION_CHANGE);
66 | }
67 | }
68 |
69 | public void left() {
70 | if (direction.getX() > -1) {
71 | direction = new Point2D(direction.getX() - ROTATION_CHANGE, direction.getY());
72 | }
73 | }
74 |
75 | public void right() {
76 | if (direction.getX() < 1) {
77 | direction = new Point2D(direction.getX() + ROTATION_CHANGE, direction.getY());
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/fxgl-game/src/main/java/module-info.java:
--------------------------------------------------------------------------------
1 | /*-
2 | * #%L
3 | * **********************************************************************
4 | * ORGANIZATION : Pi4J
5 | * PROJECT : Pi4J :: EXAMPLE :: Sample Code
6 | * FILENAME : module-info.java
7 | *
8 | * This file is part of the Pi4J project. More information about
9 | * this project can be found here: https://pi4j.com/
10 | * **********************************************************************
11 | * %%
12 | * Copyright (C) 2012 - 2020 Pi4J
13 | * %%
14 | * Licensed under the Apache License, Version 2.0 (the "License");
15 | * you may not use this file except in compliance with the License.
16 | * You may obtain a copy of the License at
17 | *
18 | * http://www.apache.org/licenses/LICENSE-2.0
19 | *
20 | * Unless required by applicable law or agreed to in writing, software
21 | * distributed under the License is distributed on an "AS IS" BASIS,
22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 | * See the License for the specific language governing permissions and
24 | * limitations under the License.
25 | * #L%
26 | */
27 | /**
28 | * Use "open module" here so FXGL can access the images in resources.
29 | * For more info see https://github.com/AlmasB/FXGL/wiki/FXGL-11-Migration-Guide#modularity
30 | */
31 | open module be.webtechie.fxgl {
32 | // Pi4J MODULES
33 | requires com.pi4j;
34 | requires com.pi4j.plugin.pigpio;
35 |
36 | // SLF4J MODULES
37 | requires org.slf4j;
38 | requires org.slf4j.simple;
39 | requires com.almasb.fxgl.all;
40 |
41 | uses com.pi4j.extension.Extension;
42 | uses com.pi4j.provider.Provider;
43 |
44 | // allow access to classes in the following namespaces for Pi4J annotation processing
45 | exports be.webtechie.fxgl to com.almasb.fxgl.core;
46 | }
47 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/fxgl-game/src/main/resources/assets/textures/cloud-network.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/fxgl-game/src/main/resources/assets/textures/cloud-network.png
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/fxgl-game/src/main/resources/assets/textures/duke.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/fxgl-game/src/main/resources/assets/textures/duke.png
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/fxgl-game/src/main/resources/assets/textures/sprite_bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/fxgl-game/src/main/resources/assets/textures/sprite_bullet.png
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-digital-input-button/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | be.webtechie
6 | pi4j-digital-input-button
7 | jar
8 | 1.0-SNAPSHOT
9 | Pi4J example: Digital input with button
10 | http://maven.apache.org
11 |
12 |
13 |
14 | junit
15 | junit
16 | 4.13.1
17 | test
18 |
19 |
20 | com.pi4j
21 | pi4j-core
22 | 1.3
23 |
24 |
25 |
26 |
27 |
28 |
29 | org.apache.maven.plugins
30 | maven-compiler-plugin
31 | 3.8.0
32 |
33 | 11
34 |
35 |
36 |
37 |
38 | maven-assembly-plugin
39 | 2.2.1
40 |
41 |
42 | jar-with-dependencies
43 |
44 |
45 |
46 | true
47 | be.webtechie.pi4jgpio.App
48 |
49 |
50 |
51 |
52 |
53 | make-assembly
54 | package
55 |
56 | single
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-digital-input-button/src/main/java/be/webtechie/pi4jgpio/App.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio;
2 |
3 | import com.pi4j.io.gpio.GpioController;
4 | import com.pi4j.io.gpio.GpioFactory;
5 | import com.pi4j.io.gpio.GpioPinDigitalInput;
6 | import com.pi4j.io.gpio.Pin;
7 | import com.pi4j.io.gpio.PinPullResistance;
8 | import com.pi4j.io.gpio.RaspiPin;
9 |
10 | import be.webtechie.pi4jgpio.handler.InputChangeEventListener;
11 |
12 | /**
13 | * Based on https://www.pi4j.com/1.2/usage.html#Read_Pin_State
14 | */
15 | public class App {
16 |
17 | private static final Pin PIN_BUTTON = RaspiPin.GPIO_05; // BCM 24
18 |
19 | /**
20 | * Reference to the listener, so we can read its values after initialization.
21 | */
22 | private static InputChangeEventListener listener;
23 |
24 | public static void main(String[] args) {
25 | System.out.println("Starting input example...");
26 |
27 | try {
28 | // Initialize the GPIO controller
29 | final GpioController gpio = GpioFactory.getInstance();
30 |
31 | // Initialize the input pin with pull down resistor
32 | GpioPinDigitalInput button = gpio.provisionDigitalInputPin(
33 | PIN_BUTTON, "Button", PinPullResistance.PULL_DOWN);
34 |
35 | // Attach an event listener
36 | listener = new InputChangeEventListener();
37 | button.addListener(listener);
38 |
39 | // Loop until the button has been pressed 10 times
40 | while (listener.getNumberOfPresses() < 10) {
41 | Thread.sleep(10);
42 | }
43 |
44 | // Shut down the GPIO controller
45 | gpio.shutdown();
46 |
47 | System.out.println("Done");
48 | } catch (Exception ex) {
49 | System.err.println("Error: " + ex.getMessage());
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-digital-input-button/src/main/java/be/webtechie/pi4jgpio/handler/InputChangeEventListener.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.handler;
2 |
3 | import com.pi4j.io.gpio.PinState;
4 | import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
5 | import com.pi4j.io.gpio.event.GpioPinListenerDigital;
6 |
7 | /**
8 | * Listener which will be called each time the button is pressed.
9 | */
10 | public class InputChangeEventListener implements GpioPinListenerDigital {
11 | private int numberOfPresses = 0;
12 | private long lastPress = System.currentTimeMillis();
13 |
14 | /**
15 | * Event handler
16 | */
17 | @Override
18 | public void handleGpioPinDigitalStateChangeEvent(
19 | GpioPinDigitalStateChangeEvent event) {
20 |
21 | if (event.getState() == PinState.HIGH) {
22 | this.numberOfPresses++;
23 |
24 | long diff = System.currentTimeMillis() - this.lastPress;
25 |
26 | System.out.println("Button pressed for "
27 | + this.numberOfPresses + "th time, diff: "
28 | + diff + "millis");
29 |
30 | this.lastPress = System.currentTimeMillis();
31 | }
32 | }
33 |
34 | /**
35 | * @return the number of times the button has been pressed
36 | */
37 | public int getNumberOfPresses() {
38 | return this.numberOfPresses;
39 | }
40 | }
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-digital-output-led/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | be.webtechie
6 | pi4j-digital-output-led
7 | jar
8 | 1.0-SNAPSHOT
9 | Pi4J example: digital output with LED
10 | http://maven.apache.org
11 |
12 |
13 |
14 | junit
15 | junit
16 | 4.13.1
17 | test
18 |
19 |
20 | com.pi4j
21 | pi4j-core
22 | 1.3
23 |
24 |
25 |
26 |
27 |
28 |
29 | org.apache.maven.plugins
30 | maven-compiler-plugin
31 | 3.8.0
32 |
33 | 11
34 |
35 |
36 |
37 |
38 | maven-assembly-plugin
39 | 2.2.1
40 |
41 |
42 | jar-with-dependencies
43 |
44 |
45 |
46 | true
47 | be.webtechie.pi4jgpio.App
48 |
49 |
50 |
51 |
52 |
53 | make-assembly
54 | package
55 |
56 | single
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-distancesensor/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ### Read more
4 | * [Ultrasonic Ranging Module HC - SR04](https://www.electroschematics.com/wp-content/uploads/2013/07/HCSR04-datasheet-version-1.pdf)
5 | * [Using a Raspberry Pi distance sensor (ultrasonic sensor HC-SR04)](https://tutorials-raspberrypi.com/raspberry-pi-ultrasonic-sensor-hc-sr04/)
6 | * [Measure Distance using Ultrasonic Sensor | Pi4J | JAVA | Pi](https://www.hackster.io/weargenius/measure-distance-using-ultrasonic-sensor-pi4j-java-pi-48a249)
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-distancesensor/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | be.webtechie
6 | pi4j-distancesensor
7 | jar
8 | 1.0-SNAPSHOT
9 | Pi4J example: distance sensor
10 | http://maven.apache.org
11 |
12 |
13 |
14 | com.pi4j
15 | pi4j-core
16 | 1.3
17 |
18 |
19 | junit
20 | junit
21 | 4.13.1
22 | test
23 |
24 |
25 |
26 |
27 |
28 |
29 | org.apache.maven.plugins
30 | maven-compiler-plugin
31 | 3.8.0
32 |
33 | 11
34 |
35 |
36 |
37 |
38 | maven-assembly-plugin
39 | 2.2.1
40 |
41 |
42 | jar-with-dependencies
43 |
44 |
45 |
46 | true
47 | be.webtechie.pi4jgpio.App
48 |
49 |
50 |
51 |
52 |
53 | make-assembly
54 | package
55 |
56 | single
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-distancesensor/src/main/java/be/webtechie/pi4jgpio/helper/Calculation.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.helper;
2 |
3 | /**
4 | * Helper class for duration and distance calculation.
5 | */
6 | public class Calculation {
7 | /**
8 | * Get the distance (in cm) for a given duration.
9 | * The calculation is based on the speed of sound which is 34300 cm/s.
10 | *
11 | * @param seconds Number of seconds
12 | * @param half Flag to define if the calculated distance must be divided
13 | */
14 | public static int getDistance(float seconds, boolean half) {
15 | float distance = seconds * 34300;
16 | return Math.round(half ? distance / 2 : distance);
17 | }
18 |
19 | /**
20 | * Get the number of seconds between two nanosecond timestamps.
21 | * 1 second = 1000000000 nanoseconds
22 | *
23 | * @param start Start timestamp in nanoseconds
24 | * @param end End timestamp in nanoseconds
25 | */
26 | public static float getSecondsDifference(long start, long end) {
27 | return (end - start) / 1000000000F;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-distancesensor/src/test/java/be/webtechie/pi4jgpio/Calculation/CalculationTest.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.Calculation;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import be.webtechie.pi4jgpio.helper.Calculation;
6 | import org.junit.Test;
7 |
8 | public class CalculationTest {
9 |
10 | @Test
11 | public void testDistanceZero() {
12 | assertEquals(0, Calculation.getDistance(0, false));
13 | }
14 |
15 | @Test
16 | public void testDistanceZeroHalf() {
17 | assertEquals(0, Calculation.getDistance(0, true));
18 | }
19 |
20 | @Test
21 | public void testDistanceOne() {
22 | assertEquals(34300, Calculation.getDistance(1, false));
23 | }
24 |
25 | @Test
26 | public void testDistanceOneHalf() {
27 | assertEquals(34300 / 2, Calculation.getDistance(1, true));
28 | }
29 |
30 | @Test
31 | public void testDifferenceOneSecond() {
32 | long now = System.nanoTime();
33 | // Compare two floats, which in this case need to match with a precision (delta) 1
34 | assertEquals(1F, Calculation.getSecondsDifference(now, now + 1000000000), 1);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/README.md:
--------------------------------------------------------------------------------
1 | # Pi4J example: show the weather forecast on an LCD screen
2 |
3 | 
4 |
5 | ## OpenWeatherMap API
6 |
7 | To be able to request a forecast from the API, you need to register to receive an AppID on [https://openweathermap.org/api](https://openweathermap.org/api).
8 |
9 | ## Wiring
10 |
11 | 
12 |
13 | ## Read more
14 | * [Specification for LCD Module](https://www.openhacks.com/uploadsproductos/eone-1602a1.pdf)
15 | * [How to Setup an LCD on the Raspberry Pi and Program It With Python](http://www.circuitbasics.com/raspberry-pi-lcd-set-up-and-programming-in-python/)
16 | * [Raspberry Pi LCD using a 16×2 Liquid-Crystal Display](https://pimylifeup.com/raspberry-pi-lcd-16x2/)
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/images/lcd-output.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/java-pi4j-lcddisplay/images/lcd-output.jpg
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/images/lcd-wiring.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/java-pi4j-lcddisplay/images/lcd-wiring.png
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/src/main/java/be/webtechie/pi4jgpio/weather/data/Coordinates.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.weather.data;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 |
5 | public class Coordinates {
6 | @JsonProperty("lon")
7 | public float longitude;
8 |
9 | @JsonProperty("lat")
10 | public float latitude;
11 | }
12 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/src/main/java/be/webtechie/pi4jgpio/weather/data/Forecast.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.weather.data;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import java.util.List;
5 |
6 | public class Forecast {
7 | @JsonProperty("coord")
8 | public Coordinates coordinates;
9 |
10 | @JsonProperty("weather")
11 | public List weatherDescription;
12 |
13 | @JsonProperty("main")
14 | public WeatherInfo weatherInfo;
15 |
16 | @JsonProperty("wind")
17 | public WindInfo windInfo;
18 |
19 | @JsonProperty("name")
20 | public String name;
21 | }
22 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/src/main/java/be/webtechie/pi4jgpio/weather/data/WeatherDescription.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.weather.data;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 |
5 | public class WeatherDescription {
6 | @JsonProperty("id")
7 | public long id;
8 |
9 | @JsonProperty("main")
10 | public String main;
11 |
12 | @JsonProperty("description")
13 | public String description;
14 |
15 | @JsonProperty("icon")
16 | public String icon;
17 | }
18 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/src/main/java/be/webtechie/pi4jgpio/weather/data/WeatherInfo.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.weather.data;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 |
5 | public class WeatherInfo {
6 | @JsonProperty("temp")
7 | public float temperature;
8 |
9 | @JsonProperty("feels_like")
10 | public float temperatureFeeling;
11 |
12 | @JsonProperty("temp_min")
13 | public float temperatureMinimum;
14 |
15 | @JsonProperty("temp_max")
16 | public float temperatureMaximum;
17 |
18 | @JsonProperty("pressure")
19 | public int pressure;
20 |
21 | @JsonProperty("humidity")
22 | public int humidity;
23 | }
24 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/src/main/java/be/webtechie/pi4jgpio/weather/data/WindInfo.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.weather.data;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 |
5 | public class WindInfo {
6 | @JsonProperty("speed")
7 | public float speed;
8 |
9 | @JsonProperty("deg")
10 | public int degrees;
11 | }
12 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/src/main/java/be/webtechie/pi4jgpio/weather/helper/WeatherMapper.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.weather.helper;
2 |
3 | import be.webtechie.pi4jgpio.weather.data.Forecast;
4 | import com.fasterxml.jackson.databind.DeserializationFeature;
5 | import com.fasterxml.jackson.databind.ObjectMapper;
6 | import java.io.IOException;
7 |
8 | /**
9 | * Helper to convert the json received from OpenWeatherAPI to Java objects.
10 | */
11 | public class WeatherMapper {
12 | public static Forecast getWeather(String jsonString) {
13 | try {
14 | ObjectMapper mapper = new ObjectMapper();
15 | mapper.configure(
16 | DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
17 | false);
18 | return mapper.readValue(jsonString, Forecast.class);
19 | } catch (IOException ex) {
20 | System.err.println("Unable to parse the given string to Forecast object: "
21 | + ex.getMessage());
22 | return null;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/src/main/java/be/webtechie/pi4jgpio/weather/helper/WeatherRequest.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.weather.helper;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.InputStreamReader;
5 | import java.net.HttpURLConnection;
6 | import java.net.URL;
7 |
8 | /**
9 | * Helper to get the forecast from OpenWeatherAPI.
10 | */
11 | public class WeatherRequest {
12 | public static String getForecast(String location, String appId) {
13 | StringBuilder rt = new StringBuilder();
14 |
15 | try {
16 | URL url = new URL("http://api.openweathermap.org/data/2.5/weather"
17 | + "?units=metric"
18 | + "&q=" + location
19 | + "&appid=" + appId);
20 |
21 | HttpURLConnection conn = (HttpURLConnection) url.openConnection();
22 | conn.setRequestMethod("GET");
23 |
24 | int responseCode = conn.getResponseCode();
25 | if (responseCode == HttpURLConnection.HTTP_OK) {
26 | BufferedReader in = new BufferedReader(
27 | new InputStreamReader(conn.getInputStream()));
28 | String readLine;
29 | while ((readLine = in.readLine()) != null) {
30 | rt.append(readLine);
31 | }
32 | in.close();
33 | } else {
34 | System.err.println("Wrong response code: " + responseCode);
35 | }
36 | } catch (Exception ex) {
37 | System.err.println("Request error: " + ex.getMessage());
38 | }
39 |
40 | return rt.toString();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/src/test/java/be/webtechie/pi4jgpio/weather/helper/WeatherMapperTest.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.weather.helper;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 |
6 | import be.webtechie.pi4jgpio.weather.data.Forecast;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | public class WeatherMapperTest {
11 | private Forecast forecast;
12 |
13 | @Before
14 | public void init() {
15 | this.forecast = WeatherMapper.getWeather("{\"coord\":{\"lon\":2.89,\"lat\":50.85},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"base\":\"stations\",\"main\":{\"temp\":3.52,\"feels_like\":-0.42,\"temp_min\":0.56,\"temp_max\":7.22,\"pressure\":1046,\"humidity\":86},\"visibility\":10000,\"wind\":{\"speed\":3.1,\"deg\":350},\"clouds\":{\"all\":0},\"dt\":1579469707,\"sys\":{\"type\":1,\"id\":6559,\"country\":\"BE\",\"sunrise\":1579419691,\"sunset\":1579450561},\"timezone\":3600,\"id\":2795100,\"name\":\"Ypres\",\"cod\":200}\n");
16 | assertNotNull(this.forecast);
17 | }
18 |
19 | @Test
20 | public void testBase() {
21 | assertEquals("Ypres", this.forecast.name);
22 | }
23 |
24 | @Test
25 | public void testCoordinates() {
26 | assertEquals(2.89, this.forecast.coordinates.longitude, 0.01);
27 | assertEquals(50.85, this.forecast.coordinates.latitude, 0.01);
28 | }
29 |
30 | @Test
31 | public void testWeatherDescription() {
32 | assertEquals(1, this.forecast.weatherDescription.size());
33 | assertEquals("Clear", this.forecast.weatherDescription.get(0).main);
34 | assertEquals("clear sky", this.forecast.weatherDescription.get(0).description);
35 | assertEquals("01n", this.forecast.weatherDescription.get(0).icon);
36 | }
37 |
38 | @Test
39 | public void testWeatherInfo() {
40 | assertEquals(3.52, this.forecast.weatherInfo.temperature, 0.01);
41 | assertEquals(-0.42, this.forecast.weatherInfo.temperatureFeeling, 0.01);
42 | assertEquals(0.56, this.forecast.weatherInfo.temperatureMinimum, 0.01);
43 | assertEquals(7.22, this.forecast.weatherInfo.temperatureMaximum, 0.01);
44 | assertEquals(1046, this.forecast.weatherInfo.pressure);
45 | assertEquals(86, this.forecast.weatherInfo.humidity);
46 | }
47 |
48 | @Test
49 | public void testWindInfo() {
50 | assertEquals(3.1, this.forecast.windInfo.speed, 0.01);
51 | assertEquals(350, this.forecast.windInfo.degrees);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-lcddisplay/src/test/java/be/webtechie/pi4jgpio/weather/helper/WeatherRequestTest.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.weather.helper;
2 |
3 | import static junit.framework.Assert.assertNotNull;
4 |
5 | import org.junit.Test;
6 |
7 | public class WeatherRequestTest {
8 | // Create an app id by signing up on
9 | // https://home.openweathermap.org/users/sign_up
10 | private static final String APP_ID = "9f72246c2183b3e577fb925fafa0cfbf";
11 |
12 | @Test
13 | public void testRequest() {
14 | String result = WeatherRequest.getForecast("Passendale", APP_ID);
15 | assertNotNull(result);
16 |
17 | System.out.println(result);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-motorshield/README.md:
--------------------------------------------------------------------------------
1 | # Controlling a JOY-iT MotoPi shield
2 |
3 | ## Test with Python
4 |
5 | ### Install Adafruit Python PCA9685
6 | ```
7 | sudo apt-get install git build-essential python-dev
8 | cd ~
9 | git clone https://github.com/adafruit/Adafruit_Python_PCA9685.git
10 | cd Adafruit_Python_PCA9685
11 | sudo python setup.py install
12 | ```
13 |
14 | ## Read more
15 | * [https://github.com/adafruit/Adafruit_Python_PCA9685/](https://github.com/adafruit/Adafruit_Python_PCA9685/)
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-pwm-output-led/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | be.webtechie
6 | pi4j-pwm-output-led
7 | jar
8 | 1.0-SNAPSHOT
9 | Pi4J example: PWM output with LED
10 | http://maven.apache.org
11 |
12 |
13 |
14 | junit
15 | junit
16 | 4.13.1
17 | test
18 |
19 |
20 | com.pi4j
21 | pi4j-core
22 | 1.3
23 |
24 |
25 |
26 |
27 |
28 |
29 | org.apache.maven.plugins
30 | maven-compiler-plugin
31 | 3.8.0
32 |
33 | 11
34 |
35 |
36 |
37 |
38 | maven-assembly-plugin
39 | 2.2.1
40 |
41 |
42 | jar-with-dependencies
43 |
44 |
45 |
46 | true
47 | be.webtechie.pi4jgpio.App
48 |
49 |
50 |
51 |
52 |
53 | make-assembly
54 | package
55 |
56 | single
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-pwm-output-led/src/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "type": "java",
5 | "name": "CodeLens (Launch) - App",
6 | "request": "launch",
7 | "mainClass": "be.webtechie.pi4jgpio.App"
8 | }
9 | ]
10 | }
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-pwm-output-led/src/main/java/be/webtechie/pi4jgpio/App.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio;
2 |
3 | import com.pi4j.io.gpio.GpioController;
4 | import com.pi4j.io.gpio.GpioFactory;
5 | import com.pi4j.io.gpio.GpioPinPwmOutput;
6 | import com.pi4j.io.gpio.Pin;
7 | import com.pi4j.io.gpio.RaspiPin;
8 | import com.pi4j.util.CommandArgumentParser;
9 |
10 | /**
11 | * Based on https://github.com/Pi4J/pi4j/blob/master/pi4j-example/src/main/java/PwmExample.java
12 | */
13 | public class App {
14 | private static final int MAX_PMW_VALUE = 1000;
15 | private static final int FADE_STEPS = 10;
16 | private static final Pin PIN_LED = RaspiPin.GPIO_01; // BCM 18
17 |
18 | public static void main(String[] args) {
19 | System.out.println("Starting PWM output example...");
20 |
21 | try {
22 | // Initialize the GPIO controller
23 | GpioController gpio = GpioFactory.getInstance();
24 |
25 | // All Raspberry Pi models support a hardware PWM pin on GPIO_01.
26 | // Raspberry Pi models A+, B+, 2B, 3B also support hardware PWM pins:
27 | // GPIO_23, GPIO_24, GPIO_26
28 | GpioPinPwmOutput pwm = gpio.provisionPwmOutputPin(PIN_LED);
29 |
30 | // You can optionally use these wiringPi methods to further customize
31 | // the PWM generator see:
32 | // http://wiringpi.com/reference/raspberry-pi-specifics/
33 | com.pi4j.wiringpi.Gpio.pwmSetMode(com.pi4j.wiringpi.Gpio.PWM_MODE_MS);
34 | com.pi4j.wiringpi.Gpio.pwmSetRange(1000);
35 | com.pi4j.wiringpi.Gpio.pwmSetClock(50);
36 |
37 | // Loop through PWM values 10 times
38 | for (int loop = 0; loop < 10; loop++) {
39 | for (int useValue = MAX_PMW_VALUE; useValue >= 0;
40 | useValue-=MAX_PMW_VALUE/FADE_STEPS) {
41 | pwm.setPwm(useValue);
42 | System.out.println("PWM rate is: " + pwm.getPwm());
43 |
44 | Thread.sleep(200);
45 | }
46 | }
47 |
48 | // Shut down the GPIO controller
49 | gpio.shutdown();
50 |
51 | System.out.println("Done");
52 | } catch (Exception ex) {
53 | System.err.println("Error: " + ex.getMessage());
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-pwm-output-motor/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | be.webtechie
6 | pi4j-pwm-output-motor
7 | jar
8 | 1.0-SNAPSHOT
9 | Pi4J example: PWM output with motor shield
10 | http://maven.apache.org
11 |
12 |
13 |
14 | junit
15 | junit
16 | 4.13.1
17 | test
18 |
19 |
20 | com.pi4j
21 | pi4j-core
22 | 1.3
23 |
24 |
25 |
26 |
27 |
28 |
29 | org.apache.maven.plugins
30 | maven-compiler-plugin
31 | 3.8.0
32 |
33 | 11
34 |
35 |
36 |
37 |
38 | maven-assembly-plugin
39 | 2.2.1
40 |
41 |
42 | jar-with-dependencies
43 |
44 |
45 |
46 | true
47 | be.webtechie.pi4jgpio.App
48 |
49 |
50 |
51 |
52 |
53 | make-assembly
54 | package
55 |
56 | single
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-pwm-output-motor/src/main/java/be/webtechie/pi4jgpio/App.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio;
2 |
3 | import com.pi4j.io.gpio.GpioController;
4 | import com.pi4j.io.gpio.GpioFactory;
5 | import com.pi4j.io.gpio.GpioPinPwmOutput;
6 | import com.pi4j.io.gpio.Pin;
7 | import com.pi4j.io.gpio.RaspiPin;
8 | import com.pi4j.util.CommandArgumentParser;
9 |
10 | /**
11 | * Based on https://github.com/Pi4J/pi4j/blob/master/pi4j-example/src/main/java/PwmExample.java
12 | *
13 | * This motor control example uses the MOTOPI board of joy-it.net
14 | * https://joy-it.net/en/products/RB-Moto3
15 | * https://joy-it.net/files/files/Produkte/RB-Moto3/RB-Moto3-Manual_13-11-2017.pdf
16 | *
17 | */
18 | public class App {
19 | public static final int MAX_PMW_VALUE = 1000;
20 | public static final int FADE_STEPS = 10;
21 |
22 | public static void main( String[] args ) {
23 | System.out.println("Starting PWM output example...");
24 |
25 | try {
26 | // Initialize the GPIO controller
27 | GpioController gpio = GpioFactory.getInstance();
28 |
29 | // All Raspberry Pi models support a hardware PWM pin on GPIO_01.
30 | // Raspberry Pi models A+, B+, 2B, 3B also support hardware PWM pins: GPIO_23, GPIO_24, GPIO_26
31 | //
32 | // by default we will use gpio pin #01; however, if an argument
33 | // has been provided, then lookup the pin by address
34 | Pin pin = CommandArgumentParser.getPin(
35 | RaspiPin.class, // pin provider class to obtain pin instance from
36 | RaspiPin.GPIO_01, // default pin if no pin argument found = BCM 18
37 | args); // argument array to search in
38 |
39 | GpioPinPwmOutput pwm = gpio.provisionPwmOutputPin(pin);
40 |
41 | // you can optionally use these wiringPi methods to further customize the PWM generator
42 | // see: http://wiringpi.com/reference/raspberry-pi-specifics/
43 | com.pi4j.wiringpi.Gpio.pwmSetMode(com.pi4j.wiringpi.Gpio.PWM_MODE_MS);
44 | com.pi4j.wiringpi.Gpio.pwmSetRange(1000);
45 | com.pi4j.wiringpi.Gpio.pwmSetClock(5);
46 |
47 | // TODO
48 |
49 | // stop all GPIO activity/threads by shutting down the GPIO controller
50 | // (this method will forcefully shutdown all GPIO monitoring threads and scheduled tasks)
51 | gpio.shutdown();
52 |
53 | System.out.println("Done");
54 | } catch (Exception ex) {
55 | System.err.println("Error: " + ex.getMessage());
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi-tft/README.md:
--------------------------------------------------------------------------------
1 | # Controlling an SPI 240x320 TFT
2 |
3 | ## Read more
4 | * [ILI9341a-Si TFT LCD Single Chip Driver 240RGBx320 Resolution and 262K color - Specification](https://www.displaytech-us.com/sites/default/files/driver-ic-data-sheet/Ilitek-ILI9341.pdf)
5 | * [What is the difference between com.pi4j.io.spi.SpiDevice and "manual" SPI? (ILI9341 LCD Display)](https://groups.google.com/forum/#!topic/pi4j/4fnB3e0EtXs)
6 | * [Rpi3B/Rpi4B ILI9341 / XPT2046 SPI 2.8" Touch TFT LCD Connection / Driver Problem](https://raspberrypi.stackexchange.com/questions/98549/rpi3b-rpi4b-ili9341-xpt2046-spi-2-8-touch-tft-lcd-connection-driver-problem)
7 | * [ILI9341Java](https://github.com/saxond/ILI9341Java)
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi-tft/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | be.webtechie
6 | pi4j-spi-tft
7 | jar
8 | 1.0-SNAPSHOT
9 | Pi4J example: SPI with 240x320 TFT display
10 | http://maven.apache.org
11 |
12 |
13 |
14 | com.pi4j
15 | pi4j-core
16 | 1.3
17 |
18 |
19 |
20 |
21 |
22 |
23 | org.apache.maven.plugins
24 | maven-compiler-plugin
25 | 3.8.0
26 |
27 | 11
28 |
29 |
30 |
31 |
32 | maven-assembly-plugin
33 | 2.2.1
34 |
35 |
36 | jar-with-dependencies
37 |
38 |
39 |
40 | true
41 | be.webtechie.pi4jgpio.App
42 |
43 |
44 |
45 |
46 |
47 | make-assembly
48 | package
49 |
50 | single
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi-tft/src/main/java/be/webtechie/pi4jgpio/App.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio;
2 |
3 | import be.webtechie.pi4jgpio.helper.AsciiCharacterMode;
4 | import be.webtechie.pi4jgpio.helper.DemoMode;
5 | import be.webtechie.pi4jgpio.helper.ImageMode;
6 | import be.webtechie.pi4jgpio.definition.SpiCommand;
7 | import com.pi4j.io.spi.SpiChannel;
8 | import com.pi4j.io.spi.SpiDevice;
9 | import com.pi4j.io.spi.SpiFactory;
10 |
11 | /**
12 | * Based on https://github.com/Pi4J/pi4j/blob/master/pi4j-example/src/main/java/SpiExample.java
13 | */
14 | public class App {
15 |
16 | public static void main(String args[]) {
17 | try {
18 | System.out.println("Starting SPI example...");
19 |
20 | // Initialize the SpiFactory
21 | SpiDevice spi = SpiFactory.getInstance(SpiChannel.CS0,
22 | SpiDevice.DEFAULT_SPI_SPEED, // default spi speed 1 MHz
23 | SpiDevice.DEFAULT_SPI_MODE); // default spi mode 0
24 |
25 | spi.write(SpiCommand.TEST.getValue(), (byte) 0x01);
26 | System.out.println("Test mode all on");
27 | Thread.sleep(1000);
28 |
29 | spi.write(SpiCommand.TEST.getValue(), (byte) 0x00);
30 | System.out.println("Test mode all off");
31 | Thread.sleep(1000);
32 |
33 | spi.write(SpiCommand.DECODE_MODE.getValue(), (byte) 0x00);
34 | System.out.println("Use all bits");
35 |
36 | spi.write(SpiCommand.BRIGHTNESS.getValue(), (byte) 0x08);
37 | System.out.println("Changed brightness to medium level"
38 | + " (0x00 lowest, 0x0F highest)");
39 |
40 | spi.write(SpiCommand.SCAN_LIMIT.getValue(), (byte) 0x0f);
41 | System.out.println("Configured to scan all digits");
42 |
43 | spi.write(SpiCommand.SHUTDOWN_MODE.getValue(), (byte) 0x01);
44 | System.out.println("Woke up the MAX7219, is off on startup");
45 |
46 | DemoMode.showRows(spi, 250);
47 | DemoMode.showCols(spi, 250);
48 | DemoMode.showRandomOutput(spi, 5, 500);
49 |
50 | ImageMode.showAllImages(spi, 2000);
51 | AsciiCharacterMode.showAllAsciiCharacters(spi, 750);
52 | AsciiCharacterMode.scrollAllAsciiCharacters(spi, 50);
53 | } catch (Exception ex) {
54 | System.err.println("Error in main function: " + ex.getMessage());
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi-tft/src/main/java/be/webtechie/pi4jgpio/definition/SpiCommand.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.definition;
2 |
3 | /**
4 | * Reserved byte values to send a command.
5 | */
6 | public enum SpiCommand {
7 | DECODE_MODE((byte) 0x09),
8 | BRIGHTNESS((byte) 0x0A),
9 | SCAN_LIMIT((byte) 0x0B),
10 | SHUTDOWN_MODE((byte) 0x0C),
11 | TEST((byte) 0x0F);
12 |
13 | private final byte value;
14 |
15 | SpiCommand(byte value) {
16 | this.value = value;
17 | }
18 |
19 | public byte getValue() {
20 | return value;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi-tft/src/main/java/be/webtechie/pi4jgpio/helper/ImageMode.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.helper;
2 |
3 | import be.webtechie.pi4jgpio.definition.Image;
4 | import com.pi4j.io.spi.SpiDevice;
5 |
6 | public class ImageMode {
7 |
8 | /**
9 | * Show all the images as defined in the enum.
10 | *
11 | * @param spi SpiDevice
12 | * @param waitBetween Number of milliseconds to wait between every image output
13 | */
14 | public static void showAllImages(SpiDevice spi, int waitBetween) {
15 | try {
16 | for (Image image : Image.values()) {
17 | showImage(spi, image);
18 | System.out.println("Showing image " + image.name());
19 | Thread.sleep(waitBetween);
20 | }
21 | } catch (Exception ex) {
22 | System.err.println("Error during images: " + ex.getMessage());
23 | }
24 | }
25 |
26 | /**
27 | * Output the given image to the matrix.
28 | *
29 | * @param spi SpiDevice
30 | * @param image Image to be shown
31 | */
32 | public static void showImage(SpiDevice spi, Image image) {
33 | try {
34 | for (int i = 0; i < 8; i++) {
35 | spi.write((byte) (i + 1), image.getRows().get(i));
36 | }
37 | } catch (Exception ex) {
38 | System.err.println("Error during images: " + ex.getMessage());
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi/README.md:
--------------------------------------------------------------------------------
1 | # Controlling a 8x8 LED matrix display with a MAX7219 controller
2 |
3 | ## Prepare the Raspberry Pi
4 |
5 | ### Full Raspbian OS with Java 11
6 |
7 | Prepare an SD card with the latest full Raspbian OS and test the Java version when you're ready to start. Java 11 or higher is needed.
8 |
9 | ```
10 | $ java -version
11 | openjdk version "11.0.3" 2019-04-16
12 | OpenJDK Runtime Environment (build 11.0.3+7-post-Raspbian-5)
13 | OpenJDK Server VM (build 11.0.3+7-post-Raspbian-5, mixed mode)
14 | ```
15 |
16 | ### Install Pi4J
17 |
18 | Pi4J is the "bridge" between Java and the GPIO's.
19 |
20 | ```
21 | $ curl -sSL https://pi4j.com/install | sudo bash
22 | ```
23 |
24 | ### Upgrade WiringPi to version 2.52
25 |
26 | Required when you are using a Raspberry Pi as the internal structure of the chip is different compared to the previous versions.
27 |
28 | ```
29 | $ wget https://project-downloads.drogon.net/wiringpi-latest.deb
30 | $ sudo dpkg -i wiringpi-latest.deb
31 | $ gpio -v
32 | gpio version: 2.52
33 | ```
34 |
35 | ## Wiring
36 |
37 | 
38 |
39 | ## Result
40 |
41 | 
42 |
43 | ## Read more
44 | * [Displaying on MAX7219 Dot Matrix Using Raspberry Pi](https://tutorial.cytron.io/2018/11/22/displaying-max7219-dot-matrix-using-raspberry-pi/)
45 | * [Connecting MAX7219_LED_MATRIX with SPI bus](https://einhugur.com/blog/index.php/xojo-gpio/connecting-max7219_led_matrix-with-spi-bus/)
46 | * [How to Use the MAX7219 to drive an 8x8 LED display Matrix on the Arduino](https://www.best-microcontroller-projects.com/max7219.html)
47 | * [Pixel scrolling of a text message on 8x8 LED matrix displays with a MAX7219](https://picaxeforum.co.uk/threads/pixel-scrolling-of-a-text-message-on-8x8-led-matrix-displays-with-a-max7219.31594/)
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi/pictures/matrix-output.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/java-pi4j-spi/pictures/matrix-output.jpg
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi/pictures/matrix-wiring-setup.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/java-pi4j-spi/pictures/matrix-wiring-setup.jpg
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | be.webtechie
6 | pi4j-spi
7 | jar
8 | 1.0-SNAPSHOT
9 | Pi4J example: SPI with 8x8 led display
10 | http://maven.apache.org
11 |
12 |
13 |
14 | com.pi4j
15 | pi4j-core
16 | 1.3
17 |
18 |
19 |
20 |
21 |
22 |
23 | org.apache.maven.plugins
24 | maven-compiler-plugin
25 | 3.8.0
26 |
27 | 11
28 |
29 |
30 |
31 |
32 | maven-assembly-plugin
33 | 2.2.1
34 |
35 |
36 | jar-with-dependencies
37 |
38 |
39 |
40 | true
41 | be.webtechie.pi4jgpio.App
42 |
43 |
44 |
45 |
46 |
47 | make-assembly
48 | package
49 |
50 | single
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi/src/main/java/be/webtechie/pi4jgpio/App.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio;
2 |
3 | import be.webtechie.pi4jgpio.definition.SpiCommand;
4 | import be.webtechie.pi4jgpio.helper.AsciiCharacterMode;
5 | import be.webtechie.pi4jgpio.helper.DemoMode;
6 | import be.webtechie.pi4jgpio.helper.ImageMode;
7 | import com.pi4j.io.spi.SpiChannel;
8 | import com.pi4j.io.spi.SpiDevice;
9 | import com.pi4j.io.spi.SpiFactory;
10 |
11 | /**
12 | * Based on https://github.com/Pi4J/pi4j/blob/master/pi4j-example/src/main/java/SpiExample.java
13 | */
14 | public class App {
15 |
16 | public static void main(String args[]) {
17 | try {
18 | System.out.println("Starting SPI example...");
19 |
20 | // Initialize the SpiFactory
21 | SpiDevice spi = SpiFactory.getInstance(SpiChannel.CS0,
22 | SpiDevice.DEFAULT_SPI_SPEED, // default spi speed 1 MHz
23 | SpiDevice.DEFAULT_SPI_MODE); // default spi mode 0
24 |
25 | spi.write(SpiCommand.TEST.getValue(), (byte) 0x01);
26 | System.out.println("Test mode all on");
27 | Thread.sleep(1000);
28 |
29 | spi.write(SpiCommand.TEST.getValue(), (byte) 0x00);
30 | System.out.println("Test mode all off");
31 | Thread.sleep(1000);
32 |
33 | spi.write(SpiCommand.DECODE_MODE.getValue(), (byte) 0x00);
34 | System.out.println("Use all bits");
35 |
36 | spi.write(SpiCommand.BRIGHTNESS.getValue(), (byte) 0x08);
37 | System.out.println("Changed brightness to medium level"
38 | + " (0x00 lowest, 0x0F highest)");
39 |
40 | spi.write(SpiCommand.SCAN_LIMIT.getValue(), (byte) 0x0f);
41 | System.out.println("Configured to scan all digits");
42 |
43 | spi.write(SpiCommand.SHUTDOWN_MODE.getValue(), (byte) 0x01);
44 | System.out.println("Woke up the MAX7219, is off on startup");
45 |
46 | DemoMode.showRows(spi, 250);
47 | DemoMode.showCols(spi, 250);
48 | DemoMode.showRandomOutput(spi, 5, 500);
49 |
50 | ImageMode.showAllImages(spi, 2000);
51 | AsciiCharacterMode.showAllAsciiCharacters(spi, 750);
52 | AsciiCharacterMode.scrollAllAsciiCharacters(spi, 50);
53 | } catch (Exception ex) {
54 | System.err.println("Error in main function: " + ex.getMessage());
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi/src/main/java/be/webtechie/pi4jgpio/definition/SpiCommand.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.definition;
2 |
3 | /**
4 | * Reserved byte values to send a command.
5 | */
6 | public enum SpiCommand {
7 | DECODE_MODE((byte) 0x09),
8 | BRIGHTNESS((byte) 0x0A),
9 | SCAN_LIMIT((byte) 0x0B),
10 | SHUTDOWN_MODE((byte) 0x0C),
11 | TEST((byte) 0x0F);
12 |
13 | private final byte value;
14 |
15 | SpiCommand(byte value) {
16 | this.value = value;
17 | }
18 |
19 | public byte getValue() {
20 | return value;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/java-pi4j-spi/src/main/java/be/webtechie/pi4jgpio/helper/ImageMode.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4jgpio.helper;
2 |
3 | import be.webtechie.pi4jgpio.definition.Image;
4 | import com.pi4j.io.spi.SpiDevice;
5 |
6 | public class ImageMode {
7 |
8 | /**
9 | * Show all the images as defined in the enum.
10 | *
11 | * @param spi SpiDevice
12 | * @param waitBetween Number of milliseconds to wait between every image output
13 | */
14 | public static void showAllImages(SpiDevice spi, int waitBetween) {
15 | try {
16 | for (Image image : Image.values()) {
17 | showImage(spi, image);
18 | System.out.println("Showing image " + image.name());
19 | Thread.sleep(waitBetween);
20 | }
21 | } catch (Exception ex) {
22 | System.err.println("Error during images: " + ex.getMessage());
23 | }
24 | }
25 |
26 | /**
27 | * Output the given image to the matrix.
28 | *
29 | * @param spi SpiDevice
30 | * @param image Image to be shown
31 | */
32 | public static void showImage(SpiDevice spi, Image image) {
33 | try {
34 | for (int i = 0; i < 8; i++) {
35 | spi.write((byte) (i + 1), image.getRows().get(i));
36 | }
37 | } catch (Exception ex) {
38 | System.err.println("Error during images: " + ex.getMessage());
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/javafx-pi4j-serial/README.md:
--------------------------------------------------------------------------------
1 | # JavaFX example with Pi4J and serial communication
2 |
3 |
4 | ## Reconfigure serial GPIO's
5 |
6 | In case you want to use the serial communication GPIO's to be used for the serial link, you can find more info here:
7 |
8 | * [Disable Serial Port Terminal Shell Output on the Raspbian/Raspberry Pi](https://www.cube-controls.com/2015/11/02/disable-serial-port-terminal-output-on-raspbian/)
9 | * [Configuring The GPIO Serial Port On Raspbian Jessie and Stretch Including Pi 3 and 4](https://spellfoundry.com/2016/05/29/configuring-gpio-serial-port-raspbian-jessie-including-pi-3-4/)
10 |
11 | ## Read more
12 | * [Serial Communication Example using Pi4J](https://pi4j.com/1.2/example/serial.html)
13 | * [Pi4J Serial Example](https://github.com/Pi4J/pi4j/blob/master/pi4j-example/src/main/java/SerialExample.java)
14 | * [Read and Write From Serial Port With Raspberry Pi](https://www.instructables.com/id/Read-and-write-from-serial-port-with-Raspberry-Pi/)
15 | * [Light Sensor using Arduino](https://rookieelectronics.com/light-sensor-using-arduino)
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/javafx-pi4j-serial/src/main/java/be/webtechie/pi4j/serial/App.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4j.serial;
2 |
3 | import be.webtechie.pi4j.serial.ui.MeasurementChart;
4 | import javafx.application.Application;
5 | import javafx.scene.Scene;
6 | import javafx.stage.Stage;
7 |
8 | /**
9 | * Based on https://github.com/Pi4J/pi4j/blob/master/pi4j-example/src/main/java/SerialExample.java
10 | */
11 | public class App extends Application {
12 |
13 | private static final String SERIAL_DEVICE = "/dev/ttyACM0";
14 |
15 | @Override
16 | public void start(Stage stage) {
17 | System.out.println("Starting serial communication example");
18 |
19 | var scene = new Scene(new MeasurementChart(SERIAL_DEVICE), 640, 480);
20 | stage.setScene(scene);
21 | stage.setTitle("Light measurement");
22 | stage.show();
23 | }
24 |
25 | public static void main(String[] args) {
26 | launch();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/javafx-pi4j-serial/src/main/java/be/webtechie/pi4j/serial/data/ArduinoMessage.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4j.serial.data;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 |
5 | public class ArduinoMessage {
6 | @JsonProperty("type")
7 | public String type;
8 |
9 | @JsonProperty("value")
10 | public String value;
11 |
12 | public Integer getIntValue() {
13 | if (this.value.matches("-?(0|[1-9]\\d*)")) {
14 | return Integer.parseInt(this.value);
15 | }
16 |
17 | return null;
18 | }
19 |
20 | public Float getFloatValue() {
21 | if (this.value.matches("[-+]?[0-9]*\\.?[0-9]+")) {
22 | return Float.parseFloat(this.value);
23 | }
24 |
25 | return null;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/javafx-pi4j-serial/src/main/java/be/webtechie/pi4j/serial/data/ArduinoMessageMapper.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4j.serial.data;
2 |
3 | import com.fasterxml.jackson.databind.DeserializationFeature;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import java.io.IOException;
6 |
7 | public class ArduinoMessageMapper {
8 | public static ArduinoMessage map(String jsonString) {
9 | try {
10 | ObjectMapper mapper = new ObjectMapper();
11 | mapper.configure(
12 | DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
13 | false);
14 | return mapper.readValue(jsonString, ArduinoMessage.class);
15 | } catch (
16 | IOException ex) {
17 | System.err.println("Unable to parse the given string to Forecast object: "
18 | + ex.getMessage());
19 | return null;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/javafx-pi4j-serial/src/main/java/be/webtechie/pi4j/serial/serial/SerialListener.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4j.serial.serial;
2 |
3 | import be.webtechie.pi4j.serial.data.ArduinoMessage;
4 | import be.webtechie.pi4j.serial.data.ArduinoMessageMapper;
5 | import com.pi4j.io.serial.SerialDataEvent;
6 | import com.pi4j.io.serial.SerialDataEventListener;
7 | import java.io.IOException;
8 | import java.time.LocalTime;
9 | import java.time.format.DateTimeFormatter;
10 | import javafx.application.Platform;
11 | import javafx.scene.chart.XYChart;
12 |
13 | /**
14 | * Listener which will print out the data received on the serial connection
15 | */
16 | public class SerialListener implements SerialDataEventListener {
17 |
18 | private final DateTimeFormatter formatter;
19 | private final XYChart.Series data;
20 |
21 | /**
22 | * Constructor which initializes the date formatter.
23 | *
24 | * @param data The data series to which the light values must be added
25 | */
26 | public SerialListener(XYChart.Series data) {
27 | this.data = data;
28 | this.formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
29 | }
30 |
31 | /**
32 | * Called by Serial when new data is received.
33 | */
34 | @Override
35 | public void dataReceived(SerialDataEvent event) {
36 | try {
37 | String received = event.getAsciiString()
38 | .replace("\t", "")
39 | .replace("\n", "");
40 |
41 | ArduinoMessage arduinoMessage = ArduinoMessageMapper.map(received);
42 | String timestamp = LocalTime.now().format(formatter);
43 |
44 | if (arduinoMessage.type.equals("light")) {
45 | // We need to use the runLater approach as this data is handled
46 | // in another thread as the UI-component
47 | Platform.runLater(() -> {
48 | data.getData().add(new XYChart.Data(timestamp, arduinoMessage.getIntValue()));
49 | });
50 | }
51 |
52 | System.out.println(timestamp + " - Received: " + received);
53 | } catch (IOException ex) {
54 | System.err.println("Serial error: " + ex.getMessage());
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/javafx-pi4j-serial/src/main/java/be/webtechie/pi4j/serial/serial/SerialSender.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.pi4j.serial.serial;
2 |
3 | import com.pi4j.io.serial.Serial;
4 |
5 | /**
6 | * Runnable to send a timestamp to the Arduino board to demonstrate the echo function.
7 | */
8 | public class SerialSender implements Runnable {
9 |
10 | private static int INTERVAL_SEND_SECONDS = 5;
11 |
12 | final Serial serial;
13 |
14 | /**
15 | * Constructor which gets the serial communication object to be used to send data.
16 | *
17 | * @param serial
18 | */
19 | public SerialSender(Serial serial) {
20 | this.serial = serial;
21 | }
22 |
23 | @Override
24 | public void run() {
25 | // Keep looping until an error occurs
26 | boolean keepRunning = true;
27 | while (keepRunning) {
28 | try {
29 | // Write a text to the Arduino, as demo
30 | this.serial.writeln("Timestamp: " + System.currentTimeMillis());
31 |
32 | // Wait predefined time for next loop
33 | Thread.sleep(INTERVAL_SEND_SECONDS * 1000);
34 | } catch (Exception ex) {
35 | System.err.println("Error: " + ex.getMessage());
36 | keepRunning = false;
37 | }
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/javafx-pi4j-serial/src/main/java/module-info.java:
--------------------------------------------------------------------------------
1 | module be.webtechie.pi4j.serial {
2 | requires javafx.controls;
3 | requires pi4j.core;
4 | requires com.fasterxml.jackson.annotation;
5 | requires com.fasterxml.jackson.databind;
6 | exports be.webtechie.pi4j.serial;
7 | exports be.webtechie.pi4j.serial.data;
8 | }
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/schemes/8x8-led-matrix.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/schemes/8x8-led-matrix.fzz
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/schemes/digital-input-button.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/schemes/digital-input-button.fzz
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/schemes/digital-output-led-multiple-resistors.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/schemes/digital-output-led-multiple-resistors.fzz
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/schemes/digital-output-led-one-resistor.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/schemes/digital-output-led-one-resistor.fzz
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/schemes/digital-output-pwm-led.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/schemes/digital-output-pwm-led.fzz
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/schemes/distancesensor.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/schemes/distancesensor.fzz
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/schemes/lcd.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/schemes/lcd.fzz
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/schemes/serial-arduino-lightsensor.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/schemes/serial-arduino-lightsensor.fzz
--------------------------------------------------------------------------------
/Chapter_09_Pi4J/schemes/spi-max7219.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FDelporte/JavaOnRaspberryPi/31e2c419c462521376089e4b89621c4e84b5b7d0/Chapter_09_Pi4J/schemes/spi-max7219.fzz
--------------------------------------------------------------------------------
/Chapter_10_Spring/README.md:
--------------------------------------------------------------------------------
1 | # Chapter 10: Spring
2 |
3 | ## Read more
4 | * [What is Spring? Component-based development for Java](https://www.javaworld.com/article/3444936/what-is-spring-component-based-development-for-java.html)
5 | * [Spring Data REST Reference Guide](https://docs.spring.io/spring-data/rest/docs/current/reference/html/#reference)
6 | * [Accessing JPA Data with REST](https://spring.io/guides/gs/accessing-data-rest/)
7 | * [Properties with Spring and Spring Boot](https://www.baeldung.com/properties-with-spring)
8 | * [Reactive Spring: Define a REST Endpoint as a Continuous Stream](https://dzone.com/articles/reactive-spring-define-a-rest-endpoint-as-a-contin)
9 |
--------------------------------------------------------------------------------
/Chapter_10_Spring/java-spring-image-server/README.md:
--------------------------------------------------------------------------------
1 | # Java Spring image web server
2 |
3 | ### Links provided by the application
4 |
5 | * http://localhost:8080/swagger-ui.html
6 | * http://localhost:8080/files
7 | * http://localhost:8080/file/{FILENAME}
8 |
9 |
--------------------------------------------------------------------------------
/Chapter_10_Spring/java-spring-image-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.1.8.RELEASE
9 |
10 |
11 | be.webtechie
12 | java-spring-image-server
13 | 0.0.1-SNAPSHOT
14 | java-spring-image-server
15 | Spring Boot project to access pictures via the browser
16 |
17 |
18 | 11
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-web
25 |
26 |
27 |
28 | io.springfox
29 | springfox-swagger2
30 | 2.9.2
31 |
32 |
33 | io.springfox
34 | springfox-swagger-ui
35 | 2.9.2
36 |
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-starter-test
41 | test
42 |
43 |
44 |
45 |
46 |
47 |
48 | org.springframework.boot
49 | spring-boot-maven-plugin
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/Chapter_10_Spring/java-spring-image-server/src/main/java/be/webtechie/javaspringrest/JavaSpringRestApplication.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.javaspringrest;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class JavaSpringRestApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(JavaSpringRestApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/Chapter_10_Spring/java-spring-image-server/src/main/java/be/webtechie/javaspringrest/configuration/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.javaspringrest.configuration;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 |
6 | import springfox.documentation.builders.PathSelectors;
7 | import springfox.documentation.builders.RequestHandlerSelectors;
8 | import springfox.documentation.spi.DocumentationType;
9 | import springfox.documentation.spring.web.plugins.Docket;
10 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
11 |
12 | @Configuration
13 | @EnableSwagger2
14 | public class SwaggerConfig {
15 | @Bean
16 | public Docket api() {
17 | return new Docket(DocumentationType.SWAGGER_2)
18 | .select()
19 | .apis(RequestHandlerSelectors.any())
20 | .paths(PathSelectors.any())
21 | .build();
22 | }
23 | }
--------------------------------------------------------------------------------
/Chapter_10_Spring/java-spring-image-server/src/main/java/be/webtechie/javaspringrest/controller/MyErrorController.java:
--------------------------------------------------------------------------------
1 | package be.webtechie.javaspringrest.controller;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 |
5 | import org.springframework.boot.web.servlet.error.ErrorController;
6 | import org.springframework.stereotype.Controller;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.ResponseBody;
9 |
10 | @Controller
11 | public class MyErrorController implements ErrorController {
12 |
13 | @RequestMapping("/error")
14 | @ResponseBody
15 | public String handleError(HttpServletRequest request) {
16 | Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
17 | Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
18 | return String.format("