Using event mode

Updated: April 19, 2023

Use event mode when you want the sensor to asynchronously notify your application when the sensor has data available or status has changed.

You can use custom events to have the Sensor library asynchronously notify you when the sensor has some data or status information available that can be acted upon. Unlike callback mode, the handling of a sensor event is executed in your application's thread. When you register a sigevent with a specific sensor event, the Sensor library will send you this sigevent type when the given sensor event occurs. It's up to your application to receive this event and handle it accordingly within the thread model of your application. Usually, applications implement a separate event loop to listen for sigevents to handle them approprioately.

In general when you're using event mode to access sensor data or status, do the following:

  1. Define your events. These events are custom signals that are of the structure sigevent (e.g., a SIGEV_PULSE sigevent).
  2. Establish a connection to your application to receive messages from the Sensor library.
  3. Open a connection to the sensor whose data and status you want access to. See Opening and closing a connection to a sensor unit.
  4. Enable your events to associate with a specific sensor event.
  5. Start streaming from the sensor whose data and status you want access to. See Starting and stopping a sensor unit or Starting an interim data unit. Usually, it's the publishers that control the streaming of interim data. Therefore, subscribers are unlikely to call the start and stop functions.
  6. Handle your events when your application receives them.
  7. Stop streaming from the sensor whose data and status you want access to. See Starting and stopping a sensor unit or Starting an interim data unit. Usually, it's the publishers that control the streaming of interim data. Therefore, subscribers are unlikely to call the start and stop functions.
  8. Disable your events when you no longer need them.
  9. Close connection to the sensor whose data and status you want access to. See Opening and closing a connection to a sensor unit.

If you're accessing sensor data, the Sensor library can send events to your application for receiving data when the following sensor events occur:

SENSOR_EVENT_BUFFER
Indicates that a data buffer is now available. Usually this event is of interest to a publisher that's waiting for an available buffer so that it can store the interim data for publishing.
SENSOR_EVENT_STREAM_DATA
Indicates that a data buffer from a sensor that's streaming is available. Usually this event is of interest to a subscriber that's waiting for data to read.

If you're accessing sensor status, the Sensor library can send events to your application for receiving status change when the following sensor events occur:

SENSOR_EVENT_STREAM_STATUS
Indicates that stream status information is available. The Sensor library provides the specific status of the stream to you in the status parameter of the callback function. The status can be one of the statuses of type sensor_devstatus_t.

Some statues may have additional information that's related to the event. For these statuses, the Sensor library specifies the additional information to you in the extra parameter of the callback function.

Ensure that you release any resources that you still have access to before you disable your custom events of type sigvent. Once you disable your events from a specified sensor event, the Sensor library no longer sends your custom event to your application when that sensor event occurs.

Event mode permits you simultaneous access to multiple buffers. However, if you aren't releasing buffers in a timely manner, either the publisher or the subscriber may run out of buffers for processing.

Define your sigevents

The events that the Sensor library sends to you application are structures of type sigevent. Define sigevents that's most suitable for your application; the sigevents can be of different notification types. See sigevent in the QNX Neutrino RTOS C Library Reference.

A simple sigevent that can be used is a pulse. A pulse is a non-blocking message that can carry a small payload. See _pulse in the QNX Neutrino RTOS C Library Reference. For example, you can define pulse codes for each sensor event that you are registering for:

...
#define PULSE_CODE_EVENT_BUFFER   _PULSE_CODE_MINAVAIL
#define PULSE_CODE_STREAM_DATA   (PULSE_CODE_EVENT_BUFFER + 1)
#define PULSE_CODE_STREAM_STATUS (PULSE_CODE_EVENT_BUFFER + 2)
        ...
           

Establish a connection to your application

You need to establish a connection to your application. The Sensor library uses this connection to signal your application to receive an event. For example:

...
int chid = -1;
chid = ChannelCreate(0);

int coid = -1;
coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0);
...              
            

