News Flash: The persistent publish/subscribe service from QNX has just been shortlisted for a 2010 embedded AWARD. (Yeah, I know, the capitalization is weird.) QNX Software Systems has won two of these awards in the past. Can it score a hat trick? Stay tuned for updates.
And now, back to our regularly scheduled programming...
In the first installment of this two-part series, I provided an overview of PPS and explained how it offered several benefits over the direct, point-to-point connections often used for interprocess communication. Compared to these "brittle" approaches, which tend to break when new features or requirements are introduced, PPS allows developers to create loose, flexible connections between components. As a result, it becomes much easier to add, remove, or replace components without having to modify other components.
Example: Smart energy panel
To appreciate the benefits offered by QNX PPS, consider a smart energy panel that lets a homeowner control heating, air conditioning, burglar alarms, and other subsystems. This system would include temperature sensors, an on/off thermostat, and an HMI that displays the state of the various subsystems.
In a traditional system, the sensors and the HMI are tightly coupled. The HMI often knows exactly what hardware it’s talking to, which makes changing or introducing new devices very difficult. With PPS, the sensors and other devices don’t communicate with the HMI directly; rather, they become publishers of data objects. As a result, it becomes easier to swap out underlying hardware or to add new brands of temperature or control mechanisms. Just as important, multiple panels throughout the home can subscribe to the same objects, without worrying about the impact of multiple callers to a low-level sensor API.
A smart energy panel that uses PPS.
For a whitepaper that goes into more detail on using PPS in a smart energy/building automation system, click here (registration required).
Example: Automotive instrument cluster
For another example, consider an automotive instrument cluster that includes a speedometer, tachometer, temperature gauges, and other instruments. A CAN stack acquires the speedometer and RPM data from the CAN bus and, when new data arrives, issues callbacks into the cluster’s HMI. In a conventional implementation, any modifications to the underlying stack or protocol are directly reflected in the API, forcing modifications to the HMI.
In the PPS model, the CAN stack publishes two data sources, RPM and speed. The HMI then subscribes to those data sources. This loosely coupled approach allows developers to replace or modify the underlying stack or protocol without having to make any changes to the HMI. Prototyping and parallel development are also simplified, since developers can easily simulate the RPM or speed data if the hardware is still being developed.
PPS provides a key feature for systems running in harsh or unpredictable environments: persistent storage. For instance, in a smart energy system, a user’s requested zone temperature, if implemented as a published data object, will persist across a system restart or power outage.
When the system comes back up, the data object will retain the same temperature value it held prior to the interruption. On startup, PPS will restore the data object, either immediately or on first access — the developer can choose either option.
Designed for humans
When designing a PPS service, you have to decide early on whether it will use binary or human-readable objects. The binary option results in smaller objects. The human-readable option makes for simpler development and debugging. QNX chose door number 2.
Human-readable objects allow developers to debug from the command-line using simple file system utilities, such as cat for subscribe and echo for publish. They also make it easy to create a simple program that subscribes to an object and prints out debugging information, including PPS object and attributes.
For instance, to display all PPS objects in a system, you can simply type:
ls -lR /fs/pps/
To create, query, or modify QNX PPS objects, developers can use industry-standard POSIX API calls: open(), read(), write(), and so on. For instance, to publish to a PPS object, a publisher simply calls open() for the object file. The publisher can then call write() to modify any attribute of the PPS object.
Likewise, to subscribe to an object, a client simply calls open(). The client can then query the object with read(). In response, PPS returns the object name, followed by the object’s current attributes.
For instance, if a car multimedia system publishes the metadata for the currently playing song in an object called “PlayCurrent”, a subscriber that queries PlayCurrent with read() might see something like this:
Caveat: This section provides a high-level overview. Read the preliminary PPS docs to get the full skinny.
Flexible design options
PPS keeps your options open. For instance:
- Multiple publishers to the same object — Multiple publishers can publish to the same PPS object, and each publisher can “own” a different attribute of the object. In a multimedia system, for instance, one component may be the source of a “time::value” attribute, while the HMI may be the source of a “duration::value” attribute.
- Multiple subscribers — PPS clients can subscribe to multiple objects and PPS objects can have multiple subscribers. When a publisher changes an object, all clients subscribed to that object are informed of the change.
- No artificial limits — The number and depth of PPS directories and the number of PPS objects in a directory are limited only by available memory.
- Push and pull — By default, QNX PPS functions as a push publishing system. But it also allows a subscriber to pull data from a publisher, so that publishing occurs on demand.
Persistent storage requires a reliable file system. So in addition to PPS, QNX Software Systems also provides a choice of high-reliability file systems, including a power-safe disk file system, an embedded transaction file system for NAND flash, and a fault-tolerant file system for NOR flash. PPS can also work with customer-created file systems.
So there you have it: a less brittle way to connect software components together.
p.s. To read Part I of this two-part series, click here.
p.p.s. Thanks again to Andy Gryc for all his invaluable contributions. Thanks also to Nicola Vulpe for making the PPS docs human readable. :-)