Common Application Framework overview¶
Common Application Framework (CAF) is a set of ready-for-use modules and events built on top of Event Manager. Using CAF allows you to have a consistent event-based architecture in your application.
An example of the application that is using the CAF modules in nRF Connect SDK is nRF Desktop.
Architecture¶
In an event-based application, parts of the application functionality are separated into isolated modules that communicate with each other using Event Manager’s events. These events are defined either by CAF or by the application. They are submitted by modules and other modules can subscribe and react to them.
Every CAF module can use additional libraries or drivers.
The drivers can be used to communicate with hardware.
The module can then broadcast information from the driver using events (for example, the buttons module can submit a button_event
on a button press).
It can also forward information from application to the driver (for example, the LEDs module can display a given LED effect upon receiving led_event
).
In your application, you can use any number of CAF modules together with your own custom modules. Custom modules can use both CAF and custom events. The figure shows an example application that uses one CAF module and one custom module, which has one custom event.
Enabling CAF¶
To enable CAF, complete the following steps:
Enable
CONFIG_CAF
Kconfig option in your project configuration file.Enable and initialize Event Manager. See Configuration for more details.
Submit the first
module_state_event
.
Submit module_state_event
¶
CAF modules are initialized when they receive a module_state_event
that reports MODULE_STATE_READY
of the module main
.
For this to happen, you need to do the following:
Add the following in your
main.c
file:
#define MODULE main
#include <caf/events/module_state_event.h>
Call the following function after Event Manager is initialized:
module_set_state(MODULE_STATE_READY);
This function call submits the required module_state_event
.
For an example implementation, see applications/nrf_desktop/src/main.c
.
CAF modules¶
CAF supports a set of predefined modules. Each of these modules is available for use out of the box and needs to be enabled and configured separately.
There is no limit to the number of modules and events that can be used. However, Event Manager sets the limit of event types in an application to 32, and CAF inherits this limitation.
Configuration of CAF modules¶
Each module must be configured separately. When configuring CAF modules, you will be asked to use the following configuration methods:
Edit Devicetree Specification (DTS) files - These files reflect the hardware configuration. See Devicetree Guide for more information about the DTS data structure.
Edit
_def
files - These files contain configuration arrays for the application modules and are specific to CAF.Select Kconfig options or modify Kconfig files, or both - These reflect the software configuration. See Kconfig - Tips and Best Practices for information about how to configure them.
CAF modules can use all or some of these methods. For example, enabling the CAF: Bluetooth LE advertising module requires enabling Kconfig options and creating a configuration file, while CAF: Bluetooth LE state module can be configured using only Kconfig options.
Adding custom modules¶
As part of your application, you can add your own custom modules. These modules can communicate using Event Manager’s events. However, if you want to add custom modules that communicate with CAF modules using CAF events, you must make sure that they meet the following requirements:
A custom module must register as Event Manager’s listener and subscribe for CAF events that should be handled by that custom module. You can subscribe for a CAF event in the same way as you subscribe for any other Event Manager event. See the Registering a module as listener documentation for instructions about how to configure this.
The module must work with
module_state_event
. It must submit it and react to it.
Note
If you want a module to react to a CAF event, check the event’s documentation for information about the event.
CAF events¶
Listed below are all available CAF events grouped by module, including details about events and how to handle them.
CAF Bluetooth LE common events¶
include/caf/events/ble_common_event.h
subsys/caf/events/ble_common_event.c
-
group
caf_ble_common_event
CAF Bluetooth LE Common Event.
Enums
-
enum
peer_state
¶ Peer states.
State of the Bluetooth connected peer.
Values:
-
enumerator
PEER_STATE_DISCONNECTED
¶ Bluetooth stack disconnected from the remote peer.
-
enumerator
PEER_STATE_DISCONNECTING
¶ An application module called bt_conn_disconnect to disconnect the remote peer. This state can be reported by the module that requests peer disconnection to let other application modules prepare for the planned disconnection.
-
enumerator
PEER_STATE_CONNECTED
¶ Bluetooth stack successfully connected to the remote peer.
-
enumerator
PEER_STATE_SECURED
¶ Bluetooth stack set the connection security to at least level 2 (that is, encryption and no authentication).
-
enumerator
PEER_STATE_CONN_FAILED
¶ Bluetooth stack failed to connect the remote peer.
-
enumerator
PEER_STATE_COUNT
¶ Number of peer states.
-
enumerator
-
enum
peer_operation
¶ Peer operations.
Values:
-
enumerator
PEER_OPERATION_SELECT
¶ The peer change is triggered and waiting for confirmation. The operation is not performed by the Bluetooth stack before the selection is confirmed. PEER_OPERATION_SELECTED should be used for confirmed operation.
-
enumerator
PEER_OPERATION_SELECTED
¶ The peer change is confirmed. That results in swapping used local identity. The peers that are connected to previously used Bluetooth local identity should be disconnected. The application can start peer search for peers related to a new local identity.
-
enumerator
PEER_OPERATION_SCAN_REQUEST
¶ Bluetooth scanning is requested.
-
enumerator
PEER_OPERATION_ERASE
¶ The bond erase is triggered and waiting for confirmation. The operation is not performed by the Bluetooth stack before the erase is confirmed. PEER_OPERATION_ERASED should be used for a confirmed operation.
-
enumerator
PEER_OPERATION_ERASE_ADV
¶ Trigger erase advertising for selected local identity.
-
enumerator
PEER_OPERATION_ERASE_ADV_CANCEL
¶ Cancel ongoing erase advertising.
-
enumerator
PEER_OPERATION_ERASED
¶ The bond erase is confirmed. That results in removing all of the Bluetooth bonds of related local identity.
-
enumerator
PEER_OPERATION_CANCEL
¶ Cancel ongoing peer operation. If PEER_OPERATION_ERASE_ADV is cancelled, PEER_OPERATION_ERASE_ADV_CANCEL must be used instead.
-
enumerator
PEER_OPERATION_COUNT
¶ Number of peer operations.
-
enumerator
-
struct
ble_peer_event
¶ - #include <ble_common_event.h>
Bluetooth LE peer event.
The Bluetooth LE peer event is submitted to inform about state change of a Bluetooth connected peer.
Public Members
-
struct event_header
header
¶ Event header.
-
enum peer_state
state
¶ State of the Bluetooth LE peer.
-
void *
id
¶ ID used to identify Bluetooth connection - pointer to the bt_conn structure.
-
struct event_header
-
struct
ble_peer_operation_event
¶ - #include <ble_common_event.h>
Bluetooth LE peer operation event.
The Bluetooth LE peer operation event informs about operation that is performed on Bluetooth peers related to a given Bluetooth local identity (and application local identity).
For detailed information related to local identities, peer and bond management, see documentation of the Bluetooth LE bond module in nRF Desktop. The Bluetooth LE bond module is an example of application-specific module that implements Bluetooth peer and bond management.
Public Members
-
struct event_header
header
¶ Event header.
-
enum peer_operation
op
¶ Bluetooth LE peer operation.
-
uint8_t
bt_app_id
¶ Local identity related to the peer operation (used by the application).
-
uint8_t
bt_stack_id
¶ Bluetooth local identity related to the peer operation (used by the Bluetooth stack).
-
struct event_header
-
struct
ble_peer_conn_params_event
¶ - #include <ble_common_event.h>
Bluetooth LE connection parameters event.
The Bluetooth LE connection parameters event is submitted to inform either about received Bluetooth connection parameter update request or fact that connection parameters were already updated.
If the event is related to fact that the connection parameters were already updated, values of interval_min and interval_max are the same. They are equal to the connection interval that is in use.
Public Members
-
struct event_header
header
¶ Event header.
-
void *
id
¶ ID used to identify Bluetooth connection - pointer to the bt_conn structure.
-
uint16_t
interval_min
¶ Minimum Connection Interval (N * 1.25 ms).
-
uint16_t
interval_max
¶ Maximum Connection Interval (N * 1.25 ms).
-
uint16_t
latency
¶ Connection Latency.
-
uint16_t
timeout
¶ Supervision Timeout (N * 10 ms).
-
bool
updated
¶ Information if the event is related to the fact that connection parameters were already updated or connection parameter update request was received.
-
struct event_header
-
struct
ble_peer_search_event
¶ - #include <ble_common_event.h>
Bluetooth LE peer search event.
The Bluetooth LE peer search event is submitted to inform if applcation is currently looking for a Bluetooth peer. The event can be related either to Bluetooth scanning or advertising.
Public Members
-
struct event_header
header
¶ Event header.
-
bool
active
¶ Information if application is currently looking for a Bluetooth peer.
-
struct event_header
-
enum
CAF button events¶
include/caf/events/button_event.h
subsys/caf/events/button_event.c
-
group
caf_button_event
CAF Button Event.
- #include <button_event.h>
Button event.
The button event is submitted when a button is pressed or released.
Public Members
Event header.
ID of the button.
Information if the button was pressed or released.
- #include <button_event.h>
CAF click events¶
include/caf/events/click_event.h
subsys/caf/events/click_event.c
-
group
caf_click_event
CAF Click Event.
Enums
-
enum
click
¶ Click types.
The click type refers to the way a button can be pressed.
Values:
-
enumerator
CLICK_NONE
¶ Button pressed and held for a period of time that is too long for CLICK_SHORT, but too short for CLICK_LONG.
-
enumerator
CLICK_SHORT
¶ Button pressed and released after a short time.
-
enumerator
CLICK_LONG
¶ Button pressed and held for a long period of time.
-
enumerator
CLICK_DOUBLE
¶ Two sequences of the button press and release in a short time interval.
-
enumerator
CLICK_COUNT
¶ Number of click types.
-
enumerator
-
struct
click_event
¶ - #include <click_event.h>
Click event.
The click event is submitted when a click type is recorded for one of the monitored buttons.
Public Members
-
struct event_header
header
¶ Event header.
-
uint16_t
key_id
¶ ID of the button - matching the key_id used by the button_event.
-
struct event_header
-
enum
CAF LED events¶
include/caf/events/led_event.h
subsys/caf/events/led_event.c
-
group
caf_led_event
CAF LED Event.
-
struct
led_event
¶ - #include <led_event.h>
LED event.
The LED event is submitted to change effect displayed by the selected LED. The LED effect affects operating mode and color of the LED. The LED effect displayed by the given LED is overridden if LED receives a new LED event. For more information about LED effects see LED Effect.
Public Members
-
struct event_header
header
¶ Event header.
-
size_t
led_id
¶ ID of the LED.
-
const struct led_effect *
led_effect
¶ Pointer to LED effect to be displayed.
-
struct event_header
-
struct
led_ready_event
¶ - #include <led_event.h>
LED ready event.
The LED ready event is submitted to inform that a LED has finished displaying a LED effect. The event is used to notify that the LED is ready to display next effect.
If the displayed LED effect has loop_forever set to true, the effect never ends and the LED ready event should not be submitted.
Public Members
-
struct event_header
header
¶ Event header.
-
size_t
led_id
¶ ID of the LED.
-
const struct led_effect *
led_effect
¶ Pointer to the LED effect that was displayed.
-
struct event_header
-
struct
CAF module state events¶
include/caf/events/module_state_event.h
subsys/caf/events/module_state_event.c
-
group
caf_module_state_event
CAF Module State Event.
Defines
-
MODULE_ID_LIST_SECTION_PREFIX
¶
-
MODULE_ID_PTR_VAR
(mname)¶
-
MODULE_ID_LIST_SECTION_NAME
¶
-
MODULE_ID_LIST_START
¶
-
MODULE_ID_LIST_STOP
¶
-
MODULE_ID_PTR_VAR_EXTERN_DEC
(mname)¶
-
MODULE_IDX
(mname)¶ Get index of module.
For example, the MODULE_IDX(buttons) can be used to get module index of module named buttons.
- Parameters
mname – [in] Name of the module.
- Returns
Index of the module.
-
MODULE_ID
(mname)¶ Get module ID.
For example, the MODULE_ID(buttons) can be used to get module ID of module named buttons.
- Parameters
mname – [in] Name of the module.
- Returns
ID of the module.
Enums
-
enum
module_state
¶ Module states.
Values:
-
enumerator
MODULE_STATE_READY
¶ Module is active. This state is reported when the module is initialized or woken up after suspending.
-
enumerator
MODULE_STATE_OFF
¶ Module is suspended in reaction to power_down_event. The module cannot submit wake_up_event.
-
enumerator
MODULE_STATE_STANDBY
¶ Module is suspended in reaction to power_down_event. The module can submit wake_up_event.
-
enumerator
MODULE_STATE_ERROR
¶ Module reported fatal error.
-
enumerator
MODULE_STATE_COUNT
¶ Number of module states.
-
enumerator
Functions
-
static inline size_t
module_count
(void)¶ Get number of modules.
- Returns
Number of modules.
-
static inline const void *const
module_id_get
(size_t idx)¶ Get ID of module with given index.
- Parameters
idx – [in] Index of the module.
- Returns
Module ID.
-
static inline bool
module_check_id_valid
(size_t module_idx)¶ Check if given module index is valid.
- Parameters
module_idx – [in] The index to check.
- Returns true
Index is valid.
- Returns false
Index is out of valid range.
-
static inline bool
module_flags_check_zero
(const struct module_flags *mf)¶ Check if there is 0 in all the flags.
- Parameters
mf – [in] Pointer to module flags variable.
- Returns true
All the flags have value of 0.
- Returns false
Any of the flags is not 0.
-
static inline bool
module_flags_test_bit
(const struct module_flags *mf, size_t module_idx)¶ Test single module bit.
- Parameters
mf – [in] Pointer to module flags variable.
module_idx – [in] The index of the selected module.
- Returns true
The module bit in flags is set.
- Returns false
The module bit in flags is cleared.
-
static inline void
module_flags_clear_bit
(struct module_flags *mf, size_t module_idx)¶ Clear single module bit.
- Parameters
mf – [inout] Pointer to module flags variable.
module_idx – [in] The index of the selected module.
-
static inline void
module_flags_set_bit
(struct module_flags *mf, size_t module_idx)¶ Set single module bit.
- Parameters
mf – [inout] Pointer to module flags variable.
module_idx – [in] The index of the selected module.
-
static inline void
module_flags_set_bit_to
(struct module_flags *mf, size_t module_idx, bool val)¶ Set single module bit to specified value.
- Parameters
mf – [inout] Pointer to module flags variable.
module_idx – [in] The index of the selected module.
val – [in] The value to be set in a specified module’s bit.
-
static inline bool
check_state
(const struct module_state_event *event, const void *module_id, enum module_state state)¶ Check if the selected module reported the selected state.
The function can be used in event handler to verify if received module state event informs that selected module reported selected state. The MODULE_ID can be used to get module ID of module with selected name.
- Parameters
event – [in] Poitner to handled module state event.
module_id – [in] ID of the selected module.
state – [in] Selected module state.
- Returns true
The module state event informs that selected module reported selected state. Otherwise, false is returned.
-
struct
module_flags
¶ - #include <module_state_event.h>
Structure that provides a flag for every module available in application.
-
struct
module_state_event
¶ - #include <module_state_event.h>
Module state event.
The module state event is submitted by a module to inform that state of the module changed. The module_set_state can be used to submit the module state event for a module. The check_state can be used in event_handler to check if the event carries information that selected module reported selected state. See module_state for details about available module states.
Name of the module must be defined as MODULE before including the module_state_event.h header. For example, “#define MODULE buttons” defines name of the module as buttons. The module name is used to identify a module.
Every application module must register for module state event and submit this event when state of the module changes. An application module can initialize itself when all the required application modules are initialized (report MODULE_STATE_READY). This ensures proper initialization order of the application modules.
Public Members
-
struct event_header
header
¶ Event header.
-
const void *
module_id
¶ ID of the module.
-
enum module_state
state
¶ New state of the module.
-
struct event_header
-
CAF power events¶
include/caf/events/power_event.h
subsys/caf/events/power_event.c
-
group
caf_power_event
CAF Power Event.
-
struct
power_down_event
¶ - #include <power_event.h>
Power down event.
The power down event is submitted to inform the application modules that they should be suspended to reduce the power consumption. The power down event can also be submitted to suspend the modules after an application module reports fatal error submitting module_state_event with state set to MODULE_STATE_ERROR.
An application module that handles the power down event should submit module_state_event with state set to MODULE_STATE_OFF or MODULE_STATE_STANDBY. The MODULE_STATE_STANDBY should be submitted by a module that is capable of submitting wake_up_event to wake up the system on external event. Otherwise MODULE_STATE_OFF should be reported. If the module is unable to suspend at the moment, it should consume the received power down events until it’s ready to suspend itself. The module should also delay submitting the module_state_event until it’s ready to suspend itself.
The module may handle the power down event differently if it’s related to fatal error. In general, an application module should suspend itself, but some of the modules may still need to be active after the fatal error. For example, module that controls hardware LEDs may be used to display LED effect related to the fatal error.
Only the module that controls the power management in the application can submit the power down event. It is also the final subscriber for the power down event. When it receives the power down event, it’s ensured that all other application modules that handle power down event are already suspended. Then it can continue the power down procedure.
Warning
An application module that handles power down event must also handle wake_up_event. Otherwise the module will never be woken up after suspending.
Public Members
-
struct event_header
header
¶ Event header.
-
bool
error
¶ Information if the power down was triggered by a fatal error.
-
struct event_header
-
struct
wake_up_event
¶ - #include <power_event.h>
Wake up event.
The wake up event is submitted to trigger exiting the suspended state.
The wake up event can be submitted by any application module after the application is suspended. The event can be submitted for example on button press or sensor trigger.
Every application module that handles wake up event should exit suspended state, turn on functionalities disabled on power_down_event and submit module_state_event with state set to MODULE_STATE_READY. If the module is already woken up, it should ignore the event. The module must not consume the wake up event to ensure that other listeners will be informed.
The module that controls power management of the application should be an only early subscriber for the wake up event. This module can consume the wake up events to prevent waking up the application modules after fatal error.
Note
For more information about suspending modules see power_down_event.
Public Members
-
struct event_header
header
¶ Event header.
-
struct event_header
-
struct
CAF sensor events¶
include/caf/events/sensor_event.h
subsys/caf/events/sensor_event.c
-
group
caf_sensor_event
CAF Sensor Event.
Enums
-
enum
sensor_state
¶ Sensor states.
Values:
-
enumerator
SENSOR_STATE_DISABLED
¶ Initial state of the sensor. The state is used only before sensor is initialized and it should not be broadcasted using sensor_state_event.
-
enumerator
SENSOR_STATE_SLEEP
¶ Sensor is sleeping and no sampling is performed.
-
enumerator
SENSOR_STATE_ACTIVE
¶ Sensor is sampled periodically.
-
enumerator
SENSOR_STATE_ERROR
¶ Sensor error occurred. The sensor is no longer sampled.
-
enumerator
SENSOR_STATE_COUNT
¶ Number of sensor states.
-
enumerator
Functions
-
static inline size_t
sensor_event_get_data_cnt
(const struct sensor_event *event)¶ Get size of sensor data.
- Parameters
event – [in] Pointer to the sensor_event.
- Returns
Size of the sensor data, expressed as a number of floating-point values.
-
static inline float *
sensor_event_get_data_ptr
(const struct sensor_event *event)¶ Get pointer to the sensor data.
- Parameters
event – [in] Pointer to the sensor_event.
- Returns
Pointer to the sensor data.
-
struct
sensor_state_event
¶ - #include <sensor_event.h>
Sensor state event.
The sensor state event is submitted when state of a sensor changes.
The description field is a pointer to a string that is used to identify the sensor by the application. The Common Application Framework does not impose any standard way of describing sensors. Format and content of the sensor description is defined by the application.
Warning
The sensor state event related to the given sensor must use the same description as @sensor_event related to the sensor.
Public Members
-
struct event_header
header
¶ Event header.
-
const char *
descr
¶ Description of the sensor.
-
enum sensor_state
state
¶ New state of the sensor.
-
struct event_header
-
struct
sensor_event
¶ - #include <sensor_event.h>
Sensor event.
The sensor event is submitted when a sensor is sampled.
The description field is a pointer to a string that is used to identify the sensor by the application. The Common Application Framework does not impose any standard way of describing sensors. Format and content of the sensor description is defined by the application.
The dyndata contains sensor readouts represented as array of floating-point values. Content of the array depends only on selected sensor. For example an accelerometer may report acceleration in X, Y and Z axis as three floating-point values. sensor_event_get_data_cnt and sensor_event_get_data_ptr can be used to access the sensor data provided by a given sensor event.
Warning
The sensor event related to the given sensor must use the same description as @sensor_state_event related to the sensor.
Public Members
-
struct event_header
header
¶ Event header.
-
const char *
descr
¶ Description of the sensor.
-
struct event_dyndata
dyndata
¶ Sensor data. Provided as floating-point values.
-
struct event_header
-
enum