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.
You can check the Common Application Framework preview for a demonstration of how to add ready-for-use and custom CAF modules into an application.
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, you need to enable the required Kconfig option and enable and initialize Event Manager.
You then must submit the first module_state_event
, because CAF modules are initialized when they receive a module_state_event
that reports MODULE_STATE_READY
of the module main
.
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
: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 PEER_STATE_DISCONNECTED
-
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 PEER_OPERATION_SELECT
-
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.
-
struct event_header 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 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.
-
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 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.
-
enum peer_state
CAF button events
include/caf/events/button_event.h
subsys/caf/events/button_event.c
- group caf_button_event
CAF Button Event.
-
struct button_event
- #include <button_event.h>
Button event.
The button event is submitted when a button is pressed or released.
-
struct button_event
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 CLICK_NONE
-
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 header
-
enum click
CAF force power down events
include/caf/events/force_power_down_event.h
subsys/caf/events/force_power_down_event.c
- group caf_force_power_down_event
CAF Force Power Down Event.
Functions
-
static inline void force_power_down(void)
Force power down now.
-
struct force_power_down_event
- #include <force_power_down_event.h>
Simple event to force a quick power down.
The event is called when the device has to power down quickly, without waiting. The device would power down if no wakeup event is generated in short period of time. The keep_alive event would be ignored.
Public Members
-
struct event_header header
Event header.
-
struct event_header header
-
static inline void force_power_down(void)
CAF keep alive events
include/caf/events/keep_alive_event.h
subsys/caf/events/keep_alive_event.c
- group caf_keep_alive_event
CAF Keep Alive Event.
Functions
-
static inline void keep_alive(void)
Keep the device alive.
The function generates the power manager event that would reset the power down counter when processed.
-
static inline void keep_alive(void)
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 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 header
-
struct led_event
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_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.
-
MODULE_NAME
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 MODULE_STATE_READY
Functions
-
static inline size_t module_count(void)
Get number of modules.
- Returns
Number of modules.
-
static inline const void *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 size_t module_idx_get(const void *module_id)
Get IDX of module with given id.
- Parameters
module_id – [in] ID of the module.
- Returns
Module IDX.
-
static inline const char *module_name_get(const void *id)
Get name of the module with given id.
- Parameters
id – [in] Id of the module.
- Returns
Module name.
-
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.
- Return values
true – Index is valid.
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.
- Return values
true – All the flags have value of 0.
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.
- Return values
true – The module bit in flags is set.
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.
- Return values
true – The module state event informs that selected module reported selected state. Otherwise, false is returned.
-
static inline void module_set_state(enum module_state state)
Submit module state event to inform that state of the module changed.
ID of the module is automatically assigned based on name that is defined as MODULE.
- Parameters
state – [in] New state of the module.
-
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 header
-
MODULE_ID_LIST_SECTION_PREFIX
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.
-
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 header
-
struct power_down_event
CAF power manager events
include/caf/events/power_manager_event.h
subsys/caf/events/power_manager_event.c
- group caf_power_manager_event
CAF Power Manager Event.
Enums
-
enum power_manager_level
Available power levels.
The power levels provided by the power manager.
Values:
-
enumerator POWER_MANAGER_LEVEL_ALIVE
Stay alive.
-
enumerator POWER_MANAGER_LEVEL_SUSPENDED
Suspend but do not go to power off.
-
enumerator POWER_MANAGER_LEVEL_OFF
Go to full power off.
-
enumerator POWER_MANAGER_LEVEL_MAX
Number of supported levels.
-
enumerator POWER_MANAGER_LEVEL_ALIVE
Functions
-
static inline void power_manager_restrict(size_t module_idx, enum power_manager_level lvl)
Set the deepest power sleep mode allowed.
- Parameters
module_idx – The index of the module
lvl – Maximal allowed mode
-
struct power_manager_restrict_event
- #include <power_manager_event.h>
An event to specify which power state is allowed by module.
Any module can set maximum allowed power state that can be configured by power manager.
Public Members
-
struct event_header header
Event header.
-
size_t module_idx
The module index.
The index of the module that wish to block possibility to set power mode below specified level.
-
enum power_manager_level level
The deepest sleep mode allowed.
-
struct event_header header
-
enum power_manager_level
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 SENSOR_STATE_DISABLED
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 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.
-
enum sensor_state