Publishing interim data

Updated: April 19, 2023

Publishers are applications that generate interim data information for other applications.

Publishing interim data requires that the publisher and subscriber be somewhat in synchronization with each other. For example, if a subscriber isn't releasing buffers in a timely manner, the publisher can be blocked waiting for a buffer to be available for publishing.

The Sensor Framework releases any buffers that have been acquired by a subscriber if that subscriber terminates unexpectedly. Therefore, the publisher won't be blocked indefintely if one of its subscriber crashes.

In general when you're publishing interim data, do the following:

  1. Open a connection to the interim data unit of interest. See Opening and closing a connection to an interim data unit.
  2. Start the publishing of the interim data. See Starting an interim data unit.
  3. Allocate a buffer to store the interim data, and then populate the buffer with interim data that you want to publish.
  4. Publish the buffer that contains the interim data.
  5. Close the connection to the interim data unit. See Opening and closing a connection to an interim data unit.

Allocate and populate buffers

Publishers allocate buffers, and populate them with data to publish. You can specify the maximum number of buffers that your publisher needs with the num_buffers parameter in the data configuration file. See the Interim Data configuration file section in the Sensor Framework Services guide.

The number of buffers that's available for the publisher to allocate depends also on the subscribers. When subscribers are consuming the interim data that's been published, they have access to the buffers. Until the subscribers release the buffers, the publisher can be blocked from publishing. Therefore, publishers can register with the Sensor library to invoke a callback function or to send an event when a SENSOR_EVENT_BUFFER sensor event occurs. The SENSOR_EVENT_BUFFER event occurs when a subscriber calls sensor_return_buffer() to free a buffer; the result of that call means that a buffer is available for the publisher to allocate. For information on how to register for sensor events, see Accessing sensor data and status.

For each buffer that's available to the publisher for storing and publishing interim data, you use the Sensor API function to allocate a buffer and then populate it.

Allocating a buffer

To allocate an empty buffer in which you are populating interim data, call sensor_interim_data_alloc(). For example:
...
int err;
sensor_handle_t handle = NULL;
sensor_buffer_t         buffer;

...
err = sensor_interim_data_alloc(handle, &buffer, true);
...
      

A pointer to an available buffer is returned to you in the buffer parameter of sensor_interim_data_alloc(). When you set the block parameter to true, this function blocks until there is a buffer available to return to you.

The buffer is of type sensor_buffer_t.

Populating a buffer with interim data

After you successfully allocate a buffer, you can populate its data member with the interim data as the payload. To be able to properly populate the buffer's data payload with interim data for publishing, you need to ensure that the interim data is in the format that corresponds to the interim data unit (your handle to the interim data unit). You configure the format of the data that's associated with the interim data unit in the data_format parameter of the interim data configuration file. See the Interim Data configuration file Interim Data configuration file” section in the Sensor Framework Services guide.

You can also access the format from the buffer itself by reading the format member of the buffer that's been returned to you from sensor_interim_data_alloc(). The format of the buffer is one of the sensor_format_t types. If your publisher's interim data doesn't correspond to a format that's pre-defined by the Sensor library (e.g., sensor_format_video_packed_t, you can configure the data unit's data format as SENSOR_FORMAT_USER_DATA so that your publisher can define its own format for populating the buffer with its interim data. For example:

...
#define DEFAULT_PUBLISH_LATENCY_US  33000
static uint32_t publishLatency = DEFAULT_PUBLISH_LATENCY_US;
/* Example hard-coded values for user data */
#define USER_DATA_TOP               0x10
#define USER_DATA_LEFT              0x20
#define USER_DATA_WIDTH             0x30
#define USER_DATA_HEIGHT            0x40

/* Example user data struct for user extension */
typedef struct {
    uint16_t        top;
    uint16_t        left;
    uint16_t        width;
    uint16_t        height;
} userDataBox_t;
...
uint32_t bufferSize;
bool                    updateHeader;
userDataBox_t           *box;
...

        if (buffer.format != SENSOR_FORMAT_USER_DATA) {
            printf("Buffer is not of expected format: %d\n", buffer.format);
            break;
        }    
...      
        bufferSize = buffer.info.user_data.data_size;

        /* Fill buffer with data keyed on the buffer number */
        for (j = 0; j < bufferSize; j++) {
            buffer.data[j] = (uint8_t) (i + j);
        }

        // Set timestamp based on publisher's rate - start as 0
        buffer.timestamp = i * publishLatency;

        // Update header portion only if required
        box = (userDataBox_t*) buffer.info.user_data.reserved;
        if (box->left != USER_DATA_LEFT) {
            box->left   = USER_DATA_LEFT;
            box->top    = USER_DATA_TOP;
            box->width  = USER_DATA_WIDTH;
            box->height = USER_DATA_HEIGHT;
            buffer.size = sizeof(sensor_buffer_t) - sizeof(sensor_format_info_t);
            buffer.size += sizeof(sensor_format_user_data_t) - SENSOR_DATA_EXTENDED_SIZE;
            buffer.size += sizeof(userDataBox_t);
            updateHeader = true;
        } else {
            updateHeader = false;
        }
...
      

Publishing interim data

For each buffer that the publisher populates with interim data, you call sensor_interim_data_publish() to indicate that the buffer is ready for a subscriber to use. For example:

...
int err;
sensor_handle_t handle = NULL;
sensor_buffer_t         buffer;
bool updateHeader;
...
err = sensor_interim_data_publish(handle, updateHeader, &buffer);
...