Reactive Spring Flux data from a Pi
Trisha Gee (Coder, blogger, speaker, Developer Advocate at JetBrains, @trisha_gee), which I interviewed for “Chapter 4: Choosing an IDE”, and Josh Long (Spring Developer Advocate at Pivotal, @starbuxman) worked together on a blog series in which they showed the power of reactive data produced by a Spring application. Instead of repeating a REST call each time you want to get data from the server, you do one call which returns a continuous stream in which new data is pushed based on an interval.
Their example uses a Kotlin service to send stock values every second. I was wondering if this could be achieved on the Pi. And of course! This example is based on the one from “Chapter 9: Pi4J” with the distance sensor. It uses the same wiring with some rework of the code integrated in a Spring application.
Wiring
Code
The sources can be found as an example project within all the sources from the book on GitHub. The most important part is the service generation the distance measurement Flux:
private static final Pin PIN_TRIGGER = RaspiPin.GPIO_01; // BCM 18 private static final Pin PIN_ECHO = RaspiPin.GPIO_05; // BCM 24 private final GpioPinDigitalOutput trigger; private final GpioPinDigitalInput echo; public DistanceService() { // Initialize the GPIO controller GpioController gpio = GpioFactory.getInstance(); // Initialize the pins this.trigger = gpio.provisionDigitalOutputPin(PIN_TRIGGER, "Trigger", PinState.LOW); this.echo = gpio.provisionDigitalInputPin(PIN_ECHO, "Echo", PinPullResistance.PULL_UP); } public FluxgetDistances() { return Flux.fromStream(Stream.generate(() -> this.getDistanceMeasurement())) .delayElements(Duration.ofSeconds(1)); } private DistanceMeasurement getDistanceMeasurement() { try { // Set trigger high for 0.01ms this.trigger.pulse(10, PinState.HIGH, true, TimeUnit.NANOSECONDS); // Start the measurement while (this.echo.isLow()) { // Wait until the echo pin is high, // indicating the ultrasound was sent } long start = System.nanoTime(); // Wait till measurement is finished while (this.echo.isHigh()) { // Wait until the echo pin is low, // indicating the ultrasound was received back } long end = System.nanoTime(); // Output the distance float measuredSeconds = (end - start) / 1000000000F; int distance = Math.round(measuredSeconds * 34300 / 2); logger.info("Measured distance is: {} for {}s", distance, measuredSeconds); return new DistanceMeasurement(distance, measuredSeconds); } catch (Exception ex) { logger.error("Error: {}", ex.getMessage()); } return null; }
Result
After building the jar and running it on the Pi, the data is streamed to the browser:
Conclusion
As always with Java, the required code is only a few lines, but you have to find which lines ;-)
This reactive API is only the starting point and only becomes valuable with some clients consuming and using the generated data, but that’s a fun project for you…