esp-idf/examples/system/esp_event/default_event_loop
2019-09-04 10:53:25 +10:00
..
main examples: use new component registration api 2019-06-21 19:53:29 +08:00
CMakeLists.txt event: Implement event loop library 2018-10-26 13:14:19 +08:00
example_test.py ci: limit example test to ESP32s 2019-09-04 10:53:25 +10:00
Makefile event: Implement event loop library 2018-10-26 13:14:19 +08:00
README.md example: fix expected logging output order for esp_event example 2019-02-14 14:06:04 +08:00

Event Loop Library ('esp_event') Default Event Loop Example

This example illustrates the basics of the event loop library. To keep the example simple, demonstration is limited to the use of the default event loop. The default event loop is the event loop the system uses for its events. For some use cases, this could be sufficient. However, should the user need to create their own event loops, the example user_event_loops should be able to provide guidance.

Here are the things this example illustrates:

Declaring and Defining Events

This example shows the typical setup of having the event base and event IDs declared in a header file and then having the definitions in a source file.

Declaration of the event base makes use of the macro ESP_EVENT_DECLARE_BASE, while the event IDs are declared as an enum; see event_source.h. The source file main.c holds the definition of the event base using the macro ESP_EVENT_DEFINE_BASE.

Creating the Default Event Loop

This example illustrates the creation of the default event loop using the API function esp_event_loop_create_default.

Posting Events to the Default Event Loop

Simply put, posting an event to a loop is the act of queueing its handlers for execution. For the default loop, this is done using the API esp_event_post. The ability to pass event-specific data to the handler is also illustrated.

Handler Registration/Unregistration

This example illustrates handler registration to the default event loop using esp_event_handler_register for (1) specific events, (2) any event under a certain base, and (3) any event. This also shows the possbility of registering multiple handlers to the same event.

Unregistering a handler is done using esp_event_handler_register. Unregistering a handler means that it no longer executes even when the event it was previously registered to gets posted to the loop.

Example Flow Explained

The example flow is best explained using a sample log output.

I (276) default_event_loop: setting up
I (276) default_event_loop: starting event sources
I (276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: posting to default loop
I (276) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 1 out of 5
I (296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_started_handler
I (306) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_any_handler
I (316) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: all_event_handler
I (326) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 1 times
I (336) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
I (806) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 2 out of 5
I (806) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 2 times
I (806) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
I (1276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop
I (1276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 1 out of 3 times
I (1286) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler
I (1296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler
I (1306) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 3 out of 5
I (1316) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: unregistering task_iteration_handler
I (1316) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 3 times
I (1336) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
I (1846) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 4 out of 5
I (1846) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
I (2276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop
I (2276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 2 out of 3 times
I (2286) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler
I (2296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler
I (2346) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 5 out of 5
I (2346) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler
I (3276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop
I (3276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: posting to default loop
I (3286) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 3 out of 3 times
I (3296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler
I (3306) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler
I (3316) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: timer_stopped_handler
I (3326) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: deleted timer event source
I (3326) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: timer_any_handler
I (3336) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: all_event_handler
I (3346) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: deleting task event source

Setting

This example uses two event sources: a periodic timer and a task with a loop inside. Events are raised for the periodic timer when (1) the timer is started (2) the timer period expires and (3) the timer is stopped. Events are raised for the when (1) the loop iterates.

All of the events mentioned above has their own specific handler. There are additional handlers, however. One handler executes when any event under the periodic timer event is posted; while the other executes if any event is posted.

The number of periodic timer expiries and loop iterations are limited. When the limit for the timer expiry is reached, the timer is stopped. When the limit for the iterarations is reached, the task is deleted. In the case of the loop iteration, there is another limit: the number of iterations for when its handler will be unregistered.

Step-by-Step Explanation

The following text explains the important points of the sample log output.

a.

I (297)  default_event_loop: setting up

At this stage the default event loop is created, as well as the handlers for the different events registered.

b.

I (276) default_event_loop: starting event sources
I (276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: posting to default loop
I (276) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 1 out of 5

The two event sources are started. The respective events are posted to the default event loop.

c.

I (296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_started_handler
I (306) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_any_handler
I (316) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: all_event_handler
I (326) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 1 times
I (336) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler

The handlers are executed for the events posted in (b). In addition to event-specific handlers timer_started_handler and task_iteration_handler, the handlers timer_any_handler and all_event_handler also executed.

The handler timer_any_handler executes for any timer event. It can be seen executing for the timer expiry and timer stopped events in the upcoming parts of the log.

On the other hand, all_event_handler executes for any event. This is the reason why it executes for both TIMER_EVENTS:TIMER_EVENT_STARTED and TASK_EVENTS:TASK_ITERATION_EVENT.

For both the timer and task events, notice that the handlers are executed in the same order they are registered in the code. This is a guarantee that the esp_event library provides.

The proceeding lines of the log follows the same pattern: the event is posted to the loop and the handlers are executed.

d.

...
I (1316) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: unregistering task_iteration_handler

At this point in the execution the handler task_iteration_handler is unregistered, therefore it no longer executes when the event TASK_EVENTS:TASK_ITERATION_EVENT is posted.

I (1867) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 4 out of 5
I (1867) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler

...

I (1846) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 4 out of 5
I (1846) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handle

The iteration event continues to get posted, but only all_event_handler gets executed.

e.

...
I (3276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop
I (3276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: posting to default loop
I (3286) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 3 out of 3 times
I (3296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler
I (3306) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler
I (3316) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: timer_stopped_handler
I (3326) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: deleted timer event source

When the periodic timer expiry limit is reached, the event TIMER_EVENTS:TIMER_EVENT_STOPPED is posted to the loop. The periodic timer is consequently deleted in the handler timer_stopped_handler.

...
I (3346) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: deleting task event source
...

The task containing the loop that posts iteration events also gets deleted. The example ends at this point.


See the README.md file in the upper level 'examples' directory for more information about examples.