diff --git a/components/esp8266/CMakeLists.txt b/components/esp8266/CMakeLists.txt index f4ffabba..09bdb5fc 100644 --- a/components/esp8266/CMakeLists.txt +++ b/components/esp8266/CMakeLists.txt @@ -29,8 +29,6 @@ else() "source/esp_wifi_os_adapter.c" "source/esp_wifi.c" "source/ets_printf.c" - "source/event_default_handlers.c" - "source/event_loop.c" "source/phy_init.c" "source/reset_reason.c" "source/startup.c" @@ -53,7 +51,7 @@ else() set(include_dirs "include" "include/driver") - set(requires "esp_common") + set(requires "esp_common" "esp_event") set(priv_requires "wpa_supplicant" "log" "spi_flash" "tcpip_adapter" "esp_ringbuf" "bootloader_support" "nvs_flash" "util") set(fragments linker.lf ld/esp8266_fragments.lf ld/esp8266_bss_fragments.lf) diff --git a/components/esp8266/include/esp_event.h b/components/esp8266/include/esp_event.h deleted file mode 100644 index c3d8e75a..00000000 --- a/components/esp8266/include/esp_event.h +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef __ESP_EVENT_H__ -#define __ESP_EVENT_H__ - -#include -#include - -#include "esp_err.h" -#include "esp_wifi_types.h" -#include "lwip/ip_addr.h" -#include "tcpip_adapter.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ESP_EVENT_IPV6 LWIP_IPV6 - -typedef enum { - SYSTEM_EVENT_WIFI_READY = 0, /**< ESP8266 WiFi ready */ - SYSTEM_EVENT_SCAN_DONE, /**< ESP8266 finish scanning AP */ - SYSTEM_EVENT_STA_START, /**< ESP8266 station start */ - SYSTEM_EVENT_STA_STOP, /**< ESP8266 station stop */ - SYSTEM_EVENT_STA_CONNECTED, /**< ESP8266 station connected to AP */ - SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP8266 station disconnected from AP */ - SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP8266 station changed */ - SYSTEM_EVENT_STA_GOT_IP, /**< ESP8266 station got IP from connected AP */ - SYSTEM_EVENT_STA_LOST_IP, /**< ESP8266 station lost IP and the IP is reset to 0 */ - SYSTEM_EVENT_STA_WPS_ER_SUCCESS, /**< ESP8266 station wps succeeds in enrollee mode */ - SYSTEM_EVENT_STA_WPS_ER_FAILED, /**< ESP8266 station wps fails in enrollee mode */ - SYSTEM_EVENT_STA_WPS_ER_TIMEOUT, /**< ESP8266 station wps timeout in enrollee mode */ - SYSTEM_EVENT_STA_WPS_ER_PIN, /**< ESP8266 station wps pin code in enrollee mode */ - SYSTEM_EVENT_AP_START, /**< ESP8266 soft-AP start */ - SYSTEM_EVENT_AP_STOP, /**< ESP8266 soft-AP stop */ - SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP8266 soft-AP */ - SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP8266 soft-AP */ - SYSTEM_EVENT_AP_STAIPASSIGNED, /**< ESP8266 soft-AP assign an IP to a connected station */ - SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ - SYSTEM_EVENT_GOT_IP6, /**< ESP8266 station or ap or ethernet interface v6IP addr is preferred */ - SYSTEM_EVENT_ETH_START, /**< ESP8266 ethernet start */ - SYSTEM_EVENT_ETH_STOP, /**< ESP8266 ethernet stop */ - SYSTEM_EVENT_ETH_CONNECTED, /**< ESP8266 ethernet phy link up */ - SYSTEM_EVENT_ETH_DISCONNECTED, /**< ESP8266 ethernet phy link down */ - SYSTEM_EVENT_ETH_GOT_IP, /**< ESP8266 ethernet got IP from connected AP */ - SYSTEM_EVENT_MAX -} system_event_id_t; - -/* add this macro define for compatible with old IDF version */ -#ifndef SYSTEM_EVENT_AP_STA_GOT_IP6 -#define SYSTEM_EVENT_AP_STA_GOT_IP6 SYSTEM_EVENT_GOT_IP6 -#endif - -typedef enum { - WPS_FAIL_REASON_NORMAL = 0, /**< ESP8266 WPS normal fail reason */ - WPS_FAIL_REASON_RECV_M2D, /**< ESP8266 WPS receive M2D frame */ - WPS_FAIL_REASON_MAX -}system_event_sta_wps_fail_reason_t; - -typedef struct { - uint32_t status; /**< status of scanning APs */ - uint8_t number; - uint8_t scan_id; -} system_event_sta_scan_done_t; - -typedef struct { - uint8_t ssid[32]; /**< SSID of connected AP */ - uint8_t ssid_len; /**< SSID length of connected AP */ - uint8_t bssid[6]; /**< BSSID of connected AP*/ - uint8_t channel; /**< channel of connected AP*/ - wifi_auth_mode_t authmode; -} system_event_sta_connected_t; - -typedef struct { - uint8_t ssid[32]; /**< SSID of disconnected AP */ - uint8_t ssid_len; /**< SSID length of disconnected AP */ - uint8_t bssid[6]; /**< BSSID of disconnected AP */ - uint8_t reason; /**< reason of disconnection */ -} system_event_sta_disconnected_t; - -typedef struct { - wifi_auth_mode_t old_mode; /**< the old auth mode of AP */ - wifi_auth_mode_t new_mode; /**< the new auth mode of AP */ -} system_event_sta_authmode_change_t; - -typedef struct { - tcpip_adapter_ip_info_t ip_info; - bool ip_changed; -} system_event_sta_got_ip_t; - -typedef struct { - uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */ -} system_event_sta_wps_er_pin_t; - -typedef struct { - tcpip_adapter_if_t if_index; - tcpip_adapter_ip6_info_t ip6_info; -} system_event_got_ip6_t; - -typedef struct { - uint8_t mac[6]; /**< MAC address of the station connected to ESP8266 soft-AP */ - uint8_t aid; /**< the aid that ESP8266 soft-AP gives to the station connected to */ -} system_event_ap_staconnected_t; - -typedef struct { - uint8_t mac[6]; /**< MAC address of the station disconnects to ESP8266 soft-AP */ - uint8_t aid; /**< the aid that ESP8266 soft-AP gave to the station disconnects to */ -} system_event_ap_stadisconnected_t; - -typedef struct { - int rssi; /**< Received probe request signal strength */ - uint8_t mac[6]; /**< MAC address of the station which send probe request */ -} system_event_ap_probe_req_rx_t; - -typedef union { - system_event_sta_connected_t connected; /**< ESP8266 station connected to AP */ - system_event_sta_disconnected_t disconnected; /**< ESP8266 station disconnected to AP */ - system_event_sta_scan_done_t scan_done; /**< ESP8266 station scan (APs) done */ - system_event_sta_authmode_change_t auth_change; /**< the auth mode of AP ESP8266 station connected to changed */ - system_event_sta_got_ip_t got_ip; /**< ESP8266 station got IP, first time got IP or when IP is changed */ - system_event_sta_wps_er_pin_t sta_er_pin; /**< ESP8266 station WPS enrollee mode PIN code received */ - system_event_sta_wps_fail_reason_t sta_er_fail_reason;/**< ESP8266 station WPS enrollee mode failed reason code received */ - system_event_ap_staconnected_t sta_connected; /**< a station connected to ESP8266 soft-AP */ - system_event_ap_stadisconnected_t sta_disconnected; /**< a station disconnected to ESP8266 soft-AP */ - system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP8266 soft-AP receive probe request packet */ - system_event_got_ip6_t got_ip6; /**< ESP8266 station or ap or ethernet ipv6 addr state change to preferred */ -} system_event_info_t; - -typedef struct { - system_event_id_t event_id; /**< event ID */ - system_event_info_t event_info; /**< event information */ -} system_event_t; - -typedef esp_err_t (*system_event_handler_t)(system_event_t *event); - -/** - * @brief Send a event to event task - * - * @attention 1. Other task/modules, such as the TCPIP module, can call this API to send an event to event task - * - * @param system_event_t * event : event - * - * @return ESP_OK : succeed - * @return others : fail - */ -esp_err_t esp_event_send(system_event_t *event); - -/** - * @brief Default event handler for system events - * - * This function performs default handling of system events. - * When using esp_event_loop APIs, it is called automatically before invoking the user-provided - * callback function. - * - * Applications which implement a custom event loop must call this function - * as part of event processing. - * - * @param event pointer to event to be handled - * @return ESP_OK if an event was handled successfully - */ -esp_err_t esp_event_process_default(system_event_t *event); - -/** - * @brief Install default event handlers for Wi-Fi interfaces (station and AP) - * - */ -void esp_event_set_default_wifi_handlers(); - -/** - * @brief Create default event loop - * - * @return - * - ESP_OK: Success - * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list - * - ESP_FAIL: Failed to create task loop - * - Others: Fail - */ -esp_err_t esp_event_loop_create_default(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __ESP_EVENT_H__ */ diff --git a/components/esp8266/include/esp_event_loop.h b/components/esp8266/include/esp_event_loop.h deleted file mode 100644 index 8823b0d3..00000000 --- a/components/esp8266/include/esp_event_loop.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef __ESP_EVENT_LOOP_H__ -#define __ESP_EVENT_LOOP_H__ - -#include -#include - -#include "esp_err.h" -#include "esp_event.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" - -#define EVENT_LOOP_STACKSIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Application specified event callback function - * - * @param void *ctx : reserved for user - * @param system_event_t *event : event type defined in this file - * - * @return ESP_OK : succeed - * @return others : fail - */ -typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event); - -/** - * @brief Initialize event loop - * Create the event handler and task - * - * @param system_event_cb_t cb : application specified event callback, it can be modified by call esp_event_set_cb - * @param void *ctx : reserved for user - * - * @return ESP_OK : succeed - * @return others : fail - */ -esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx); - -/** - * @brief Set application specified event callback function - * - * @attention 1. If cb is NULL, means application don't need to handle - * If cb is not NULL, it will be call when an event is received, after the default event callback is completed - * - * @param system_event_cb_t cb : callback - * @param void *ctx : reserved for user - * - * @return system_event_cb_t : old callback - */ -system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx); - -/** - * @brief Get the queue used by event loop - * - * @attention : currently this API is used to initialize "q" parameter - * of wifi_init structure. - * - * @return QueueHandle_t : event queue handle - */ -QueueHandle_t esp_event_loop_get_queue(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* __ESP_EVENT_LOOP_H__ */ diff --git a/components/esp8266/include/esp_wifi_types.h b/components/esp8266/include/esp_wifi_types.h index 58fdb2b5..f0048aad 100755 --- a/components/esp8266/include/esp_wifi_types.h +++ b/components/esp8266/include/esp_wifi_types.h @@ -18,8 +18,10 @@ #include #include +#include #include "esp_err.h" #include "esp_interface.h" +#include "esp_event_base.h" #ifdef __cplusplus extern "C" { @@ -418,6 +420,91 @@ typedef struct { unsigned unused: 4; /*!< Resolved */ } wifi_tx_status_t; +/** @cond **/ +/** @brief WiFi event base declaration */ +ESP_EVENT_DECLARE_BASE(WIFI_EVENT); +/** @endcond **/ + +/** WiFi event declarations */ +typedef enum { + WIFI_EVENT_WIFI_READY = 0, /**< WiFi ready */ + WIFI_EVENT_SCAN_DONE, /**< finish scanning AP */ + WIFI_EVENT_STA_START, /**< station start */ + WIFI_EVENT_STA_STOP, /**< station stop */ + WIFI_EVENT_STA_CONNECTED, /**< station connected to AP */ + WIFI_EVENT_STA_DISCONNECTED, /**< station disconnected from AP */ + WIFI_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by station changed */ + WIFI_EVENT_STA_WPS_ER_SUCCESS, /**< station wps succeeds in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_FAILED, /**< station wps fails in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_TIMEOUT, /**< station wps timeout in enrollee mode */ + WIFI_EVENT_STA_WPS_ER_PIN, /**< station wps pin code in enrollee mode */ + WIFI_EVENT_AP_START, /**< soft-AP start */ + WIFI_EVENT_AP_STOP, /**< soft-AP stop */ + WIFI_EVENT_AP_STACONNECTED, /**< a station connected to soft-AP */ + WIFI_EVENT_AP_STADISCONNECTED, /**< a station disconnected from soft-AP */ + WIFI_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ +} wifi_event_t; + +/** Argument structure for WIFI_EVENT_STA_WPS_ER_FAILED event */ +typedef enum { + WPS_FAIL_REASON_NORMAL = 0, /**< WPS normal fail reason */ + WPS_FAIL_REASON_RECV_M2D, /**< WPS receive M2D frame */ + WPS_FAIL_REASON_MAX +} wifi_event_sta_wps_fail_reason_t; + +/** Argument structure for WIFI_EVENT_SCAN_DONE event */ +typedef struct { + uint32_t status; /**< status of scanning APs: 0 — success, 1 - failure */ + uint8_t number; /**< number of scan results */ + uint8_t scan_id; /**< scan sequence number, used for block scan */ +} wifi_event_sta_scan_done_t; + +/** Argument structure for WIFI_EVENT_STA_CONNECTED event */ +typedef struct { + uint8_t ssid[32]; /**< SSID of connected AP */ + uint8_t ssid_len; /**< SSID length of connected AP */ + uint8_t bssid[6]; /**< BSSID of connected AP*/ + uint8_t channel; /**< channel of connected AP*/ + wifi_auth_mode_t authmode;/**< authentication mode used by AP*/ +} wifi_event_sta_connected_t; + +/** Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event */ +typedef struct { + wifi_auth_mode_t old_mode; /**< the old auth mode of AP */ + wifi_auth_mode_t new_mode; /**< the new auth mode of AP */ +} wifi_event_sta_authmode_change_t; + +/** Argument structure for WIFI_EVENT_STA_WPS_ER_PIN event */ +typedef struct { + uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */ +} wifi_event_sta_wps_er_pin_t; + +/** Argument structure for WIFI_EVENT_AP_STACONNECTED event */ +typedef struct { + uint8_t mac[6]; /**< MAC address of the station connected to soft-AP */ + uint8_t aid; /**< the aid that soft-AP gives to the station connected to */ +} wifi_event_ap_staconnected_t; + +/** Argument structure for WIFI_EVENT_AP_STADISCONNECTED event */ +typedef struct { + uint8_t mac[6]; /**< MAC address of the station disconnects to soft-AP */ + uint8_t aid; /**< the aid that soft-AP gave to the station disconnects to */ +} wifi_event_ap_stadisconnected_t; + +/** Argument structure for WIFI_EVENT_AP_PROBEREQRECVED event */ +typedef struct { + int rssi; /**< Received probe request signal strength */ + uint8_t mac[6]; /**< MAC address of the station which send probe request */ +} wifi_event_ap_probe_req_rx_t; + +/** Argument structure for WIFI_EVENT_STA_DISCONNECTED event */ +typedef struct { + uint8_t ssid[32]; /**< SSID of disconnected AP */ + uint8_t ssid_len; /**< SSID length of disconnected AP */ + uint8_t bssid[6]; /**< BSSID of disconnected AP */ + uint8_t reason; /**< reason of disconnection */ +} wifi_event_sta_disconnected_t; + #ifdef __cplusplus } #endif diff --git a/components/esp8266/source/esp_wifi.c b/components/esp8266/source/esp_wifi.c index e1ca2c7e..b42a76cb 100644 --- a/components/esp8266/source/esp_wifi.c +++ b/components/esp8266/source/esp_wifi.c @@ -16,9 +16,12 @@ #include "esp_libc.h" #include "esp_system.h" #include "esp_wifi.h" +#include "esp_log.h" #include "internal/esp_wifi_internal.h" #include "phy.h" +#define TAG "wifi_init" + const size_t _g_esp_wifi_ppt_task_stk_size = CONFIG_WIFI_PPT_TASKSTACK_SIZE; #if CONFIG_ESP8266_WIFI_CONNECT_OPEN_ROUTER_WHEN_PWD_IS_SET @@ -29,6 +32,8 @@ const bool _g_esp_wifi_connect_open_router_when_pwd_is_set = false; esp_err_t esp_wifi_init_internal(const wifi_init_config_t *config); +ESP_EVENT_DEFINE_BASE(WIFI_EVENT); + static void esp_wifi_set_debug_log() { /* set WiFi log level and module */ @@ -124,11 +129,16 @@ static void esp_wifi_set_debug_log() */ esp_err_t esp_wifi_init(const wifi_init_config_t *config) { - esp_event_set_default_wifi_handlers(); esp_err_t result = esp_wifi_init_internal(config); if (result == ESP_OK) { esp_wifi_set_debug_log(); } + + result = tcpip_adapter_set_default_wifi_handlers(); + if (result != ESP_OK) { + ESP_LOGW(TAG, "Failed to set default Wi-Fi event handlers (0x%x)", result); + } + return result; } diff --git a/components/esp8266/source/event_default_handlers.c b/components/esp8266/source/event_default_handlers.c deleted file mode 100644 index a3ef8732..00000000 --- a/components/esp8266/source/event_default_handlers.c +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include - -#include "rom/ets_sys.h" - -#include "esp_err.h" -#include "esp_wifi.h" -#include "esp_event.h" -#include "esp_event_loop.h" -#include "esp_system.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" - -#include "tcpip_adapter.h" -#include "esp_log.h" - -static const char* TAG = "event"; - -#define WIFI_API_CALL_CHECK(info, api_call, ret) \ -do{\ - esp_err_t __err = (api_call);\ - if ((ret) != __err) {\ - ESP_LOGE(TAG, "%s %d %s ret=0x%X", __FUNCTION__, __LINE__, (info), __err);\ - return __err;\ - }\ -} while(0) - -typedef esp_err_t (*system_event_handler_t)(system_event_t *e); - -static esp_err_t system_event_ap_start_handle_default(system_event_t *event); -static esp_err_t system_event_ap_stop_handle_default(system_event_t *event); -static esp_err_t system_event_sta_start_handle_default(system_event_t *event); -static esp_err_t system_event_sta_stop_handle_default(system_event_t *event); -static esp_err_t system_event_sta_connected_handle_default(system_event_t *event); -static esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event); -static esp_err_t system_event_sta_got_ip_default(system_event_t *event); -static esp_err_t system_event_sta_lost_ip_default(system_event_t *event); - -/* Default event handler functions - - Any entry in this table which is disabled by config will have a NULL handler. -*/ -static system_event_handler_t default_event_handlers[SYSTEM_EVENT_MAX] = { 0 }; - -static esp_err_t system_event_sta_got_ip_default(system_event_t *event) -{ - ESP_LOGI(TAG, "sta ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR, - IP2STR(&event->event_info.got_ip.ip_info.ip), - IP2STR(&event->event_info.got_ip.ip_info.netmask), - IP2STR(&event->event_info.got_ip.ip_info.gw)); - - return ESP_OK; -} - -static esp_err_t system_event_sta_lost_ip_default(system_event_t *event) -{ - ESP_LOGI(TAG, "station ip lost"); - return ESP_OK; -} - -esp_err_t system_event_ap_start_handle_default(system_event_t *event) -{ - tcpip_adapter_ip_info_t ap_ip; - uint8_t ap_mac[6]; - - WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_AP, ap_mac), ESP_OK); - - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ap_ip); - tcpip_adapter_start(TCPIP_ADAPTER_IF_AP, ap_mac, &ap_ip); - - return ESP_OK; -} - -esp_err_t system_event_ap_stop_handle_default(system_event_t *event) -{ - tcpip_adapter_stop(TCPIP_ADAPTER_IF_AP); - - return ESP_OK; -} - -esp_err_t system_event_sta_start_handle_default(system_event_t *event) -{ - tcpip_adapter_ip_info_t sta_ip; - uint8_t sta_mac[6]; - - WIFI_API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_STA, sta_mac), ESP_OK); - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); - tcpip_adapter_start(TCPIP_ADAPTER_IF_STA, sta_mac, &sta_ip); - - return ESP_OK; -} - -esp_err_t system_event_sta_stop_handle_default(system_event_t *event) -{ - tcpip_adapter_stop(TCPIP_ADAPTER_IF_STA); - - return ESP_OK; -} - -esp_err_t system_event_sta_connected_handle_default(system_event_t *event) -{ - tcpip_adapter_dhcp_status_t status; - - tcpip_adapter_up(TCPIP_ADAPTER_IF_STA); - tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status); - - if (status == TCPIP_ADAPTER_DHCP_INIT) { - tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); - } else if (status == TCPIP_ADAPTER_DHCP_STOPPED) { - tcpip_adapter_ip_info_t sta_ip; - tcpip_adapter_ip_info_t sta_old_ip; - - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); - tcpip_adapter_get_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_old_ip); - - if (!(ip4_addr_isany_val(sta_ip.ip) || ip4_addr_isany_val(sta_ip.netmask) || ip4_addr_isany_val(sta_ip.gw))) { - system_event_t evt; - - evt.event_id = SYSTEM_EVENT_STA_GOT_IP; - evt.event_info.got_ip.ip_changed = false; - - if (memcmp(&sta_ip, &sta_old_ip, sizeof(sta_ip))) { - evt.event_info.got_ip.ip_changed = true; - } - - memcpy(&evt.event_info.got_ip.ip_info, &sta_ip, sizeof(tcpip_adapter_ip_info_t)); - tcpip_adapter_set_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); - - esp_event_send(&evt); - ESP_LOGD(TAG, "static ip: ip changed=%d", evt.event_info.got_ip.ip_changed); - } else { - ESP_LOGE(TAG, "invalid static ip"); - } - } - - return ESP_OK; -} - -esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event) -{ - tcpip_adapter_down(TCPIP_ADAPTER_IF_STA); - return ESP_OK; -} - -static esp_err_t esp_system_event_debug(system_event_t *event) -{ - if (event == NULL) { - ESP_LOGE(TAG, "event is null!"); - printf("event is null!"); - return ESP_FAIL; - } - - switch (event->event_id) { - case SYSTEM_EVENT_WIFI_READY: { - ESP_LOGD(TAG, "SYSTEM_EVENT_WIFI_READY"); - break; - } - case SYSTEM_EVENT_SCAN_DONE: { - system_event_sta_scan_done_t *scan_done = &event->event_info.scan_done; - ESP_LOGD(TAG, "SYSTEM_EVENT_SCAN_DONE, status:%d, number:%d", scan_done->status, scan_done->number); - break; - } - case SYSTEM_EVENT_STA_START: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_START"); - break; - } - case SYSTEM_EVENT_STA_STOP: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_STOP"); - break; - } - case SYSTEM_EVENT_STA_CONNECTED: { - system_event_sta_connected_t *connected = &event->event_info.connected; - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_CONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", channel:%d, authmode:%d", \ - connected->ssid, connected->ssid_len, MAC2STR(connected->bssid), connected->channel, connected->authmode); - break; - } - case SYSTEM_EVENT_STA_DISCONNECTED: { - system_event_sta_disconnected_t *disconnected = &event->event_info.disconnected; - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_DISCONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", reason:%d", \ - disconnected->ssid, disconnected->ssid_len, MAC2STR(disconnected->bssid), disconnected->reason); - break; - } - case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: { - system_event_sta_authmode_change_t *auth_change = &event->event_info.auth_change; - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_AUTHMODE_CHNAGE, old_mode:%d, new_mode:%d", auth_change->old_mode, auth_change->new_mode); - break; - } - case SYSTEM_EVENT_STA_GOT_IP: { - system_event_sta_got_ip_t *got_ip = &event->event_info.got_ip; - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_GOT_IP, ip:" IPSTR ", mask:" IPSTR ", gw:" IPSTR, - IP2STR(&got_ip->ip_info.ip), - IP2STR(&got_ip->ip_info.netmask), - IP2STR(&got_ip->ip_info.gw)); - break; - } - case SYSTEM_EVENT_STA_LOST_IP: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_LOST_IP"); - break; - } - case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_SUCCESS"); - break; - } - case SYSTEM_EVENT_STA_WPS_ER_FAILED: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_FAILED"); - break; - } - case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_TIMEOUT"); - break; - } - case SYSTEM_EVENT_STA_WPS_ER_PIN: { - ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_PIN"); - break; - } - case SYSTEM_EVENT_AP_START: { - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_START"); - break; - } - case SYSTEM_EVENT_AP_STOP: { - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STOP"); - break; - } - case SYSTEM_EVENT_AP_STACONNECTED: { - system_event_ap_staconnected_t *staconnected = &event->event_info.sta_connected; - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STACONNECTED, mac:" MACSTR ", aid:%d", \ - MAC2STR(staconnected->mac), staconnected->aid); - break; - } - case SYSTEM_EVENT_AP_STADISCONNECTED: { - system_event_ap_stadisconnected_t *stadisconnected = &event->event_info.sta_disconnected; - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STADISCONNECTED, mac:" MACSTR ", aid:%d", \ - MAC2STR(stadisconnected->mac), stadisconnected->aid); - break; - } - case SYSTEM_EVENT_AP_STAIPASSIGNED: { - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STAIPASSIGNED"); - break; - } - case SYSTEM_EVENT_AP_PROBEREQRECVED: { - system_event_ap_probe_req_rx_t *ap_probereqrecved = &event->event_info.ap_probereqrecved; - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_PROBEREQRECVED, rssi:%d, mac:" MACSTR, \ - ap_probereqrecved->rssi, \ - MAC2STR(ap_probereqrecved->mac)); - break; - } -#if ESP_EVENT_IPV6 - case SYSTEM_EVENT_GOT_IP6: { - ip6_addr_t *addr = &event->event_info.got_ip6.ip6_info.ip; - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STA_GOT_IP6 address %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", - IP6_ADDR_BLOCK1(addr), - IP6_ADDR_BLOCK2(addr), - IP6_ADDR_BLOCK3(addr), - IP6_ADDR_BLOCK4(addr), - IP6_ADDR_BLOCK5(addr), - IP6_ADDR_BLOCK6(addr), - IP6_ADDR_BLOCK7(addr), - IP6_ADDR_BLOCK8(addr)); - break; - } -#endif - - default: { - ESP_LOGW(TAG, "unexpected system event %d!", event->event_id); - break; - } - } - - return ESP_OK; -} - -esp_err_t esp_event_process_default(system_event_t *event) -{ - if (event == NULL) { - ESP_LOGE(TAG, "Error: event is null!"); - return ESP_FAIL; - } - - esp_system_event_debug(event); - if ((event->event_id < SYSTEM_EVENT_MAX)) { - if (default_event_handlers[event->event_id] != NULL) { - ESP_LOGV(TAG, "enter default callback"); - default_event_handlers[event->event_id](event); - ESP_LOGV(TAG, "exit default callback"); - } - } else { - ESP_LOGE(TAG, "mismatch or invalid event, id=%d", event->event_id); - return ESP_FAIL; - } - return ESP_OK; -} - -void esp_event_set_default_wifi_handlers() -{ - default_event_handlers[SYSTEM_EVENT_STA_START] = system_event_sta_start_handle_default; - default_event_handlers[SYSTEM_EVENT_STA_STOP] = system_event_sta_stop_handle_default; - default_event_handlers[SYSTEM_EVENT_STA_CONNECTED] = system_event_sta_connected_handle_default; - default_event_handlers[SYSTEM_EVENT_STA_DISCONNECTED] = system_event_sta_disconnected_handle_default; - default_event_handlers[SYSTEM_EVENT_STA_GOT_IP] = system_event_sta_got_ip_default; - default_event_handlers[SYSTEM_EVENT_STA_LOST_IP] = system_event_sta_lost_ip_default; - default_event_handlers[SYSTEM_EVENT_AP_START] = system_event_ap_start_handle_default; - default_event_handlers[SYSTEM_EVENT_AP_STOP] = system_event_ap_stop_handle_default; - - //esp_register_shutdown_handler((shutdown_handler_t)esp_wifi_stop); -} \ No newline at end of file diff --git a/components/esp8266/source/event_loop.c b/components/esp8266/source/event_loop.c deleted file mode 100644 index 14f67c65..00000000 --- a/components/esp8266/source/event_loop.c +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include - -#include "esp_err.h" -#include "esp_wifi.h" -#include "esp_event.h" -#include "esp_event_loop.h" - -#include "esp_log.h" -#include "sdkconfig.h" - -#include "FreeRTOS.h" -#include "task.h" -#include "queue.h" - -static const char* TAG = "event"; -static bool s_event_init_flag = false; -static void *s_event_queue = NULL; -static system_event_cb_t s_event_handler_cb = NULL; -static void *s_event_ctx = NULL; - -static esp_err_t esp_event_post_to_user(system_event_t *event) -{ - if (s_event_handler_cb) { - return (*s_event_handler_cb)(s_event_ctx, event); - } - return ESP_OK; -} - -static void esp_event_loop_task(void *pvParameters) -{ - while (1) { - system_event_t evt; - if (xQueueReceive(s_event_queue, &evt, portMAX_DELAY) == pdPASS) { - esp_err_t ret = esp_event_process_default(&evt); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "default event handler failed!"); - } - ret = esp_event_post_to_user(&evt); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "post event to user fail!"); - } - } - } -} - -system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx) -{ - system_event_cb_t old_cb = s_event_handler_cb; - s_event_handler_cb = cb; - s_event_ctx = ctx; - return old_cb; -} - -esp_err_t esp_event_send(system_event_t *event) -{ - if (s_event_queue == NULL) { - ESP_LOGE(TAG, "Event loop not initialized via esp_event_loop_init, but esp_event_send called"); - return ESP_ERR_INVALID_STATE; - } - - int ret = xQueueGenericSend(s_event_queue, event, 0, queueSEND_TO_BACK); - if (ret != pdPASS) { - if (event) { - ESP_LOGE(TAG, "e=%d f", event->event_id); - } else { - ESP_LOGE(TAG, "e null"); - } - return ESP_FAIL; - } - return ESP_OK; -} - -QueueHandle_t esp_event_loop_get_queue(void) -{ - return s_event_queue; -} - -esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx) -{ - if (s_event_init_flag) { - return ESP_FAIL; - } - s_event_handler_cb = cb; - s_event_ctx = ctx; - s_event_queue = xQueueCreate(32, sizeof(system_event_t)); - if(s_event_queue == NULL) - return ESP_ERR_NO_MEM; - if(xTaskCreate(esp_event_loop_task, "esp_event_loop_task", EVENT_LOOP_STACKSIZE, NULL, configMAX_PRIORITIES - 5, NULL) != pdPASS) { - return ESP_ERR_NO_MEM; - } - s_event_handler_cb = cb; - s_event_ctx = ctx; - s_event_init_flag = true; - return ESP_OK; -} - -esp_err_t esp_event_loop_create_default(void) -{ - return ESP_OK; -} diff --git a/components/esp_event/CMakeLists.txt b/components/esp_event/CMakeLists.txt new file mode 100644 index 00000000..5f651174 --- /dev/null +++ b/components/esp_event/CMakeLists.txt @@ -0,0 +1,13 @@ +idf_component_register(SRCS "default_event_loop.c" + "esp_event.c" + "esp_event_private.c" + "event_loop_legacy.c" + "event_send.c" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "private_include" + REQUIRES log tcpip_adapter) + +if(GCC_NOT_5_2_0 AND CONFIG_ESP_EVENT_LOOP_PROFILING) + # uses C11 atomic feature + set_source_files_properties(esp_event.c PROPERTIES COMPILE_FLAGS -std=gnu11) +endif() diff --git a/components/esp_event/Kconfig b/components/esp_event/Kconfig new file mode 100644 index 00000000..ce3c50fd --- /dev/null +++ b/components/esp_event/Kconfig @@ -0,0 +1,17 @@ +menu "Event Loop Library" + + config ESP_EVENT_LOOP_PROFILING + bool "Enable event loop profiling" + default n + help + Enables collections of statistics in the event loop library such as the number of events posted + to/recieved by an event loop, number of callbacks involved, number of events dropped to to a full event + loop queue, run time of event handlers, and number of times/run time of each event handler. + + config ESP_EVENT_POST_FROM_ISR + bool "Support posting events from ISRs" + default y + help + Enable posting events from interrupt handlers. + +endmenu diff --git a/components/esp_event/component.mk b/components/esp_event/component.mk new file mode 100644 index 00000000..c59eccc4 --- /dev/null +++ b/components/esp_event/component.mk @@ -0,0 +1,17 @@ +# +# Component Makefile +# +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_PRIV_INCLUDEDIRS := private_include +COMPONENT_SRCDIRS := . + +ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + PROFILING_ENABLED := 1 +else + PROFILING_ENABLED := 0 +endif + +ifeq ($(and $(GCC_NOT_5_2_0),$(PROFILING_ENABLED)), 1) +# uses C11 atomic feature +esp_event.o: CFLAGS += -std=gnu11 +endif diff --git a/components/esp_event/default_event_loop.c b/components/esp_event/default_event_loop.c new file mode 100644 index 00000000..01418c72 --- /dev/null +++ b/components/esp_event/default_event_loop.c @@ -0,0 +1,120 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_event.h" +#include "esp_event_internal.h" +#include "esp_task.h" + +/* ------------------------- Static Variables ------------------------------- */ + +static esp_event_loop_handle_t s_default_loop = NULL; + +/* ---------------------------- Public API ---------------------------------- */ + +esp_err_t esp_event_handler_register(esp_event_base_t event_base, int32_t event_id, + esp_event_handler_t event_handler, void* event_handler_arg) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_handler_register_with(s_default_loop, event_base, event_id, + event_handler, event_handler_arg); +} + +esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t event_id, + esp_event_handler_t event_handler) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_handler_unregister_with(s_default_loop, event_base, event_id, + event_handler); +} + +esp_err_t esp_event_post(esp_event_base_t event_base, int32_t event_id, + void* event_data, size_t event_data_size, TickType_t ticks_to_wait) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_post_to(s_default_loop, event_base, event_id, + event_data, event_data_size, ticks_to_wait); +} + + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +esp_err_t esp_event_isr_post(esp_event_base_t event_base, int32_t event_id, + void* event_data, size_t event_data_size, BaseType_t* task_unblocked) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_isr_post_to(s_default_loop, event_base, event_id, + event_data, event_data_size, task_unblocked); +} +#endif + + +esp_err_t esp_event_loop_create_default() +{ + if (s_default_loop) { + return ESP_ERR_INVALID_STATE; + } + + esp_event_loop_args_t loop_args = { + .queue_size = CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE, + .task_name = "sys_evt", + .task_stack_size = ESP_TASKD_EVENT_STACK, + .task_priority = ESP_TASKD_EVENT_PRIO, + .task_core_id = 0 + }; + + esp_err_t err; + + err = esp_event_loop_create(&loop_args, &s_default_loop); + if (err != ESP_OK) { + return err; + } + + return ESP_OK; +} + +esp_err_t esp_event_loop_delete_default() +{ + if (!s_default_loop) { + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err; + + err = esp_event_loop_delete(s_default_loop); + + if (err != ESP_OK) { + return err; + } + + s_default_loop = NULL; + + return ESP_OK; +} + + +/* Include the code to forward legacy system_event_t events to the this default + * event loop. + */ +#include "event_send_compat.inc" diff --git a/components/esp_event/esp_event.c b/components/esp_event/esp_event.c new file mode 100644 index 00000000..99a3cf70 --- /dev/null +++ b/components/esp_event/esp_event.c @@ -0,0 +1,944 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "esp_log.h" + +#include "esp_event.h" +#include "esp_event_internal.h" +#include "esp_event_private.h" + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING +#include "esp_timer.h" +#endif + +/* ---------------------------- Definitions --------------------------------- */ + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING +// LOOP @ rx: dr: +#define LOOP_DUMP_FORMAT "LOOP @%p,%s rx:%u dr:%u\n" + // handler @
ev: inv: time: +#define HANDLER_DUMP_FORMAT " HANDLER @%p ev:%s,%s inv:%u time:%lld us\n" + +#define PRINT_DUMP_INFO(dst, sz, ...) do { \ + int cb = snprintf(dst, sz, __VA_ARGS__); \ + dst += cb; \ + sz -= cb; \ + } while(0); +#endif + +/* ------------------------- Static Variables ------------------------------- */ + +static const char* TAG = "event"; +static const char* esp_event_any_base = "any"; + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING +static SLIST_HEAD(esp_event_loop_instance_list_t, esp_event_loop_instance) s_event_loops = + SLIST_HEAD_INITIALIZER(s_event_loops); + +static portMUX_TYPE s_event_loops_spinlock = portMUX_INITIALIZER_UNLOCKED; +#endif + + +/* ------------------------- Static Functions ------------------------------- */ + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + + +static int esp_event_dump_prepare() +{ + esp_event_loop_instance_t* loop_it; + esp_event_loop_node_t *loop_node_it; + esp_event_base_node_t* base_node_it; + esp_event_id_node_t* id_node_it; + esp_event_handler_instance_t* handler_it; + + // Count the number of items to be printed. This is needed to compute how much memory to reserve. + int loops = 0, handlers = 0; + + portENTER_CRITICAL(&s_event_loops_spinlock); + + SLIST_FOREACH(loop_it, &s_event_loops, next) { + SLIST_FOREACH(loop_node_it, &(loop_it->loop_nodes), next) { + SLIST_FOREACH(handler_it, &(loop_node_it->handlers), next) { + handlers++; + } + + SLIST_FOREACH(base_node_it, &(loop_node_it->base_nodes), next) { + SLIST_FOREACH(handler_it, &(base_node_it->handlers), next) { + handlers++; + } + SLIST_FOREACH(id_node_it, &(base_node_it->id_nodes), next) { + SLIST_FOREACH(handler_it, &(id_node_it->handlers), next) { + handlers++; + } + } + } + } + loops++; + } + + portEXIT_CRITICAL(&s_event_loops_spinlock); + + // Reserve slightly more memory than computed + int allowance = 3; + int size = (((loops + allowance) * (sizeof(LOOP_DUMP_FORMAT) + 10 + 20 + 2 * 11)) + + ((handlers + allowance) * (sizeof(HANDLER_DUMP_FORMAT) + 10 + 2 * 20 + 11 + 20))); + + return size; +} +#endif + +static void esp_event_loop_run_task(void* args) +{ + esp_err_t err; + esp_event_loop_handle_t event_loop = (esp_event_loop_handle_t) args; + + ESP_LOGD(TAG, "running task for loop %p", event_loop); + + while(1) { + err = esp_event_loop_run(event_loop, portMAX_DELAY); + if (err != ESP_OK) { + break; + } + } + + ESP_LOGE(TAG, "suspended task for loop %p", event_loop); + vTaskSuspend(NULL); +} + +static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_instance_t *handler, esp_event_post_instance_t post) +{ + ESP_LOGD(TAG, "running post %s:%d with handler %p on loop %p", post.base, post.id, handler->handler, loop); + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + int64_t start, diff; + start = esp_timer_get_time(); +#endif + // Execute the handler +#if CONFIG_ESP_EVENT_POST_FROM_ISR + void* data_ptr = NULL; + + if (post.data_set) { + if (post.data_allocated) { + data_ptr = post.data.ptr; + } else { + data_ptr = &post.data.val; + } + } + + (*(handler->handler))(handler->arg, post.base, post.id, data_ptr); +#else + (*(handler->handler))(handler->arg, post.base, post.id, post.data); +#endif + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + diff = esp_timer_get_time() - start; + + xSemaphoreTake(loop->profiling_mutex, portMAX_DELAY); + + handler->invoked++; + handler->time += diff; + + xSemaphoreGive(loop->profiling_mutex); +#endif +} + +static esp_err_t handler_instances_add(esp_event_handler_instances_t* handlers, esp_event_handler_t handler, void* handler_arg) +{ + esp_event_handler_instance_t* handler_instance = calloc(1, sizeof(*handler_instance)); + + if (!handler_instance) { + return ESP_ERR_NO_MEM; + } + + handler_instance->handler = handler; + handler_instance->arg = handler_arg; + + if (SLIST_EMPTY(handlers)) { + SLIST_INSERT_HEAD(handlers, handler_instance, next); + } + else { + esp_event_handler_instance_t *it = NULL, *last = NULL; + + SLIST_FOREACH(it, handlers, next) { + if (handler == it->handler) { + it->arg = handler_arg; + ESP_LOGW(TAG, "handler already registered, overwriting"); + free(handler_instance); + return ESP_OK; + } + last = it; + } + + SLIST_INSERT_AFTER(last, handler_instance, next); + } + + return ESP_OK; +} + +static esp_err_t base_node_add_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_t handler, void* handler_arg) +{ + if (id == ESP_EVENT_ANY_ID) { + return handler_instances_add(&(base_node->handlers), handler, handler_arg); + } + else { + esp_err_t err = ESP_OK; + esp_event_id_node_t *it = NULL, *id_node = NULL, *last_id_node = NULL; + + SLIST_FOREACH(it, &(base_node->id_nodes), next) { + if (it->id == id) { + id_node = it; + } + last_id_node = it; + } + + if (!last_id_node || !id_node) { + id_node = (esp_event_id_node_t*) calloc(1, sizeof(*id_node)); + + if (!id_node) { + ESP_LOGE(TAG, "alloc for new id node failed"); + return ESP_ERR_NO_MEM; + } + + id_node->id = id; + + SLIST_INIT(&(id_node->handlers)); + + err = handler_instances_add(&(id_node->handlers), handler, handler_arg); + + if (err == ESP_OK) { + if (!last_id_node) { + SLIST_INSERT_HEAD(&(base_node->id_nodes), id_node, next); + } + else { + SLIST_INSERT_AFTER(last_id_node, id_node, next); + } + } else { + free(id_node); + } + + return err; + } + else { + return handler_instances_add(&(id_node->handlers), handler, handler_arg); + } + } +} + +static esp_err_t loop_node_add_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_t handler, void* handler_arg) +{ + if (base == esp_event_any_base && id == ESP_EVENT_ANY_ID) { + return handler_instances_add(&(loop_node->handlers), handler, handler_arg); + } + else { + esp_err_t err = ESP_OK; + esp_event_base_node_t *it = NULL, *base_node = NULL, *last_base_node = NULL; + + SLIST_FOREACH(it, &(loop_node->base_nodes), next) { + if (it->base == base) { + base_node = it; + } + last_base_node = it; + } + + if (!last_base_node || + !base_node || + (base_node && !SLIST_EMPTY(&(base_node->id_nodes)) && id == ESP_EVENT_ANY_ID) || + (last_base_node && last_base_node->base != base && !SLIST_EMPTY(&(last_base_node->id_nodes)) && id == ESP_EVENT_ANY_ID)) { + base_node = (esp_event_base_node_t*) calloc(1, sizeof(*base_node)); + + if (!base_node) { + ESP_LOGE(TAG, "alloc mem for new base node failed"); + return ESP_ERR_NO_MEM; + } + + base_node->base = base; + + SLIST_INIT(&(base_node->handlers)); + SLIST_INIT(&(base_node->id_nodes)); + + err = base_node_add_handler(base_node, id, handler, handler_arg); + + if (err == ESP_OK) { + if (!last_base_node) { + SLIST_INSERT_HEAD(&(loop_node->base_nodes), base_node, next); + } + else { + SLIST_INSERT_AFTER(last_base_node, base_node, next); + } + } else { + free(base_node); + } + + return err; + } else { + return base_node_add_handler(base_node, id, handler, handler_arg); + } + } +} + +static esp_err_t handler_instances_remove(esp_event_handler_instances_t* handlers, esp_event_handler_t handler) +{ + esp_event_handler_instance_t *it, *temp; + + SLIST_FOREACH_SAFE(it, handlers, next, temp) { + if (it->handler == handler) { + SLIST_REMOVE(handlers, it, esp_event_handler_instance, next); + free(it); + return ESP_OK; + } + } + + return ESP_ERR_NOT_FOUND; +} + + +static esp_err_t base_node_remove_handler(esp_event_base_node_t* base_node, int32_t id, esp_event_handler_t handler) +{ + if (id == ESP_EVENT_ANY_ID) { + return handler_instances_remove(&(base_node->handlers), handler); + } + else { + esp_event_id_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(base_node->id_nodes), next, temp) { + if (it->id == id) { + esp_err_t res = handler_instances_remove(&(it->handlers), handler); + + if (res == ESP_OK) { + if (SLIST_EMPTY(&(it->handlers))) { + SLIST_REMOVE(&(base_node->id_nodes), it, esp_event_id_node, next); + free(it); + return ESP_OK; + } + } + } + } + } + + return ESP_ERR_NOT_FOUND; +} + +static esp_err_t loop_node_remove_handler(esp_event_loop_node_t* loop_node, esp_event_base_t base, int32_t id, esp_event_handler_t handler) +{ + if (base == esp_event_any_base && id == ESP_EVENT_ANY_ID) { + return handler_instances_remove(&(loop_node->handlers), handler); + } + else { + esp_event_base_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(loop_node->base_nodes), next, temp) { + if (it->base == base) { + esp_err_t res = base_node_remove_handler(it, id, handler); + + if (res == ESP_OK) { + if (SLIST_EMPTY(&(it->handlers)) && SLIST_EMPTY(&(it->id_nodes))) { + SLIST_REMOVE(&(loop_node->base_nodes), it, esp_event_base_node, next); + free(it); + return ESP_OK; + } + } + } + } + } + + return ESP_ERR_NOT_FOUND; +} + +static void handler_instances_remove_all(esp_event_handler_instances_t* handlers) +{ + esp_event_handler_instance_t *it, *temp; + SLIST_FOREACH_SAFE(it, handlers, next, temp) { + SLIST_REMOVE(handlers, it, esp_event_handler_instance, next); + free(it); + } +} + +static void base_node_remove_all_handler(esp_event_base_node_t* base_node) +{ + handler_instances_remove_all(&(base_node->handlers)); + + esp_event_id_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(base_node->id_nodes), next, temp) { + handler_instances_remove_all(&(it->handlers)); + SLIST_REMOVE(&(base_node->id_nodes), it, esp_event_id_node, next); + free(it); + } +} + +static void loop_node_remove_all_handler(esp_event_loop_node_t* loop_node) +{ + handler_instances_remove_all(&(loop_node->handlers)); + + esp_event_base_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(loop_node->base_nodes), next, temp) { + base_node_remove_all_handler(it); + SLIST_REMOVE(&(loop_node->base_nodes), it, esp_event_base_node, next); + free(it); + } +} + +static void inline __attribute__((always_inline)) post_instance_delete(esp_event_post_instance_t* post) +{ +#if CONFIG_ESP_EVENT_POST_FROM_ISR + if (post->data_allocated && post->data.ptr) { + free(post->data.ptr); + } +#else + if (post->data) { + free(post->data); + } +#endif + memset(post, 0, sizeof(*post)); +} + +/* ---------------------------- Public API --------------------------------- */ + +esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, esp_event_loop_handle_t* event_loop) +{ + assert(event_loop_args); + + esp_event_loop_instance_t* loop; + esp_err_t err = ESP_ERR_NO_MEM; // most likely error + + loop = calloc(1, sizeof(*loop)); + if (loop == NULL) { + ESP_LOGE(TAG, "alloc for event loop failed"); + return err; + } + + loop->queue = xQueueCreate(event_loop_args->queue_size , sizeof(esp_event_post_instance_t)); + if (loop->queue == NULL) { + ESP_LOGE(TAG, "create event loop queue failed"); + goto on_err; + } + + loop->mutex = xSemaphoreCreateRecursiveMutex(); + if (loop->mutex == NULL) { + ESP_LOGE(TAG, "create event loop mutex failed"); + goto on_err; + } + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + loop->profiling_mutex = xSemaphoreCreateMutex(); + if (loop->profiling_mutex == NULL) { + ESP_LOGE(TAG, "create event loop profiling mutex failed"); + goto on_err; + } +#endif + + SLIST_INIT(&(loop->loop_nodes)); + + // Create the loop task if requested + if (event_loop_args->task_name != NULL) { + BaseType_t task_created = xTaskCreatePinnedToCore(esp_event_loop_run_task, event_loop_args->task_name, + event_loop_args->task_stack_size, (void*) loop, + event_loop_args->task_priority, &(loop->task), event_loop_args->task_core_id); + + if (task_created != pdPASS) { + ESP_LOGE(TAG, "create task for loop failed"); + err = ESP_FAIL; + goto on_err; + } + + loop->name = event_loop_args->task_name; + + ESP_LOGD(TAG, "created task for loop %p", loop); + } else { + loop->name = ""; + loop->task = NULL; + } + + loop->running_task = NULL; + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + portENTER_CRITICAL(&s_event_loops_spinlock); + SLIST_INSERT_HEAD(&s_event_loops, loop, next); + portEXIT_CRITICAL(&s_event_loops_spinlock); +#endif + + *event_loop = (esp_event_loop_handle_t) loop; + + ESP_LOGD(TAG, "created event loop %p", loop); + + return ESP_OK; + +on_err: + if (loop->queue != NULL) { + vQueueDelete(loop->queue); + } + + if (loop->mutex != NULL) { + vSemaphoreDelete(loop->mutex); + } + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + if (loop->profiling_mutex != NULL) { + vSemaphoreDelete(loop->profiling_mutex); + } +#endif + + free(loop); + + return err; +} + +// On event lookup performance: The library implements the event list as a linked list, which results to O(n) +// lookup time. The test comparing this implementation to the O(lg n) performance of rbtrees +// (https://github.com/freebsd/freebsd/blob/master/sys/sys/tree.h) +// indicate that the difference is not that substantial, especially considering the additional +// pointers per node of rbtrees. Code for the rbtree implementation of the event loop library is archived +// in feature/esp_event_loop_library_rbtrees if needed. +esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t ticks_to_run) +{ + assert(event_loop); + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + esp_event_post_instance_t post; + TickType_t marker = xTaskGetTickCount(); + TickType_t end = 0; + +#if (configUSE_16_BIT_TICKS == 1) + int32_t remaining_ticks = ticks_to_run; +#else + int64_t remaining_ticks = ticks_to_run; +#endif + + while(xQueueReceive(loop->queue, &post, ticks_to_run) == pdTRUE) { + // The event has already been unqueued, so ensure it gets executed. + xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); + + loop->running_task = xTaskGetCurrentTaskHandle(); + + bool exec = false; + + esp_event_handler_instance_t *handler; + esp_event_loop_node_t *loop_node; + esp_event_base_node_t *base_node; + esp_event_id_node_t *id_node; + + SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) { + // Execute loop level handlers + SLIST_FOREACH(handler, &(loop_node->handlers), next) { + handler_execute(loop, handler, post); + exec |= true; + } + + SLIST_FOREACH(base_node, &(loop_node->base_nodes), next) { + if (base_node->base == post.base) { + // Execute base level handlers + SLIST_FOREACH(handler, &(base_node->handlers), next) { + handler_execute(loop, handler, post); + exec |= true; + } + + SLIST_FOREACH(id_node, &(base_node->id_nodes), next) { + if (id_node->id == post.id) { + // Execute id level handlers + SLIST_FOREACH(handler, &(id_node->handlers), next) { + handler_execute(loop, handler, post); + exec |= true; + } + // Skip to next base node + break; + } + } + } + } + } + + esp_event_base_t base = post.base; + int32_t id = post.id; + + post_instance_delete(&post); + + if (ticks_to_run != portMAX_DELAY) { + end = xTaskGetTickCount(); + remaining_ticks -= end - marker; + // If the ticks to run expired, return to the caller + if (remaining_ticks <= 0) { + xSemaphoreGiveRecursive(loop->mutex); + break; + } else { + marker = end; + } + } + + loop->running_task = NULL; + + xSemaphoreGiveRecursive(loop->mutex); + + if (!exec) { + // No handlers were registered, not even loop/base level handlers + ESP_LOGD(TAG, "no handlers have been registered for event %s:%d posted to loop %p", base, id, event_loop); + } + } + + return ESP_OK; +} + +esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop) +{ + assert(event_loop); + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + SemaphoreHandle_t loop_mutex = loop->mutex; +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + SemaphoreHandle_t loop_profiling_mutex = loop->profiling_mutex; +#endif + + xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + xSemaphoreTakeRecursive(loop->profiling_mutex, portMAX_DELAY); + portENTER_CRITICAL(&s_event_loops_spinlock); + SLIST_REMOVE(&s_event_loops, loop, esp_event_loop_instance, next); + portEXIT_CRITICAL(&s_event_loops_spinlock); +#endif + + // Delete the task if it was created + if (loop->task != NULL) { + vTaskDelete(loop->task); + } + + // Remove all registered events and handlers in the loop + esp_event_loop_node_t *it, *temp; + SLIST_FOREACH_SAFE(it, &(loop->loop_nodes), next, temp) { + loop_node_remove_all_handler(it); + SLIST_REMOVE(&(loop->loop_nodes), it, esp_event_loop_node, next); + free(it); + } + + // Drop existing posts on the queue + esp_event_post_instance_t post; + while(xQueueReceive(loop->queue, &post, 0) == pdTRUE) { + post_instance_delete(&post); + } + + // Cleanup loop + vQueueDelete(loop->queue); + free(loop); + // Free loop mutex before deleting + xSemaphoreGiveRecursive(loop_mutex); +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + xSemaphoreGiveRecursive(loop_profiling_mutex); + vSemaphoreDelete(loop_profiling_mutex); +#endif + vSemaphoreDelete(loop_mutex); + + ESP_LOGD(TAG, "deleted loop %p", (void*) event_loop); + + return ESP_OK; +} + +esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, + int32_t event_id, esp_event_handler_t event_handler, void* event_handler_arg) +{ + assert(event_loop); + assert(event_handler); + + if (event_base == ESP_EVENT_ANY_BASE && event_id != ESP_EVENT_ANY_ID) { + ESP_LOGE(TAG, "registering to any event base with specific id unsupported"); + return ESP_ERR_INVALID_ARG; + } + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + if (event_base == ESP_EVENT_ANY_BASE) { + event_base = esp_event_any_base; + } + + esp_err_t err = ESP_OK; + + xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); + + esp_event_loop_node_t *loop_node = NULL, *last_loop_node = NULL; + + SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) { + last_loop_node = loop_node; + } + + bool is_loop_level_handler = (event_base == esp_event_any_base) && (event_id == ESP_EVENT_ANY_ID); + + if (!last_loop_node || + (last_loop_node && !SLIST_EMPTY(&(last_loop_node->base_nodes)) && is_loop_level_handler)) { + loop_node = (esp_event_loop_node_t*) calloc(1, sizeof(*loop_node)); + + SLIST_INIT(&(loop_node->handlers)); + SLIST_INIT(&(loop_node->base_nodes)); + + if (!loop_node) { + ESP_LOGE(TAG, "alloc for new loop node failed"); + err = ESP_ERR_NO_MEM; + goto on_err; + } + + err = loop_node_add_handler(loop_node, event_base, event_id, event_handler, event_handler_arg); + + if (err == ESP_OK) { + if (!last_loop_node) { + SLIST_INSERT_HEAD(&(loop->loop_nodes), loop_node, next); + } + else { + SLIST_INSERT_AFTER(last_loop_node, loop_node, next); + } + } else { + free(loop_node); + } + } + else { + err = loop_node_add_handler(last_loop_node, event_base, event_id, event_handler, event_handler_arg); + } + +on_err: + xSemaphoreGiveRecursive(loop->mutex); + return err; +} + +esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, + int32_t event_id, esp_event_handler_t event_handler) +{ + assert(event_loop); + assert(event_handler); + + if (event_base == ESP_EVENT_ANY_BASE && event_id != ESP_EVENT_ANY_ID) { + ESP_LOGE(TAG, "unregistering to any event base with specific id unsupported"); + return ESP_FAIL; + } + + if (event_base == ESP_EVENT_ANY_BASE) { + event_base = esp_event_any_base; + } + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + xSemaphoreTakeRecursive(loop->mutex, portMAX_DELAY); + + esp_event_loop_node_t *it, *temp; + + SLIST_FOREACH_SAFE(it, &(loop->loop_nodes), next, temp) { + esp_err_t res = loop_node_remove_handler(it, event_base, event_id, event_handler); + + if (res == ESP_OK && SLIST_EMPTY(&(it->base_nodes)) && SLIST_EMPTY(&(it->handlers))) { + SLIST_REMOVE(&(loop->loop_nodes), it, esp_event_loop_node, next); + free(it); + break; + } + } + + xSemaphoreGiveRecursive(loop->mutex); + + return ESP_OK; +} + +esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, + void* event_data, size_t event_data_size, TickType_t ticks_to_wait) +{ + assert(event_loop); + + if (event_base == ESP_EVENT_ANY_BASE || event_id == ESP_EVENT_ANY_ID) { + return ESP_ERR_INVALID_ARG; + } + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + esp_event_post_instance_t post; + memset((void*)(&post), 0, sizeof(post)); + + if (event_data != NULL && event_data_size != 0) { + // Make persistent copy of event data on heap. + void* event_data_copy = calloc(1, event_data_size); + + if (event_data_copy == NULL) { + return ESP_ERR_NO_MEM; + } + + memcpy(event_data_copy, event_data, event_data_size); +#if CONFIG_ESP_EVENT_POST_FROM_ISR + post.data.ptr = event_data_copy; + post.data_allocated = true; + post.data_set = true; +#else + post.data = event_data_copy; +#endif + } + post.base = event_base; + post.id = event_id; + + BaseType_t result = pdFALSE; + + // Find the task that currently executes the loop. It is safe to query loop->task since it is + // not mutated since loop creation. ENSURE THIS REMAINS TRUE. + if (loop->task == NULL) { + // The loop has no dedicated task. Find out what task is currently running it. + result = xSemaphoreTakeRecursive(loop->mutex, ticks_to_wait); + + if (result == pdTRUE) { + if (loop->running_task != xTaskGetCurrentTaskHandle()) { + xSemaphoreGiveRecursive(loop->mutex); + result = xQueueSendToBack(loop->queue, &post, ticks_to_wait); + } else { + xSemaphoreGiveRecursive(loop->mutex); + result = xQueueSendToBack(loop->queue, &post, 0); + } + } + } else { + // The loop has a dedicated task. + if (loop->task != xTaskGetCurrentTaskHandle()) { + result = xQueueSendToBack(loop->queue, &post, ticks_to_wait); + } else { + result = xQueueSendToBack(loop->queue, &post, 0); + } + } + + if (result != pdTRUE) { + post_instance_delete(&post); + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + atomic_fetch_add(&loop->events_dropped, 1); +#endif + return ESP_ERR_TIMEOUT; + } + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + atomic_fetch_add(&loop->events_recieved, 1); +#endif + + return ESP_OK; +} + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +esp_err_t esp_event_isr_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, + void* event_data, size_t event_data_size, BaseType_t* task_unblocked) +{ + assert(event_loop); + + if (event_base == ESP_EVENT_ANY_BASE || event_id == ESP_EVENT_ANY_ID) { + return ESP_ERR_INVALID_ARG; + } + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + esp_event_post_instance_t post; + memset((void*)(&post), 0, sizeof(post)); + + if (event_data_size > sizeof(post.data.val)) { + return ESP_ERR_INVALID_ARG; + } + + if (event_data != NULL && event_data_size != 0) { + memcpy((void*)(&(post.data.val)), event_data, event_data_size); + post.data_allocated = false; + post.data_set = true; + } + post.base = event_base; + post.id = event_id; + + BaseType_t result = pdFALSE; + + // Post the event from an ISR, + result = xQueueSendToBackFromISR(loop->queue, &post, task_unblocked); + + if (result != pdTRUE) { + post_instance_delete(&post); + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + atomic_fetch_add(&loop->events_dropped, 1); +#endif + return ESP_FAIL; + } + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + atomic_fetch_add(&loop->events_recieved, 1); +#endif + + return ESP_OK; +} +#endif + +esp_err_t esp_event_dump(FILE* file) +{ +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + assert(file); + + esp_event_loop_instance_t* loop_it; + esp_event_loop_node_t *loop_node_it; + esp_event_base_node_t* base_node_it; + esp_event_id_node_t* id_node_it; + esp_event_handler_instance_t* handler_it; + + // Allocate memory for printing + int sz = esp_event_dump_prepare(); + char* buf = calloc(sz, sizeof(char)); + char* dst = buf; + + char id_str_buf[20]; + + // Print info to buffer + portENTER_CRITICAL(&s_event_loops_spinlock); + + SLIST_FOREACH(loop_it, &s_event_loops, next) { + uint32_t events_recieved, events_dropped; + + events_recieved = atomic_load(&loop_it->events_recieved); + events_dropped = atomic_load(&loop_it->events_dropped); + + PRINT_DUMP_INFO(dst, sz, LOOP_DUMP_FORMAT, loop_it, loop_it->task != NULL ? loop_it->name : "none" , + events_recieved, events_dropped); + + int sz_bak = sz; + + SLIST_FOREACH(loop_node_it, &(loop_it->loop_nodes), next) { + SLIST_FOREACH(handler_it, &(loop_node_it->handlers), next) { + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, "ESP_EVENT_ANY_BASE", + "ESP_EVENT_ANY_ID", handler_it->invoked, handler_it->time); + } + + SLIST_FOREACH(base_node_it, &(loop_node_it->base_nodes), next) { + SLIST_FOREACH(handler_it, &(base_node_it->handlers), next) { + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, base_node_it->base , + "ESP_EVENT_ANY_ID", handler_it->invoked, handler_it->time); + } + + SLIST_FOREACH(id_node_it, &(base_node_it->id_nodes), next) { + SLIST_FOREACH(handler_it, &(id_node_it->handlers), next) { + memset(id_str_buf, 0, sizeof(id_str_buf)); + snprintf(id_str_buf, sizeof(id_str_buf), "%d", id_node_it->id); + + PRINT_DUMP_INFO(dst, sz, HANDLER_DUMP_FORMAT, handler_it->handler, base_node_it->base , + id_str_buf, handler_it->invoked, handler_it->time); + } + } + } + } + + // No handlers registered for this loop + if (sz == sz_bak) { + PRINT_DUMP_INFO(dst, sz, " NO HANDLERS REGISTERED\n"); + } + } + + portEXIT_CRITICAL(&s_event_loops_spinlock); + + // Print the contents of the buffer to the file + fprintf(file, buf); + + // Free the allocated buffer + free(buf); +#endif + return ESP_OK; +} diff --git a/components/esp_event/esp_event_private.c b/components/esp_event/esp_event_private.c new file mode 100644 index 00000000..828e458c --- /dev/null +++ b/components/esp_event/esp_event_private.c @@ -0,0 +1,68 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_event_private.h" +#include "esp_event_internal.h" + +#include "esp_log.h" + +bool esp_event_is_handler_registered(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler) +{ + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + bool result = false; + + esp_event_loop_node_t* loop_node; + esp_event_base_node_t* base_node; + esp_event_id_node_t* id_node; + esp_event_handler_instance_t* handler; + + SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) { + SLIST_FOREACH(handler, &(loop_node->handlers), next) { + if(event_base == ESP_EVENT_ANY_BASE && event_id == ESP_EVENT_ANY_ID && handler->handler == event_handler) + { + result = true; + goto out; + } + } + + SLIST_FOREACH(base_node, &(loop_node->base_nodes), next) { + if (base_node->base == event_base) { + SLIST_FOREACH(handler, &(base_node->handlers), next) { + if(event_id == ESP_EVENT_ANY_ID && handler->handler == event_handler) + { + result = true; + goto out; + } + } + + SLIST_FOREACH(id_node, &(base_node->id_nodes), next) { + if(id_node->id == event_id) { + SLIST_FOREACH(handler, &(id_node->handlers), next) { + if(handler->handler == event_handler) + { + result = true; + goto out; + } + } + } + } + } + } + } + +out: + xSemaphoreGive(loop->mutex); + return result; +} \ No newline at end of file diff --git a/components/esp_event/event_loop_legacy.c b/components/esp_event/event_loop_legacy.c new file mode 100644 index 00000000..2b4615aa --- /dev/null +++ b/components/esp_event/event_loop_legacy.c @@ -0,0 +1,101 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_err.h" +#include "esp_log.h" +#include "esp_event_legacy.h" +#include "esp_event.h" + +#include "sdkconfig.h" + +static const char* TAG = "event"; + +static system_event_cb_t s_event_handler_cb; +static void *s_event_ctx; +static bool s_initialized; + +ESP_EVENT_DEFINE_BASE(SYSTEM_EVENT); + +static void esp_event_post_to_user(void* arg, esp_event_base_t base, int32_t id, void* data) +{ + if (s_event_handler_cb) { + system_event_t* event = (system_event_t*) data; + (*s_event_handler_cb)(s_event_ctx, event); + } +} + +system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx) +{ + system_event_cb_t old_cb = s_event_handler_cb; + s_event_handler_cb = cb; + s_event_ctx = ctx; + return old_cb; +} + +esp_err_t esp_event_send_legacy(system_event_t *event) +{ + if (!s_initialized) { + ESP_LOGE(TAG, "system event loop not initialized via esp_event_loop_init"); + return ESP_ERR_INVALID_STATE; + } + + return esp_event_post(SYSTEM_EVENT, event->event_id, event, sizeof(*event), portMAX_DELAY); +} + +esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx) +{ + if (s_initialized) { + ESP_LOGE(TAG, "system event loop already initialized"); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = esp_event_loop_create_default(); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + return err; + } + + err = esp_event_handler_register(SYSTEM_EVENT, ESP_EVENT_ANY_ID, esp_event_post_to_user, NULL); + if (err != ESP_OK) { + return err; + } + + s_initialized = true; + s_event_handler_cb = cb; + s_event_ctx = ctx; + return ESP_OK; +} + +esp_err_t esp_event_loop_deinit() +{ + if (!s_initialized) { + ESP_LOGE(TAG, "system event loop not initialized"); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = esp_event_handler_unregister(SYSTEM_EVENT, ESP_EVENT_ANY_ID, esp_event_post_to_user); + if (err != ESP_OK) { + return err; + } + + err = esp_event_loop_delete_default(); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + return err; + } + + s_initialized = false; + s_event_handler_cb = NULL; + s_event_ctx = NULL; + return ESP_OK; +} + diff --git a/components/esp_event/event_send.c b/components/esp_event/event_send.c new file mode 100644 index 00000000..2c31ee0f --- /dev/null +++ b/components/esp_event/event_send.c @@ -0,0 +1,45 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include "esp_event.h" +#include "esp_event_legacy.h" + +esp_err_t esp_event_send_noop(system_event_t *event); + +extern esp_err_t esp_event_send_legacy(system_event_t *event) __attribute__((weak, alias("esp_event_send_noop"))); +extern esp_err_t esp_event_send_to_default_loop(system_event_t *event) __attribute((weak, alias("esp_event_send_noop"))); + + +esp_err_t esp_event_send_noop(system_event_t *event) +{ + return ESP_OK; +} + +esp_err_t esp_event_send(system_event_t *event) +{ + // send the event to the new style event loop + esp_err_t err = esp_event_send_to_default_loop(event); + if (err != ESP_OK) { + return err; + } + + // send the event to the legacy event loop + err = esp_event_send_legacy(event); + if (err != ESP_OK) { + return err; + } + + return ESP_OK; +} diff --git a/components/esp_event/event_send_compat.inc b/components/esp_event/event_send_compat.inc new file mode 100644 index 00000000..4a954112 --- /dev/null +++ b/components/esp_event/event_send_compat.inc @@ -0,0 +1,275 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_event.h" +#include "esp_log.h" +#include "esp_event_legacy.h" +#include "esp_wifi_types.h" +#include "tcpip_adapter.h" + +/** + * The purpose of this file is to provide an "esp_event_send_to_default_loop" + * function, which is used to forward legacy events (system_event_t) sent using + * esp_event_send, to the new default event loop (esp_event_post). + * + * For each of the events in system_event_id_t, we extract the event data from + * the corresponding system_event_info_t member, and forward that to + * esp_event_post function. + * + * Some macros are used to reduce the amount of boilerplate. + * + * Note that this function only needs to be included into the output file if + * the new default event loop is used. This function is in a separate file for + * readability reasons. In order to be linked if the contents of + * default_event_loop.c is linked, this file is #include-ed into default_event_loop.c. + */ + +//#if LOG_LOCAL_LEVEL >= 4 /* ESP_LOG_DEBUG */ +#if 1 +#define WITH_EVENT_DEBUG +#endif + +#ifdef WITH_EVENT_DEBUG +static void esp_system_event_debug(const system_event_t* event); +#endif + +#define HANDLE_SYS_EVENT(base_, name_) \ + case SYSTEM_EVENT_ ## name_: \ + return esp_event_post(base_ ## _EVENT, base_ ## _EVENT_ ## name_, \ + NULL, 0, send_timeout) + +#define HANDLE_SYS_EVENT_ARG(base_, name_, member_) \ + case SYSTEM_EVENT_ ## name_: \ + return esp_event_post(base_ ## _EVENT, base_ ## _EVENT_ ## name_, \ + &event->event_info.member_, sizeof(event->event_info.member_), \ + send_timeout) + +esp_err_t esp_event_send_to_default_loop(system_event_t *event) +{ +#ifdef WITH_EVENT_DEBUG + esp_system_event_debug(event); +#endif // WITH_EVENT_DEBUG + + const TickType_t send_timeout = 0; + switch (event->event_id) { + /* Wi-Fi common events */ + HANDLE_SYS_EVENT(WIFI, WIFI_READY); + HANDLE_SYS_EVENT_ARG(WIFI, SCAN_DONE, scan_done); + HANDLE_SYS_EVENT(WIFI, STA_START); + HANDLE_SYS_EVENT(WIFI, STA_STOP); + + /* STA events */ + HANDLE_SYS_EVENT_ARG(WIFI, STA_CONNECTED, connected); + HANDLE_SYS_EVENT_ARG(WIFI, STA_DISCONNECTED, disconnected); + HANDLE_SYS_EVENT_ARG(WIFI, STA_AUTHMODE_CHANGE, auth_change); + + /* WPS events */ + HANDLE_SYS_EVENT(WIFI, STA_WPS_ER_SUCCESS); + HANDLE_SYS_EVENT(WIFI, STA_WPS_ER_TIMEOUT); + HANDLE_SYS_EVENT_ARG(WIFI, STA_WPS_ER_FAILED, sta_er_fail_reason); + HANDLE_SYS_EVENT_ARG(WIFI, STA_WPS_ER_PIN, sta_er_pin); + + /* AP events */ + HANDLE_SYS_EVENT(WIFI, AP_START); + HANDLE_SYS_EVENT(WIFI, AP_STOP); + HANDLE_SYS_EVENT_ARG(WIFI, AP_STACONNECTED, sta_connected); + HANDLE_SYS_EVENT_ARG(WIFI, AP_STADISCONNECTED, sta_disconnected); + HANDLE_SYS_EVENT_ARG(WIFI, AP_PROBEREQRECVED, ap_probereqrecved); + + /* IP events */ + HANDLE_SYS_EVENT_ARG(IP, STA_GOT_IP, got_ip); + HANDLE_SYS_EVENT(IP, STA_LOST_IP); + HANDLE_SYS_EVENT_ARG(IP, GOT_IP6, got_ip6); + HANDLE_SYS_EVENT(IP, AP_STAIPASSIGNED); + default: + return ESP_ERR_NOT_SUPPORTED; + } +} + +#ifdef WITH_EVENT_DEBUG + +static const char* TAG = "system_event"; + +typedef struct { + int err; + const char *reason; +} wifi_reason_t; + +static const wifi_reason_t wifi_reason[] = +{ + {0, "other reason"}, + {WIFI_REASON_UNSPECIFIED, "unspecified"}, + {WIFI_REASON_AUTH_EXPIRE, "auth expire"}, + {WIFI_REASON_AUTH_LEAVE, "auth leave"}, + {WIFI_REASON_ASSOC_EXPIRE, "assoc expire"}, + {WIFI_REASON_ASSOC_TOOMANY, "assoc too many"}, + {WIFI_REASON_NOT_AUTHED, "not authed"}, + {WIFI_REASON_NOT_ASSOCED, "not assoced"}, + {WIFI_REASON_ASSOC_LEAVE, "assoc leave"}, + {WIFI_REASON_ASSOC_NOT_AUTHED, "assoc not authed"}, + {WIFI_REASON_BEACON_TIMEOUT, "beacon timeout"}, + {WIFI_REASON_NO_AP_FOUND, "no ap found"}, + {WIFI_REASON_AUTH_FAIL, "auth fail"}, + {WIFI_REASON_ASSOC_FAIL, "assoc fail"}, + {WIFI_REASON_HANDSHAKE_TIMEOUT, "hanshake timeout"}, + {WIFI_REASON_DISASSOC_PWRCAP_BAD, "bad Power Capability, disassoc"}, + {WIFI_REASON_DISASSOC_SUPCHAN_BAD, "bad Supported Channels, disassoc"}, + {WIFI_REASON_IE_INVALID, "invalid IE"}, + {WIFI_REASON_MIC_FAILURE, "MIC failure"}, + {WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT, "4-way keying handshake timeout"}, + {WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT, "Group key handshake"}, + {WIFI_REASON_IE_IN_4WAY_DIFFERS, "IE in 4-way differs"}, + {WIFI_REASON_GROUP_CIPHER_INVALID, "invalid group cipher"}, + {WIFI_REASON_PAIRWISE_CIPHER_INVALID, "invalid pairwise cipher"}, + {WIFI_REASON_AKMP_INVALID, "invalid AKMP"}, + {WIFI_REASON_UNSUPP_RSN_IE_VERSION, "unsupported RSN IE version"}, + {WIFI_REASON_INVALID_RSN_IE_CAP, "invalid RSN IE capability"}, + {WIFI_REASON_802_1X_AUTH_FAILED, "802.1x auth failed"}, + {WIFI_REASON_CIPHER_SUITE_REJECTED, "cipher suite rejected"} +}; + +static const char* wifi_disconnect_reason_to_str(int err) +{ + for (int i=0; i< sizeof(wifi_reason)/sizeof(wifi_reason[0]); i++){ + if (err == wifi_reason[i].err){ + return wifi_reason[i].reason; + } + } + return wifi_reason[0].reason; +} + +static void esp_system_event_debug(const system_event_t* event) +{ + if (event == NULL) { + return; + } + + switch (event->event_id) { + case SYSTEM_EVENT_WIFI_READY: { + ESP_LOGD(TAG, "SYSTEM_EVENT_WIFI_READY"); + break; + } + case SYSTEM_EVENT_SCAN_DONE: { + const system_event_sta_scan_done_t *scan_done = &event->event_info.scan_done; + ESP_LOGD(TAG, "SYSTEM_EVENT_SCAN_DONE, status:%d, number:%d", scan_done->status, scan_done->number); + break; + } + case SYSTEM_EVENT_STA_START: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_START"); + break; + } + case SYSTEM_EVENT_STA_STOP: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_STOP"); + break; + } + case SYSTEM_EVENT_STA_CONNECTED: { + const system_event_sta_connected_t *connected = &event->event_info.connected; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_CONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", channel:%d, authmode:%d", \ + connected->ssid, connected->ssid_len, MAC2STR(connected->bssid), connected->channel, connected->authmode); + break; + } + case SYSTEM_EVENT_STA_DISCONNECTED: { + const system_event_sta_disconnected_t *disconnected = &event->event_info.disconnected; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_DISCONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", reason:%d (%s)", \ + disconnected->ssid, disconnected->ssid_len, MAC2STR(disconnected->bssid), disconnected->reason, + wifi_disconnect_reason_to_str(disconnected->reason)); + break; + } + case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: { + const system_event_sta_authmode_change_t *auth_change = &event->event_info.auth_change; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_AUTHMODE_CHNAGE, old_mode:%d, new_mode:%d", auth_change->old_mode, auth_change->new_mode); + break; + } + case SYSTEM_EVENT_STA_GOT_IP: { + const system_event_sta_got_ip_t *got_ip = &event->event_info.got_ip; + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_GOT_IP, ip:" IPSTR ", mask:" IPSTR ", gw:" IPSTR, + IP2STR(&got_ip->ip_info.ip), + IP2STR(&got_ip->ip_info.netmask), + IP2STR(&got_ip->ip_info.gw)); + break; + } + case SYSTEM_EVENT_STA_LOST_IP: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_LOST_IP"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_SUCCESS"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_FAILED: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_FAILED"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_TIMEOUT"); + break; + } + case SYSTEM_EVENT_STA_WPS_ER_PIN: { + ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_PIN"); + break; + } + case SYSTEM_EVENT_AP_START: { + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_START"); + break; + } + case SYSTEM_EVENT_AP_STOP: { + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STOP"); + break; + } + case SYSTEM_EVENT_AP_STACONNECTED: { + const system_event_ap_staconnected_t *staconnected = &event->event_info.sta_connected; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STACONNECTED, mac:" MACSTR ", aid:%d", \ + MAC2STR(staconnected->mac), staconnected->aid); + break; + } + case SYSTEM_EVENT_AP_STADISCONNECTED: { + const system_event_ap_stadisconnected_t *stadisconnected = &event->event_info.sta_disconnected; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STADISCONNECTED, mac:" MACSTR ", aid:%d", \ + MAC2STR(stadisconnected->mac), stadisconnected->aid); + break; + } + case SYSTEM_EVENT_AP_STAIPASSIGNED: { + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STAIPASSIGNED"); + break; + } + case SYSTEM_EVENT_AP_PROBEREQRECVED: { + const system_event_ap_probe_req_rx_t *ap_probereqrecved = &event->event_info.ap_probereqrecved; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_PROBEREQRECVED, rssi:%d, mac:" MACSTR, \ + ap_probereqrecved->rssi, \ + MAC2STR(ap_probereqrecved->mac)); + break; + } +#if LWIP_IPV6 + case SYSTEM_EVENT_GOT_IP6: { + const ip6_addr_t *addr = &event->event_info.got_ip6.ip6_info.ip; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STA_GOT_IP6 address %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + IP6_ADDR_BLOCK1(addr), + IP6_ADDR_BLOCK2(addr), + IP6_ADDR_BLOCK3(addr), + IP6_ADDR_BLOCK4(addr), + IP6_ADDR_BLOCK5(addr), + IP6_ADDR_BLOCK6(addr), + IP6_ADDR_BLOCK7(addr), + IP6_ADDR_BLOCK8(addr)); + break; + } +#endif + default: { + ESP_LOGW(TAG, "unexpected system event %d!", event->event_id); + break; + } + } +} + +#endif // WITH_EVENT_DEBUG diff --git a/components/esp_event/include/esp_event.h b/components/esp_event/include/esp_event.h new file mode 100644 index 00000000..c7863641 --- /dev/null +++ b/components/esp_event/include/esp_event.h @@ -0,0 +1,382 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_EVENT_H_ +#define ESP_EVENT_H_ + +#include "esp_err.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" + +#include "esp_event_base.h" +#include "esp_event_legacy.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// Configuration for creating event loops +typedef struct { + int32_t queue_size; /**< size of the event loop queue */ + const char* task_name; /**< name of the event loop task; if NULL, + a dedicated task is not created for event loop*/ + UBaseType_t task_priority; /**< priority of the event loop task, ignored if task name is NULL */ + uint32_t task_stack_size; /**< stack size of the event loop task, ignored if task name is NULL */ + BaseType_t task_core_id; /**< core to which the event loop task is pinned to, + ignored if task name is NULL */ +} esp_event_loop_args_t; + +/** + * @brief Create a new event loop. + * + * @param[in] event_loop_args configuration structure for the event loop to create + * @param[out] event_loop handle to the created event loop + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list + * - ESP_FAIL: Failed to create task loop + * - Others: Fail + */ +esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, esp_event_loop_handle_t* event_loop); + +/** + * @brief Delete an existing event loop. + * + * @param[in] event_loop event loop to delete + * + * @return + * - ESP_OK: Success + * - Others: Fail + */ +esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop); + +/** + * @brief Create default event loop + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list + * - ESP_FAIL: Failed to create task loop + * - Others: Fail + */ +esp_err_t esp_event_loop_create_default(); + +/** + * @brief Delete the default event loop + * + * @return + * - ESP_OK: Success + * - Others: Fail + */ +esp_err_t esp_event_loop_delete_default(); + +/** + * @brief Dispatch events posted to an event loop. + * + * This function is used to dispatch events posted to a loop with no dedicated task, i.e task name was set to NULL + * in event_loop_args argument during loop creation. This function includes an argument to limit the amount of time + * it runs, returning control to the caller when that time expires (or some time afterwards). There is no guarantee + * that a call to this function will exit at exactly the time of expiry. There is also no guarantee that events have + * been dispatched during the call, as the function might have spent all of the alloted time waiting on the event queue. + * Once an event has been unqueued, however, it is guaranteed to be dispatched. This guarantee contributes to not being + * able to exit exactly at time of expiry as (1) blocking on internal mutexes is necessary for dispatching the unqueued + * event, and (2) during dispatch of the unqueued event there is no way to control the time occupied by handler code + * execution. The guaranteed time of exit is therefore the alloted time + amount of time required to dispatch + * the last unqueued event. + * + * In cases where waiting on the queue times out, ESP_OK is returned and not ESP_ERR_TIMEOUT, since it is + * normal behavior. + * + * @param[in] event_loop event loop to dispatch posted events from + * @param[in] ticks_to_run number of ticks to run the loop + * + * @note encountering an unknown event that has been posted to the loop will only generate a warning, not an error. + * + * @return + * - ESP_OK: Success + * - Others: Fail + */ +esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t ticks_to_run); + +/** + * @brief Register an event handler to the system event loop. + * + * This function can be used to register a handler for either: (1) specific events, + * (2) all events of a certain event base, or (3) all events known by the system event loop. + * + * - specific events: specify exact event_base and event_id + * - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id + * - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id + * + * Registering multiple handlers to events is possible. Registering a single handler to multiple events is + * also possible. However, registering the same handler to the same event multiple times would cause the + * previous registrations to be overwritten. + * + * @param[in] event_base the base id of the event to register the handler for + * @param[in] event_id the id of the event to register the handler for + * @param[in] event_handler the handler function which gets called when the event is dispatched + * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called + * + * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should + * ensure that event_handler_arg still points to a valid location by the time the handler gets called + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_handler_register(esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, + void* event_handler_arg); + +/** + * @brief Register an event handler to a specific loop. + * + * This function behaves in the same manner as esp_event_handler_register, except the additional + * specification of the event loop to register the handler to. + * + * @param[in] event_loop the event loop to register this handler function to + * @param[in] event_base the base id of the event to register the handler for + * @param[in] event_id the id of the event to register the handler for + * @param[in] event_handler the handler function which gets called when the event is dispatched + * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called + * + * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should + * ensure that event_handler_arg still points to a valid location by the time the handler gets called + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler, + void* event_handler_arg); + +/** + * @brief Unregister a handler with the system event loop. + * + * This function can be used to unregister a handler so that it no longer gets called during dispatch. + * Handlers can be unregistered for either: (1) specific events, (2) all events of a certain event base, + * or (3) all events known by the system event loop + * + * - specific events: specify exact event_base and event_id + * - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id + * - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id + * + * This function ignores unregistration of handlers that has not been previously registered. + * + * @param[in] event_base the base of the event with which to unregister the handler + * @param[in] event_id the id of the event with which to unregister the handler + * @param[in] event_handler the handler to unregister + * + * @return ESP_OK success + * @return ESP_ERR_INVALID_ARG invalid combination of event base and event id + * @return others fail + */ +esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler); + +/** + * @brief Unregister a handler with the system event loop. + * + * This function behaves in the same manner as esp_event_handler_unregister, except the additional specification of + * the event loop to unregister the handler with. + * + * @param[in] event_loop the event loop with which to unregister this handler function + * @param[in] event_base the base of the event with which to unregister the handler + * @param[in] event_id the id of the event with which to unregister the handler + * @param[in] event_handler the handler to unregister + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + esp_event_handler_t event_handler); + +/** + * @brief Posts an event to the system default event loop. The event loop library keeps a copy of event_data and manages + * the copy's lifetime automatically (allocation + deletion); this ensures that the data the + * handler recieves is always valid. + * + * @param[in] event_base the event base that identifies the event + * @param[in] event_id the event id that identifies the event + * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler + * @param[in] event_data_size the size of the event data + * @param[in] ticks_to_wait number of ticks to block on a full event queue + * + * @return + * - ESP_OK: Success + * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, + * queue full when posting from ISR + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_post(esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, + TickType_t ticks_to_wait); + +/** + * @brief Posts an event to the specified event loop. The event loop library keeps a copy of event_data and manages + * the copy's lifetime automatically (allocation + deletion); this ensures that the data the + * handler recieves is always valid. + * + * This function behaves in the same manner as esp_event_post_to, except the additional specification of the event loop + * to post the event to. + * + * @param[in] event_loop the event loop to post to + * @param[in] event_base the event base that identifies the event + * @param[in] event_id the event id that identifies the event + * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler + * @param[in] event_data_size the size of the event data + * @param[in] ticks_to_wait number of ticks to block on a full event queue + * + * @return + * - ESP_OK: Success + * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, + * queue full when posting from ISR + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id + * - Others: Fail + */ +esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, + TickType_t ticks_to_wait); + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +/** + * @brief Special variant of esp_event_post for posting events from interrupt handlers. + * + * @param[in] event_base the event base that identifies the event + * @param[in] event_id the event id that identifies the event + * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler + * @param[in] event_data_size the size of the event data; max is 4 bytes + * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with + * higher priority than currently running task has been unblocked by the posted event; + * a context switch should be requested before the interrupt is existed. + * + * @note this function is only available when CONFIG_ESP_EVENT_POST_FROM_ISR is enabled + * @note when this function is called from an interrupt handler placed in IRAM, this function should + * be placed in IRAM as well by enabling CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Event queue for the default event loop full + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id, + * data size of more than 4 bytes + * - Others: Fail + */ +esp_err_t esp_event_isr_post(esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, + BaseType_t* task_unblocked); + +/** + * @brief Special variant of esp_event_post_to for posting events from interrupt handlers + * + * @param[in] event_base the event base that identifies the event + * @param[in] event_id the event id that identifies the event + * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler + * @param[in] event_data_size the size of the event data + * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with + * higher priority than currently running task has been unblocked by the posted event; + * a context switch should be requested before the interrupt is existed. + * + * @note this function is only available when CONFIG_ESP_EVENT_POST_FROM_ISR is enabled + * @note when this function is called from an interrupt handler placed in IRAM, this function should + * be placed in IRAM as well by enabling CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Event queue for the loop full + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id, + * data size of more than 4 bytes + * - Others: Fail + */ +esp_err_t esp_event_isr_post_to(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, + BaseType_t* task_unblocked); +#endif + +/** + * @brief Dumps statistics of all event loops. + * + * Dumps event loop info in the format: + * + @verbatim + event loop + handler + handler + ... + event loop + handler + handler + ... + + where: + + event loop + format: address,name rx:total_recieved dr:total_dropped + where: + address - memory address of the event loop + name - name of the event loop, 'none' if no dedicated task + total_recieved - number of successfully posted events + total_dropped - number of events unsucessfully posted due to queue being full + + handler + format: address ev:base,id inv:total_invoked run:total_runtime + where: + address - address of the handler function + base,id - the event specified by event base and id this handler executes + total_invoked - number of times this handler has been invoked + total_runtime - total amount of time used for invoking this handler + + @endverbatim + * + * @param[in] file the file stream to output to + * + * @note this function is a noop when CONFIG_ESP_EVENT_LOOP_PROFILING is disabled + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list + * - Others: Fail + */ +esp_err_t esp_event_dump(FILE* file); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // #ifndef ESP_EVENT_H_ diff --git a/components/esp_event/include/esp_event_base.h b/components/esp_event/include/esp_event_base.h new file mode 100644 index 00000000..73bc73be --- /dev/null +++ b/components/esp_event/include/esp_event_base.h @@ -0,0 +1,43 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_EVENT_BASE_H_ +#define ESP_EVENT_BASE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// Defines for declaring and defining event base +#define ESP_EVENT_DECLARE_BASE(id) extern esp_event_base_t id +#define ESP_EVENT_DEFINE_BASE(id) esp_event_base_t id = #id + +// Event loop library types +typedef const char* esp_event_base_t; /**< unique pointer to a subsystem that exposes events */ +typedef void* esp_event_loop_handle_t; /**< a number that identifies an event with respect to a base */ +typedef void (*esp_event_handler_t)(void* event_handler_arg, + esp_event_base_t event_base, + int32_t event_id, + void* event_data); /**< function called when an event is posted to the queue */ + + +// Defines for registering/unregistering event handlers +#define ESP_EVENT_ANY_BASE NULL /**< register handler for any event base */ +#define ESP_EVENT_ANY_ID -1 /**< register handler for any event id */ + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef ESP_EVENT_BASE_H_ diff --git a/components/esp_event/include/esp_event_legacy.h b/components/esp_event/include/esp_event_legacy.h new file mode 100644 index 00000000..671696af --- /dev/null +++ b/components/esp_event/include/esp_event_legacy.h @@ -0,0 +1,221 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#include "esp_err.h" +#include "esp_wifi_types.h" +#include "tcpip_adapter.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** System event types enumeration */ +typedef enum { + SYSTEM_EVENT_WIFI_READY = 0, /*!< WiFi ready */ + SYSTEM_EVENT_SCAN_DONE, /*!< finish scanning AP */ + SYSTEM_EVENT_STA_START, /*!< station start */ + SYSTEM_EVENT_STA_STOP, /*!< station stop */ + SYSTEM_EVENT_STA_CONNECTED, /*!< station connected to AP */ + SYSTEM_EVENT_STA_DISCONNECTED, /*!< station disconnected from AP */ + SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /*!< the auth mode of AP connected by station changed */ + SYSTEM_EVENT_STA_GOT_IP, /*!< station got IP from connected AP */ + SYSTEM_EVENT_STA_LOST_IP, /*!< station lost IP and the IP is reset to 0 */ + SYSTEM_EVENT_STA_WPS_ER_SUCCESS, /*!< station wps succeeds in enrollee mode */ + SYSTEM_EVENT_STA_WPS_ER_FAILED, /*!< station wps fails in enrollee mode */ + SYSTEM_EVENT_STA_WPS_ER_TIMEOUT, /*!< station wps timeout in enrollee mode */ + SYSTEM_EVENT_STA_WPS_ER_PIN, /*!< station wps pin code in enrollee mode */ + SYSTEM_EVENT_AP_START, /*!< soft-AP start */ + SYSTEM_EVENT_AP_STOP, /*!< soft-AP stop */ + SYSTEM_EVENT_AP_STACONNECTED, /*!< a station connected to soft-AP */ + SYSTEM_EVENT_AP_STADISCONNECTED, /*!< a station disconnected from soft-AP */ + SYSTEM_EVENT_AP_STAIPASSIGNED, /*!< soft-AP assign an IP to a connected station */ + SYSTEM_EVENT_AP_PROBEREQRECVED, /*!< Receive probe request packet in soft-AP interface */ + SYSTEM_EVENT_ETH_START, /*!< ethernet start */ + SYSTEM_EVENT_ETH_STOP, /*!< ethernet stop */ + SYSTEM_EVENT_ETH_CONNECTED, /*!< ethernet phy link up */ + SYSTEM_EVENT_ETH_DISCONNECTED, /*!< ethernet phy link down */ + SYSTEM_EVENT_ETH_GOT_IP, /*!< ethernet got IP from connected AP */ + SYSTEM_EVENT_GOT_IP6, /*!< station or ap or ethernet interface v6IP addr is preferred */ + SYSTEM_EVENT_MAX /*!< Number of members in this enum */ +} system_event_id_t; + +/* add this macro define for compatible with old IDF version */ +#ifndef SYSTEM_EVENT_AP_STA_GOT_IP6 +#define SYSTEM_EVENT_AP_STA_GOT_IP6 SYSTEM_EVENT_GOT_IP6 +#endif + + +/** Argument structure of SYSTEM_EVENT_STA_WPS_ER_FAILED event */ +typedef wifi_event_sta_wps_fail_reason_t system_event_sta_wps_fail_reason_t; + +/** Argument structure of SYSTEM_EVENT_SCAN_DONE event */ +typedef wifi_event_sta_scan_done_t system_event_sta_scan_done_t; + +/** Argument structure of SYSTEM_EVENT_STA_CONNECTED event */ +typedef wifi_event_sta_connected_t system_event_sta_connected_t; + +/** Argument structure of SYSTEM_EVENT_STA_DISCONNECTED event */ +typedef wifi_event_sta_disconnected_t system_event_sta_disconnected_t; + +/** Argument structure of SYSTEM_EVENT_STA_AUTHMODE_CHANGE event */ +typedef wifi_event_sta_authmode_change_t system_event_sta_authmode_change_t; + +/** Argument structure of SYSTEM_EVENT_STA_WPS_ER_PIN event */ +typedef wifi_event_sta_wps_er_pin_t system_event_sta_wps_er_pin_t; + +/** Argument structure of event */ +typedef wifi_event_ap_staconnected_t system_event_ap_staconnected_t; + +/** Argument structure of event */ +typedef wifi_event_ap_stadisconnected_t system_event_ap_stadisconnected_t; + +/** Argument structure of event */ +typedef wifi_event_ap_probe_req_rx_t system_event_ap_probe_req_rx_t; + +/** Argument structure of event */ +typedef ip_event_ap_staipassigned_t system_event_ap_staipassigned_t; + +/** Argument structure of event */ +typedef ip_event_got_ip_t system_event_sta_got_ip_t; + +/** Argument structure of event */ +typedef ip_event_got_ip6_t system_event_got_ip6_t; + +/** Union of all possible system_event argument structures */ +typedef union { + system_event_sta_connected_t connected; /*!< station connected to AP */ + system_event_sta_disconnected_t disconnected; /*!< station disconnected to AP */ + system_event_sta_scan_done_t scan_done; /*!< station scan (APs) done */ + system_event_sta_authmode_change_t auth_change; /*!< the auth mode of AP station connected to changed */ + system_event_sta_got_ip_t got_ip; /*!< station got IP, first time got IP or when IP is changed */ + system_event_sta_wps_er_pin_t sta_er_pin; /*!< station WPS enrollee mode PIN code received */ + system_event_sta_wps_fail_reason_t sta_er_fail_reason; /*!< station WPS enrollee mode failed reason code received */ + system_event_ap_staconnected_t sta_connected; /*!< a station connected to soft-AP */ + system_event_ap_stadisconnected_t sta_disconnected; /*!< a station disconnected to soft-AP */ + system_event_ap_probe_req_rx_t ap_probereqrecved; /*!< soft-AP receive probe request packet */ + system_event_ap_staipassigned_t ap_staipassigned; /**< soft-AP assign an IP to the station*/ + system_event_got_ip6_t got_ip6; /*!< station or ap or ethernet ipv6 addr state change to preferred */ +} system_event_info_t; + +/** Event, as a tagged enum */ +typedef struct { + system_event_id_t event_id; /*!< event ID */ + system_event_info_t event_info; /*!< event information */ +} system_event_t; + +/** Event handler function type */ +typedef esp_err_t (*system_event_handler_t)(system_event_t *event); + +/** + * @brief Send a event to event task + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + * Other task/modules, such as the tcpip_adapter, can call this API to send an event to event task + * + * @param event Event to send + * + * @return ESP_OK : succeed + * @return others : fail + */ +esp_err_t esp_event_send(system_event_t *event); + +/** + * @brief Default event handler for system events + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + * This function performs default handling of system events. + * When using esp_event_loop APIs, it is called automatically before invoking the user-provided + * callback function. + * + * Applications which implement a custom event loop must call this function + * as part of event processing. + * + * @param event pointer to event to be handled + * @return ESP_OK if an event was handled successfully + */ +esp_err_t esp_event_process_default(system_event_t *event); + +/** + * @brief Install default event handlers for Ethernet interface + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + */ +void esp_event_set_default_eth_handlers(); + +/** + * @brief Install default event handlers for Wi-Fi interfaces (station and AP) + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + */ +void esp_event_set_default_wifi_handlers(); + +/** + * @brief Application specified event callback function + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + * + * @param ctx reserved for user + * @param event event type defined in this file + * + * @return + * - ESP_OK: succeed + * - others: fail + */ +typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event); + +/** + * @brief Initialize event loop + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + * Create the event handler and task + * + * @param cb application specified event callback, it can be modified by call esp_event_set_cb + * @param ctx reserved for user + * + * @return + * - ESP_OK: succeed + * - others: fail + */ +esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx); + +/** + * @brief Set application specified event callback function + * + * @note This API is part of the legacy event system. New code should use event library API in esp_event.h + * + * @attention 1. If cb is NULL, means application don't need to handle + * If cb is not NULL, it will be call when an event is received, after the default event callback is completed + * + * @param cb application callback function + * @param ctx argument to be passed to callback + * + * + * @return old callback + */ +system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/components/esp_event/include/esp_event_loop.h b/components/esp_event/include/esp_event_loop.h new file mode 100644 index 00000000..6267ee37 --- /dev/null +++ b/components/esp_event/include/esp_event_loop.h @@ -0,0 +1 @@ +#include "esp_event_legacy.h" diff --git a/components/esp_event/private_include/esp_event_internal.h b/components/esp_event/private_include/esp_event_internal.h new file mode 100644 index 00000000..fb970a80 --- /dev/null +++ b/components/esp_event/private_include/esp_event_internal.h @@ -0,0 +1,112 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_EVENT_INTERNAL_H_ +#define ESP_EVENT_INTERNAL_H_ + +#include "esp_event.h" +#include "stdatomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef SLIST_HEAD(base_nodes, base_node) base_nodes_t; + +/// Event handler +typedef struct esp_event_handler_instance { + esp_event_handler_t handler; /**< event handler function*/ + void* arg; /**< event handler argument */ +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + uint32_t invoked; /**< number of times this handler has been invoked */ + int64_t time; /**< total runtime of this handler across all calls */ +#endif + SLIST_ENTRY(esp_event_handler_instance) next; /**< next event handler in the list */ +} esp_event_handler_instance_t; + +typedef SLIST_HEAD(esp_event_handler_instances, esp_event_handler_instance) esp_event_handler_instances_t; + +/// Event +typedef struct esp_event_id_node { + int32_t id; /**< id number of the event */ + esp_event_handler_instances_t handlers; /**< list of handlers to be executed when + this event is raised */ + SLIST_ENTRY(esp_event_id_node) next; /**< pointer to the next event node on the linked list */ +} esp_event_id_node_t; + +typedef SLIST_HEAD(esp_event_id_nodes, esp_event_id_node) esp_event_id_nodes_t; + +typedef struct esp_event_base_node { + esp_event_base_t base; /**< base identifier of the event */ + esp_event_handler_instances_t handlers; /**< event base level handlers, handlers for + all events with this base */ + esp_event_id_nodes_t id_nodes; /**< list of event ids with this base */ + SLIST_ENTRY(esp_event_base_node) next; /**< pointer to the next base node on the linked list */ +} esp_event_base_node_t; + +typedef SLIST_HEAD(esp_event_base_nodes, esp_event_base_node) esp_event_base_nodes_t; + +typedef struct esp_event_loop_node { + esp_event_handler_instances_t handlers; /** event loop level handlers */ + esp_event_base_nodes_t base_nodes; /** list of event bases registered to the loop */ + SLIST_ENTRY(esp_event_loop_node) next; /** pointer to the next loop node containing + event loop level handlers and the rest of + event bases registered to the loop */ +} esp_event_loop_node_t; + +typedef SLIST_HEAD(esp_event_loop_nodes, esp_event_loop_node) esp_event_loop_nodes_t; + +/// Event loop +typedef struct esp_event_loop_instance { + const char* name; /**< name of this event loop */ + QueueHandle_t queue; /**< event queue */ + TaskHandle_t task; /**< task that consumes the event queue */ + TaskHandle_t running_task; /**< for loops with no dedicated task, the + task that consumes the queue */ + SemaphoreHandle_t mutex; /**< mutex for updating the events linked list */ + esp_event_loop_nodes_t loop_nodes; /**< set of linked lists containing the + registered handlers for the loop */ +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + atomic_uint_least32_t events_recieved; /**< number of events successfully posted to the loop */ + atomic_uint_least32_t events_dropped; /**< number of events dropped due to queue being full */ + SemaphoreHandle_t profiling_mutex; /**< mutex used for profiliing */ + SLIST_ENTRY(esp_event_loop_instance) next; /**< next event loop in the list */ +#endif +} esp_event_loop_instance_t; + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +typedef union esp_event_post_data { + uint32_t val; + void *ptr; +} esp_event_post_data_t; +#else +typedef void* esp_event_post_data_t; +#endif + +/// Event posted to the event queue +typedef struct esp_event_post_instance { +#if CONFIG_ESP_EVENT_POST_FROM_ISR + bool data_allocated; /**< indicates whether data is allocated from heap */ + bool data_set; /**< indicates if data is null */ +#endif + esp_event_base_t base; /**< the event base */ + int32_t id; /**< the event id */ + esp_event_post_data_t data; /**< data associated with the event */ +} esp_event_post_instance_t; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // #ifndef ESP_EVENT_INTERNAL_H_ diff --git a/components/esp_event/private_include/esp_event_private.h b/components/esp_event/private_include/esp_event_private.h new file mode 100644 index 00000000..990d5187 --- /dev/null +++ b/components/esp_event/private_include/esp_event_private.h @@ -0,0 +1,54 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_EVENT_PRIVATE_H_ +#define ESP_EVENT_PRIVATE_H_ + +#include "esp_event.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Searches handlers registered with an event loop to see if it has been registered. + * + * @param[in] event_loop the loop to search + * @param[in] event_base the event base to search + * @param[in] event_id the event id to search + * @param[in] event_handler the event handler to look for + * + * @return true handler registered + * @return false handler not registered + * + * @return + * - true: Handler registered + * - false: Handler not registered + */ +bool esp_event_is_handler_registered(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler); + +/** + * @brief Deinitializes the event loop library + * + * @return + * - ESP_OK: Success + * - Others: Fail + */ +esp_err_t esp_event_loop_deinit(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // #ifndef ESP_EVENT_PRIVATE_H_ \ No newline at end of file diff --git a/components/esp_event/test/CMakeLists.txt b/components/esp_event/test/CMakeLists.txt new file mode 100644 index 00000000..8264f10d --- /dev/null +++ b/components/esp_event/test/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRC_DIRS "." + PRIV_INCLUDE_DIRS "../private_include" "." + REQUIRES unity test_utils esp_event driver) diff --git a/components/esp_event/test/component.mk b/components/esp_event/test/component.mk new file mode 100644 index 00000000..22e49edd --- /dev/null +++ b/components/esp_event/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# +COMPONENT_PRIV_INCLUDEDIRS := ../private_include . +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive \ No newline at end of file diff --git a/components/esp_event/test/test_event.c b/components/esp_event/test/test_event.c new file mode 100644 index 00000000..0efc2d49 --- /dev/null +++ b/components/esp_event/test/test_event.c @@ -0,0 +1,1280 @@ +#include +#include + +#include "esp_event.h" +#include "sdkconfig.h" + +#include "freertos/FreeRTOS.h" +#include "esp_event_loop.h" +#include "freertos/task.h" +#include "freertos/portmacro.h" +#include "esp_log.h" +#include "driver/periph_ctrl.h" +#include "driver/timer.h" + +#include "esp_event.h" +#include "esp_event_private.h" +#include "esp_event_internal.h" + +#include "esp_heap_caps.h" + +#include "sdkconfig.h" +#include "unity.h" + +#include "test_utils.h" + +static const char* TAG = "test_event"; + +#define TEST_CONFIG_ITEMS_TO_REGISTER 5 +#define TEST_CONFIG_TASKS_TO_SPAWN 2 + +#define TEST_CONFIG_WAIT_MULTIPLIER 5 + +// The initial logging "initializing test" is to ensure mutex allocation is not counted against memory not being freed +// during teardown. +#define TEST_SETUP() \ + ESP_LOGI(TAG, "initializing test"); \ + size_t free_mem_before = heap_caps_get_free_size(MALLOC_CAP_DEFAULT); \ + test_setup(); \ + s_test_core_id = xPortGetCoreID(); \ + s_test_priority = uxTaskPriorityGet(NULL); + +#define TEST_TEARDOWN() \ + test_teardown(); \ + vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); \ + TEST_ASSERT_EQUAL(free_mem_before, heap_caps_get_free_size(MALLOC_CAP_DEFAULT)); + +typedef struct { + void* data; + SemaphoreHandle_t start; + SemaphoreHandle_t done; +} task_arg_t; + +typedef struct { + esp_event_base_t base; + int32_t id; + esp_event_handler_t* handles; + int32_t num; + esp_event_loop_handle_t loop; + bool is_registration; +} handler_registration_data_t; + +typedef struct { + esp_event_base_t base; + int32_t id; + esp_event_loop_handle_t loop; + int32_t num; +} post_event_data_t; + +typedef struct { + int performed; + int expected; + SemaphoreHandle_t done; +} performance_data_t; + +typedef struct { + void* data; + SemaphoreHandle_t mutex; +} simple_arg_t; + +typedef struct { + int *arr; + int index; +} ordered_data_t; + +static BaseType_t s_test_core_id; +static UBaseType_t s_test_priority; + +ESP_EVENT_DECLARE_BASE(s_test_base1); +ESP_EVENT_DECLARE_BASE(s_test_base2); + +ESP_EVENT_DEFINE_BASE(s_test_base1); +ESP_EVENT_DEFINE_BASE(s_test_base2); + +enum { + TEST_EVENT_BASE1_EV1, + TEST_EVENT_BASE1_EV2, + TEST_EVENT_BASE1_MAX +}; + +enum { + TEST_EVENT_BASE2_EV1, + TEST_EVENT_BASE2_EV2, + TEST_EVENT_BASE2_MAX +}; + +static BaseType_t test_event_get_core() +{ + static int calls = 0; + + if (portNUM_PROCESSORS > 1) { + return (s_test_core_id + calls++) % portNUM_PROCESSORS; + } else { + return s_test_core_id; + } +} + +static esp_event_loop_args_t test_event_get_default_loop_args() +{ + esp_event_loop_args_t loop_config = { + .queue_size = CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE, + .task_name = "loop", + .task_priority = s_test_priority, + .task_stack_size = 2048, + .task_core_id = test_event_get_core() + }; + + return loop_config; +} + +static void test_event_simple_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + if (!event_handler_arg) { + return; + } + simple_arg_t* arg = (simple_arg_t*) event_handler_arg; + xSemaphoreTake(arg->mutex, portMAX_DELAY); + + int* count = (int*) arg->data; + + if (event_data == NULL) { + (*count)++; + } else { + (*count) += *((int*) event_data); + } + + xSemaphoreGive(arg->mutex); +} + +static void test_event_ordered_dispatch(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + int *arg = (int*) event_handler_arg; + ordered_data_t *data = *((ordered_data_t**) (event_data)); + + data->arr[data->index++] = *arg; +} + +static void test_event_performance_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + performance_data_t* data = (performance_data_t*) event_handler_arg; + + data->performed++; + + if (data->performed >= data->expected) { + xSemaphoreGive(data->done); + } +} + +static void test_event_post_task(void* args) +{ + task_arg_t* arg = (task_arg_t*) args; + post_event_data_t* data = arg->data; + + xSemaphoreTake(arg->start, portMAX_DELAY); + + for (int i = 0; i < data->num; i++) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(data->loop, data->base, data->id, NULL, 0, portMAX_DELAY)); + vTaskDelay(1); + } + + xSemaphoreGive(arg->done); + + vTaskDelete(NULL); +} + +static void test_event_simple_handler_registration_task(void* args) +{ + task_arg_t* arg = (task_arg_t*) args; + handler_registration_data_t* data = (handler_registration_data_t*) arg->data; + + xSemaphoreTake(arg->start, portMAX_DELAY); + + for(int i = 0; i < data->num; i++) { + if (data->is_registration) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(data->loop, data->base, data->id, data->handles[i], NULL)); + } else { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(data->loop, data->base, data->id, data->handles[i])); + } + vTaskDelay(1); + } + + xSemaphoreGive(arg->done); + + vTaskDelete(NULL); +} + +static void test_handler_post_w_task(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + simple_arg_t* arg = (simple_arg_t*) event_handler_arg; + + esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data; + int* count = (int*) arg->data; + + (*count)++; + + if (*count <= 2) { + if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + } else{ + xSemaphoreGive((SemaphoreHandle_t) arg->mutex); + } + } else { + // Test that once the queue is full and the handler attempts to post to the same loop, + // posting does not block indefinitely. + if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) { + xSemaphoreTake((SemaphoreHandle_t) arg->mutex, portMAX_DELAY); + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + } + } +} + +static void test_handler_post_wo_task(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + simple_arg_t* arg = (simple_arg_t*) event_handler_arg; + + esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_data; + int* count = (int*) arg->data; + + (*count)++; + + if (*count <= 2) { + if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + } else{ + xSemaphoreGive((SemaphoreHandle_t) arg->mutex); + } + } else { + // Test that once the queue is full and the handler attempts to post to the same loop, + // posting does not block indefinitely. + if (event_base == s_test_base1 && event_id == TEST_EVENT_BASE1_EV1) { + xSemaphoreTake((SemaphoreHandle_t) arg->mutex, portMAX_DELAY); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + } + } +} + +static void test_post_from_handler_loop_task(void* args) +{ + esp_event_loop_handle_t event_loop = (esp_event_loop_handle_t) args; + + while(1) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(event_loop, portMAX_DELAY)); + } +} + +static void test_setup() +{ + TEST_ASSERT_TRUE(TEST_CONFIG_TASKS_TO_SPAWN >= 2); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); +} + +static void test_teardown() +{ + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); +} + +#define TIMER_DIVIDER 16 // Hardware timer clock divider +#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds +#define TIMER_INTERVAL0_SEC (2.0) // sample test interval for the first timer + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +static void test_handler_post_from_isr(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + SemaphoreHandle_t *sem = (SemaphoreHandle_t*) event_handler_arg; + // Event data is just the address value (maybe have been truncated due to casting). + int *data = (int*) event_data; + TEST_ASSERT_EQUAL(*data, (int) (*sem)); + xSemaphoreGive(*sem); +} +#endif + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +void IRAM_ATTR test_event_on_timer_alarm(void* para) +{ + /* Retrieve the interrupt status and the counter value + from the timer that reported the interrupt */ + TIMERG0.hw_timer[TIMER_0].update = 1; + uint64_t timer_counter_value = + ((uint64_t) TIMERG0.hw_timer[TIMER_0].cnt_high) << 32 + | TIMERG0.hw_timer[TIMER_0].cnt_low; + + TIMERG0.int_clr_timers.t0 = 1; + timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE); + TIMERG0.hw_timer[TIMER_0].alarm_high = (uint32_t) (timer_counter_value >> 32); + TIMERG0.hw_timer[TIMER_0].alarm_low = (uint32_t) timer_counter_value; + + int data = (int) para; + // Posting events with data more than 4 bytes should fail. + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, 5, NULL)); + // This should succeedd, as data is int-sized. The handler for the event checks that the passed event data + // is correct. + BaseType_t task_unblocked; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, sizeof(data), &task_unblocked)); + if (task_unblocked == pdTRUE) { + portYIELD_FROM_ISR(); + } +} +#endif //CONFIG_ESP_EVENT_POST_FROM_ISR + +TEST_CASE("can create and delete event loops", "[event]") +{ + /* this test aims to verify that: + * - creating loops with and without a task succeeds + * - event queue can accomodate the set queue size, and drops the post when exceeded + * - deleting loops with unconsumed posts and unregistered handlers (when unregistration is enabled) does not leak memory */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop1; // with dedicated task + esp_event_loop_handle_t loop2; // without dedicated task + esp_event_loop_handle_t loop3; // with leftover post and handlers + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop1)); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop2)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop3)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, (void*) 0x00000001, NULL)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, (void*) 0x00000002, NULL)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, (void*) 0x00000003, NULL)); + + for (int i = 0; i < loop_args.queue_size; i++) { + int mod = i % 4; + + switch(mod) { + case 0: + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + break; + case 1: + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + break; + case 2: + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + break; + case 3: + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop3, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + break; + default: + break; + } + } + + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop3, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop2)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop3)); + + TEST_TEARDOWN(); +} + +TEST_CASE("can register/unregister handlers for all events/all events for a specific base", "[event]") +{ + /* this test aims to verify that handlers can be registered to be called on all events + * or for all events with specific bases */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop; + + int count = 0; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateMutex() + }; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + /* Register the handler twice to the same base and id but with a different argument (expects to return ESP_OK and log a warning) + * This aims to verify: 1) Handler's argument to be updated + * 2) Registration not to leak memory + */ + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, NULL)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, s_test_base1, ESP_EVENT_ANY_ID, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_post_to(loop, ESP_EVENT_ANY_BASE, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); // exec loop, base and id level (+3) + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); // exec loop, base and id level (+3) + + // Post unknown events. Respective loop level and base level handlers should still execute. + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_MAX, NULL, 0, portMAX_DELAY)); // exec loop and base level (+2) + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_MAX, NULL, 0, portMAX_DELAY)); // exec loop level (+1) + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(9, count); // 3 + 3 + 2 + 1 + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} + +TEST_CASE("can unregister handler", "[event]") +{ + /* this test aims to verify that unregistered handlers no longer execute when events are raised */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop; + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + int count = 0; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateMutex() + }; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(2, count); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(3, count); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} + +TEST_CASE("can exit running loop at approximately the set amount of time", "[event]") +{ + /* this test aims to verify that running loop does not block indefinitely in cases where + * events are posted frequently */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop; + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + performance_data_t handler_data = { + .performed = 0, + .expected = INT32_MAX, + .done = xSemaphoreCreateBinary() + }; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_performance_handler, &handler_data)); + + post_event_data_t post_event_data = { + .base = s_test_base1, + .id = TEST_EVENT_BASE1_EV1, + .loop = loop, + .num = INT32_MAX + }; + + task_arg_t post_event_arg = { + .data = &post_event_data, + .done = xSemaphoreCreateBinary(), + .start = xSemaphoreCreateBinary() + }; + + TaskHandle_t post_task; + + xTaskCreatePinnedToCore(test_event_post_task, "post", 2048, &post_event_arg, s_test_priority, &post_task, test_event_get_core()); + + int runtime_ms = 10; + int runtime_us = runtime_ms * 1000; + + int64_t start, diff; + start = esp_timer_get_time(); + + xSemaphoreGive(post_event_arg.start); + + // Run the loop for the runtime_ms set amount of time, regardless of whether events + // are still being posted to the loop. + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(runtime_ms))); + + diff = (esp_timer_get_time() - start); + + // Threshold is 25 percent. + TEST_ASSERT(diff < runtime_us * 1.25f); + + // Verify that the post task still continues + TEST_ASSERT_NOT_EQUAL(pdTRUE, xSemaphoreTake(post_event_arg.done, pdMS_TO_TICKS(10))); + + vSemaphoreDelete(post_event_arg.done); + vSemaphoreDelete(post_event_arg.start); + vSemaphoreDelete(handler_data.done); + vTaskDelete(post_task); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +TEST_CASE("can register/unregister handlers simultaneously", "[event]") +{ + /* this test aims to verify that the event handlers list remains consistent despite + * simultaneous access by differenct tasks */ + + TEST_SETUP(); + + const char* base = "base"; + int32_t id = 0; + + esp_event_loop_handle_t loop; + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + ESP_LOGI(TAG, "registering handlers"); + + handler_registration_data_t* registration_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*registration_data)); + task_arg_t* registration_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*registration_arg)); + + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + registration_data[i].base = base; + registration_data[i].id = id; + registration_data[i].loop = loop; + registration_data[i].handles = calloc(TEST_CONFIG_ITEMS_TO_REGISTER, sizeof(esp_event_handler_t)); + registration_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER; + registration_data[i].is_registration = true; + + for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) { + registration_data[i].handles[j] = (void*) (i * TEST_CONFIG_ITEMS_TO_REGISTER) + (j + TEST_CONFIG_ITEMS_TO_REGISTER); + } + + registration_arg[i].start = xSemaphoreCreateBinary(); + registration_arg[i].done = xSemaphoreCreateBinary(); + registration_arg[i].data = ®istration_data[i]; + + xTaskCreatePinnedToCore(test_event_simple_handler_registration_task, "register", 2048, ®istration_arg[i], s_test_priority, NULL, test_event_get_core()); + } + + // Give the semaphores to the spawned registration task + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreGive(registration_arg[i].start); + } + + // Take the same semaphores in order to proceed + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreTake(registration_arg[i].done, portMAX_DELAY); + } + + ESP_LOGI(TAG, "checking consistency of handlers list"); + + // Check consistency of events list + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) { + TEST_ASSERT_TRUE(esp_event_is_handler_registered(loop, base, id, registration_data[i].handles[j])); + } + } + + ESP_LOGI(TAG, "unregistering handlers"); + + /* Test if tasks can unregister simultaneously */ + + // Unregister registered events + handler_registration_data_t* unregistration_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*unregistration_data)); + task_arg_t* unregistration_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*unregistration_arg)); + + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + unregistration_data[i].base = base; + unregistration_data[i].id = id; + unregistration_data[i].loop = loop; + unregistration_data[i].handles = calloc(TEST_CONFIG_ITEMS_TO_REGISTER, sizeof(esp_event_handler_t)); + unregistration_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER; + unregistration_data[i].is_registration = false; + + memcpy(unregistration_data[i].handles, registration_data[i].handles, TEST_CONFIG_ITEMS_TO_REGISTER * sizeof(esp_event_handler_t)); + + unregistration_arg[i].data = &unregistration_data[i]; + unregistration_arg[i].start = xSemaphoreCreateBinary(); + unregistration_arg[i].done = xSemaphoreCreateBinary(); + + xTaskCreatePinnedToCore(test_event_simple_handler_registration_task, "unregister", 2048, &unregistration_arg[i], s_test_priority, NULL, test_event_get_core()); + } + + // Give the semaphores to the spawned unregistration task + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreGive(unregistration_arg[i].start); + } + + // Take the same semaphores in order to proceed + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreTake(unregistration_arg[i].done, portMAX_DELAY); + } + + ESP_LOGI(TAG, "checking consistency of handlers list"); + + // Check consistency of events list + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + for (int j = 0; j < TEST_CONFIG_ITEMS_TO_REGISTER; j++) { + TEST_ASSERT_FALSE(esp_event_is_handler_registered(loop, base, id, registration_data[i].handles[j])); + } + } + + // Do cleanup + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + free(registration_data[i].handles); + vSemaphoreDelete(registration_arg[i].start); + vSemaphoreDelete(registration_arg[i].done); + + free(unregistration_data[i].handles); + vSemaphoreDelete(unregistration_arg[i].start); + vSemaphoreDelete(unregistration_arg[i].done); + } + + free(registration_data); + free(unregistration_data); + free(registration_arg); + free(unregistration_arg); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +TEST_CASE("can post and run events", "[event]") +{ + /* this test aims to verify that: + * - multiple tasks can post to the queue simultaneously + * - handlers recieve the appropriate handler arg and associated event data */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + loop_args.queue_size = TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + int count = 0; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateMutex() + }; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + + post_event_data_t* post_event_data = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_data)); + task_arg_t* post_event_arg = calloc(TEST_CONFIG_TASKS_TO_SPAWN, sizeof(*post_event_arg)); + + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) + { + post_event_data[i].base = s_test_base1; + post_event_data[i].id = TEST_EVENT_BASE1_EV1; + post_event_data[i].loop = loop; + post_event_data[i].num = TEST_CONFIG_ITEMS_TO_REGISTER; + + post_event_arg[i].data = &post_event_data[i]; + post_event_arg[i].start = xSemaphoreCreateBinary(); + post_event_arg[i].done = xSemaphoreCreateBinary(); + + xTaskCreatePinnedToCore(test_event_post_task, "post", 2048, &post_event_arg[i], s_test_priority, NULL, test_event_get_core()); + } + + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreGive(post_event_arg[i].start); + } + + // Execute some events as they are posted + for (int i = 0; i < (TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER) / 2; i++) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + } + + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + xSemaphoreTake(post_event_arg[i].done, portMAX_DELAY); + } + + // Execute the rest + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(TEST_CONFIG_TASKS_TO_SPAWN * TEST_CONFIG_ITEMS_TO_REGISTER, count); + + // Cleanup + for (int i = 0; i < TEST_CONFIG_TASKS_TO_SPAWN; i++) { + vSemaphoreDelete(post_event_arg[i].start); + vSemaphoreDelete(post_event_arg[i].done); + } + + free(post_event_data); + free(post_event_arg); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} + +static void loop_run_task(void* args) +{ + esp_event_loop_handle_t event_loop = (esp_event_loop_handle_t) args; + + while(1) { + esp_event_loop_run(event_loop, portMAX_DELAY); + } +} + +static void performance_test(bool dedicated_task) +{ + // rand() seems to do a one-time allocation. Call it here so that the memory it allocates + // is not counted as a leak. + unsigned int _rand __attribute__((unused)) = rand(); + + TEST_SETUP(); + + const char test_base[] = "qwertyuiopasdfghjklzxvbnmmnbvcxzqwertyuiopasdfghjklzxvbnmmnbvcxz"; + + #define TEST_CONFIG_BASES (sizeof(test_base) - 1) + #define TEST_CONFIG_IDS (TEST_CONFIG_BASES / 2) + + // Create loop + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + esp_event_loop_handle_t loop; + + if (!dedicated_task) { + loop_args.task_name = NULL; + } + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + performance_data_t data; + + // Register the handlers + for (int base = 0; base < TEST_CONFIG_BASES; base++) { + for (int id = 0; id < TEST_CONFIG_IDS; id++) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, test_base + base, id, test_event_performance_handler, &data)); + } + } + + TaskHandle_t mtask = NULL; + + if (!dedicated_task) { + xTaskCreate(loop_run_task, "loop_run", loop_args.task_stack_size, (void*) loop, loop_args.task_priority, &mtask); + } + + // Perform performance test + float running_sum = 0; + float running_count = 0; + + for (int bases = 1; bases <= TEST_CONFIG_BASES; bases *= 2) { + for (int ids = 1; ids <= TEST_CONFIG_IDS; ids *= 2) { + + data.performed = 0; + data.expected = bases * ids; + data.done = xSemaphoreCreateBinary(); + + // Generate randomized list of posts + int post_bases[TEST_CONFIG_BASES]; + int post_ids[TEST_CONFIG_IDS]; + + for (int i = 0; i < bases; i++) { + post_bases[i] = i; + } + + for (int i = 0; i < ids; i++) { + post_ids[i] = i; + } + + for (int i = 0; i < bases; i++) { + int rand_a = rand() % bases; + int rand_b = rand() % bases; + + int temp = post_bases[rand_a]; + post_bases[rand_a]= post_bases[rand_b]; + post_bases[rand_b] = temp; + } + + for (int i = 0; i < ids; i++) { + int rand_a = rand() % ids; + int rand_b = rand() % ids; + + int temp = post_ids[rand_a]; + post_ids[rand_a]= post_ids[rand_b]; + post_ids[rand_b] = temp; + } + + // Post the events + int64_t start = esp_timer_get_time(); + for (int base = 0; base < bases; base++) { + for (int id = 0; id < ids; id++) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, test_base + post_bases[base], post_ids[id], NULL, 0, portMAX_DELAY)); + } + } + + xSemaphoreTake(data.done, portMAX_DELAY); + int64_t elapsed = esp_timer_get_time() - start; + + // Record data + TEST_ASSERT_EQUAL(data.expected, data.performed); + + running_count++; + running_sum += data.performed / (elapsed / (1000000.0)); + + vSemaphoreDelete(data.done); + } + } + + int average = (int) (running_sum / (running_count)); + + if (!dedicated_task) { + ((esp_event_loop_instance_t*) loop)->task = mtask; + } + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING + ESP_LOGI(TAG, "events dispatched/second with profiling enabled: %d", average); + // Enabling profiling will slow down event dispatch, so the set threshold + // is not valid when it is enabled. +#else +#ifndef CONFIG_ESP32_SPIRAM_SUPPORT + TEST_PERFORMANCE_GREATER_THAN(EVENT_DISPATCH, "%d", average); +#else + TEST_PERFORMANCE_GREATER_THAN(EVENT_DISPATCH_PSRAM, "%d", average); +#endif // CONFIG_ESP32_SPIRAM_SUPPORT +#endif // CONFIG_ESP_EVENT_LOOP_PROFILING +} + +TEST_CASE("performance test - dedicated task", "[event]") +{ + performance_test(true); +} + +TEST_CASE("performance test - no dedicated task", "[event]") +{ + performance_test(false); +} + +TEST_CASE("can post to loop from handler - dedicated task", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop_w_task; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + int count; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateBinary() + }; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop_w_task)); + + count = 0; + + // Test that a handler can post to a different loop while there is still slots on the queue + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_w_task, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_post_w_task, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_w_task, sizeof(&loop_w_task), portMAX_DELAY)); + + xSemaphoreTake(arg.mutex, portMAX_DELAY); + + TEST_ASSERT_EQUAL(2, count); + + // Test that other tasks can still post while there is still slots in the queue, while handler is executing + count = 100; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_w_task, sizeof(&loop_w_task), portMAX_DELAY)); + + for (int i = 0; i < loop_args.queue_size; i++) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + } + + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_w_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, + pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER))); + + xSemaphoreGive(arg.mutex); + + vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop_w_task)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} + +TEST_CASE("can post to loop from handler - no dedicated task", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop_wo_task; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + int count; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateBinary() + }; + + count = 0; + + loop_args.queue_size = 1; + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop_wo_task)); + + TaskHandle_t mtask; + + xTaskCreate(test_post_from_handler_loop_task, "task", 2584, (void*) loop_wo_task, s_test_priority, &mtask); + + // Test that a handler can post to a different loop while there is still slots on the queue + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, test_handler_post_wo_task, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, test_handler_post_wo_task, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_wo_task, sizeof(&loop_wo_task), portMAX_DELAY)); + + xSemaphoreTake(arg.mutex, portMAX_DELAY); + + TEST_ASSERT_EQUAL(2, count); + + count = 100; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV1, &loop_wo_task, sizeof(&loop_wo_task), portMAX_DELAY)); + + vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); + + // For loop without tasks, posting is more restrictive. Posting should wait until execution of handler finishes + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop_wo_task, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, + pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER))); + + xSemaphoreGive(arg.mutex); + + vTaskDelay(pdMS_TO_TICKS(CONFIG_ESP_INT_WDT_TIMEOUT_MS * TEST_CONFIG_WAIT_MULTIPLIER)); + + vTaskDelete(mtask); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop_wo_task)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} + +static void test_event_simple_handler_template(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + int* count = (int*) handler_arg; + (*count)++; +} + +static void test_event_simple_handler_1(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + test_event_simple_handler_template(handler_arg, base, id, event_arg); +} + +static void test_event_simple_handler_3(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + test_event_simple_handler_template(handler_arg, base, id, event_arg); +} + +static void test_event_simple_handler_2(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + test_event_simple_handler_template(handler_arg, base, id, event_arg); +} + +static void test_registration_from_handler_hdlr(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_arg; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_1, handler_arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_2, handler_arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_3, handler_arg)); +} + +static void test_unregistration_from_handler_hdlr(void* handler_arg, esp_event_base_t base, int32_t id, void* event_arg) +{ + esp_event_loop_handle_t* loop = (esp_event_loop_handle_t*) event_arg; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_2)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_unregister_with(*loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler_3)); +} + +TEST_CASE("can register from handler", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + int count = 0; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_registration_from_handler_hdlr, &count)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_unregistration_from_handler_hdlr, &count)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &loop, sizeof(&loop), portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(3, count); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE2_EV1, &loop, sizeof(&loop), portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(3, count); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +static void test_create_loop_handler(void* handler_args, esp_event_base_t base, int32_t id, void* event_data) +{ + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + if (id == TEST_EVENT_BASE1_EV1) { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, (esp_event_loop_handle_t*) handler_args)); + } else { + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(*((esp_event_loop_handle_t*) handler_args))); + } +} + +TEST_CASE("can create and delete loop from handler", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop; + esp_event_loop_handle_t test_loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_create_loop_handler, &test_loop)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_create_loop_handler, &test_loop)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +TEST_CASE("events are dispatched in the order they are registered", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop; + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + int id_arr[7]; + + for (int i = 0; i < 7; i++) { + id_arr[i] = i; + } + + int data_arr[12] = {0}; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV1, test_event_ordered_dispatch, id_arr + 0)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 2)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE2_EV2, test_event_ordered_dispatch, id_arr + 3)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_ordered_dispatch, id_arr + 4)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, ESP_EVENT_ANY_ID, test_event_ordered_dispatch, id_arr + 5)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_ordered_dispatch, id_arr + 6)); + + esp_event_dump(stdout); + + ordered_data_t data = { + .arr = data_arr, + .index = 0 + }; + + ordered_data_t* dptr = &data; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, &dptr, sizeof(dptr), portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &dptr, sizeof(dptr), portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, &dptr, sizeof(dptr), portMAX_DELAY)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, &dptr, sizeof(dptr), portMAX_DELAY)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + // Expected data executing the posts above + int ref_arr[12] = {1, 3, 5, 1, 2, 4, 1, 2, 6, 0, 1, 5}; + + for (int i = 0; i < 12; i++) { + TEST_ASSERT_EQUAL(ref_arr[i], data_arr[i]); + } + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +#if CONFIG_ESP_EVENT_POST_FROM_ISR +TEST_CASE("can properly prepare event data posted to loop", "[event]") +{ + TEST_SETUP(); + + esp_event_loop_handle_t loop; + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + esp_event_post_instance_t post; + esp_event_loop_instance_t* loop_def = (esp_event_loop_instance_t*) loop; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, portMAX_DELAY)); + TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(loop_def->queue, &post, portMAX_DELAY)); + TEST_ASSERT_EQUAL(false, post.data_set); + TEST_ASSERT_EQUAL(false, post.data_allocated); + TEST_ASSERT_EQUAL(NULL, post.data.ptr); + + int sample = 0; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_isr_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, &sample, sizeof(sample), NULL)); + TEST_ASSERT_EQUAL(pdTRUE, xQueueReceive(loop_def->queue, &post, portMAX_DELAY)); + TEST_ASSERT_EQUAL(true, post.data_set); + TEST_ASSERT_EQUAL(false, post.data_allocated); + TEST_ASSERT_EQUAL(false, post.data.val); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + TEST_TEARDOWN(); +} + +TEST_CASE("can post events from interrupt handler", "[event]") +{ + SemaphoreHandle_t sem = xSemaphoreCreateBinary(); + + /* Select and initialize basic parameters of the timer */ + timer_config_t config; + config.divider = TIMER_DIVIDER; + config.counter_dir = TIMER_COUNT_UP; + config.counter_en = TIMER_PAUSE; + config.alarm_en = TIMER_ALARM_EN; + config.intr_type = TIMER_INTR_LEVEL; + config.auto_reload = false; + timer_init(TIMER_GROUP_0, TIMER_0, &config); + + /* Timer's counter will initially start from value below. + Also, if auto_reload is set, this value will be automatically reload on alarm */ + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL); + + /* Configure the alarm value and the interrupt on alarm. */ + timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_INTERVAL0_SEC * TIMER_SCALE); + timer_enable_intr(TIMER_GROUP_0, TIMER_0); + timer_isr_register(TIMER_GROUP_0, TIMER_0, test_event_on_timer_alarm, + (void *) sem, ESP_INTR_FLAG_IRAM, NULL); + + timer_start(TIMER_GROUP_0, TIMER_0); + + TEST_SETUP(); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register(s_test_base1, TEST_EVENT_BASE1_EV1, + test_handler_post_from_isr, &sem)); + + xSemaphoreTake(sem, portMAX_DELAY); + + TEST_TEARDOWN(); +} +#endif + +#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING +TEST_CASE("can dump event loop profile", "[event]") +{ + /* this test aims to verify that dumping event loop statistics succeed */ + + TEST_SETUP(); + + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + loop_args.task_name = NULL; + loop_args.queue_size = 5; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create(&loop_args, &loop)); + + int count = 0; + + simple_arg_t arg = { + .data = &count, + .mutex = xSemaphoreCreateMutex() + }; + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, ESP_EVENT_ANY_ID, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base1, TEST_EVENT_BASE1_EV2, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV1, test_event_simple_handler, &arg)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register_with(loop, s_test_base2, TEST_EVENT_BASE1_EV2, test_event_simple_handler, &arg)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, 1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, 1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV2, NULL, 0, 1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV2, NULL, 0, 1)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_post_to(loop, s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, 1)); + TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, esp_event_post_to(loop, s_test_base2, TEST_EVENT_BASE1_EV1, NULL, 0, 1)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_run(loop, pdMS_TO_TICKS(10))); + + // 5 invocations of loop-levlel handlers + 3 invocation of base-level handlers (s_test_base1) + + // 5 invocations of respective event-level handlers + TEST_ASSERT_EQUAL(13, count); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_dump(stdout)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete(loop)); + + vSemaphoreDelete(arg.mutex); + + TEST_TEARDOWN(); +} +#endif diff --git a/components/tcpip_adapter/event_handlers.c b/components/tcpip_adapter/event_handlers.c new file mode 100644 index 00000000..806bd8b4 --- /dev/null +++ b/components/tcpip_adapter/event_handlers.c @@ -0,0 +1,184 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "tcpip_adapter.h" +#include "esp_event.h" +#include "esp_wifi.h" +#include "esp_err.h" +#include "esp_log.h" + +static const char *TAG = "tcpip_adapter"; + +#define API_CALL_CHECK(info, api_call, ret) \ +do{\ + esp_err_t __err = (api_call);\ + if ((ret) != __err) {\ + ESP_LOGE(TAG, "%s %d %s ret=0x%X", __FUNCTION__, __LINE__, (info), __err);\ + return;\ + }\ +} while(0) + +typedef esp_err_t (*system_event_handler_t)(system_event_t *e); + +static void handle_ap_start(void *arg, esp_event_base_t base, int32_t event_id, void *data); +static void handle_ap_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data); +static void handle_sta_start(void *arg, esp_event_base_t base, int32_t event_id, void *data); +static void handle_sta_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data); +static void handle_sta_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data); +static void handle_sta_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data); +static void handle_sta_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data); + +static void handle_sta_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data) +{ + const ip_event_got_ip_t *event = (const ip_event_got_ip_t *) data; + + ESP_LOGI(TAG, "sta ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR, + IP2STR(&event->ip_info.ip), + IP2STR(&event->ip_info.netmask), + IP2STR(&event->ip_info.gw)); +} + +static void handle_ap_start(void *arg, esp_event_base_t base, int32_t event_id, void *data) +{ + tcpip_adapter_ip_info_t ap_ip; + uint8_t ap_mac[6]; + + API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_AP, ap_mac), ESP_OK); + + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ap_ip); + tcpip_adapter_start(TCPIP_ADAPTER_IF_AP, ap_mac, &ap_ip); +} + +static void handle_ap_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data) +{ + tcpip_adapter_stop(TCPIP_ADAPTER_IF_AP); +} + +static void handle_sta_start(void *arg, esp_event_base_t base, int32_t event_id, void *data) +{ + tcpip_adapter_ip_info_t sta_ip; + uint8_t sta_mac[6]; + + API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_STA, sta_mac), ESP_OK); + + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); + tcpip_adapter_start(TCPIP_ADAPTER_IF_STA, sta_mac, &sta_ip); +} + +static void handle_sta_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data) +{ + tcpip_adapter_stop(TCPIP_ADAPTER_IF_STA); +} + +static void handle_sta_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data) +{ + tcpip_adapter_dhcp_status_t status; + + tcpip_adapter_up(TCPIP_ADAPTER_IF_STA); + tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status); + + if (status == TCPIP_ADAPTER_DHCP_INIT) { + tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); + } else if (status == TCPIP_ADAPTER_DHCP_STOPPED) { + tcpip_adapter_ip_info_t sta_ip; + tcpip_adapter_ip_info_t sta_old_ip; + + tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); + tcpip_adapter_get_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_old_ip); + + if (!(ip4_addr_isany_val(sta_ip.ip) || ip4_addr_isany_val(sta_ip.netmask))) { + system_event_t evt; + + evt.event_id = SYSTEM_EVENT_STA_GOT_IP; + evt.event_info.got_ip.ip_changed = false; + + if (memcmp(&sta_ip, &sta_old_ip, sizeof(sta_ip))) { + evt.event_info.got_ip.ip_changed = true; + } + + memcpy(&evt.event_info.got_ip.ip_info, &sta_ip, sizeof(tcpip_adapter_ip_info_t)); + tcpip_adapter_set_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); + + esp_event_send(&evt); + ESP_LOGD(TAG, "static ip: ip changed=%d", evt.event_info.got_ip.ip_changed); + } else { + ESP_LOGE(TAG, "invalid static ip"); + } + } +} + +static void handle_sta_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data) +{ + tcpip_adapter_down(TCPIP_ADAPTER_IF_STA); +} + + +esp_err_t tcpip_adapter_set_default_wifi_handlers() +{ + esp_err_t err; + err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_START, handle_sta_start, NULL); + if (err != ESP_OK) { + goto fail; + } + + err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_STOP, handle_sta_stop, NULL); + if (err != ESP_OK) { + goto fail; + } + + err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, handle_sta_connected, NULL); + if (err != ESP_OK) { + goto fail; + } + + err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, handle_sta_disconnected, NULL); + if (err != ESP_OK) { + goto fail; + } + + err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_START, handle_ap_start, NULL); + if (err != ESP_OK) { + goto fail; + } + + err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STOP, handle_ap_stop, NULL); + if (err != ESP_OK) { + goto fail; + } + + err = esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, handle_sta_got_ip, NULL); + if (err != ESP_OK) { + goto fail; + } + + return ESP_OK; + +fail: + tcpip_adapter_clear_default_wifi_handlers(); + return err; +} + +esp_err_t tcpip_adapter_clear_default_wifi_handlers() +{ + esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_START, handle_sta_start); + esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_STOP, handle_sta_stop); + esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, handle_sta_connected); + esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, handle_sta_disconnected); + esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_AP_START, handle_ap_start); + esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_AP_STOP, handle_ap_stop); + esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, handle_sta_got_ip); + + return ESP_OK; +} diff --git a/components/tcpip_adapter/include/tcpip_adapter.h b/components/tcpip_adapter/include/tcpip_adapter.h index 3f74d13f..141ce09e 100644 --- a/components/tcpip_adapter/include/tcpip_adapter.h +++ b/components/tcpip_adapter/include/tcpip_adapter.h @@ -174,6 +174,35 @@ typedef enum{ TCPIP_ADAPTER_IP_REQUEST_RETRY_TIME = 52, /**< request IP address retry counter */ } tcpip_adapter_option_id_t; +/** @brief IP event base declaration */ +ESP_EVENT_DECLARE_BASE(IP_EVENT); + +/** IP event declarations */ +typedef enum { + IP_EVENT_STA_GOT_IP, /*!< station got IP from connected AP */ + IP_EVENT_STA_LOST_IP, /*!< station lost IP and the IP is reset to 0 */ + IP_EVENT_AP_STAIPASSIGNED, /*!< soft-AP assign an IP to a connected station */ + IP_EVENT_GOT_IP6, /*!< station or ap or ethernet interface v6IP addr is preferred */ +} ip_event_t; + +/** Event structure for IP_EVENT_AP_STAIPASSIGNED event */ +typedef struct { + ip4_addr_t ip; /*!< IP address which was assigned to the station */ +} ip_event_ap_staipassigned_t; + +/** Event structure for IP_EVENT_STA_GOT_IP, IP_EVENT_ETH_GOT_IP events */ +typedef struct { + tcpip_adapter_if_t if_index; /*!< Interface for which the event is received */ + tcpip_adapter_ip_info_t ip_info; /*!< IP address, netmask, gatway IP address */ + bool ip_changed; /*!< Whether the assigned IP has changed or not */ +} ip_event_got_ip_t; + +/** Event structure for IP_EVENT_GOT_IP6 event */ +typedef struct { + tcpip_adapter_if_t if_index; /*!< Interface for which the event is received */ + tcpip_adapter_ip6_info_t ip6_info; /*!< IPv6 address of the interface */ +} ip_event_got_ip6_t; + struct tcpip_adapter_api_msg_s; typedef int (*tcpip_adapter_api_fn)(struct tcpip_adapter_api_msg_s *msg); @@ -615,6 +644,22 @@ esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif); */ bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if); +/** + * @brief Install default event handlers for Wi-Fi interfaces (station and AP) + * @return + * - ESP_OK on success + * - one of the errors from esp_event on failure + */ +esp_err_t tcpip_adapter_set_default_wifi_handlers(); + +/** + * @brief Uninstall default event handlers for Wi-Fi interfaces (station and AP) + * @return + * - ESP_OK on success + * - one of the errors from esp_event on failure + */ +esp_err_t tcpip_adapter_clear_default_wifi_handlers(); + #ifdef __cplusplus } #endif diff --git a/components/tcpip_adapter/tcpip_adapter_lwip.c b/components/tcpip_adapter/tcpip_adapter_lwip.c index 77d28d99..55c2eb82 100644 --- a/components/tcpip_adapter/tcpip_adapter_lwip.c +++ b/components/tcpip_adapter/tcpip_adapter_lwip.c @@ -79,6 +79,8 @@ static bool tcpip_inited = false; static const char* TAG = "tcpip_adapter"; +ESP_EVENT_DEFINE_BASE(IP_EVENT); + /* Avoid warning. No header file has include these function */ err_t ethernetif_init(struct netif* netif); void system_station_got_ip_set(); @@ -93,6 +95,7 @@ static void tcpip_adapter_dhcps_cb(u8_t client_ip[4]) client_ip[0],client_ip[1],client_ip[2],client_ip[3]); system_event_t evt; evt.event_id = SYSTEM_EVENT_AP_STAIPASSIGNED; + memcpy(&evt.event_info.ap_staipassigned.ip, client_ip, 4); esp_event_send(&evt); } @@ -584,6 +587,7 @@ esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_i evt.event_info.got_ip.ip_changed = true; } + evt.event_info.got_ip.if_index = TCPIP_ADAPTER_IF_STA; memcpy(&evt.event_info.got_ip.ip_info, ip_info, sizeof(tcpip_adapter_ip_info_t)); memcpy(&esp_ip_old[tcpip_if], ip_info, sizeof(tcpip_adapter_ip_info_t)); esp_event_send(&evt); diff --git a/examples/common_components/protocol_examples_common/connect.c b/examples/common_components/protocol_examples_common/connect.c index 5b6b2814..fd348c8a 100644 --- a/examples/common_components/protocol_examples_common/connect.c +++ b/examples/common_components/protocol_examples_common/connect.c @@ -8,6 +8,7 @@ */ #include + #include "protocol_examples_common.h" #include "sdkconfig.h" #include "esp_event.h" @@ -32,7 +33,8 @@ static EventGroupHandle_t s_connect_event_group; static ip4_addr_t s_ip_addr; -static const char *s_connection_name; +static char s_connection_name[32] = CONFIG_EXAMPLE_WIFI_SSID; +static char s_connection_passwd[32] = CONFIG_EXAMPLE_WIFI_PASSWORD; #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 static ip6_addr_t s_ipv6_addr; @@ -40,65 +42,70 @@ static ip6_addr_t s_ipv6_addr; static const char *TAG = "example_connect"; -static esp_err_t event_handler(void *ctx, system_event_t *event) +static void on_wifi_disconnect(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; + system_event_sta_disconnected_t *event = (system_event_sta_disconnected_t *)event_data; - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - memcpy(&s_ip_addr, &event->event_info.got_ip.ip_info.ip, sizeof(s_ip_addr)); - xEventGroupSetBits(s_connect_event_group, GOT_IPV4_BIT);; - break; -#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 - case SYSTEM_EVENT_STA_CONNECTED: - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: - memcpy(&s_ipv6_addr, &event->event_info.got_ip6.ip6_info, sizeof(s_ipv6_addr)); - xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); - break; -#endif - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(s_connect_event_group, GOT_IPV4_BIT); -#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 - xEventGroupClearBits(s_connect_event_group, GOT_IPV6_BIT); -#endif - break; - default: - break; + ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect..."); + if (event->reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { + /*Switch to 802.11 bgn mode */ + esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); } - return ESP_OK; + ESP_ERROR_CHECK(esp_wifi_connect()); } +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 +static void on_wifi_connect(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); +} +#endif + +static void on_got_ip(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; + memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr)); + xEventGroupSetBits(s_connect_event_group, GOT_IPV4_BIT); +} + +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + +static void on_got_ipv6(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data; + memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); + xEventGroupSetBits(s_connect_event_group, GOT_IPV6_BIT); +} + +#endif // CONFIG_EXAMPLE_CONNECT_IPV6 + static void start(void) { - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL)); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6, NULL)); +#endif + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = CONFIG_EXAMPLE_WIFI_SSID, - .password = CONFIG_EXAMPLE_WIFI_PASSWORD, - }, - }; + wifi_config_t wifi_config = { 0 }; + + strncpy((char *)&wifi_config.sta.ssid, s_connection_name, 32); + strncpy((char *)&wifi_config.sta.password, s_connection_passwd, 32); + ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); - s_connection_name = CONFIG_EXAMPLE_WIFI_SSID; + ESP_ERROR_CHECK(esp_wifi_connect()); } static void stop(void) @@ -108,6 +115,14 @@ static void stop(void) return; } ESP_ERROR_CHECK(err); + + ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect)); + ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip)); +#ifdef CONFIG_EXAMPLE_CONNECT_IPV6 + ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_GOT_IP6, &on_got_ipv6)); + ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &on_wifi_connect)); +#endif + ESP_ERROR_CHECK(esp_wifi_deinit()); } @@ -137,6 +152,14 @@ esp_err_t example_disconnect(void) s_connect_event_group = NULL; stop(); ESP_LOGI(TAG, "Disconnected from %s", s_connection_name); - s_connection_name = NULL; + s_connection_name[0] = '\0'; + return ESP_OK; +} + +esp_err_t example_set_connection_info(const char *ssid, const char *passwd) +{ + strncpy(s_connection_name, ssid, sizeof(s_connection_name)); + strncpy(s_connection_passwd, passwd, sizeof(s_connection_passwd)); + return ESP_OK; } diff --git a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h index 222ab6c1..3eb1ff42 100644 --- a/examples/common_components/protocol_examples_common/include/protocol_examples_common.h +++ b/examples/common_components/protocol_examples_common/include/protocol_examples_common.h @@ -48,6 +48,11 @@ esp_err_t example_disconnect(void); */ esp_err_t example_configure_stdin_stdout(void); +/** + * @brief Configure SSID and password + */ +esp_err_t example_set_connection_info(const char *ssid, const char *passwd); + #ifdef __cplusplus } #endif diff --git a/examples/protocols/coap_client/CMakeLists.txt b/examples/protocols/coap_client/CMakeLists.txt index 671988b7..77a85f8d 100644 --- a/examples/protocols/coap_client/CMakeLists.txt +++ b/examples/protocols/coap_client/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(coap_client) diff --git a/examples/protocols/coap_client/Makefile b/examples/protocols/coap_client/Makefile index c9a25d11..84a2905f 100644 --- a/examples/protocols/coap_client/Makefile +++ b/examples/protocols/coap_client/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := coap_client +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/coap_client/main/Kconfig.projbuild b/examples/protocols/coap_client/main/Kconfig.projbuild index 045137a0..78de5fac 100644 --- a/examples/protocols/coap_client/main/Kconfig.projbuild +++ b/examples/protocols/coap_client/main/Kconfig.projbuild @@ -6,16 +6,4 @@ config TARGET_DOMAIN_URI help Target uri for the example to use. -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - endmenu \ No newline at end of file diff --git a/examples/protocols/coap_client/main/coap_client_example_main.c b/examples/protocols/coap_client/main/coap_client_example_main.c index f28df68d..9ee11d06 100644 --- a/examples/protocols/coap_client/main/coap_client_example_main.c +++ b/examples/protocols/coap_client/main/coap_client_example_main.c @@ -13,25 +13,16 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" - +#include "esp_system.h" #include "esp_log.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" #include "nvs_flash.h" #include "coap.h" -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #define COAP_DEFAULT_TIME_SEC 5 #define COAP_DEFAULT_TIME_USEC 0 @@ -43,13 +34,6 @@ */ #define COAP_DEFAULT_DEMO_URI CONFIG_TARGET_DOMAIN_URI -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const static int CONNECTED_BIT = BIT0; - const static char *TAG = "CoAP_client"; static void message_handler(struct coap_context_t *ctx, const coap_endpoint_t *local_interface, const coap_address_t *remote, @@ -81,13 +65,6 @@ static void coap_example_task(void *p) uint8_t get_method = 1; while (1) { - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); - if (coap_split_uri((const uint8_t *)server_uri, strlen(server_uri), &uri) == -1) { ESP_LOGE(TAG, "CoAP server uri error"); break; @@ -157,55 +134,14 @@ static void coap_example_task(void *p) vTaskDelete(NULL); } -static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void wifi_conn_init(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(wifi_event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - void app_main(void) { - ESP_ERROR_CHECK( nvs_flash_init() ); - wifi_conn_init(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + + ESP_ERROR_CHECK(example_connect()); + xTaskCreate(coap_example_task, "coap", 2048, NULL, 5, NULL); } diff --git a/examples/protocols/coap_server/CMakeLists.txt b/examples/protocols/coap_server/CMakeLists.txt index 28389253..7a5876cb 100644 --- a/examples/protocols/coap_server/CMakeLists.txt +++ b/examples/protocols/coap_server/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(coap_server) diff --git a/examples/protocols/coap_server/Makefile b/examples/protocols/coap_server/Makefile index f82e5fc2..63af79f7 100644 --- a/examples/protocols/coap_server/Makefile +++ b/examples/protocols/coap_server/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := coap_server +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/coap_server/main/Kconfig.projbuild b/examples/protocols/coap_server/main/Kconfig.projbuild deleted file mode 100644 index 7a9cb97a..00000000 --- a/examples/protocols/coap_server/main/Kconfig.projbuild +++ /dev/null @@ -1,15 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - -endmenu \ No newline at end of file diff --git a/examples/protocols/coap_server/main/coap_server_example_main.c b/examples/protocols/coap_server/main/coap_server_example_main.c index 9ec2be39..fa5401e5 100644 --- a/examples/protocols/coap_server/main/coap_server_example_main.c +++ b/examples/protocols/coap_server/main/coap_server_example_main.c @@ -12,35 +12,19 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" - +#include "esp_system.h" #include "esp_log.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" #include "nvs_flash.h" #include "coap.h" -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #define COAP_DEFAULT_TIME_SEC 5 #define COAP_DEFAULT_TIME_USEC 0 -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const static int CONNECTED_BIT = BIT0; - const static char *TAG = "CoAP_server"; static coap_async_state_t *async = NULL; @@ -90,13 +74,6 @@ static void coap_example_thread(void *p) int flags = 0; while (1) { - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); - /* Prepare the CoAP server socket */ coap_address_init(&serv_addr); serv_addr.addr.sin.sin_family = AF_INET; @@ -143,56 +120,14 @@ static void coap_example_thread(void *p) vTaskDelete(NULL); } -static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void wifi_conn_init(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(wifi_event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - void app_main(void) { - ESP_ERROR_CHECK( nvs_flash_init() ); - wifi_conn_init(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + + ESP_ERROR_CHECK(example_connect()); xTaskCreate(coap_example_thread, "coap", 2048, NULL, 5, NULL); } diff --git a/examples/protocols/esp_http_client/CMakeLists.txt b/examples/protocols/esp_http_client/CMakeLists.txt index 6896d5ac..cce8eb1e 100644 --- a/examples/protocols/esp_http_client/CMakeLists.txt +++ b/examples/protocols/esp_http_client/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(esp-http-client-example) diff --git a/examples/protocols/esp_http_client/Makefile b/examples/protocols/esp_http_client/Makefile index 851c3475..50d3b5f3 100644 --- a/examples/protocols/esp_http_client/Makefile +++ b/examples/protocols/esp_http_client/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := esp-http-client-example +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/esp_http_client/main/CMakeLists.txt b/examples/protocols/esp_http_client/main/CMakeLists.txt index 093811e6..48f4e831 100644 --- a/examples/protocols/esp_http_client/main/CMakeLists.txt +++ b/examples/protocols/esp_http_client/main/CMakeLists.txt @@ -1,7 +1,4 @@ -set(COMPONENT_SRCS "app_wifi.c" - "esp_http_client_example.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") - +set(COMPONENT_SRCS "esp_http_client_example.c") # Embed the server root certificate into the final binary # diff --git a/examples/protocols/esp_http_client/main/Kconfig.projbuild b/examples/protocols/esp_http_client/main/Kconfig.projbuild deleted file mode 100644 index 1c7241da..00000000 --- a/examples/protocols/esp_http_client/main/Kconfig.projbuild +++ /dev/null @@ -1,17 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - -endmenu diff --git a/examples/protocols/esp_http_client/main/app_wifi.c b/examples/protocols/esp_http_client/main/app_wifi.c deleted file mode 100644 index 7d8d8d97..00000000 --- a/examples/protocols/esp_http_client/main/app_wifi.c +++ /dev/null @@ -1,81 +0,0 @@ -/* ESP HTTP Client Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "esp_system.h" -#include "freertos/event_groups.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "app_wifi.h" - -static const char *TAG = "WIFI"; - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -void app_wifi_initialise(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = CONFIG_WIFI_SSID, - .password = CONFIG_WIFI_PASSWORD, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); - -} - -void app_wifi_wait_connected() -{ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); -} diff --git a/examples/protocols/esp_http_client/main/app_wifi.h b/examples/protocols/esp_http_client/main/app_wifi.h deleted file mode 100644 index 91c886d5..00000000 --- a/examples/protocols/esp_http_client/main/app_wifi.h +++ /dev/null @@ -1,17 +0,0 @@ -/* ESP HTTP Client Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#ifndef _APP_WIFI_H_ -#define _APP_WIFI_H_ - -void app_wifi_initialise(void); -void app_wifi_wait_connected(); - - -#endif diff --git a/examples/protocols/esp_http_client/main/esp_http_client_example.c b/examples/protocols/esp_http_client/main/esp_http_client_example.c index 9d564277..4c5a751c 100644 --- a/examples/protocols/esp_http_client/main/esp_http_client_example.c +++ b/examples/protocols/esp_http_client/main/esp_http_client_example.c @@ -9,12 +9,16 @@ #include #include + #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_log.h" #include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" -#include "app_wifi.h" #include "esp_http_client.h" @@ -375,7 +379,6 @@ static void https_async() static void http_test_task(void *pvParameters) { - app_wifi_wait_connected(); ESP_LOGI(TAG, "Connected to AP, begin http example"); http_rest(); http_auth_basic(); @@ -394,13 +397,12 @@ static void http_test_task(void *pvParameters) void app_main() { - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - app_wifi_initialise(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + + ESP_ERROR_CHECK(example_connect()); xTaskCreate(&http_test_task, "http_test_task", 8192, NULL, 5, NULL); } diff --git a/examples/protocols/http_request/CMakeLists.txt b/examples/protocols/http_request/CMakeLists.txt index 173ebfa7..a4c540a0 100644 --- a/examples/protocols/http_request/CMakeLists.txt +++ b/examples/protocols/http_request/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(http_request) diff --git a/examples/protocols/http_request/Makefile b/examples/protocols/http_request/Makefile index 26250750..3d31a530 100644 --- a/examples/protocols/http_request/Makefile +++ b/examples/protocols/http_request/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := http-request +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/http_request/main/Kconfig.projbuild b/examples/protocols/http_request/main/Kconfig.projbuild deleted file mode 100644 index 92a75195..00000000 --- a/examples/protocols/http_request/main/Kconfig.projbuild +++ /dev/null @@ -1,17 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - -endmenu diff --git a/examples/protocols/http_request/main/http_request_example_main.c b/examples/protocols/http_request/main/http_request_example_main.c index 23266c33..220d5fe1 100644 --- a/examples/protocols/http_request/main/http_request_example_main.c +++ b/examples/protocols/http_request/main/http_request_example_main.c @@ -11,34 +11,17 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" - -#include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_system.h" #include "esp_log.h" - +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" #include #include -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - /* Constants that aren't configurable in menuconfig */ #define WEB_SERVER "example.com" #define WEB_PORT 80 @@ -51,53 +34,6 @@ static const char *REQUEST = "GET " WEB_URL " HTTP/1.0\r\n" "User-Agent: esp-idf/1.0 esp32\r\n" "\r\n"; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - static void http_get_task(void *pvParameters) { const struct addrinfo hints = { @@ -110,13 +46,6 @@ static void http_get_task(void *pvParameters) char recv_buf[64]; while(1) { - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); - int err = getaddrinfo(WEB_SERVER, "80", &hints, &res); if(err != 0 || res == NULL) { @@ -192,7 +121,12 @@ static void http_get_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + + ESP_ERROR_CHECK(example_connect()); + xTaskCreate(&http_get_task, "http_get_task", 16384, NULL, 5, NULL); } diff --git a/examples/protocols/http_server/advanced_tests/CMakeLists.txt b/examples/protocols/http_server/advanced_tests/CMakeLists.txt index b6f65f8f..1af5093c 100644 --- a/examples/protocols/http_server/advanced_tests/CMakeLists.txt +++ b/examples/protocols/http_server/advanced_tests/CMakeLists.txt @@ -2,6 +2,10 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(tests) diff --git a/examples/protocols/http_server/advanced_tests/Makefile b/examples/protocols/http_server/advanced_tests/Makefile index 178ddf69..07699abc 100644 --- a/examples/protocols/http_server/advanced_tests/Makefile +++ b/examples/protocols/http_server/advanced_tests/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := tests +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/http_server/advanced_tests/main/Kconfig.projbuild b/examples/protocols/http_server/advanced_tests/main/Kconfig.projbuild deleted file mode 100644 index 9e2813c6..00000000 --- a/examples/protocols/http_server/advanced_tests/main/Kconfig.projbuild +++ /dev/null @@ -1,16 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - -endmenu diff --git a/examples/protocols/http_server/advanced_tests/main/main.c b/examples/protocols/http_server/advanced_tests/main/main.c index 48dead08..05a5786c 100644 --- a/examples/protocols/http_server/advanced_tests/main/main.c +++ b/examples/protocols/http_server/advanced_tests/main/main.c @@ -1,88 +1,51 @@ -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" #include "tests.h" -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. +static const char *TAG = "example"; - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD +static httpd_handle_t server = NULL; -static const char *TAG="TEST_WIFI"; - -static esp_err_t event_handler(void *ctx, system_event_t *event) +static void disconnect_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) { - httpd_handle_t *hd = (httpd_handle_t *) ctx; - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - ESP_ERROR_CHECK(esp_wifi_connect()); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - ESP_LOGI(TAG, "Got IP: '%s'", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - - // Start webserver tests - if (*hd == NULL) { - *hd = start_tests(); - } - - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED"); - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - ESP_ERROR_CHECK(esp_wifi_connect()); - - // Stop webserver tests - if (*hd) { - stop_tests(*hd); - *hd = NULL; - } - - break; - default: - break; + httpd_handle_t* server = (httpd_handle_t*) arg; + if (*server) { + ESP_LOGI(TAG, "Stopping webserver"); + stop_tests(*server); + *server = NULL; } - return ESP_OK; } -static void initialise_wifi(void) +static void connect_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) { - tcpip_adapter_init(); - static httpd_handle_t hd = NULL; - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, &hd)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); + httpd_handle_t* server = (httpd_handle_t*) arg; + if (*server == NULL) { + ESP_LOGI(TAG, "Starting webserver"); + *server = start_tests(); + } } void app_main() { ESP_ERROR_CHECK(nvs_flash_init()); - initialise_wifi(); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + + ESP_ERROR_CHECK(example_connect()); + + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server)); + + server = start_tests(); } diff --git a/examples/protocols/http_server/persistent_sockets/CMakeLists.txt b/examples/protocols/http_server/persistent_sockets/CMakeLists.txt index 2d453b67..b6d34fb2 100644 --- a/examples/protocols/http_server/persistent_sockets/CMakeLists.txt +++ b/examples/protocols/http_server/persistent_sockets/CMakeLists.txt @@ -2,6 +2,10 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(persistent_sockets) diff --git a/examples/protocols/http_server/persistent_sockets/Makefile b/examples/protocols/http_server/persistent_sockets/Makefile index 9c178022..f20d51a6 100644 --- a/examples/protocols/http_server/persistent_sockets/Makefile +++ b/examples/protocols/http_server/persistent_sockets/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := persistent_sockets +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/http_server/persistent_sockets/main/Kconfig.projbuild b/examples/protocols/http_server/persistent_sockets/main/Kconfig.projbuild deleted file mode 100644 index 9e2813c6..00000000 --- a/examples/protocols/http_server/persistent_sockets/main/Kconfig.projbuild +++ /dev/null @@ -1,16 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - -endmenu diff --git a/examples/protocols/http_server/persistent_sockets/main/main.c b/examples/protocols/http_server/persistent_sockets/main/main.c index 4bebbed8..6790d388 100644 --- a/examples/protocols/http_server/persistent_sockets/main/main.c +++ b/examples/protocols/http_server/persistent_sockets/main/main.c @@ -7,23 +7,18 @@ CONDITIONS OF ANY KIND, either express or implied. */ -#include -#include -#include -#include -#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" #include -/* An example to demonstrate persistent sockets, with context maintained across - * multiple requests on that socket. - * The examples use simple WiFi configuration that you can set via 'make menuconfig'. - * If you'd rather not, just change the below entries to strings with - * the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" - */ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - static const char *TAG="APP"; /* Function to free context */ @@ -190,70 +185,39 @@ void stop_webserver(httpd_handle_t server) httpd_stop(server); } -static esp_err_t event_handler(void *ctx, system_event_t *event) +static httpd_handle_t server = NULL; + +static void disconnect_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) { - httpd_handle_t *server = (httpd_handle_t *) ctx; - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - ESP_ERROR_CHECK(esp_wifi_connect()); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - ESP_LOGI(TAG, "Got IP: '%s'", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - - /* Start the web server */ - if (*server == NULL) { - *server = start_webserver(); - } - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED"); - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - ESP_ERROR_CHECK(esp_wifi_connect()); - - /* Stop the webserver */ - if (*server) { - stop_webserver(*server); - *server = NULL; - } - break; - default: - break; + httpd_handle_t* server = (httpd_handle_t*) arg; + if (*server) { + ESP_LOGI(TAG, "Stopping webserver"); + stop_webserver(*server); + *server = NULL; } - return ESP_OK; } -static void initialise_wifi(void *arg) +static void connect_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) { - tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, arg)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); + httpd_handle_t* server = (httpd_handle_t*) arg; + if (*server == NULL) { + ESP_LOGI(TAG, "Starting webserver"); + *server = start_webserver(); + } } void app_main() { - static httpd_handle_t server = NULL; ESP_ERROR_CHECK(nvs_flash_init()); - initialise_wifi(&server); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); + + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server)); + + server = start_webserver(); } diff --git a/examples/protocols/http_server/simple/CMakeLists.txt b/examples/protocols/http_server/simple/CMakeLists.txt index cc9d4fd8..db2ef2fa 100644 --- a/examples/protocols/http_server/simple/CMakeLists.txt +++ b/examples/protocols/http_server/simple/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(simple) diff --git a/examples/protocols/http_server/simple/Makefile b/examples/protocols/http_server/simple/Makefile index 48f628a6..85660a20 100644 --- a/examples/protocols/http_server/simple/Makefile +++ b/examples/protocols/http_server/simple/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := simple +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/http_server/simple/main/Kconfig.projbuild b/examples/protocols/http_server/simple/main/Kconfig.projbuild deleted file mode 100644 index 9e2813c6..00000000 --- a/examples/protocols/http_server/simple/main/Kconfig.projbuild +++ /dev/null @@ -1,16 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - -endmenu diff --git a/examples/protocols/http_server/simple/main/main.c b/examples/protocols/http_server/simple/main/main.c index d29ccaac..1c532b8d 100644 --- a/examples/protocols/http_server/simple/main/main.c +++ b/examples/protocols/http_server/simple/main/main.c @@ -6,26 +6,19 @@ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ - -#include -#include -#include -#include -#include #include -#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" -/* A simple example that demonstrates how to create GET and POST - * handlers for the web server. - * The examples use simple WiFi configuration that you can set via - * 'make menuconfig'. - * If you'd rather not, just change the below entries to strings - * with the config you want - - * ie. #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD +#include static const char *TAG="APP"; @@ -217,70 +210,40 @@ void stop_webserver(httpd_handle_t server) httpd_stop(server); } -static esp_err_t event_handler(void *ctx, system_event_t *event) +static httpd_handle_t server = NULL; + +static void disconnect_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) { - httpd_handle_t *server = (httpd_handle_t *) ctx; - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - ESP_ERROR_CHECK(esp_wifi_connect()); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - ESP_LOGI(TAG, "Got IP: '%s'", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - - /* Start the web server */ - if (*server == NULL) { - *server = start_webserver(); - } - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED"); - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - ESP_ERROR_CHECK(esp_wifi_connect()); - - /* Stop the web server */ - if (*server) { - stop_webserver(*server); - *server = NULL; - } - break; - default: - break; + httpd_handle_t* server = (httpd_handle_t*) arg; + if (*server) { + ESP_LOGI(TAG, "Stopping webserver"); + stop_webserver(*server); + *server = NULL; } - return ESP_OK; } -static void initialise_wifi(void *arg) +static void connect_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) { - tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, arg)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); + httpd_handle_t* server = (httpd_handle_t*) arg; + if (*server == NULL) { + ESP_LOGI(TAG, "Starting webserver"); + *server = start_webserver(); + } } void app_main() { - static httpd_handle_t server = NULL; ESP_ERROR_CHECK(nvs_flash_init()); - initialise_wifi(&server); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + + ESP_ERROR_CHECK(example_connect()); + + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server)); + + server = start_webserver(); } diff --git a/examples/protocols/https_mbedtls/CMakeLists.txt b/examples/protocols/https_mbedtls/CMakeLists.txt index 1990bc1a..e969fdca 100644 --- a/examples/protocols/https_mbedtls/CMakeLists.txt +++ b/examples/protocols/https_mbedtls/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(https_mbedtls) diff --git a/examples/protocols/https_mbedtls/Makefile b/examples/protocols/https_mbedtls/Makefile index a6777c41..538b584f 100644 --- a/examples/protocols/https_mbedtls/Makefile +++ b/examples/protocols/https_mbedtls/Makefile @@ -5,4 +5,6 @@ PROJECT_NAME := https-mbedtls +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk \ No newline at end of file diff --git a/examples/protocols/https_mbedtls/main/Kconfig.projbuild b/examples/protocols/https_mbedtls/main/Kconfig.projbuild deleted file mode 100644 index 92a75195..00000000 --- a/examples/protocols/https_mbedtls/main/Kconfig.projbuild +++ /dev/null @@ -1,17 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - -endmenu diff --git a/examples/protocols/https_mbedtls/main/https_mbedtls_example_main.c b/examples/protocols/https_mbedtls/main/https_mbedtls_example_main.c index c2879f55..0378fef2 100644 --- a/examples/protocols/https_mbedtls/main/https_mbedtls_example_main.c +++ b/examples/protocols/https_mbedtls/main/https_mbedtls_example_main.c @@ -26,12 +26,12 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" - -#include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_system.h" #include "esp_log.h" - +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" #include @@ -46,23 +46,6 @@ #include "mbedtls/error.h" #include "mbedtls/certs.h" -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - /* Constants that aren't configurable in menuconfig */ #define WEB_SERVER "www.howsmyssl.com" #define WEB_PORT "443" @@ -88,53 +71,6 @@ static const char *REQUEST = "GET " WEB_URL " HTTP/1.0\r\n" extern const uint8_t server_root_cert_pem_start[] asm("_binary_server_root_cert_pem_start"); extern const uint8_t server_root_cert_pem_end[] asm("_binary_server_root_cert_pem_end"); -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - static void https_get_task(void *pvParameters) { char buf[512]; @@ -212,13 +148,6 @@ static void https_get_task(void *pvParameters) } while(1) { - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); - mbedtls_net_init(&server_fd); ESP_LOGI(TAG, "Connecting to %s:%s...", WEB_SERVER, WEB_PORT); @@ -340,7 +269,12 @@ static void https_get_task(void *pvParameters) void app_main(void) { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + + ESP_ERROR_CHECK(example_connect()); + xTaskCreate(&https_get_task, "https_get_task", 8192, NULL, 5, NULL); } diff --git a/examples/protocols/https_request/CMakeLists.txt b/examples/protocols/https_request/CMakeLists.txt index f77bc661..6e3f1265 100644 --- a/examples/protocols/https_request/CMakeLists.txt +++ b/examples/protocols/https_request/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(https_request) diff --git a/examples/protocols/https_request/Makefile b/examples/protocols/https_request/Makefile index 55c5f943..f81163b0 100644 --- a/examples/protocols/https_request/Makefile +++ b/examples/protocols/https_request/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := https_request +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/https_request/main/Kconfig.projbuild b/examples/protocols/https_request/main/Kconfig.projbuild deleted file mode 100644 index 1c7241da..00000000 --- a/examples/protocols/https_request/main/Kconfig.projbuild +++ /dev/null @@ -1,17 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - -endmenu diff --git a/examples/protocols/https_request/main/https_request_example_main.c b/examples/protocols/https_request/main/https_request_example_main.c index e8057f41..1e14c462 100644 --- a/examples/protocols/https_request/main/https_request_example_main.c +++ b/examples/protocols/https_request/main/https_request_example_main.c @@ -23,13 +23,15 @@ */ #include #include + #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" #include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" #include "lwip/err.h" @@ -40,23 +42,6 @@ #include "esp_tls.h" -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - /* Constants that aren't configurable in menuconfig */ #define WEB_SERVER "www.howsmyssl.com" #define WEB_PORT 443 @@ -81,53 +66,6 @@ static const char *REQUEST = "GET " WEB_URL " HTTP/1.0\r\n" */ extern const uint8_t server_root_cert_pem_start[] asm("_binary_server_root_cert_pem_start"); extern const uint8_t server_root_cert_pem_end[] asm("_binary_server_root_cert_pem_end"); - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} static void https_get_task(void *pvParameters) { @@ -135,12 +73,6 @@ static void https_get_task(void *pvParameters) int ret, len; while(1) { - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); esp_tls_cfg_t cfg = { .cacert_pem_buf = server_root_cert_pem_start, .cacert_pem_bytes = server_root_cert_pem_end - server_root_cert_pem_start, @@ -218,7 +150,11 @@ static void https_get_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); + xTaskCreate(&https_get_task, "https_get_task", 8192, NULL, 5, NULL); } diff --git a/examples/protocols/mdns/CMakeLists.txt b/examples/protocols/mdns/CMakeLists.txt index 88b7c1e3..ddd7263c 100644 --- a/examples/protocols/mdns/CMakeLists.txt +++ b/examples/protocols/mdns/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mdns-test) diff --git a/examples/protocols/mdns/Makefile b/examples/protocols/mdns/Makefile index 0353c51c..91a417c7 100644 --- a/examples/protocols/mdns/Makefile +++ b/examples/protocols/mdns/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := mdns-test +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/mdns/main/Kconfig.projbuild b/examples/protocols/mdns/main/Kconfig.projbuild index a55b0bf4..5fb52b28 100644 --- a/examples/protocols/mdns/main/Kconfig.projbuild +++ b/examples/protocols/mdns/main/Kconfig.projbuild @@ -1,19 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - config MDNS_HOSTNAME string "mDNS Hostname" default "esp32-mdns" diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index bac352da..7f17e961 100644 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -7,101 +7,26 @@ CONDITIONS OF ANY KIND, either express or implied. */ #include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" -#include "mdns.h" -#include "driver/gpio.h" #include #include -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" +#include "driver/gpio.h" - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD +#include "mdns.h" #define EXAMPLE_MDNS_HOSTNAME CONFIG_MDNS_HOSTNAME #define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int IP4_CONNECTED_BIT = BIT0; -const int IP6_CONNECTED_BIT = BIT1; - static const char *TAG = "mdns-test"; -static bool auto_reconnect = true; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_CONNECTED: - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IP4_CONNECTED_BIT); - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: - xEventGroupSetBits(wifi_event_group, IP6_CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - /* This is a workaround as ESP32 WiFi libs don't currently - auto-reassociate. */ - if (auto_reconnect) { - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - } - xEventGroupClearBits(wifi_event_group, IP4_CONNECTED_BIT | IP6_CONNECTED_BIT); - break; - default: - break; - } - mdns_handle_system_event(ctx, event); - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} static void initialise_mdns(void) { @@ -233,9 +158,6 @@ static void check_button(void) static void mdns_example_task(void *pvParameters) { - /* Wait for the callback to set the CONNECTED_BIT in the event group. */ - xEventGroupWaitBits(wifi_event_group, IP4_CONNECTED_BIT | IP6_CONNECTED_BIT, - false, true, portMAX_DELAY); while(1) { check_button(); vTaskDelay(50 / portTICK_PERIOD_MS); @@ -244,9 +166,14 @@ static void mdns_example_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); + initialise_mdns(); - initialise_wifi(); initialise_button(); + xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); } diff --git a/examples/protocols/mqtt/ssl/CMakeLists.txt b/examples/protocols/mqtt/ssl/CMakeLists.txt index 13bdd8c2..63ce6063 100644 --- a/examples/protocols/mqtt/ssl/CMakeLists.txt +++ b/examples/protocols/mqtt/ssl/CMakeLists.txt @@ -2,6 +2,10 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mqtt_ssl) diff --git a/examples/protocols/mqtt/ssl/Makefile b/examples/protocols/mqtt/ssl/Makefile index bae0d73b..efe7f7d5 100644 --- a/examples/protocols/mqtt/ssl/Makefile +++ b/examples/protocols/mqtt/ssl/Makefile @@ -4,4 +4,6 @@ # PROJECT_NAME := mqtt_ssl +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/mqtt/ssl/main/Kconfig.projbuild b/examples/protocols/mqtt/ssl/main/Kconfig.projbuild index 8b4eda41..6aa3e08f 100644 --- a/examples/protocols/mqtt/ssl/main/Kconfig.projbuild +++ b/examples/protocols/mqtt/ssl/main/Kconfig.projbuild @@ -1,17 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - config BROKER_URI string "Broker URL" default "mqtts://iot.eclipse.org:8883" diff --git a/examples/protocols/mqtt/ssl/main/app_main.c b/examples/protocols/mqtt/ssl/main/app_main.c index 17818e4e..e1a70b55 100644 --- a/examples/protocols/mqtt/ssl/main/app_main.c +++ b/examples/protocols/mqtt/ssl/main/app_main.c @@ -2,81 +2,25 @@ #include #include #include -#include "esp_wifi.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event_loop.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" #include "lwip/sockets.h" #include "lwip/dns.h" #include "lwip/netdb.h" -#include "esp_log.h" #include "mqtt_client.h" static const char *TAG = "MQTTS_EXAMPLE"; -static EventGroupHandle_t wifi_event_group; -const static int CONNECTED_BIT = BIT0; - - - -static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void wifi_init(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = CONFIG_WIFI_SSID, - .password = CONFIG_WIFI_PASSWORD, - }, - }; - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_LOGI(TAG, "start the WIFI SSID:[%s]", CONFIG_WIFI_SSID); - ESP_ERROR_CHECK(esp_wifi_start()); - ESP_LOGI(TAG, "Waiting for wifi"); - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); -} - #if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1 static const uint8_t iot_eclipse_org_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; #else @@ -144,6 +88,12 @@ static void mqtt_app_start(void) void app_main() { + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); + ESP_LOGI(TAG, "[APP] Startup.."); ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); @@ -155,8 +105,5 @@ void app_main() esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); - nvs_flash_init(); - wifi_init(); mqtt_app_start(); - } diff --git a/examples/protocols/mqtt/ssl/sdkconfig.ci b/examples/protocols/mqtt/ssl/sdkconfig.ci index ce328a6b..27a129be 100644 --- a/examples/protocols/mqtt/ssl/sdkconfig.ci +++ b/examples/protocols/mqtt/ssl/sdkconfig.ci @@ -1,2 +1,3 @@ CONFIG_BROKER_URI="mqtts://${EXAMPLE_MQTT_BROKER_SSL}" CONFIG_BROKER_CERTIFICATE_OVERRIDE="${EXAMPLE_MQTT_BROKER_CERTIFICATE}" +CONFIG_MQTT_USING_ESP=y diff --git a/examples/protocols/mqtt/ssl/sdkconfig.defaults b/examples/protocols/mqtt/ssl/sdkconfig.defaults new file mode 100644 index 00000000..31a9759a --- /dev/null +++ b/examples/protocols/mqtt/ssl/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_MQTT_USING_ESP=y diff --git a/examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt b/examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt index 84bf3752..e99ccf5f 100644 --- a/examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt +++ b/examples/protocols/mqtt/ssl_mutual_auth/CMakeLists.txt @@ -2,6 +2,10 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mqtt_ssl_mutual_auth) diff --git a/examples/protocols/mqtt/ssl_mutual_auth/Makefile b/examples/protocols/mqtt/ssl_mutual_auth/Makefile index cfc04f81..1394f99a 100644 --- a/examples/protocols/mqtt/ssl_mutual_auth/Makefile +++ b/examples/protocols/mqtt/ssl_mutual_auth/Makefile @@ -4,4 +4,6 @@ # PROJECT_NAME := mqtt_ssl_mutual_auth +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/Kconfig.projbuild b/examples/protocols/mqtt/ssl_mutual_auth/main/Kconfig.projbuild deleted file mode 100644 index 176d8fb3..00000000 --- a/examples/protocols/mqtt/ssl_mutual_auth/main/Kconfig.projbuild +++ /dev/null @@ -1,15 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - -endmenu diff --git a/examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c b/examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c index adf5db9a..c1815a53 100644 --- a/examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c +++ b/examples/protocols/mqtt/ssl_mutual_auth/main/app_main.c @@ -2,81 +2,25 @@ #include #include #include -#include "esp_wifi.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event_loop.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" #include "lwip/sockets.h" #include "lwip/dns.h" #include "lwip/netdb.h" -#include "esp_log.h" #include "mqtt_client.h" static const char *TAG = "MQTTS_EXAMPLE"; -static EventGroupHandle_t wifi_event_group; -const static int CONNECTED_BIT = BIT0; - - - -static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void wifi_init(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = CONFIG_WIFI_SSID, - .password = CONFIG_WIFI_PASSWORD, - }, - }; - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_LOGI(TAG, "start the WIFI SSID:[%s]", CONFIG_WIFI_SSID); - ESP_ERROR_CHECK(esp_wifi_start()); - ESP_LOGI(TAG, "Waiting for wifi"); - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); -} - extern const uint8_t client_cert_pem_start[] asm("_binary_client_crt_start"); extern const uint8_t client_cert_pem_end[] asm("_binary_client_crt_end"); extern const uint8_t client_key_pem_start[] asm("_binary_client_key_start"); @@ -142,6 +86,12 @@ static void mqtt_app_start(void) void app_main() { + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); + ESP_LOGI(TAG, "[APP] Startup.."); ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); @@ -153,8 +103,5 @@ void app_main() esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); - nvs_flash_init(); - wifi_init(); mqtt_app_start(); - } diff --git a/examples/protocols/mqtt/ssl_mutual_auth/sdkconfig.defaults b/examples/protocols/mqtt/ssl_mutual_auth/sdkconfig.defaults new file mode 100644 index 00000000..31a9759a --- /dev/null +++ b/examples/protocols/mqtt/ssl_mutual_auth/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_MQTT_USING_ESP=y diff --git a/examples/protocols/mqtt/tcp/CMakeLists.txt b/examples/protocols/mqtt/tcp/CMakeLists.txt index 678d787a..dd954008 100644 --- a/examples/protocols/mqtt/tcp/CMakeLists.txt +++ b/examples/protocols/mqtt/tcp/CMakeLists.txt @@ -2,6 +2,10 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mqtt_tcp) \ No newline at end of file diff --git a/examples/protocols/mqtt/tcp/Makefile b/examples/protocols/mqtt/tcp/Makefile index cd53fdbf..53027650 100644 --- a/examples/protocols/mqtt/tcp/Makefile +++ b/examples/protocols/mqtt/tcp/Makefile @@ -4,4 +4,6 @@ # PROJECT_NAME := mqtt_tcp +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/mqtt/tcp/main/Kconfig.projbuild b/examples/protocols/mqtt/tcp/main/Kconfig.projbuild index 71f95ea8..0b0f9f8f 100644 --- a/examples/protocols/mqtt/tcp/main/Kconfig.projbuild +++ b/examples/protocols/mqtt/tcp/main/Kconfig.projbuild @@ -1,17 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - config BROKER_URL string "Broker URL" default "mqtt://iot.eclipse.org" diff --git a/examples/protocols/mqtt/tcp/main/app_main.c b/examples/protocols/mqtt/tcp/main/app_main.c index ea37a740..72a16b3e 100644 --- a/examples/protocols/mqtt/tcp/main/app_main.c +++ b/examples/protocols/mqtt/tcp/main/app_main.c @@ -2,30 +2,25 @@ #include #include #include -#include "esp_wifi.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event_loop.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" #include "lwip/sockets.h" #include "lwip/dns.h" #include "lwip/netdb.h" -#include "esp_log.h" #include "mqtt_client.h" static const char *TAG = "MQTT_EXAMPLE"; -static EventGroupHandle_t wifi_event_group; -const static int CONNECTED_BIT = BIT0; - - static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) { esp_mqtt_client_handle_t client = event->client; @@ -73,56 +68,6 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) return ESP_OK; } -static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void wifi_init(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = CONFIG_WIFI_SSID, - .password = CONFIG_WIFI_PASSWORD, - }, - }; - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_LOGI(TAG, "start the WIFI SSID:[%s]", CONFIG_WIFI_SSID); - ESP_ERROR_CHECK(esp_wifi_start()); - ESP_LOGI(TAG, "Waiting for wifi"); - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); -} - static void mqtt_app_start(void) { esp_mqtt_client_config_t mqtt_cfg = { @@ -162,6 +107,12 @@ static void mqtt_app_start(void) void app_main() { + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); + ESP_LOGI(TAG, "[APP] Startup.."); ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); @@ -173,7 +124,5 @@ void app_main() esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); - nvs_flash_init(); - wifi_init(); mqtt_app_start(); } diff --git a/examples/protocols/mqtt/tcp/sdkconfig.ci b/examples/protocols/mqtt/tcp/sdkconfig.ci index 09ca8f37..f0b34b79 100644 --- a/examples/protocols/mqtt/tcp/sdkconfig.ci +++ b/examples/protocols/mqtt/tcp/sdkconfig.ci @@ -1,2 +1,3 @@ CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y CONFIG_BROKER_URL="FROM_STDIN" +CONFIG_MQTT_USING_ESP=y diff --git a/examples/protocols/mqtt/tcp/sdkconfig.defaults b/examples/protocols/mqtt/tcp/sdkconfig.defaults new file mode 100644 index 00000000..31a9759a --- /dev/null +++ b/examples/protocols/mqtt/tcp/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_MQTT_USING_ESP=y diff --git a/examples/protocols/mqtt/ws/CMakeLists.txt b/examples/protocols/mqtt/ws/CMakeLists.txt index 58a2135d..c272385f 100644 --- a/examples/protocols/mqtt/ws/CMakeLists.txt +++ b/examples/protocols/mqtt/ws/CMakeLists.txt @@ -2,6 +2,10 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mqtt_websocket) \ No newline at end of file diff --git a/examples/protocols/mqtt/ws/Makefile b/examples/protocols/mqtt/ws/Makefile index 668719bf..2b97fa44 100644 --- a/examples/protocols/mqtt/ws/Makefile +++ b/examples/protocols/mqtt/ws/Makefile @@ -4,4 +4,6 @@ # PROJECT_NAME := mqtt_websocket +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/mqtt/ws/main/Kconfig.projbuild b/examples/protocols/mqtt/ws/main/Kconfig.projbuild index 5223e885..add2256b 100644 --- a/examples/protocols/mqtt/ws/main/Kconfig.projbuild +++ b/examples/protocols/mqtt/ws/main/Kconfig.projbuild @@ -1,17 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - config BROKER_URI string "Broker URL" default "ws://iot.eclipse.org:80/ws" diff --git a/examples/protocols/mqtt/ws/main/app_main.c b/examples/protocols/mqtt/ws/main/app_main.c index 6b1e18c8..7b86b462 100644 --- a/examples/protocols/mqtt/ws/main/app_main.c +++ b/examples/protocols/mqtt/ws/main/app_main.c @@ -2,30 +2,25 @@ #include #include #include -#include "esp_wifi.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event_loop.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" #include "lwip/sockets.h" #include "lwip/dns.h" #include "lwip/netdb.h" -#include "esp_log.h" #include "mqtt_client.h" static const char *TAG = "MQTTWS_EXAMPLE"; -static EventGroupHandle_t wifi_event_group; -const static int CONNECTED_BIT = BIT0; - - static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) { esp_mqtt_client_handle_t client = event->client; @@ -70,56 +65,6 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) return ESP_OK; } -static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void wifi_init(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = CONFIG_WIFI_SSID, - .password = CONFIG_WIFI_PASSWORD, - }, - }; - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_LOGI(TAG, "start the WIFI SSID:[%s]", CONFIG_WIFI_SSID); - ESP_ERROR_CHECK(esp_wifi_start()); - ESP_LOGI(TAG, "Waiting for wifi"); - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); -} - static void mqtt_app_start(void) { const esp_mqtt_client_config_t mqtt_cfg = { @@ -134,6 +79,13 @@ static void mqtt_app_start(void) void app_main() { + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + + ESP_ERROR_CHECK(example_connect()); + ESP_LOGI(TAG, "[APP] Startup.."); ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); @@ -146,7 +98,5 @@ void app_main() esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); - nvs_flash_init(); - wifi_init(); mqtt_app_start(); } diff --git a/examples/protocols/mqtt/ws/sdkconfig.ci b/examples/protocols/mqtt/ws/sdkconfig.ci index 4f14eef9..f024d643 100644 --- a/examples/protocols/mqtt/ws/sdkconfig.ci +++ b/examples/protocols/mqtt/ws/sdkconfig.ci @@ -1 +1,2 @@ CONFIG_BROKER_URI="ws://${EXAMPLE_MQTT_BROKER_WS}/ws" +CONFIG_MQTT_USING_ESP=y diff --git a/examples/protocols/mqtt/ws/sdkconfig.defaults b/examples/protocols/mqtt/ws/sdkconfig.defaults new file mode 100644 index 00000000..31a9759a --- /dev/null +++ b/examples/protocols/mqtt/ws/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_MQTT_USING_ESP=y diff --git a/examples/protocols/mqtt/wss/CMakeLists.txt b/examples/protocols/mqtt/wss/CMakeLists.txt index 7ba5e629..ca6651bd 100644 --- a/examples/protocols/mqtt/wss/CMakeLists.txt +++ b/examples/protocols/mqtt/wss/CMakeLists.txt @@ -2,6 +2,10 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mqtt_websocket_secure) diff --git a/examples/protocols/mqtt/wss/Makefile b/examples/protocols/mqtt/wss/Makefile index 27047d04..50ed13dd 100644 --- a/examples/protocols/mqtt/wss/Makefile +++ b/examples/protocols/mqtt/wss/Makefile @@ -4,4 +4,6 @@ # PROJECT_NAME := mqtt_websocket_secure +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/mqtt/wss/main/Kconfig.projbuild b/examples/protocols/mqtt/wss/main/Kconfig.projbuild index 964d436f..7a15e2b6 100644 --- a/examples/protocols/mqtt/wss/main/Kconfig.projbuild +++ b/examples/protocols/mqtt/wss/main/Kconfig.projbuild @@ -1,17 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - config BROKER_URI string "Broker URL" default "wss://iot.eclipse.org:443/ws" diff --git a/examples/protocols/mqtt/wss/main/app_main.c b/examples/protocols/mqtt/wss/main/app_main.c index 06f6307d..c9c658a8 100644 --- a/examples/protocols/mqtt/wss/main/app_main.c +++ b/examples/protocols/mqtt/wss/main/app_main.c @@ -2,81 +2,25 @@ #include #include #include -#include "esp_wifi.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event_loop.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" #include "lwip/sockets.h" #include "lwip/dns.h" #include "lwip/netdb.h" -#include "esp_log.h" #include "mqtt_client.h" static const char *TAG = "MQTTWSS_EXAMPLE"; -static EventGroupHandle_t wifi_event_group; -const static int CONNECTED_BIT = BIT0; - - - -static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void wifi_init(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = CONFIG_WIFI_SSID, - .password = CONFIG_WIFI_PASSWORD, - }, - }; - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_LOGI(TAG, "start the WIFI SSID:[%s]", CONFIG_WIFI_SSID); - ESP_ERROR_CHECK(esp_wifi_start()); - ESP_LOGI(TAG, "Waiting for wifi"); - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); -} - #if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1 static const uint8_t iot_eclipse_org_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; #else @@ -143,6 +87,13 @@ static void mqtt_app_start(void) void app_main() { + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + + ESP_ERROR_CHECK(example_connect()); + ESP_LOGI(TAG, "[APP] Startup.."); ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); @@ -154,7 +105,5 @@ void app_main() esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); - nvs_flash_init(); - wifi_init(); mqtt_app_start(); } diff --git a/examples/protocols/mqtt/wss/sdkconfig.ci b/examples/protocols/mqtt/wss/sdkconfig.ci index d4af6205..ed4ef640 100644 --- a/examples/protocols/mqtt/wss/sdkconfig.ci +++ b/examples/protocols/mqtt/wss/sdkconfig.ci @@ -1,2 +1,3 @@ CONFIG_BROKER_URI="wss://${EXAMPLE_MQTT_BROKER_WSS}/ws" CONFIG_BROKER_CERTIFICATE_OVERRIDE="${EXAMPLE_MQTT_BROKER_CERTIFICATE}" +CONFIG_MQTT_USING_ESP=y diff --git a/examples/protocols/mqtt/wss/sdkconfig.defaults b/examples/protocols/mqtt/wss/sdkconfig.defaults new file mode 100644 index 00000000..31a9759a --- /dev/null +++ b/examples/protocols/mqtt/wss/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_MQTT_USING_ESP=y diff --git a/examples/protocols/openssl_client/CMakeLists.txt b/examples/protocols/openssl_client/CMakeLists.txt index 3b366a05..83830446 100644 --- a/examples/protocols/openssl_client/CMakeLists.txt +++ b/examples/protocols/openssl_client/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(openssl_client) diff --git a/examples/protocols/openssl_client/Makefile b/examples/protocols/openssl_client/Makefile index 7e2f4fe7..1ae39bf1 100644 --- a/examples/protocols/openssl_client/Makefile +++ b/examples/protocols/openssl_client/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := openssl_client +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/openssl_client/main/Kconfig.projbuild b/examples/protocols/openssl_client/main/Kconfig.projbuild index 13605964..d7934480 100644 --- a/examples/protocols/openssl_client/main/Kconfig.projbuild +++ b/examples/protocols/openssl_client/main/Kconfig.projbuild @@ -13,18 +13,4 @@ config TARGET_PORT_NUMBER help Target port number for the example to connect to. -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - endmenu diff --git a/examples/protocols/openssl_client/main/openssl_client_example_main.c b/examples/protocols/openssl_client/main/openssl_client_example_main.c index 29c6f494..564f3397 100644 --- a/examples/protocols/openssl_client/main/openssl_client_example_main.c +++ b/examples/protocols/openssl_client/main/openssl_client_example_main.c @@ -10,40 +10,21 @@ #include #include -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" - #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" #include #include #include "openssl/ssl.h" -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -static const char *TAG = "example"; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - extern const uint8_t ca_pem_start[] asm("_binary_ca_pem_start"); extern const uint8_t ca_pem_end[] asm("_binary_ca_pem_end"); extern const uint8_t client_pem_start[] asm("_binary_client_pem_start"); @@ -73,53 +54,6 @@ static int send_bytes = sizeof(send_data); static char recv_buf[OPENSSL_CLIENT_RECV_BUF_LEN]; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - static void openssl_client_task(void* p) { int ret; @@ -134,10 +68,6 @@ static void openssl_client_task(void* p) printf("OpenSSL client thread start...\n"); - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); - /*get addr info for hostname*/ do { entry = gethostbyname(CONFIG_TARGET_DOMAIN); @@ -282,7 +212,11 @@ failed1: void app_main(void) { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); + xTaskCreate(&openssl_client_task, "openssl_client", 8192, NULL, 6, NULL); } diff --git a/examples/protocols/openssl_demo/CMakeLists.txt b/examples/protocols/openssl_demo/CMakeLists.txt index 477e79ae..3af20bda 100644 --- a/examples/protocols/openssl_demo/CMakeLists.txt +++ b/examples/protocols/openssl_demo/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(openssl_demo) diff --git a/examples/protocols/openssl_demo/Makefile b/examples/protocols/openssl_demo/Makefile index d5f30fcd..21e33142 100644 --- a/examples/protocols/openssl_demo/Makefile +++ b/examples/protocols/openssl_demo/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := openssl_demo +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/openssl_demo/main/Kconfig.projbuild b/examples/protocols/openssl_demo/main/Kconfig.projbuild deleted file mode 100644 index 92a75195..00000000 --- a/examples/protocols/openssl_demo/main/Kconfig.projbuild +++ /dev/null @@ -1,17 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - -endmenu diff --git a/examples/protocols/openssl_demo/main/openssl_demo_example_main.c b/examples/protocols/openssl_demo/main/openssl_demo_example_main.c index a5242542..837b9e20 100644 --- a/examples/protocols/openssl_demo/main/openssl_demo_example_main.c +++ b/examples/protocols/openssl_demo/main/openssl_demo_example_main.c @@ -10,37 +10,18 @@ #include #include #include - -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" - #include #include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_netif.h" +#include "esp_event.h" #include "openssl/ssl.h" - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; +#include "protocol_examples_common.h" static const char *TAG = "example"; @@ -58,57 +39,6 @@ static int send_bytes = sizeof(send_data); static char recv_buf[OPENSSL_DEMO_RECV_BUF_LEN]; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - - default: - break; - } - - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); -} - static void openssl_task(void *p) { int ret; @@ -124,13 +54,6 @@ static void openssl_task(void *p) ESP_LOGI(TAG, "OpenSSL demo thread start..."); - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); - /*get addr info for hostname*/ do { entry = gethostbyname(OPENSSL_DEMO_TARGET_NAME); @@ -260,6 +183,11 @@ failed1: void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); - initialise_wifi(); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + + ESP_ERROR_CHECK(example_connect()); + xTaskCreate(&openssl_task, "openssl_task", 8192, NULL, 5, NULL); } diff --git a/examples/protocols/openssl_server/CMakeLists.txt b/examples/protocols/openssl_server/CMakeLists.txt index d0a68b27..22094167 100644 --- a/examples/protocols/openssl_server/CMakeLists.txt +++ b/examples/protocols/openssl_server/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(openssl_server) diff --git a/examples/protocols/openssl_server/Makefile b/examples/protocols/openssl_server/Makefile index 8f781a8c..87d6e942 100644 --- a/examples/protocols/openssl_server/Makefile +++ b/examples/protocols/openssl_server/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := openssl-server +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/openssl_server/main/Kconfig.projbuild b/examples/protocols/openssl_server/main/Kconfig.projbuild deleted file mode 100644 index 92a75195..00000000 --- a/examples/protocols/openssl_server/main/Kconfig.projbuild +++ /dev/null @@ -1,17 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - -endmenu diff --git a/examples/protocols/openssl_server/main/openssl_server_example_main.c b/examples/protocols/openssl_server/main/openssl_server_example_main.c index 7431e8a4..20a2d9e5 100644 --- a/examples/protocols/openssl_server/main/openssl_server_example_main.c +++ b/examples/protocols/openssl_server/main/openssl_server_example_main.c @@ -11,39 +11,20 @@ #include #include -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" - #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" #include #include "openssl/ssl.h" -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -static const char *TAG = "example"; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - extern const uint8_t ca_pem_start[] asm("_binary_ca_pem_start"); extern const uint8_t ca_pem_end[] asm("_binary_ca_pem_end"); extern const uint8_t server_pem_start[] asm("_binary_server_pem_start"); @@ -73,53 +54,6 @@ static int send_bytes = sizeof(send_data); static char recv_buf[OPENSSL_SERVER_RECV_BUF_LEN]; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - static void openssl_server_task(void* p) { int ret; @@ -134,13 +68,6 @@ static void openssl_server_task(void* p) printf("OpenSSL server thread start...\n"); - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); - printf("create SSL context ......"); ctx = SSL_CTX_new(TLSv1_2_server_method()); @@ -287,7 +214,11 @@ failed1: void app_main(void) { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); + xTaskCreate(&openssl_server_task, "openssl_server", 8192, NULL, 6, NULL); } diff --git a/examples/protocols/sntp/CMakeLists.txt b/examples/protocols/sntp/CMakeLists.txt index 872321a8..99c51e87 100644 --- a/examples/protocols/sntp/CMakeLists.txt +++ b/examples/protocols/sntp/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(sntp) diff --git a/examples/protocols/sntp/Makefile b/examples/protocols/sntp/Makefile index e6ef17be..d3e9a53f 100644 --- a/examples/protocols/sntp/Makefile +++ b/examples/protocols/sntp/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := sntp +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sntp/main/Kconfig.projbuild b/examples/protocols/sntp/main/Kconfig.projbuild deleted file mode 100644 index 92a75195..00000000 --- a/examples/protocols/sntp/main/Kconfig.projbuild +++ /dev/null @@ -1,17 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - -endmenu diff --git a/examples/protocols/sntp/main/sntp_example_main.c b/examples/protocols/sntp/main/sntp_example_main.c index 50687a26..7683f21d 100644 --- a/examples/protocols/sntp/main/sntp_example_main.c +++ b/examples/protocols/sntp/main/sntp_example_main.c @@ -12,34 +12,17 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" - #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" - +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" +#include "driver/gpio.h" #include "lwip/apps/sntp.h" -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - static const char *TAG = "sntp_example"; static void initialize_sntp(void) @@ -52,8 +35,6 @@ static void initialize_sntp(void) static void obtain_time(void) { - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); initialize_sntp(); // wait for time to be set @@ -70,37 +51,6 @@ static void obtain_time(void) } } -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - - default: - break; - } - - return ESP_OK; -} - static void sntp_example_task(void *arg) { time_t now; @@ -141,39 +91,13 @@ static void sntp_example_task(void *arg) } } -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); -} - void app_main() { - //Initialize NVS - esp_err_t ret = nvs_flash_init(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - - ESP_ERROR_CHECK(ret); - - initialise_wifi(); + ESP_ERROR_CHECK(example_connect()); // SNTP service uses LwIP, please allocate large stack space. xTaskCreate(sntp_example_task, "sntp_example_task", 2048, NULL, 10, NULL); diff --git a/examples/protocols/sockets/tcp_client/CMakeLists.txt b/examples/protocols/sockets/tcp_client/CMakeLists.txt index 22aa37f1..aee70cad 100644 --- a/examples/protocols/sockets/tcp_client/CMakeLists.txt +++ b/examples/protocols/sockets/tcp_client/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(tcp_client) diff --git a/examples/protocols/sockets/tcp_client/Makefile b/examples/protocols/sockets/tcp_client/Makefile index b390190f..eee056b3 100644 --- a/examples/protocols/sockets/tcp_client/Makefile +++ b/examples/protocols/sockets/tcp_client/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := tcp_client +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sockets/tcp_client/main/Kconfig.projbuild b/examples/protocols/sockets/tcp_client/main/Kconfig.projbuild index 1beefd49..b5f67bec 100644 --- a/examples/protocols/sockets/tcp_client/main/Kconfig.projbuild +++ b/examples/protocols/sockets/tcp_client/main/Kconfig.projbuild @@ -1,18 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - choice EXAMPLE_IP_MODE prompt "IP Version" help @@ -22,7 +9,7 @@ config EXAMPLE_IPV4 bool "IPV4" config EXAMPLE_IPV6 - select LWIP_IPV6 + select EXAMPLE_CONNECT_IPV6 bool "IPV6" endchoice diff --git a/examples/protocols/sockets/tcp_client/main/tcp_client.c b/examples/protocols/sockets/tcp_client/main/tcp_client.c index cd546ddb..f7bc6eab 100644 --- a/examples/protocols/sockets/tcp_client/main/tcp_client.c +++ b/examples/protocols/sockets/tcp_client/main/tcp_client.c @@ -8,13 +8,15 @@ */ #include #include + #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" #include "lwip/err.h" @@ -22,15 +24,6 @@ #include "lwip/sys.h" #include - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #ifdef CONFIG_EXAMPLE_IPV4 #define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR #else @@ -39,96 +32,9 @@ #define PORT CONFIG_EXAMPLE_PORT -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -const int IPV4_GOTIP_BIT = BIT0; -#ifdef CONFIG_EXAMPLE_IPV6 -const int IPV6_GOTIP_BIT = BIT1; -#endif - static const char *TAG = "example"; static const char *payload = "Message from ESP32 "; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - break; - case SYSTEM_EVENT_STA_CONNECTED: -#ifdef CONFIG_EXAMPLE_IPV6 - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); -#endif - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); -#ifdef CONFIG_EXAMPLE_IPV6 - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); -#endif - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: -#ifdef CONFIG_EXAMPLE_IPV6 - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP6"); - - char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip); - ESP_LOGI(TAG, "IPv6: %s", ip6); -#endif - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -static void wait_for_ip() -{ -#ifdef CONFIG_EXAMPLE_IPV6 - uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT; -#else - uint32_t bits = IPV4_GOTIP_BIT; -#endif - - ESP_LOGI(TAG, "Waiting for AP connection..."); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); -} - static void tcp_client_task(void *pvParameters) { char rx_buffer[128]; @@ -203,9 +109,11 @@ static void tcp_client_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); - wait_for_ip(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); xTaskCreate(tcp_client_task, "tcp_client", 4096, NULL, 5, NULL); } diff --git a/examples/protocols/sockets/tcp_server/CMakeLists.txt b/examples/protocols/sockets/tcp_server/CMakeLists.txt index 3514e60f..9865464b 100644 --- a/examples/protocols/sockets/tcp_server/CMakeLists.txt +++ b/examples/protocols/sockets/tcp_server/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(tcp_server) diff --git a/examples/protocols/sockets/tcp_server/Makefile b/examples/protocols/sockets/tcp_server/Makefile index e965b909..ccdc6d54 100644 --- a/examples/protocols/sockets/tcp_server/Makefile +++ b/examples/protocols/sockets/tcp_server/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := tcp_server +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sockets/tcp_server/main/Kconfig.projbuild b/examples/protocols/sockets/tcp_server/main/Kconfig.projbuild index c1209ac8..8d1d772c 100644 --- a/examples/protocols/sockets/tcp_server/main/Kconfig.projbuild +++ b/examples/protocols/sockets/tcp_server/main/Kconfig.projbuild @@ -1,18 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - choice EXAMPLE_IP_MODE prompt "IP Version" help @@ -23,7 +10,7 @@ config EXAMPLE_IPV4 config EXAMPLE_IPV6 bool "IPV6" - select LWIP_IPV6 + select EXAMPLE_CONNECT_IPV6 endchoice diff --git a/examples/protocols/sockets/tcp_server/main/tcp_server.c b/examples/protocols/sockets/tcp_server/main/tcp_server.c index d7c6472a..4b1c2d93 100644 --- a/examples/protocols/sockets/tcp_server/main/tcp_server.c +++ b/examples/protocols/sockets/tcp_server/main/tcp_server.c @@ -8,13 +8,15 @@ */ #include #include + #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" #include "lwip/err.h" @@ -22,106 +24,10 @@ #include "lwip/sys.h" #include - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #define PORT CONFIG_EXAMPLE_PORT -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -const int IPV4_GOTIP_BIT = BIT0; -#ifdef CONFIG_EXAMPLE_IPV6 -const int IPV6_GOTIP_BIT = BIT1; -#endif - static const char *TAG = "example"; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - break; - case SYSTEM_EVENT_STA_CONNECTED: -#ifdef CONFIG_EXAMPLE_IPV6 - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); -#endif - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); -#ifdef CONFIG_EXAMPLE_IPV6 - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); -#endif - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: -#ifdef CONFIG_EXAMPLE_IPV6 - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP6"); - - char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip); - ESP_LOGI(TAG, "IPv6: %s", ip6); -#endif - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -static void wait_for_ip() -{ -#ifdef CONFIG_EXAMPLE_IPV6 - uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT; -#else - uint32_t bits = IPV4_GOTIP_BIT; -#endif - - ESP_LOGI(TAG, "Waiting for AP connection..."); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); -} - static void tcp_server_task(void *pvParameters) { char rx_buffer[128]; @@ -231,9 +137,11 @@ static void tcp_server_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); - wait_for_ip(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL); } diff --git a/examples/protocols/sockets/udp_client/CMakeLists.txt b/examples/protocols/sockets/udp_client/CMakeLists.txt index ee1d3f53..2049b819 100644 --- a/examples/protocols/sockets/udp_client/CMakeLists.txt +++ b/examples/protocols/sockets/udp_client/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(udp_client) diff --git a/examples/protocols/sockets/udp_client/Makefile b/examples/protocols/sockets/udp_client/Makefile index 34849eee..604aa5af 100644 --- a/examples/protocols/sockets/udp_client/Makefile +++ b/examples/protocols/sockets/udp_client/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := udp_client +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sockets/udp_client/main/Kconfig.projbuild b/examples/protocols/sockets/udp_client/main/Kconfig.projbuild index 7dfe1ddc..240af89a 100644 --- a/examples/protocols/sockets/udp_client/main/Kconfig.projbuild +++ b/examples/protocols/sockets/udp_client/main/Kconfig.projbuild @@ -1,18 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - choice EXAMPLE_IP_MODE prompt "IP Version" help @@ -23,7 +10,7 @@ config EXAMPLE_IPV4 config EXAMPLE_IPV6 bool "IPV6" - select LWIP_IPV6 + select EXAMPLE_CONNECT_IPV6 endchoice diff --git a/examples/protocols/sockets/udp_client/main/udp_client.c b/examples/protocols/sockets/udp_client/main/udp_client.c index 79f9aaa5..caae111e 100644 --- a/examples/protocols/sockets/udp_client/main/udp_client.c +++ b/examples/protocols/sockets/udp_client/main/udp_client.c @@ -8,13 +8,15 @@ */ #include #include + #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" #include "lwip/err.h" @@ -22,15 +24,6 @@ #include "lwip/sys.h" #include - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #ifdef CONFIG_EXAMPLE_IPV4 #define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR #else @@ -39,96 +32,9 @@ #define PORT CONFIG_EXAMPLE_PORT -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -const int IPV4_GOTIP_BIT = BIT0; -#ifdef CONFIG_EXAMPLE_IPV6 -const int IPV6_GOTIP_BIT = BIT1; -#endif - static const char *TAG = "example"; static const char *payload = "Message from ESP32 "; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - break; - case SYSTEM_EVENT_STA_CONNECTED: -#ifdef CONFIG_EXAMPLE_IPV6 - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); -#endif - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); -#ifdef CONFIG_EXAMPLE_IPV6 - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); -#endif - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: -#ifdef CONFIG_EXAMPLE_IPV6 - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP6"); - - char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip); - ESP_LOGI(TAG, "IPv6: %s", ip6); -#endif - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -static void wait_for_ip() -{ -#ifdef CONFIG_EXAMPLE_IPV6 - uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT; -#else - uint32_t bits = IPV4_GOTIP_BIT; -#endif - - ESP_LOGI(TAG, "Waiting for AP connection..."); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); -} - static void udp_client_task(void *pvParameters) { char rx_buffer[128]; @@ -202,9 +108,11 @@ static void udp_client_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); - wait_for_ip(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); xTaskCreate(udp_client_task, "udp_client", 4096, NULL, 5, NULL); } diff --git a/examples/protocols/sockets/udp_multicast/CMakeLists.txt b/examples/protocols/sockets/udp_multicast/CMakeLists.txt index fe4b8fe8..f89b3347 100644 --- a/examples/protocols/sockets/udp_multicast/CMakeLists.txt +++ b/examples/protocols/sockets/udp_multicast/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(udp-multicast) diff --git a/examples/protocols/sockets/udp_multicast/Makefile b/examples/protocols/sockets/udp_multicast/Makefile index 60f3d59d..47e26b95 100644 --- a/examples/protocols/sockets/udp_multicast/Makefile +++ b/examples/protocols/sockets/udp_multicast/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := udp-multicast +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sockets/udp_multicast/main/Kconfig.projbuild b/examples/protocols/sockets/udp_multicast/main/Kconfig.projbuild index 4f0d46a3..ea9db39f 100644 --- a/examples/protocols/sockets/udp_multicast/main/Kconfig.projbuild +++ b/examples/protocols/sockets/udp_multicast/main/Kconfig.projbuild @@ -1,19 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - choice EXAMPLE_IP_MODE prompt "Multicast IP type" help @@ -38,7 +24,7 @@ config EXAMPLE_IPV4 bool config EXAMPLE_IPV6 bool - select LWIP_IPV6 + select EXAMPLE_CONNECT_IPV6 config EXAMPLE_MULTICAST_IPV4_ADDR string "Multicast IPV4 Address (send & receive)" diff --git a/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c b/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c index 5dea3f6a..fe5db370 100644 --- a/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c +++ b/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c @@ -8,13 +8,15 @@ */ #include #include + #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" #include "lwip/err.h" @@ -22,15 +24,6 @@ #include "lwip/sys.h" #include -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #define UDP_PORT CONFIG_EXAMPLE_PORT #define MULTICAST_LOOPBACK CONFIG_EXAMPLE_LOOPBACK @@ -42,15 +35,6 @@ #define LISTEN_DEFAULT_IF CONFIG_EXAMPLE_LISTEN_DEFAULT_IF -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - we use two - one for IPv4 "got ip", and - one for IPv6 "got ip". */ -const int IPV4_GOTIP_BIT = BIT0; -const int IPV6_GOTIP_BIT = BIT1; - static const char *TAG = "multicast"; #ifdef CONFIG_EXAMPLE_IPV4 static const char *V4TAG = "mcast-ipv4"; @@ -59,60 +43,6 @@ static const char *V4TAG = "mcast-ipv4"; static const char *V6TAG = "mcast-ipv6"; #endif -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_CONNECTED: - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - #ifdef CONFIG_EXAMPLE_IPV4 /* Add a socket, either IPV4-only or IPV6 dual mode, to the IPV4 multicast group */ @@ -362,19 +292,6 @@ err: static void mcast_example_task(void *pvParameters) { while (1) { - /* Wait for all the IPs we care about to be set - */ - uint32_t bits = 0; -#ifdef CONFIG_EXAMPLE_IPV4 - bits |= IPV4_GOTIP_BIT; -#endif -#ifdef CONFIG_EXAMPLE_IPV6 - bits |= IPV6_GOTIP_BIT; -#endif - ESP_LOGI(TAG, "Waiting for AP connection..."); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); - int sock; #ifdef CONFIG_EXAMPLE_IPV4_ONLY @@ -553,7 +470,11 @@ static void mcast_example_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); + xTaskCreate(&mcast_example_task, "mcast_task", 4096, NULL, 5, NULL); } diff --git a/examples/protocols/sockets/udp_server/CMakeLists.txt b/examples/protocols/sockets/udp_server/CMakeLists.txt index d1edab0f..86143180 100644 --- a/examples/protocols/sockets/udp_server/CMakeLists.txt +++ b/examples/protocols/sockets/udp_server/CMakeLists.txt @@ -2,5 +2,9 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(udp_server) diff --git a/examples/protocols/sockets/udp_server/Makefile b/examples/protocols/sockets/udp_server/Makefile index 36552c9b..bc11a430 100644 --- a/examples/protocols/sockets/udp_server/Makefile +++ b/examples/protocols/sockets/udp_server/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := udp_server +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/sockets/udp_server/main/Kconfig.projbuild b/examples/protocols/sockets/udp_server/main/Kconfig.projbuild index c1209ac8..8d1d772c 100644 --- a/examples/protocols/sockets/udp_server/main/Kconfig.projbuild +++ b/examples/protocols/sockets/udp_server/main/Kconfig.projbuild @@ -1,18 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - choice EXAMPLE_IP_MODE prompt "IP Version" help @@ -23,7 +10,7 @@ config EXAMPLE_IPV4 config EXAMPLE_IPV6 bool "IPV6" - select LWIP_IPV6 + select EXAMPLE_CONNECT_IPV6 endchoice diff --git a/examples/protocols/sockets/udp_server/main/udp_server.c b/examples/protocols/sockets/udp_server/main/udp_server.c index 2e81d0c5..07af193c 100644 --- a/examples/protocols/sockets/udp_server/main/udp_server.c +++ b/examples/protocols/sockets/udp_server/main/udp_server.c @@ -8,13 +8,15 @@ */ #include #include + #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" #include "lwip/err.h" @@ -22,106 +24,10 @@ #include "lwip/sys.h" #include - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD - #define PORT CONFIG_EXAMPLE_PORT -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -const int IPV4_GOTIP_BIT = BIT0; -#ifdef CONFIG_EXAMPLE_IPV6 -const int IPV6_GOTIP_BIT = BIT1; -#endif - static const char *TAG = "example"; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); - break; - case SYSTEM_EVENT_STA_CONNECTED: -#ifdef CONFIG_EXAMPLE_IPV6 - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); -#endif - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); -#ifdef CONFIG_EXAMPLE_IPV6 - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); -#endif - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: -#ifdef CONFIG_EXAMPLE_IPV6 - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP6"); - - char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip); - ESP_LOGI(TAG, "IPv6: %s", ip6); -#endif - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - -static void wait_for_ip() -{ -#ifdef CONFIG_EXAMPLE_IPV6 - uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT; -#else - uint32_t bits = IPV4_GOTIP_BIT; -#endif - - ESP_LOGI(TAG, "Waiting for AP connection..."); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connected to AP"); -} - static void udp_server_task(void *pvParameters) { char rx_buffer[128]; @@ -214,9 +120,11 @@ static void udp_server_task(void *pvParameters) void app_main() { - ESP_ERROR_CHECK( nvs_flash_init() ); - initialise_wifi(); - wait_for_ip(); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); xTaskCreate(udp_server_task, "udp_server", 4096, NULL, 5, NULL); } diff --git a/examples/provisioning/custom_config/CMakeLists.txt b/examples/provisioning/custom_config/CMakeLists.txt index ec9b0ce6..52f2c76f 100644 --- a/examples/provisioning/custom_config/CMakeLists.txt +++ b/examples/provisioning/custom_config/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(custom_config) diff --git a/examples/provisioning/custom_config/Makefile b/examples/provisioning/custom_config/Makefile index 8ded51d7..2a74b778 100644 --- a/examples/provisioning/custom_config/Makefile +++ b/examples/provisioning/custom_config/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := custom_config +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/provisioning/custom_config/main/Kconfig.projbuild b/examples/provisioning/custom_config/main/Kconfig.projbuild index 866227bb..33f635e0 100644 --- a/examples/provisioning/custom_config/main/Kconfig.projbuild +++ b/examples/provisioning/custom_config/main/Kconfig.projbuild @@ -49,4 +49,10 @@ config RESET_PROVISIONED This erases the NVS to reset provisioned status of the device on every reboot. Provisioned status is determined by the WiFi STA configuration, saved on the NVS. +config EXAMPLE_AP_RECONN_ATTEMPTS + int "Maximum AP connection attempts" + default 5 + help + Set the maximum connection attempts to perform when connecting to a Wi-Fi AP. + endmenu diff --git a/examples/provisioning/custom_config/main/app_main.c b/examples/provisioning/custom_config/main/app_main.c index 17bb29ae..63a8cd44 100644 --- a/examples/provisioning/custom_config/main/app_main.c +++ b/examples/provisioning/custom_config/main/app_main.c @@ -8,13 +8,17 @@ */ #include -#include -#include -#include -#include -#include -#include -#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" #include #include @@ -23,48 +27,36 @@ static const char *TAG = "app"; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* Invoke Provisioning event handler first */ - app_prov_event_handler(ctx, event); +#define EXAMPLE_AP_RECONN_ATTEMPTS CONFIG_EXAMPLE_AP_RECONN_ATTEMPTS - switch(event->event_id) { - case SYSTEM_EVENT_AP_START: - ESP_LOGI(TAG, "SoftAP started"); - break; - case SYSTEM_EVENT_AP_STOP: - ESP_LOGI(TAG, "SoftAP stopped"); - break; - case SYSTEM_EVENT_STA_START: +static void event_handler(void* arg, esp_event_base_t event_base, + int event_id, void* event_data) +{ + static int s_retry_num = 0; + + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (s_retry_num < EXAMPLE_AP_RECONN_ATTEMPTS) { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } + ESP_LOGI(TAG,"connect to the AP fail"); + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:"MACSTR" join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:"MACSTR"leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - break; - default: - break; + ip4addr_ntoa(&event->ip_info.ip)); + s_retry_num = 0; } - return ESP_OK; } static void wifi_init_sta() { - /* Start wifi in station mode with credentials set during provisioning */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + /* Set our event handling */ + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler, NULL)); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK(esp_wifi_start() ); } @@ -92,8 +84,12 @@ void app_main() /* Initialize networking stack */ tcpip_adapter_init(); - /* Set our event handling */ - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + /* Create default event loop needed by the + * main app and the provisioning service */ + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* Initialize NVS needed by Wi-Fi */ + ESP_ERROR_CHECK(nvs_flash_init()); /* Check if device is provisioned */ bool provisioned; diff --git a/examples/provisioning/softap_prov/CMakeLists.txt b/examples/provisioning/softap_prov/CMakeLists.txt index fa6ac143..95d0b77b 100644 --- a/examples/provisioning/softap_prov/CMakeLists.txt +++ b/examples/provisioning/softap_prov/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(softap_prov) diff --git a/examples/provisioning/softap_prov/Makefile b/examples/provisioning/softap_prov/Makefile index ab167ef2..cb6d6fb2 100644 --- a/examples/provisioning/softap_prov/Makefile +++ b/examples/provisioning/softap_prov/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := softap_prov +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/provisioning/softap_prov/main/Kconfig.projbuild b/examples/provisioning/softap_prov/main/Kconfig.projbuild index 08cb2f97..4ec635a9 100644 --- a/examples/provisioning/softap_prov/main/Kconfig.projbuild +++ b/examples/provisioning/softap_prov/main/Kconfig.projbuild @@ -50,4 +50,10 @@ config RESET_PROVISIONED This erases the NVS to reset provisioned status of the device on every reboot. Provisioned status is determined by the WiFi STA configuration, saved on the NVS. +config EXAMPLE_AP_RECONN_ATTEMPTS + int "Maximum AP connection attempts" + default 5 + help + Set the maximum connection attempts to perform when connecting to a Wi-Fi AP. + endmenu diff --git a/examples/provisioning/softap_prov/main/app_main.c b/examples/provisioning/softap_prov/main/app_main.c index 65a100e4..c2eec9bd 100644 --- a/examples/provisioning/softap_prov/main/app_main.c +++ b/examples/provisioning/softap_prov/main/app_main.c @@ -23,48 +23,35 @@ static const char *TAG = "app"; -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* Invoke Provisioning event handler first */ - app_prov_event_handler(ctx, event); +#define EXAMPLE_AP_RECONN_ATTEMPTS CONFIG_EXAMPLE_AP_RECONN_ATTEMPTS - switch(event->event_id) { - case SYSTEM_EVENT_AP_START: - ESP_LOGI(TAG, "SoftAP started"); - break; - case SYSTEM_EVENT_AP_STOP: - ESP_LOGI(TAG, "SoftAP stopped"); - break; - case SYSTEM_EVENT_STA_START: +static void event_handler(void* arg, esp_event_base_t event_base, + int event_id, void* event_data) +{ + static int s_retry_num = 0; + + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (s_retry_num < EXAMPLE_AP_RECONN_ATTEMPTS) { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } + ESP_LOGI(TAG,"connect to the AP fail"); + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:"MACSTR" join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:"MACSTR"leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - break; - default: - break; + ip4addr_ntoa(&event->ip_info.ip)); + s_retry_num = 0; } - return ESP_OK; } static void wifi_init_sta() { - /* Start wifi in station mode with credentials set during provisioning */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler, NULL)); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK(esp_wifi_start() ); } @@ -92,8 +79,12 @@ void app_main() /* Initialize networking stack */ tcpip_adapter_init(); - /* Set our event handling */ - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + /* Create default event loop needed by the + * main app and the provisioning service */ + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* Initialize NVS needed by Wi-Fi */ + ESP_ERROR_CHECK(nvs_flash_init()); /* Check if device is provisioned */ bool provisioned; diff --git a/examples/system/console/main/console_example_main.c b/examples/system/console/main/console_example_main.c index 73d164ae..41c9239b 100644 --- a/examples/system/console/main/console_example_main.c +++ b/examples/system/console/main/console_example_main.c @@ -47,7 +47,7 @@ static void initialize_console() * correct while APB frequency is changing in light sleep mode. */ uart_config_t uart_config = { - .baud_rate = CONFIG_CONSOLE_UART_BAUDRATE, + .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, diff --git a/examples/system/factory-test/main/main.c b/examples/system/factory-test/main/main.c index 2ac582a5..4f822e8c 100644 --- a/examples/system/factory-test/main/main.c +++ b/examples/system/factory-test/main/main.c @@ -22,10 +22,13 @@ #include "driver/uart.h" #include "nano_console.h" #include "esp_libc.h" +#include "esp_task.h" #ifndef ESP_FACTORY_TEST_EXTRA_COMPONENTS +#ifndef CONFIG_ESP_CONSOLE_UART_NUM #define CONFIG_ESP_CONSOLE_UART_NUM 0 +#endif #define TAG "factory-test" @@ -43,7 +46,7 @@ static void initialize_console() * correct while APB frequency is changing in light sleep mode. */ uart_config_t uart_config = { - .baud_rate = CONFIG_CONSOLE_UART_BAUDRATE, + .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/CMakeLists.txt b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/CMakeLists.txt index f736f959..09abd053 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/CMakeLists.txt +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(native_ota) \ No newline at end of file diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/Makefile b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/Makefile index 7ffb1023..b276959c 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/Makefile +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := ota +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/main/Kconfig.projbuild b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/main/Kconfig.projbuild index 74a06d93..051f8917 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/main/Kconfig.projbuild +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/main/Kconfig.projbuild @@ -1,19 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "myssid" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - config SERVER_IP string "HTTP Server IP" default "192.168.0.3" diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/main/ota_example_main.c b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/main/ota_example_main.c index 4f1838da..fa3fc46e 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/main/ota_example_main.c +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old/main/ota_example_main.c @@ -13,19 +13,15 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" - #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" -#include "esp_ota_ops.h" - +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" #include "nvs.h" #include "nvs_flash.h" +#include "esp_ota_ops.h" -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD #define EXAMPLE_SERVER_IP CONFIG_SERVER_IP #define EXAMPLE_SERVER_PORT CONFIG_SERVER_PORT #define EXAMPLE_FILENAME CONFIG_EXAMPLE_FILENAME @@ -68,61 +64,6 @@ static int binary_file_length = 0; /*socket id*/ static int socket_id = -1; -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - /*read buffer by byte still delim ,return read bytes counts*/ static int read_until(const char *buffer, char delim, int len) { @@ -339,13 +280,6 @@ static void ota_example_task(void *pvParameter) ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", running->type, running->subtype, running->address); - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server...."); - /*connect to http server*/ if (connect_to_http_server()) { ESP_LOGI(TAG, "Connected to http server"); @@ -447,17 +381,11 @@ static void ota_example_task(void *pvParameter) void app_main() { - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - // OTA app partition table has a smaller NVS partition size than the non-OTA - // partition table. This size mismatch may cause NVS initialization to fail. - // If this happens, we erase NVS partition and initialize NVS again. - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); - initialise_wifi(); xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); } diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/CMakeLists.txt b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/CMakeLists.txt index f736f959..09abd053 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/CMakeLists.txt +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(native_ota) \ No newline at end of file diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/Makefile b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/Makefile index 7ffb1023..b276959c 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/Makefile +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := ota +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/main/Kconfig.projbuild b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/main/Kconfig.projbuild index 74a06d93..051f8917 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/main/Kconfig.projbuild +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/main/Kconfig.projbuild @@ -1,19 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "myssid" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - config SERVER_IP string "HTTP Server IP" default "192.168.0.3" diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/main/ota_example_main.c b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/main/ota_example_main.c index 4df5a494..c9054252 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/main/ota_example_main.c +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_no_old_copy/main/ota_example_main.c @@ -13,19 +13,15 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" - #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" -#include "esp_ota_ops.h" - +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" #include "nvs.h" #include "nvs_flash.h" +#include "esp_ota_ops.h" -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD #define EXAMPLE_SERVER_IP CONFIG_SERVER_IP #define EXAMPLE_SERVER_PORT CONFIG_SERVER_PORT #define EXAMPLE_FILENAME CONFIG_EXAMPLE_FILENAME @@ -68,61 +64,6 @@ static int binary_file_length = 0; /*socket id*/ static int socket_id = -1; -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - /*read buffer by byte still delim ,return read bytes counts*/ static int read_until(const char *buffer, char delim, int len) { @@ -339,13 +280,6 @@ static void ota_example_task(void *pvParameter) ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", running->type, running->subtype, running->address); - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server...."); - /*connect to http server*/ if (connect_to_http_server()) { ESP_LOGI(TAG, "Connected to http server"); @@ -447,17 +381,11 @@ static void ota_example_task(void *pvParameter) void app_main() { - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - // OTA app partition table has a smaller NVS partition size than the non-OTA - // partition table. This size mismatch may cause NVS initialization to fail. - // If this happens, we erase NVS partition and initialize NVS again. - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); - initialise_wifi(); xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); } diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/CMakeLists.txt b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/CMakeLists.txt index f736f959..09abd053 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/CMakeLists.txt +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(native_ota) \ No newline at end of file diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/Makefile b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/Makefile index 7ffb1023..b276959c 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/Makefile +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := ota +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/Kconfig.projbuild b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/Kconfig.projbuild index b24c7756..3388e54e 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/Kconfig.projbuild +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/Kconfig.projbuild @@ -6,22 +6,6 @@ config CONNECT_ORIGINAL_AP help Connect to the original AP of old SDK -config WIFI_SSID - string "WiFi SSID" - default "myssid" - depends on !CONNECT_ORIGINAL_AP - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "myssid" - depends on !CONNECT_ORIGINAL_AP - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - config SERVER_IP string "HTTP Server IP" default "192.168.0.3" diff --git a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/ota_example_main.c b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/ota_example_main.c index 53bb569c..29fd3f63 100644 --- a/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/ota_example_main.c +++ b/examples/system/ota/native_ota/1MB_flash/new_to_new_with_old/main/ota_example_main.c @@ -11,24 +11,21 @@ #include #include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" - +#include "sdkconfig.h" #ifdef CONFIG_CONNECT_ORIGINAL_AP #include "internal/esp_system_internal.h" #endif +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" -#include "esp_ota_ops.h" - +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" #include "nvs.h" #include "nvs_flash.h" +#include "esp_ota_ops.h" -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD #define EXAMPLE_SERVER_IP CONFIG_SERVER_IP #define EXAMPLE_SERVER_PORT CONFIG_SERVER_PORT #define EXAMPLE_FILENAME CONFIG_EXAMPLE_FILENAME @@ -71,48 +68,14 @@ static int binary_file_length = 0; /*socket id*/ static int socket_id = -1; -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - static void initialise_wifi(void) { #ifdef CONFIG_CONNECT_ORIGINAL_AP int ret; uint32_t addr; struct old_sysconf *sysconf; - wifi_config_t wifi_config = { 0 }; + char ssid[32]; + char passwd[32]; if (!(addr = esp_get_old_sysconf_addr())) { ESP_LOGE(TAG, "Current firmware does not update from old SDK firmware"); @@ -130,30 +93,15 @@ static void initialise_wifi(void) return ; } - memcpy(&wifi_config.sta.ssid, sysconf->ap_ssid[sysconf->ap_index].ssid, sysconf->ap_ssid[sysconf->ap_index].len); - memcpy(&wifi_config.sta.password, sysconf->ap_ssid[sysconf->ap_index].passwd, 32); + memcpy(ssid, sysconf->ap_ssid[sysconf->ap_index].ssid, sysconf->ap_ssid[sysconf->ap_index].len); + memcpy(passwd, sysconf->ap_ssid[sysconf->ap_index].passwd, 32); + + example_set_connection_info(ssid, passwd); free(sysconf); -#else - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; #endif - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); + ESP_ERROR_CHECK(example_connect()); } /*read buffer by byte still delim ,return read bytes counts*/ @@ -381,13 +329,6 @@ static void ota_example_task(void *pvParameter) ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", running->type, running->subtype, running->address); - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server...."); - /*connect to http server*/ if (connect_to_http_server()) { ESP_LOGI(TAG, "Connected to http server"); @@ -489,17 +430,11 @@ static void ota_example_task(void *pvParameter) void app_main() { - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - // OTA app partition table has a smaller NVS partition size than the non-OTA - // partition table. This size mismatch may cause NVS initialization to fail. - // If this happens, we erase NVS partition and initialize NVS again. - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); initialise_wifi(); + xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); } diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/CMakeLists.txt b/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/CMakeLists.txt index f736f959..09abd053 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/CMakeLists.txt +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(native_ota) \ No newline at end of file diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/Makefile b/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/Makefile index 7ffb1023..b276959c 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/Makefile +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := ota +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/main/Kconfig.projbuild b/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/main/Kconfig.projbuild index 74a06d93..051f8917 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/main/Kconfig.projbuild +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/main/Kconfig.projbuild @@ -1,19 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "myssid" - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - config SERVER_IP string "HTTP Server IP" default "192.168.0.3" diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/main/ota_example_main.c b/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/main/ota_example_main.c index 4df5a494..c9054252 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/main/ota_example_main.c +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_no_old/main/ota_example_main.c @@ -13,19 +13,15 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" - #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" -#include "esp_ota_ops.h" - +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" #include "nvs.h" #include "nvs_flash.h" +#include "esp_ota_ops.h" -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD #define EXAMPLE_SERVER_IP CONFIG_SERVER_IP #define EXAMPLE_SERVER_PORT CONFIG_SERVER_PORT #define EXAMPLE_FILENAME CONFIG_EXAMPLE_FILENAME @@ -68,61 +64,6 @@ static int binary_file_length = 0; /*socket id*/ static int socket_id = -1; -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - /*read buffer by byte still delim ,return read bytes counts*/ static int read_until(const char *buffer, char delim, int len) { @@ -339,13 +280,6 @@ static void ota_example_task(void *pvParameter) ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", running->type, running->subtype, running->address); - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server...."); - /*connect to http server*/ if (connect_to_http_server()) { ESP_LOGI(TAG, "Connected to http server"); @@ -447,17 +381,11 @@ static void ota_example_task(void *pvParameter) void app_main() { - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - // OTA app partition table has a smaller NVS partition size than the non-OTA - // partition table. This size mismatch may cause NVS initialization to fail. - // If this happens, we erase NVS partition and initialize NVS again. - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); - initialise_wifi(); xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); } diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/CMakeLists.txt b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/CMakeLists.txt index f736f959..09abd053 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/CMakeLists.txt +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(native_ota) \ No newline at end of file diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/Makefile b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/Makefile index 7ffb1023..b276959c 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/Makefile +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := ota +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/Kconfig.projbuild b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/Kconfig.projbuild index b24c7756..3388e54e 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/Kconfig.projbuild +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/Kconfig.projbuild @@ -6,22 +6,6 @@ config CONNECT_ORIGINAL_AP help Connect to the original AP of old SDK -config WIFI_SSID - string "WiFi SSID" - default "myssid" - depends on !CONNECT_ORIGINAL_AP - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "myssid" - depends on !CONNECT_ORIGINAL_AP - help - WiFi password (WPA or WPA2) for the example to use. - - Can be left blank if the network has no security set. - config SERVER_IP string "HTTP Server IP" default "192.168.0.3" diff --git a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/ota_example_main.c b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/ota_example_main.c index 53bb569c..29fd3f63 100644 --- a/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/ota_example_main.c +++ b/examples/system/ota/native_ota/2+MB_flash/new_to_new_with_old/main/ota_example_main.c @@ -11,24 +11,21 @@ #include #include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" - +#include "sdkconfig.h" #ifdef CONFIG_CONNECT_ORIGINAL_AP #include "internal/esp_system_internal.h" #endif +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" -#include "esp_ota_ops.h" - +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" #include "nvs.h" #include "nvs_flash.h" +#include "esp_ota_ops.h" -#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID -#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD #define EXAMPLE_SERVER_IP CONFIG_SERVER_IP #define EXAMPLE_SERVER_PORT CONFIG_SERVER_PORT #define EXAMPLE_FILENAME CONFIG_EXAMPLE_FILENAME @@ -71,48 +68,14 @@ static int binary_file_length = 0; /*socket id*/ static int socket_id = -1; -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - static void initialise_wifi(void) { #ifdef CONFIG_CONNECT_ORIGINAL_AP int ret; uint32_t addr; struct old_sysconf *sysconf; - wifi_config_t wifi_config = { 0 }; + char ssid[32]; + char passwd[32]; if (!(addr = esp_get_old_sysconf_addr())) { ESP_LOGE(TAG, "Current firmware does not update from old SDK firmware"); @@ -130,30 +93,15 @@ static void initialise_wifi(void) return ; } - memcpy(&wifi_config.sta.ssid, sysconf->ap_ssid[sysconf->ap_index].ssid, sysconf->ap_ssid[sysconf->ap_index].len); - memcpy(&wifi_config.sta.password, sysconf->ap_ssid[sysconf->ap_index].passwd, 32); + memcpy(ssid, sysconf->ap_ssid[sysconf->ap_index].ssid, sysconf->ap_ssid[sysconf->ap_index].len); + memcpy(passwd, sysconf->ap_ssid[sysconf->ap_index].passwd, 32); + + example_set_connection_info(ssid, passwd); free(sysconf); -#else - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, - }, - }; #endif - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); + ESP_ERROR_CHECK(example_connect()); } /*read buffer by byte still delim ,return read bytes counts*/ @@ -381,13 +329,6 @@ static void ota_example_task(void *pvParameter) ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", running->type, running->subtype, running->address); - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server...."); - /*connect to http server*/ if (connect_to_http_server()) { ESP_LOGI(TAG, "Connected to http server"); @@ -489,17 +430,11 @@ static void ota_example_task(void *pvParameter) void app_main() { - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - // OTA app partition table has a smaller NVS partition size than the non-OTA - // partition table. This size mismatch may cause NVS initialization to fail. - // If this happens, we erase NVS partition and initialize NVS again. - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); initialise_wifi(); + xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); } diff --git a/examples/system/ota/simple_ota_example/CMakeLists.txt b/examples/system/ota/simple_ota_example/CMakeLists.txt index ae979292..8753cace 100644 --- a/examples/system/ota/simple_ota_example/CMakeLists.txt +++ b/examples/system/ota/simple_ota_example/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(simple_ota) \ No newline at end of file diff --git a/examples/system/ota/simple_ota_example/Makefile b/examples/system/ota/simple_ota_example/Makefile index 63bca1ab..63c0d6be 100644 --- a/examples/system/ota/simple_ota_example/Makefile +++ b/examples/system/ota/simple_ota_example/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := simple_ota +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/system/ota/simple_ota_example/main/Kconfig.projbuild b/examples/system/ota/simple_ota_example/main/Kconfig.projbuild index 38bf5cb4..8e51daa0 100644 --- a/examples/system/ota/simple_ota_example/main/Kconfig.projbuild +++ b/examples/system/ota/simple_ota_example/main/Kconfig.projbuild @@ -1,17 +1,5 @@ menu "Example Configuration" -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - config FIRMWARE_UPGRADE_URL string "firmware upgrade url endpoint" default "https://192.168.0.3:8070/hello-world.bin" diff --git a/examples/system/ota/simple_ota_example/main/simple_ota_example.c b/examples/system/ota/simple_ota_example/main/simple_ota_example.c index c2796429..f4c809b5 100644 --- a/examples/system/ota/simple_ota_example/main/simple_ota_example.c +++ b/examples/system/ota/simple_ota_example/main/simple_ota_example.c @@ -10,29 +10,23 @@ #include "freertos/task.h" #include "freertos/event_groups.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" #include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "nvs.h" +#include "nvs_flash.h" #include "esp_ota_ops.h" #include "esp_http_client.h" #include "esp_https_ota.h" -#include "nvs.h" -#include "nvs_flash.h" - static const char *TAG = "simple_ota_example"; extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start"); extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end"); -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int CONNECTED_BIT = BIT0; - esp_err_t _http_event_handler(esp_http_client_event_t *evt) { switch(evt->event_id) { @@ -61,64 +55,10 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) return ESP_OK; } -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); - ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - wifi_config_t wifi_config = { - .sta = { - .ssid = CONFIG_WIFI_SSID, - .password = CONFIG_WIFI_PASSWORD, - }, - }; - ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); - ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK( esp_wifi_start() ); -} - void simple_ota_example_task(void * pvParameter) { ESP_LOGI(TAG, "Starting OTA example..."); - - /* Wait for the callback to set the CONNECTED_BIT in the - event group. - */ - xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, - false, true, portMAX_DELAY); - ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server...."); - + esp_http_client_config_t config = { .url = CONFIG_FIRMWARE_UPGRADE_URL, .cert_pem = (char *)server_cert_pem_start, @@ -137,17 +77,11 @@ void simple_ota_example_task(void * pvParameter) void app_main() { - // Initialize NVS. - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - // OTA app partition table has a smaller NVS partition size than the non-OTA - // partition table. This size mismatch may cause NVS initialization to fail. - // If this happens, we erase NVS partition and initialize NVS again. - ESP_ERROR_CHECK(nvs_flash_erase()); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK( err ); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); - initialise_wifi(); xTaskCreate(&simple_ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); } diff --git a/examples/wifi/espnow/main/espnow_example_main.c b/examples/wifi/espnow/main/espnow_example_main.c index 8bd5a004..37407ca2 100644 --- a/examples/wifi/espnow/main/espnow_example_main.c +++ b/examples/wifi/espnow/main/espnow_example_main.c @@ -39,23 +39,13 @@ static uint16_t s_example_espnow_seq[EXAMPLE_ESPNOW_DATA_MAX] = { 0, 0 }; static void example_espnow_deinit(example_espnow_send_param_t *send_param); -static esp_err_t example_event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - ESP_LOGI(TAG, "WiFi started"); - break; - default: - break; - } - return ESP_OK; -} - /* WiFi should start before using ESPNOW */ static void example_wifi_init(void) { tcpip_adapter_init(); - ESP_ERROR_CHECK( esp_event_loop_init(example_event_handler, NULL) ); + + ESP_ERROR_CHECK(esp_event_loop_create_default()); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); diff --git a/examples/wifi/getting_started/softAP/CMakeLists.txt b/examples/wifi/getting_started/softAP/CMakeLists.txt new file mode 100644 index 00000000..e05fb18d --- /dev/null +++ b/examples/wifi/getting_started/softAP/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(wifi_softAP) diff --git a/examples/wifi/simple_wifi/Makefile b/examples/wifi/getting_started/softAP/Makefile similarity index 84% rename from examples/wifi/simple_wifi/Makefile rename to examples/wifi/getting_started/softAP/Makefile index b9ced39c..507c5e06 100644 --- a/examples/wifi/simple_wifi/Makefile +++ b/examples/wifi/getting_started/softAP/Makefile @@ -3,7 +3,7 @@ # project subdirectory. # -PROJECT_NAME := simple_wifi +PROJECT_NAME := wifi_softAP include $(IDF_PATH)/make/project.mk diff --git a/examples/wifi/getting_started/softAP/README.md b/examples/wifi/getting_started/softAP/README.md new file mode 100644 index 00000000..4b030e01 --- /dev/null +++ b/examples/wifi/getting_started/softAP/README.md @@ -0,0 +1,42 @@ +# WiFi softAP example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + + +## How to use example + +### Configure the project + +``` +idf.py menuconfig +``` + +* Set serial port under Serial Flasher Options. + +* Set WiFi SSID and WiFi Password and Maximal STA connections under Example Configuration Options. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +There is the console output for this example: + +``` +I (917) phy: phy_version: 3960, 5211945, Jul 18 2018, 10:40:07, 0, 0 +I (917) wifi: mode : softAP (30:ae:a4:80:45:69) +I (917) wifi softAP: wifi_init_softap finished.SSID:myssid password:mypassword +I (26457) wifi: n:1 0, o:1 0, ap:1 1, sta:255 255, prof:1 +I (26457) wifi: station: 70:ef:00:43:96:67 join, AID=1, bg, 20 +I (26467) wifi softAP: station:70:ef:00:43:96:67 join, AID=1 +I (27657) tcpip_adapter: softAP assign IP to station,IP is: 192.168.4.2 +``` diff --git a/examples/wifi/getting_started/softAP/main/CMakeLists.txt b/examples/wifi/getting_started/softAP/main/CMakeLists.txt new file mode 100644 index 00000000..a8938829 --- /dev/null +++ b/examples/wifi/getting_started/softAP/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "softap_example_main.c" + INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/wifi/getting_started/softAP/main/Kconfig.projbuild b/examples/wifi/getting_started/softAP/main/Kconfig.projbuild new file mode 100644 index 00000000..37829050 --- /dev/null +++ b/examples/wifi/getting_started/softAP/main/Kconfig.projbuild @@ -0,0 +1,20 @@ +menu "Example Configuration" + + config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + + config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + + config ESP_MAX_STA_CONN + int "Maximal STA connections" + default 4 + help + Max number of the STA connects to AP. +endmenu diff --git a/examples/wifi/getting_started/softAP/main/component.mk b/examples/wifi/getting_started/softAP/main/component.mk new file mode 100644 index 00000000..61f8990c --- /dev/null +++ b/examples/wifi/getting_started/softAP/main/component.mk @@ -0,0 +1,8 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# diff --git a/examples/wifi/getting_started/softAP/main/softap_example_main.c b/examples/wifi/getting_started/softAP/main/softap_example_main.c new file mode 100644 index 00000000..25c9ee54 --- /dev/null +++ b/examples/wifi/getting_started/softAP/main/softap_example_main.c @@ -0,0 +1,83 @@ +/* WiFi softAP Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sys.h" + +/* The examples use WiFi configuration that you can set via project configuration menu. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD +#define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN + +static const char *TAG = "wifi softAP"; + +static void wifi_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + if (event_id == WIFI_EVENT_AP_STACONNECTED) { + wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data; + ESP_LOGI(TAG, "station "MACSTR" join, AID=%d", + MAC2STR(event->mac), event->aid); + } else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) { + wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data; + ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d", + MAC2STR(event->mac), event->aid); + } +} + +void wifi_init_softap() +{ + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL)); + + wifi_config_t wifi_config = { + .ap = { + .ssid = EXAMPLE_ESP_WIFI_SSID, + .ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID), + .password = EXAMPLE_ESP_WIFI_PASS, + .max_connection = EXAMPLE_MAX_STA_CONN, + .authmode = WIFI_AUTH_WPA_WPA2_PSK + }, + }; + if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) { + wifi_config.ap.authmode = WIFI_AUTH_OPEN; + } + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); +} + +void app_main() +{ + ESP_ERROR_CHECK(nvs_flash_init()); + + ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); + wifi_init_softap(); +} diff --git a/examples/wifi/getting_started/station/CMakeLists.txt b/examples/wifi/getting_started/station/CMakeLists.txt new file mode 100644 index 00000000..05a40120 --- /dev/null +++ b/examples/wifi/getting_started/station/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(wifi_station) diff --git a/examples/wifi/getting_started/station/Makefile b/examples/wifi/getting_started/station/Makefile new file mode 100644 index 00000000..ed014837 --- /dev/null +++ b/examples/wifi/getting_started/station/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := wifi_station + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/wifi/getting_started/station/README.md b/examples/wifi/getting_started/station/README.md new file mode 100644 index 00000000..f6e4f702 --- /dev/null +++ b/examples/wifi/getting_started/station/README.md @@ -0,0 +1,109 @@ +# WiFi station example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + + +## How to use example + +### Configure the project + +``` +idf.py menuconfig +``` + +* Set serial port under Serial Flasher Options. + +* Set WiFi SSID and WiFi Password and Maximum retry under Example Configuration Options. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output +Note that the output, in particular the order of the output, may vary depending on the environment. + +Console output if station connects to AP successfully: +``` +I (589) wifi station: ESP_WIFI_MODE_STA +I (599) wifi: wifi driver task: 3ffc08b4, prio:23, stack:3584, core=0 +I (599) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (599) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (629) wifi: wifi firmware version: 2d94f02 +I (629) wifi: config NVS flash: enabled +I (629) wifi: config nano formating: disabled +I (629) wifi: Init dynamic tx buffer num: 32 +I (629) wifi: Init data frame dynamic rx buffer num: 32 +I (639) wifi: Init management frame dynamic rx buffer num: 32 +I (639) wifi: Init management short buffer num: 32 +I (649) wifi: Init static rx buffer size: 1600 +I (649) wifi: Init static rx buffer num: 10 +I (659) wifi: Init dynamic rx buffer num: 32 +I (759) phy: phy_version: 4180, cb3948e, Sep 12 2019, 16:39:13, 0, 0 +I (769) wifi: mode : sta (30:ae:a4:d9:bc:c4) +I (769) wifi station: wifi_init_sta finished. +I (889) wifi: new:<6,0>, old:<1,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (889) wifi: state: init -> auth (b0) +I (899) wifi: state: auth -> assoc (0) +I (909) wifi: state: assoc -> run (10) +I (939) wifi: connected with #!/bin/test, aid = 1, channel 6, BW20, bssid = ac:9e:17:7e:31:40 +I (939) wifi: security type: 3, phy: bgn, rssi: -68 +I (949) wifi: pm start, type: 1 + +I (1029) wifi: AP's beacon interval = 102400 us, DTIM period = 3 +I (2089) esp_netif_handlers: sta ip: 192.168.77.89, mask: 255.255.255.0, gw: 192.168.77.1 +I (2089) wifi station: got ip:192.168.77.89 +I (2089) wifi station: connected to ap SSID:myssid password:mypassword +``` + +Console output if the station failed to connect to AP: +``` +I (589) wifi station: ESP_WIFI_MODE_STA +I (599) wifi: wifi driver task: 3ffc08b4, prio:23, stack:3584, core=0 +I (599) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (599) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (629) wifi: wifi firmware version: 2d94f02 +I (629) wifi: config NVS flash: enabled +I (629) wifi: config nano formating: disabled +I (629) wifi: Init dynamic tx buffer num: 32 +I (629) wifi: Init data frame dynamic rx buffer num: 32 +I (639) wifi: Init management frame dynamic rx buffer num: 32 +I (639) wifi: Init management short buffer num: 32 +I (649) wifi: Init static rx buffer size: 1600 +I (649) wifi: Init static rx buffer num: 10 +I (659) wifi: Init dynamic rx buffer num: 32 +I (759) phy: phy_version: 4180, cb3948e, Sep 12 2019, 16:39:13, 0, 0 +I (759) wifi: mode : sta (30:ae:a4:d9:bc:c4) +I (769) wifi station: wifi_init_sta finished. +I (889) wifi: new:<6,0>, old:<1,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (889) wifi: state: init -> auth (b0) +I (1889) wifi: state: auth -> init (200) +I (1889) wifi: new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (1889) wifi station: retry to connect to the AP +I (1899) wifi station: connect to the AP fail +I (3949) wifi station: retry to connect to the AP +I (3949) wifi station: connect to the AP fail +I (4069) wifi: new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (4069) wifi: state: init -> auth (b0) +I (5069) wifi: state: auth -> init (200) +I (5069) wifi: new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (5069) wifi station: retry to connect to the AP +I (5069) wifi station: connect to the AP fail +I (7129) wifi station: retry to connect to the AP +I (7129) wifi station: connect to the AP fail +I (7249) wifi: new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (7249) wifi: state: init -> auth (b0) +I (8249) wifi: state: auth -> init (200) +I (8249) wifi: new:<6,0>, old:<6,0>, ap:<255,255>, sta:<6,0>, prof:1 +I (8249) wifi station: retry to connect to the AP +I (8249) wifi station: connect to the AP fail +I (10299) wifi station: connect to the AP fail +I (10299) wifi station: Failed to connect to SSID:myssid, password:mypassword +``` diff --git a/examples/wifi/getting_started/station/main/CMakeLists.txt b/examples/wifi/getting_started/station/main/CMakeLists.txt new file mode 100644 index 00000000..444b0f59 --- /dev/null +++ b/examples/wifi/getting_started/station/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "station_example_main.c" + INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/wifi/getting_started/station/main/Kconfig.projbuild b/examples/wifi/getting_started/station/main/Kconfig.projbuild new file mode 100644 index 00000000..7403f8f8 --- /dev/null +++ b/examples/wifi/getting_started/station/main/Kconfig.projbuild @@ -0,0 +1,20 @@ +menu "Example Configuration" + + config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + + config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + + config ESP_MAXIMUM_RETRY + int "Maximum retry" + default 5 + help + Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent. +endmenu diff --git a/examples/wifi/getting_started/station/main/component.mk b/examples/wifi/getting_started/station/main/component.mk new file mode 100644 index 00000000..61f8990c --- /dev/null +++ b/examples/wifi/getting_started/station/main/component.mk @@ -0,0 +1,8 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# diff --git a/examples/wifi/getting_started/station/main/station_example_main.c b/examples/wifi/getting_started/station/main/station_example_main.c new file mode 100644 index 00000000..fdd27303 --- /dev/null +++ b/examples/wifi/getting_started/station/main/station_example_main.c @@ -0,0 +1,126 @@ +/* WiFi station Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "esp_wifi.h" +#include "nvs.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sys.h" + +/* The examples use WiFi configuration that you can set via project configuration menu + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD +#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY + +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t s_wifi_event_group; + +/* The event group allows multiple bits for each event, but we only care about two events: + * - we are connected to the AP with an IP + * - we failed to connect after the maximum amount of retries */ +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 + +static const char *TAG = "wifi station"; + +static int s_retry_num = 0; + +static void event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } else { + xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); + } + ESP_LOGI(TAG,"connect to the AP fail"); + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + ESP_LOGI(TAG, "got ip:%s", + ip4addr_ntoa(&event->ip_info.ip)); + s_retry_num = 0; + xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); + } +} + +void wifi_init_sta(void) +{ + s_wifi_event_group = xEventGroupCreate(); + + tcpip_adapter_init(); + + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); + + wifi_config_t wifi_config = { + .sta = { + .ssid = EXAMPLE_ESP_WIFI_SSID, + .password = EXAMPLE_ESP_WIFI_PASS + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); + ESP_ERROR_CHECK(esp_wifi_start() ); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + + /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum + * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */ + EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, + WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, + pdFALSE, + pdFALSE, + portMAX_DELAY); + + /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually + * happened. */ + if (bits & WIFI_CONNECTED_BIT) { + ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); + } else if (bits & WIFI_FAIL_BIT) { + ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); + } else { + ESP_LOGE(TAG, "UNEXPECTED EVENT"); + } + + ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler)); + ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler)); + vEventGroupDelete(s_wifi_event_group); +} + +void app_main() +{ + ESP_ERROR_CHECK(nvs_flash_init()); + + ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); + wifi_init_sta(); +} diff --git a/examples/wifi/power_save/CMakeLists.txt b/examples/wifi/power_save/CMakeLists.txt index a9a182fe..07a1535d 100644 --- a/examples/wifi/power_save/CMakeLists.txt +++ b/examples/wifi/power_save/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(power_save) diff --git a/examples/wifi/power_save/Makefile b/examples/wifi/power_save/Makefile index 6f2f5543..32ca2cfd 100644 --- a/examples/wifi/power_save/Makefile +++ b/examples/wifi/power_save/Makefile @@ -5,5 +5,7 @@ PROJECT_NAME := power_save +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/wifi/power_save/main/Kconfig.projbuild b/examples/wifi/power_save/main/Kconfig.projbuild index 55b3a477..2a334543 100644 --- a/examples/wifi/power_save/main/Kconfig.projbuild +++ b/examples/wifi/power_save/main/Kconfig.projbuild @@ -1,17 +1,5 @@ menu "Example Configuration" - config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - choice ESP_POWER_SAVE_MODE prompt "power save mode" default EXAMPLE_POWER_SAVE_MIN_MODEM diff --git a/examples/wifi/power_save/main/power_save.c b/examples/wifi/power_save/main/power_save.c index 83872e75..df1673c7 100644 --- a/examples/wifi/power_save/main/power_save.c +++ b/examples/wifi/power_save/main/power_save.c @@ -13,19 +13,18 @@ start esp32 and when it connected to AP it will enter power save mode */ #include + #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" -#include "rom/ets_sys.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_system.h" #include "esp_log.h" +#include "esp_netif.h" +#include "esp_event.h" +#include "esp_wifi.h" +#include "protocol_examples_common.h" +#include "nvs.h" #include "nvs_flash.h" -/*set the ssid and password via "idf.py menuconfig"*/ -#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID -#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD - #if CONFIG_EXAMPLE_POWER_SAVE_MIN_MODEM #define DEFAULT_PS_MODE WIFI_PS_MIN_MODEM #elif CONFIG_EXAMPLE_POWER_SAVE_MAX_MODEM @@ -36,85 +35,13 @@ #define DEFAULT_PS_MODE WIFI_PS_NONE #endif /*CONFIG_POWER_SAVE_MODEM*/ -/* FreeRTOS event group to signal when we are connected*/ -static EventGroupHandle_t wifi_event_group; - -static const char *TAG = "power_save"; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:"MACSTR" join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:"MACSTR"leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - break; - default: - break; - } - return ESP_OK; -} - -/*init wifi as sta and set power save mode*/ -static void wifi_power_save(void) -{ - wifi_event_group = xEventGroupCreate(); - - tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_ESP_WIFI_SSID, - .password = EXAMPLE_ESP_WIFI_PASS - }, - }; - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK(esp_wifi_start() ); - - ESP_LOGI(TAG, "wifi_init_sta finished."); - ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", - EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); - ESP_LOGI(TAG, "esp_wifi_set_ps()."); - esp_wifi_set_ps(DEFAULT_PS_MODE); -} - void app_main(void) { - //Initialize NVS - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_ERROR_CHECK(example_connect()); - wifi_power_save(); + esp_wifi_set_ps(DEFAULT_PS_MODE); } diff --git a/examples/wifi/simple_wifi/CMakeLists.txt b/examples/wifi/simple_wifi/CMakeLists.txt deleted file mode 100644 index 1ef4ddb5..00000000 --- a/examples/wifi/simple_wifi/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(simple_wifi) diff --git a/examples/wifi/simple_wifi/main/CMakeLists.txt b/examples/wifi/simple_wifi/main/CMakeLists.txt deleted file mode 100644 index db9e8e94..00000000 --- a/examples/wifi/simple_wifi/main/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -set(COMPONENT_SRCS "simple_wifi.c") - -register_component() diff --git a/examples/wifi/simple_wifi/main/Kconfig.projbuild b/examples/wifi/simple_wifi/main/Kconfig.projbuild deleted file mode 100644 index 67bb8677..00000000 --- a/examples/wifi/simple_wifi/main/Kconfig.projbuild +++ /dev/null @@ -1,37 +0,0 @@ -menu "Example Configuration" - -choice ESP_WIFI_MODE - prompt "AP or STA" - default ESP_WIFI_IS_STATION - help - Whether the esp32 is softAP or station. - -config ESP_WIFI_IS_SOFTAP - bool "SoftAP" -config ESP_WIFI_IS_STATION - bool "Station" -endchoice - -config ESP_WIFI_MODE_AP - bool - default y if ESP_WIFI_IS_SOFTAP - default n if ESP_WIFI_IS_STATION - -config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - -config MAX_STA_CONN - int "Max STA conn" - default 4 - help - Max number of the STA connects to AP. -endmenu diff --git a/examples/wifi/simple_wifi/main/component.mk b/examples/wifi/simple_wifi/main/component.mk deleted file mode 100644 index 3277c9f9..00000000 --- a/examples/wifi/simple_wifi/main/component.mk +++ /dev/null @@ -1,4 +0,0 @@ -# -# "main" pseudo-component makefile. -# -# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) \ No newline at end of file diff --git a/examples/wifi/simple_wifi/main/simple_wifi.c b/examples/wifi/simple_wifi/main/simple_wifi.c deleted file mode 100644 index 975d393e..00000000 --- a/examples/wifi/simple_wifi/main/simple_wifi.c +++ /dev/null @@ -1,152 +0,0 @@ -/* Simple WiFi Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "rom/ets_sys.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_ESP_WIFI_MODE_AP CONFIG_ESP_WIFI_MODE_AP //TRUE:AP FALSE:STA -#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID -#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD -#define EXAMPLE_MAX_STA_CONN CONFIG_MAX_STA_CONN - -/* FreeRTOS event group to signal when we are connected*/ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int WIFI_CONNECTED_BIT = BIT0; - -static const char *TAG = "simple wifi"; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:"MACSTR" join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:"MACSTR"leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -void wifi_init_softap() -{ - wifi_event_group = xEventGroupCreate(); - - tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - wifi_config_t wifi_config = { - .ap = { - .ssid = EXAMPLE_ESP_WIFI_SSID, - .ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID), - .password = EXAMPLE_ESP_WIFI_PASS, - .max_connection = EXAMPLE_MAX_STA_CONN, - .authmode = WIFI_AUTH_WPA_WPA2_PSK - }, - }; - if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) { - wifi_config.ap.authmode = WIFI_AUTH_OPEN; - } - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); - - ESP_LOGI(TAG, "wifi_init_softap finished.SSID:%s password:%s", - EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); -} - -void wifi_init_sta() -{ - wifi_event_group = xEventGroupCreate(); - - tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - wifi_config_t wifi_config = { - .sta = { - .ssid = EXAMPLE_ESP_WIFI_SSID, - .password = EXAMPLE_ESP_WIFI_PASS - }, - }; - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK(esp_wifi_start() ); - - ESP_LOGI(TAG, "wifi_init_sta finished."); - ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", - EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); -} - -void app_main() -{ - //Initialize NVS - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - -#if EXAMPLE_ESP_WIFI_MODE_AP - ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); - wifi_init_softap(); -#else - ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); - wifi_init_sta(); -#endif /*EXAMPLE_ESP_WIFI_MODE_AP*/ - -} diff --git a/examples/wifi/smart_config/main/smartconfig_main.c b/examples/wifi/smart_config/main/smartconfig_main.c index 5bca3459..52c2f22b 100644 --- a/examples/wifi/smart_config/main/smartconfig_main.c +++ b/examples/wifi/smart_config/main/smartconfig_main.c @@ -13,7 +13,7 @@ #include "freertos/task.h" #include "freertos/event_groups.h" #include "esp_wifi.h" -#include "esp_event_loop.h" +#include "esp_event.h" #include "esp_log.h" #include "esp_system.h" #include "nvs_flash.h" @@ -33,44 +33,42 @@ static const char *TAG = "sc"; void smartconfig_example_task(void * parm); -static esp_err_t event_handler(void *ctx, system_event_t *event) +static void on_wifi_disconnect(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; + system_event_sta_disconnected_t *event = (system_event_sta_disconnected_t *)event_data; - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL); - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); - break; - default: - break; + ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect..."); + if (event->reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { + /*Switch to 802.11 bgn mode */ + esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); } - return ESP_OK; + ESP_ERROR_CHECK(esp_wifi_connect()); +} + +static void on_got_ip(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); } static void initialise_wifi(void) { tcpip_adapter_init(); wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); + + ESP_ERROR_CHECK(esp_event_loop_create_default()); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); + + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL)); + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_start() ); + ESP_ERROR_CHECK( esp_wifi_connect() ); } static void sc_callback(smartconfig_status_t status, void *pdata) diff --git a/examples/wifi/sniffer/main/sniffer_main.c b/examples/wifi/sniffer/main/sniffer_main.c index da2d2e2b..379f0684 100644 --- a/examples/wifi/sniffer/main/sniffer_main.c +++ b/examples/wifi/sniffer/main/sniffer_main.c @@ -12,7 +12,7 @@ #include "esp_system.h" #include "esp_log.h" #include "esp_timer.h" -#include "esp_event_loop.h" +#include "esp_event.h" #include "nvs_flash.h" #include "freertos/FreeRTOS.h" @@ -155,27 +155,27 @@ static void sniffer_task(void* pvParameters) vTaskDelete(NULL); } -static esp_err_t event_handler(void* ctx, system_event_t* event) +static void wifi_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) { - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - xEventGroupSetBits(wifi_event_group, START_BIT); - break; - - default: - break; + if (event_id == WIFI_EVENT_STA_START) { + xEventGroupSetBits(wifi_event_group, START_BIT); } - - return ESP_OK; } static void initialise_wifi(void) { tcpip_adapter_init(); + + ESP_ERROR_CHECK(esp_event_loop_create_default()); + wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL)); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start()); } diff --git a/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c b/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c index c24466cd..1c9eb3db 100644 --- a/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c +++ b/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c @@ -77,51 +77,23 @@ extern uint8_t client_crt_end[] asm("_binary_wpa2_client_crt_end"); extern uint8_t client_key_start[] asm("_binary_wpa2_client_key_start"); extern uint8_t client_key_end[] asm("_binary_wpa2_client_key_end"); -static esp_err_t event_handler(void* ctx, system_event_t* event) +static void event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) { - /* For accessing reason codes in case of disconnection */ - system_event_info_t* info = &event->event_info; + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + system_event_sta_disconnected_t *event = (system_event_sta_disconnected_t *)event_data; - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:"MACSTR" join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:"MACSTR"leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); - } - - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - - default: - break; + if (event->reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { + /*Switch to 802.11 bgn mode */ + esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); + } + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); } - - return ESP_OK; } static void initialise_wifi(void) @@ -133,9 +105,11 @@ static void initialise_wifi(void) tcpip_adapter_init(); wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_loop_create_default()); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); wifi_config_t wifi_config = { .sta = { diff --git a/examples/wifi/wps/main/wps.c b/examples/wifi/wps/main/wps.c index bef9ebb8..6ab5a813 100644 --- a/examples/wifi/wps/main/wps.c +++ b/examples/wifi/wps/main/wps.c @@ -39,78 +39,73 @@ static const char* TAG = "example_wps"; static esp_wps_config_t config = WPS_CONFIG_INIT_DEFAULT(WPS_TEST_MODE); -static esp_err_t event_handler(void* ctx, system_event_t* event) +static void wifi_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) { - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) { - case SYSTEM_EVENT_STA_START: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); + switch (event_id) { + case WIFI_EVENT_STA_START: + ESP_LOGI(TAG, "WIFI_EVENT_STA_START"); break; + case WIFI_EVENT_STA_DISCONNECTED: { + system_event_sta_disconnected_t *event = (system_event_sta_disconnected_t *)event_data; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); - ESP_LOGI(TAG, "got ip:%s\n", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED"); - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); + ESP_LOGI(TAG, "WIFI_EVENT_STA_DISCONNECTED"); + if (event->reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) { + /*Switch to 802.11 bgn mode */ + esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N); + } + ESP_ERROR_CHECK(esp_wifi_connect()); } - ESP_ERROR_CHECK(esp_wifi_connect()); break; - - case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: - /*point: the function esp_wifi_wps_start() only get ssid & password - * so call the function esp_wifi_connect() here - * */ - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_WPS_ER_SUCCESS"); + case WIFI_EVENT_STA_WPS_ER_SUCCESS: + ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_SUCCESS"); + /* esp_wifi_wps_start() only gets ssid & password, so call esp_wifi_connect() here. */ ESP_ERROR_CHECK(esp_wifi_wps_disable()); ESP_ERROR_CHECK(esp_wifi_connect()); break; - - case SYSTEM_EVENT_STA_WPS_ER_FAILED: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_WPS_ER_FAILED"); + case WIFI_EVENT_STA_WPS_ER_FAILED: + ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_FAILED"); ESP_ERROR_CHECK(esp_wifi_wps_disable()); ESP_ERROR_CHECK(esp_wifi_wps_enable(&config)); ESP_ERROR_CHECK(esp_wifi_wps_start(0)); break; - - case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_WPS_ER_TIMEOUT"); + case WIFI_EVENT_STA_WPS_ER_TIMEOUT: + ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_TIMEOUT"); ESP_ERROR_CHECK(esp_wifi_wps_disable()); ESP_ERROR_CHECK(esp_wifi_wps_enable(&config)); ESP_ERROR_CHECK(esp_wifi_wps_start(0)); break; - - case SYSTEM_EVENT_STA_WPS_ER_PIN: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_WPS_ER_PIN"); - /*show the PIN code here*/ - ESP_LOGI(TAG, "WPS_PIN = "PINSTR, PIN2STR(event->event_info.sta_er_pin.pin_code)); + case WIFI_EVENT_STA_WPS_ER_PIN: + ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_PIN"); + /* display the PIN code */ + wifi_event_sta_wps_er_pin_t* event = (wifi_event_sta_wps_er_pin_t*) event_data; + ESP_LOGI(TAG, "WPS_PIN = " PINSTR, PIN2STR(event->pin_code)); break; - default: break; } +} - return ESP_OK; +static void got_ip_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + ESP_LOGI(TAG, "got ip: %s", ip4addr_ntoa(&event->ip_info.ip)); } /*init wifi as sta and start wps*/ static void start_wps(void) { tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_loop_create_default()); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &got_ip_event_handler, NULL)); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start());