Pi4J V5.0.0: Work in Progress

2026-10-14 by Frank Delporte

Pi4J V5.0.0: Work in Progress

Since the 4.0.2 release in June, the main branch of the Pi4J core repository moved to 5.0.0-SNAPSHOT, and a lot has happened since then: about 300 commits and more than 80 merged pull requests! This post gives an overview of what is changing and who is making it happen.

There is no release date for V5.0.0 yet. Several issues and pull requests are still in progress, and we want to get the API right before releasing, as V5 is the moment to clean up things we couldn’t change in a minor release. If you want to try it out, the snapshot builds are published automatically for every change on main.

A much leaner core

The biggest theme of V5 is cleanup. Pi4J has grown over many years and a lot of code was no longer used, duplicated, or made things more complicated than needed. A selection of the changes:

  • Platforms are removed (#650), together with the platform autodetect option (#688).
  • Providers are removed (#782), turning a plugin into a factory for a Context. Minimal stubs remain for the old, prominently documented ways to create IO instances (#790).
  • Properties and name-based IO creation are removed (#652, #674), as well as the binding and group stubs (#653), PWM presets (#693), the deprecated DeferredDelay (#640), and other unused metadata and types (#706, #792).
  • The old Raspberry Pi plugin implementation and the never-used analog GPIO implementation are removed (#664, #665). The FFM plugin is the way forward.
  • The internal runtime is merged into DefaultContext (#660), and write access to the IO registry is no longer exposed (#658).
  • Config classes no longer depend on the context (#711 and others), bringing them closer to plain DTOs, and IO instances are getting rid of their Context dependency (#769, #791).
  • Intermediate base classes are removed, like GpioBase and the provider base classes (#776, #778).

One clear way to create IO instances

Over the years, many different ways to create an IO instance were added. V5 settles on one canonical approach (#704, #728): use <IOTYPE>.newConfigBuilder() and pass the config to context.create(...). Other creation paths are deprecated (with the version in the annotation) or marked as internal, and the remaining internal calls to them have been removed (#733, #735, #738). Devices are now registered while they are created (#734).

Shutting down is simplified as well: the confusing combination of close() and shutdownInternal() is replaced by a single close() method (#768), with several fixes for close ordering and robustness (#677, #678, #755, #780).

Falling back to mocks

A long-standing request (#619) is now possible: run on real hardware when it’s available, and automatically fall back to mocks on other systems, for instance on your development PC (#715). Mock providers now have a lower priority, so they no longer take precedence over real providers. The mock drivers themselves were also reworked into a proper test framework, including a GPIO mock driver (#651).

New and improved IO features

  • Parallel port: a new ParallelPort IO type to read or write multiple GPIOs simultaneously as one value, with direction control at runtime (#727, #740, #765, #785). Event support is in progress in #788.
  • PWM: frequency and duty cycle are now double values, so you can use 1.5 Hz or a 33.3% duty cycle (#644, #646), a refactored and optimized FFM PWM implementation (#701), and improved documentation (#759).
  • I2C: implementations now only need to provide writeThenRead, as defaults for the other methods are built on top of it (#744, #746). read() now returns unsigned values (#753), and the limited FILE implementation is removed (#762).
  • SPI: support for chunked transfers (#666).
  • Digital output: an initial state in the FFM implementation (#663), and blink, pulse, etc. moved to a DigitalOutputOperations helper (#749).
  • GPIO: the FFM GPIO code is refactored to reduce duplication (#698).

More boards: RISC-V and better detection

  • RISC-V support (#697): the FFM provider now asks the OS linker to find native libraries instead of using hardcoded paths per architecture. Read more in RISC-V Support Landing in Pi4J V5.
  • A LineHelper for non-Raspberry Pi boards (#694), following the experiments on Banana Pi and NVIDIA Jetson Nano.
  • Board detection with revision codes (#682): Raspberry Pi revision codes are parsed into memory size, processor, and board type, as recommended by Raspberry Pi, so new revisions of existing boards are recognized without code changes. The 16GB Compute Module 5 is also supported now (#673).
  • Friendlier FFM startup: each provider is registered separately, so a missing Linux group only disables the related provider, and the permission message suggests the correct usermod -aG command (#757, #758). Newer kernel versions are handled in the builds and tests (#662, #760).

Build, release, and documentation

  • Java 25 and Maven 4 (#612).
  • Automated releases from main with JReleaser (#685), aligned with the Commonhaus release requirements and the same approach as Pi4J Drivers, plus several fixes to make sure snapshots are actually published (#770, #771, #772).
  • The module-info files are replaced by an Automatic-Module-Name (#775). Whether the FFM plugin should get a named module again is still being discussed in #795.
  • Improved JavaDoc for all public methods (#667, #668).
  • Smoke test updates for the smoke test PCB (#676, #783).
  • An architecture map: every pull request now gets a comment showing which components it changes, based on a groma.md architecture map of the project (#786).

Still in progress

Before V5.0.0 can be released, a number of topics are still open, for example:

  • Parallel port events (#788, #789).
  • Hardware detection with the FFM plugin (#645, #642).
  • Further config cleanup (#794, #705, #714, #731) and removing the Describable/Identity complex (#730).
  • Removing the remaining Context dependency from IO instances (#764).
  • CRaC checkpoint/restore support for open IO (#797, #798).
  • 1-Wire support (#429, #435), analog pins (#699), and software PWM in the FFM plugin (#556).
  • A possible issue with FFM DigitalInput debounce (#796).

As V5 contains breaking API changes, we will also update the documentation and examples on this website before the release. Feedback is very welcome! Try the snapshot with your project and let us know in the issues or discussions what works and what breaks.

Thank you

A huge thank you to everyone who contributed code, reviews, ideas, and testing to the upcoming V5:

You can follow all the changes on GitHub in the commit history.