The event loop library allows components to declare events to which other components can register handlers -- code which will
execute when those events occur. This allows loosely coupled components to attach desired behavior to changes in state of other components
without application involvement. For instance, a high level connection handling library may subscribe to events produced
by the wifi subsystem directly and act on those events. This also simplifies event processing by serializing and deferring
code execution to another context.
Using ``esp_event`` APIs
------------------------
There are two objects of concern for users of this library: events and event loops.
Events are occurences of note. For example, for WiFi, a successful connection to the access point may be an event.
Events are referenced using a two part identifier which are discussed more :ref:`here <esp-event-declaring-defining-events>`.
Event loops are the vehicle by which events get posted by event sources and handled by event handler functions.
These two appear prominently in the event loop library APIs.
Using this library roughly entails the following flow:
1. A user defines a function that should run when an event is posted to a loop. This function is referred to as the event handler. It should have the same signature as :cpp:type:`esp_event_handler_t`.
2. An event loop is created using :cpp:func:`esp_event_loop_create`, which outputs a handle to the loop of type :cpp:type:`esp_event_loop_handle_t`. Event loops created using this API are referred to as user event loops. There is, however, a special type of event loop called the default event loop which are discussed :ref:`here <esp-event-default-loops>`.
3. Components register event handlers to the loop using :cpp:func:`esp_event_handler_register_with`. Handlers can be registered with multiple loops, more on that :ref:`here <esp-event-handler-registration>`.
4. Event sources post an event to the loop using :cpp:func:`esp_event_post_to`.
5. Components wanting to remove their handlers from being called can do so by unregistering from the loop using :cpp:func:`esp_event_handler_unregister_with`.
6. Event loops which are no longer needed can be deleted using :cpp:func:`esp_event_loop_delete`.
As mentioned previously, events consists of two-part identifers: the event base and the event ID. The event base identifies an independent group
of events; the event ID identifies the event within that group. Think of the event base and event ID as a
person's last name and first name, respectively. A last name identifies a family, and the first name identifies a person within that family.
The event loop library provides macros to declare and define the event base easily.
Event base declaration:
..code-block:: c
ESP_EVENT_DECLARE_BASE(EVENT_BASE)
Event base definition:
..code-block:: c
ESP_EVENT_DEFINE_BASE(EVENT_BASE)
..note::
In IDF, the base identifiers for system events are uppercase and are postfixed with ``_EVENT``. For example, the base for wifi events is declared and defined
as ``WIFI_EVENT``, the ethernet event base ``ETHERNET_EVENT``, and so on. The purpose is to have event bases look like constants (although
they are global variables considering the defintions of macros ``ESP_EVENT_DECLARE_BASE`` and ``ESP_EVENT_DEFINE_BASE``).
For event ID's, declaring them as enumerations is recommended. Once again, for visibility, these are typically placed in public header files.
Event ID:
..code-block:: c
enum {
EVENT_ID_1,
EVENT_ID_2,
EVENT_ID_3,
...
}
.._esp-event-default-loops:
Default Event Loop
------------------
The default event loop is a special type of loop used for system events (WiFi events, for example). The handle for this
loop is hidden from the user. The creation, deletion, handler registration/unregistration and posting of events is done
through a variant of the APIs for user event loops. The table below enumerates those variants, and the user event
If the hypothetical event ``MY_EVENT_BASE``, ``MY_EVENT_ID`` is posted, all three handlers ``run_on_event_1``, ``run_on_event_2``,
and ``run_on_event_3`` would execute.
If the hypothetical event ``MY_EVENT_BASE``, ``MY_OTHER_EVENT_ID`` is posted, only ``run_on_event_2`` and ``run_on_event_3`` would execute.
If the hypothetical event ``MY_OTHER_EVENT_BASE``, ``MY_OTHER_EVENT_ID`` is posted, only ``run_on_event_3`` would execute.
Event loop profiling
--------------------
A configuration option :envvar:`CONFIG_EVENT_LOOP_PROFILING` can be enabled in order to activate statistics collection for all event loops created.
The function :cpp:func:`esp_event_dump` can be used to output the collected statistics to a file stream. More details on the information included in the dump
can be found in the :cpp:func:`esp_event_dump` API Reference.
Examples on using the ``esp_event`` library can be found in :example:`system/esp_event`. The examples cover event declaration, loop creation, handler registration and unregistration and event posting.
Other examples which also adopt esp_event library:
*:example:`NMEA Parser <peripherals/uart/nmea0183_parser>`, which will decode the statements received from GPS.