1# Default Event Loop Example 2 3(See the README.md file in the upper level 'examples' directory for more information about examples.) 4 5Note: Should users need to create their own event loops, refer to the **user event loops** [documentation](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/esp_event.html#using-esp-event-apis) and [example](https://github.com/espressif/esp-idf/tree/master/examples/system/esp_event/user_event_loops). 6 7The [**default event loop**](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/esp_event.html#default-event-loop) is an [event loop](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/esp_event.html#) the system uses to post and handle events (e.g. Wi-Fi events). This example demonstrates the usage of the following default event loop features: 8 9### Declaring and Defining Events 10 11This example shows the typical setup of having the event base and event IDs declared in a header file, and having the definitions in a source file. Declaration of the event base makes use of the macro `ESP_EVENT_DECLARE_BASE()`, whilst 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 `ESP_EVENT_DEFINE_BASE()` macro. 12 13### Creating the Default Event Loop 14 15This example illustrates the creation of the default event loop using the API function `esp_event_loop_create_default()`. 16 17### Posting Events to the Default Event Loop 18 19Simply 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 demonstrated. 20 21### Handler Registration/Unregistration 22 23This example demonstrates 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 as well as registering one handler to the same event multiple times. 24 25Unregistering a handler is done using `esp_event_handler_unregister()`. Unregistering a handler means that it no longer executes even when the event it was previously registered to gets posted to the loop. 26 27## How to use example 28 29### Hardware Required 30 31This example should be able to run on any commonly available ESP32 development board. 32 33### Configure the project 34 35``` 36idf.py menuconfig 37``` 38 39### Build and Flash 40 41Build the project and flash it to the board, then run monitor tool to view serial output: 42 43``` 44idf.py -p PORT flash monitor 45``` 46 47(Replace PORT with the name of the serial port to use.) 48 49(To exit the serial monitor, type ``Ctrl-]``.) 50 51See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. 52 53## Example Output 54 55The example should have the following log output: 56 57``` 58I (328) default_event_loop: setting up 59I (338) default_event_loop: starting event sources 60I (338) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: posting to default loop 61I (338) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 1 out of 5 62I (358) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_started_handler, instance 0 63I (368) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_started_handler, instance 1 64I (378) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_started_handler_2 65I (388) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_any_handler 66I (388) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: all_event_handler 67I (398) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 1 times 68I (408) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler 69I (858) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 2 out of 5 70I (858) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 2 times 71I (858) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler 72I (1338) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop 73I (1338) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 1 out of 3 times 74I (1348) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler 75I (1358) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler 76I (1358) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 3 out of 5 77I (1368) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: unregistering task_iteration_handler 78I (1368) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 3 times 79I (1388) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler 80I (1898) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 4 out of 5 81I (1898) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler 82I (2338) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop 83I (2338) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 2 out of 3 times 84I (2348) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler 85I (2358) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler 86I (2398) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 5 out of 5 87I (2398) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler 88I (3338) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop 89I (3338) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: posting to default loop 90I (3348) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 3 out of 3 times 91I (3358) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler 92I (3358) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler 93I (3368) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: timer_stopped_handler 94I (3378) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: deleted timer event source 95I (3388) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: timer_any_handler 96I (3398) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: all_event_handler 97I (3398) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: deleting task event source 98``` 99 100## Example Breakdown 101 102### Setting of Event Sources 103 104This example uses two event sources: 105 106- A periodic timer. An event is raised when (1) the timer is started (2) the timer period expires and (3) the timer is stopped 107- A task with a loop inside. An event is raised for the when (1) the loop iterates. 108 109All of the events mentioned above have their own specific handler, however there are the following additional handlers. 110 111- One handler executes when **any** event under the periodic timer event is posted 112- The other handler executes if **any** event is posted. 113 114The number of periodic timer expiries and loop iterations are limited. When the limit for the number of timer expiries is reached, the timer is stopped. When the limit for the number of iterations 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. 115 116### Step-by-Step Explanation 117 118The following text explains the important points of the [sample log output](#Example-Output). 119 120#### 1. Setting up of default event loop and event handlers 121 122``` 123I (297) default_event_loop: setting up 124``` 125At this stage the default event loop is created, and the handlers for the different events are registered. 126 127 128#### 2. Posting to the event loop 129 130``` 131I (276) default_event_loop: starting event sources 132I (276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: posting to default loop 133I (276) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 1 out of 5 134``` 135The two event sources are started. The respective events are posted to the default event loop. 136 137#### 3. Execution of handlers 138 139``` 140I (358) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_started_handler, instance 0 141I (368) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_started_handler, instance 1 142I (378) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_started_handler_2 143I (306) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: timer_any_handler 144I (316) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STARTED: all_event_handler 145... 146I (326) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: task_iteration_handler, executed 1 times 147I (336) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler 148``` 149The handlers are executed for the events that were posted in **(2)**. Note how `timer_started_handler()` is called twice on the same event post. This shows the ability to register a single event handler to a single event multiple times. Note also how `timer_started_handler_2()` is called on the same event post. This shows that multiple handlers can be registered to a single event. 150In addition to the event-specific handlers `timer_started_handler()` (registered twice), `timer_started_handler_2()` and `task_iteration_handler()`, the `timer_any_handler()` and `all_event_handler()` are also executed. 151 152The `timer_any_handler()` executes for **any** timer event. It can be seen executing for the timer expiry and timer stopped events in the subsequent parts of the log. 153 154On the other hand, `all_event_handler()` executes for **any** event, hence why it executes for both ``TIMER_EVENTS:TIMER_EVENT_STARTED`` and ``TASK_EVENTS:TASK_ITERATION_EVENT``. 155 156For 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. 157 158The subsequent lines of the log follows the same pattern: the event is posted to the loop and the handlers are executed. 159 160#### 4. Unregistering the `task_iteration_handler()` 161 162``` 163... 164I (1316) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: unregistering task_iteration_handler 165``` 166At 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. 167``` 168I (1867) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 4 out of 5 169I (1867) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handler 170... 171I (1846) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: posting to default loop, 4 out of 5 172I (1846) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: all_event_handle 173``` 174The iteration event continues to get posted, but only the `all_event_handler()` gets executed. 175 176#### 5. Iteration Limit 177 178``` 179... 180I (3276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: posting to default loop 181I (3276) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: posting to default loop 182I (3286) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_expiry_handler, executed 3 out of 3 times 183I (3296) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: timer_any_handler 184I (3306) default_event_loop: TIMER_EVENTS:TIMER_EVENT_EXPIRY: all_event_handler 185I (3316) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: timer_stopped_handler 186I (3326) default_event_loop: TIMER_EVENTS:TIMER_EVENT_STOPPED: deleted timer event source 187``` 188When 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()`. 189 190``` 191... 192I (3346) default_event_loop: TASK_EVENTS:TASK_ITERATION_EVENT: deleting task event source 193... 194``` 195The task containing the loop that posts iteration events also gets deleted. The example ends at this point. 196