Written by Chris Gammell, a member of the Zephyr technical community and Developer Relations Lead at Golioth
This article originally ran on the Golioth website. For more content like this, click here.
As members and contributors to the Zephyr Project, we keep an eye on new developments. Last year, there was a published feature of particular interest because it represents a new way to structure programs and messaging between different parts of your program.
ZBus (Zephyr Bus), which brings a standardized version of event driven architecture in the form of a publish and subscribe model inside of your program. The lead author Rodrigo Peixoto spoke with Golioth about the details of this feature and how it might help Golioth users to make more responsive, flexible programs. In the associated video, Rodrigo walks through the history and capabilities of ZBus.
Why should you consider an event-driven bus architecture?
The decision to take on a new system architecture is not something to do willy nilly. It’s important to understand where an event driven architecture is a good fit.
The first that I think about is scalability. When you have a bus architecture, adding an additional “listener” can be done with much less work.
Consider the alternative to event-driven architecture. When you want to add a new action (say some code that initiates a sensor reading), you need to call that new code from your trigger event (say a timer being finished). That means you need to know where the trigger is located in the code and make changes there to add the call to your new task. Once you add in the required testing, each additional feature can become burdensom. This scales poorly.
With an event-driven system, the trigger is already set up to publish an event. New tasks can be added that look for the event. You don’t need to change any trigger code, you don’t even need to know where that code lives. This performs well as the amount of data increases, which will ultimately depend on how large you think your system will be.
Flexibility is another consideration. An event-driven bus allows the system to be easily adapted to handle new events or changes in the environment. This means that the system can be easily updated and modified without having to completely rewrite large swaths of code. Another type of “flexibility” is how and where you can re-use your code. This makes it easier to develop and test your system, as well as to troubleshoot and fix any problems that may arise.
Finally, if your device needs to meet critical timing, an event-driven system will not only deal with higher levels of complexity, but also respond quickly to new inputs to the system, such as external events. For example, an embedded system might be designed to control a robot, and it would use event-driven architecture to respond to sensor data from the robot’s environment and control its movements accordingly.
How ZBus implements an event-driven architecture
In ZBus, there are “producers” that generate messages and “consumers” that act upon them. There are also “Filters” help to process raw data (such as a sensor output). Each of these are organized into different “channels” to allow listening on a particular lane of data being produced.
Each of these are built into normal scenarios such as listening for timers and taking a reading from a sensor and then alerting other parts of the program that the data is now available. A common scenario is show below:
How will you use ZBus?
Microcontrollers are used in increasingly complex scenarios and are being asked to do more and more. Connecting a low power device to the internet often requires higher levels of complexity that Zephyr helps with. We expect to see more devices using Ecosystems and RTOSes like Zephyr in the future, and implementing ZBus on high complexity devices.
Are you looking at using an event-driven architecture in your system? Let us know on the Golioth forum and tell us how we can help!
If you have any questions or comments, please connect with the Zephyr technical community on the Zephyr Discord Channel.