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 Flux getDistances() {
        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…