Now, define the events that the Sensor library notifies your application with when it's time for sending that notification type. If you are registering for more than one notification type, you'll need one event for each notification type. Your application can register up to 16 events for each notification type for any one sensor. For example, you can define events that send pulses:

...
struct sigevent buffer_event;
struct sigevent stream_data_event;
struct sigevent stream_status_event;

SIGEV_PULSE_INIT(&buffer_event, coid, SIGEV_PULSE_PRIO_INHERIT, PULSE_CODE_EVENT_BUFFER, 0);

SIGEV_PULSE_INIT(&stream_data_event, coid, SIGEV_PULSE_PRIO_INHERIT, PULSE_CODE_STREAM_DATA, 0);

SIGEV_PULSE_INIT(&stream_status_event, coid, SIGEV_PULSE_PRIO_INHERIT, PULSE_CODE_STREAM_STATUS, 0);
...  
            

Enable your events

Now, enable your events with the Sensor library by calling sensor_enable_event(). For example:

...
sensor_error_t err;
sensor_event_key_t keyBuffer, keyStreamData, keyStreamStatus;
sensor_handle_t handle = NULL;
...
err = sensor_enable_event(handle,
                          SENSOR_EVENT_BUFFER, SENSOR_EVENTMODE_READONLY,
                          &keyBuffer, &buffer_event );
                          
err = sensor_enable_event(handle,
                          SENSOR_EVENT_STREAM_DATA, SENSOR_EVENTMODE_READONLY,
                          &keyStreamData, &stream_data_event );
                          
err = sensor_enable_event(handle,
                          SENSOR_EVENT_STREAM_STATUS, SENSOR_EVENTMODE_READONLY,
                          &keyStreamStatus, &stream_status_event );
...
            

The mode parameter of sensor_enable_event() is applicable only when you're enabling an event to receive data.

Handle your events

In your application, you must have an event loop to handle the events that Sensor library sends to you. Call the appropriate functions to access data or status according to the event that you receive. For example:

...
int chid;
int rcvid;
struct _pulse pulse;
sensor_error_t err;
sensor_handle_t handle = NULL;
sensor_buffer_t buffer
sensor_devstatus_t devstatus;
uint16_t devstatusextra;
union sigval sig_value;
...
while (1) {
   rcvid = MsgReceivePulse(chid, &pulse, sizeof(pulse), NULL);
   ...
   switch (pulse.code) {
      case PULSE_CODE_EVENT_BUFFER:
        ...
        printf("Received a SENSOR_EVENT_BUFFER event\n");
        err = sensor_get_buffer(handle, keyBuffer, &buffer);
        ...
        err = sensor_return_buffer(handle, &buffer);
        ...
      case PULSE_CODE_STREAM_DATA:
        ...
        printf("Received a SENSOR_EVENT_STREAM_DATA event\n");
        err = sensor_get_buffer(handle, keyStreamData, &buffer);
        ...
        err = sensor_return_buffer(handle, &buffer);
        ...
      case PULSE_CODE_STREAM_STATUS:
        ...
        printf("Received a SENSOR_EVENT_STREAM_STATUS event\n");
        ...
        err = sensor_get_status_details(handle, value, &devstatus, &devstatusextra);
        ...
        
}
...
  

Disable your events

When you no longer need signals for specific sensor events, disable them from being sent from the Sensor library by calling sensor_disable_event(). For example:

...
sensor_error_t err;
sensor_event_key_t keyBuffer, keyStreamData, keyStreamStatus;
sensor_handle_t handle = NULL;
...
err = sensor_disable_event(handle, &keyBuffer,);
err = sensor_disable_event(handle, &keyStreamData);
err = sensor_disable_event(handle, &keyStreamStatus);
...
            

Ensure that you release any resources that you still have access to before you disable your events. Once you disable your events from a specified sensor event, the Sensor library no longer invokes triggers your events when that sensor event occurs.