diff --git a/examples/provisioning/ble_prov/main/Kconfig.projbuild b/examples/provisioning/ble_prov/main/Kconfig.projbuild index 0836da9a6e..b236d0551a 100644 --- a/examples/provisioning/ble_prov/main/Kconfig.projbuild +++ b/examples/provisioning/ble_prov/main/Kconfig.projbuild @@ -29,6 +29,12 @@ menu "Example Configuration" prompt "Reset provisioned status of the device" help 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. + Provisioned status is determined by the Wi-Fi STA configuration, saved on the NVS. + + config 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/ble_prov/main/app_main.c b/examples/provisioning/ble_prov/main/app_main.c index bcb11a8a32..6341c9fe3d 100644 --- a/examples/provisioning/ble_prov/main/app_main.c +++ b/examples/provisioning/ble_prov/main/app_main.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -21,55 +21,73 @@ #include "app_prov.h" +#define EXAMPLE_AP_RECONN_ATTEMPTS CONFIG_AP_RECONN_ATTEMPTS + 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); +static void start_ble_provisioning(); - 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_ap_not_found = 0; + static int s_retry_num_ap_auth_fail = 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) { + wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data; + switch (disconnected->reason) { + case WIFI_REASON_AUTH_EXPIRE: + case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: + case WIFI_REASON_BEACON_TIMEOUT: + case WIFI_REASON_AUTH_FAIL: + case WIFI_REASON_ASSOC_FAIL: + case WIFI_REASON_HANDSHAKE_TIMEOUT: + ESP_LOGW(TAG, "connect to the AP fail : auth Error"); + if (s_retry_num_ap_auth_fail < EXAMPLE_AP_RECONN_ATTEMPTS) { + s_retry_num_ap_auth_fail++; + esp_wifi_connect(); + ESP_LOGI(TAG, "retry connecting to the AP..."); + } else { + /* Restart provisioning if authentication fails */ + start_ble_provisioning(); + } + break; + case WIFI_REASON_NO_AP_FOUND: + ESP_LOGW(TAG, "connect to the AP fail : not found"); + if (s_retry_num_ap_not_found < EXAMPLE_AP_RECONN_ATTEMPTS) { + s_retry_num_ap_not_found++; + esp_wifi_connect(); + ESP_LOGI(TAG, "retry to connecting to the AP..."); + } + break; + default: + /* None of the expected reasons */ + esp_wifi_connect(); + break; + } + } 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_ap_not_found = 0; + s_retry_num_ap_auth_fail = 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_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_start() ); + /* 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)); + + /* Start Wi-Fi in station mode with credentials set during provisioning */ + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_start()); } -void app_main() +static void start_ble_provisioning() { /* Security version */ int security = 0; @@ -89,11 +107,24 @@ void app_main() pop = &app_pop; #endif + ESP_ERROR_CHECK(app_prov_start_ble_provisioning(security, pop)); +} + +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()); + + /* Initialize Wi-Fi with default config */ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); /* Check if device is provisioned */ bool provisioned; @@ -105,10 +136,10 @@ void app_main() if (provisioned == false) { /* If not provisioned, start provisioning via BLE */ ESP_LOGI(TAG, "Starting BLE provisioning"); - app_prov_start_ble_provisioning(security, pop); + start_ble_provisioning(); } else { /* Else start as station with credentials set during provisioning */ ESP_LOGI(TAG, "Starting WiFi station"); - wifi_init_sta(NULL); + wifi_init_sta(); } } diff --git a/examples/provisioning/ble_prov/main/app_prov.c b/examples/provisioning/ble_prov/main/app_prov.c index 646a8de2be..be9b0d2f81 100644 --- a/examples/provisioning/ble_prov/main/app_prov.c +++ b/examples/provisioning/ble_prov/main/app_prov.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,9 @@ static const char *TAG = "app_prov"; static const char *ssid_prefix = "PROV_"; +/* Handler for catching WiFi events */ +static void app_prov_event_handler(void* handler_arg, esp_event_base_t base, int id, void* data); + /* Handlers for wifi_config provisioning endpoint */ extern wifi_prov_config_handlers_t wifi_prov_handlers; @@ -131,6 +135,10 @@ static void app_prov_stop_service(void) /* Delete protocomm instance */ protocomm_delete(g_prov->pc); + /* Remove event handler */ + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, app_prov_event_handler); + esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, app_prov_event_handler); + /* Release memory used by BT stack */ esp_bt_mem_release(ESP_BT_MODE_BTDM); } @@ -160,33 +168,24 @@ static void _stop_prov_cb(void * arg) xTaskCreate(&stop_prov_task, "stop_prov", 2048, NULL, tskIDLE_PRIORITY, NULL); } -/* Event handler for starting/stopping provisioning. - * To be called from within the context of the main - * event handler. - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) +/* Event handler for starting/stopping provisioning */ +static void app_prov_event_handler(void* handler_arg, esp_event_base_t event_base, + int event_id, void* event_data) { - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - /* If pointer to provisioning application data is NULL - * then provisioning is not running, therefore return without - * error */ + * then provisioning is not running */ if (!g_prov) { - return ESP_OK; + return; } - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { ESP_LOGI(TAG, "STA Start"); /* Once configuration is received through protocomm, * device is started as station. Once station starts, * wait for connection to establish with configured * host SSID and password */ g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; - break; - - case SYSTEM_EVENT_STA_GOT_IP: + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ESP_LOGI(TAG, "STA Got IP"); /* Station got IP. That means configuration is successful. * Schedule timer to stop provisioning app after 30 seconds. */ @@ -194,16 +193,16 @@ esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) if (g_prov && g_prov->timer) { esp_timer_start_once(g_prov->timer, 30000*1000U); } - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { ESP_LOGE(TAG, "STA Disconnected"); /* Station couldn't connect to configured host SSID */ g_prov->wifi_state = WIFI_PROV_STA_DISCONNECTED; - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); + + wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data; + ESP_LOGE(TAG, "Disconnect reason : %d", disconnected->reason); /* Set code corresponding to the reason for disconnection */ - switch (info->disconnected.reason) { + switch (disconnected->reason) { case WIFI_REASON_AUTH_EXPIRE: case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: case WIFI_REASON_BEACON_TIMEOUT: @@ -223,12 +222,7 @@ esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; esp_wifi_connect(); } - break; - - default: - break; } - return ESP_OK; } esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state) @@ -263,17 +257,6 @@ esp_err_t app_prov_is_provisioned(bool *provisioned) nvs_flash_erase(); #endif - if (nvs_flash_init() != ESP_OK) { - ESP_LOGE(TAG, "Failed to init NVS"); - return ESP_FAIL; - } - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - if (esp_wifi_init(&cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to init wifi"); - return ESP_FAIL; - } - /* Get WiFi Station configuration */ wifi_config_t wifi_cfg; if (esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_cfg) != ESP_OK) { @@ -290,12 +273,6 @@ esp_err_t app_prov_is_provisioned(bool *provisioned) esp_err_t app_prov_configure_sta(wifi_config_t *wifi_cfg) { - /* Initialize WiFi with default config */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - if (esp_wifi_init(&cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to init WiFi"); - return ESP_FAIL; - } /* Configure WiFi as station */ if (esp_wifi_set_mode(WIFI_MODE_STA) != ESP_OK) { ESP_LOGE(TAG, "Failed to set WiFi mode"); @@ -358,6 +335,18 @@ esp_err_t app_prov_start_ble_provisioning(int security, const protocomm_security return err; } + err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, app_prov_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register WiFi event handler"); + return err; + } + + err = esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, app_prov_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register IP event handler"); + return err; + } + /* Start provisioning service through BLE */ err = app_prov_start_service(); if (err != ESP_OK) { diff --git a/examples/provisioning/ble_prov/main/app_prov.h b/examples/provisioning/ble_prov/main/app_prov.h index 01b9ba07c4..97d5abaf9c 100644 --- a/examples/provisioning/ble_prov/main/app_prov.h +++ b/examples/provisioning/ble_prov/main/app_prov.h @@ -42,21 +42,6 @@ esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state); */ esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reason); -/** - * @brief Event handler for provisioning app - * - * This is called from the main event handler and controls the - * provisioning application, depeding on WiFi events - * - * @param[in] ctx Event context data - * @param[in] event Event info - * - * @return - * - ESP_OK : Event handled successfully - * - ESP_FAIL : Failed to start server on event AP start - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event); - /** * @brief Checks if device is provisioned * * diff --git a/examples/provisioning/console_prov/main/Kconfig.projbuild b/examples/provisioning/console_prov/main/Kconfig.projbuild index 0836da9a6e..b236d0551a 100644 --- a/examples/provisioning/console_prov/main/Kconfig.projbuild +++ b/examples/provisioning/console_prov/main/Kconfig.projbuild @@ -29,6 +29,12 @@ menu "Example Configuration" prompt "Reset provisioned status of the device" help 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. + Provisioned status is determined by the Wi-Fi STA configuration, saved on the NVS. + + config 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/console_prov/main/app_main.c b/examples/provisioning/console_prov/main/app_main.c index 9edfdd2efd..b149e5cee5 100644 --- a/examples/provisioning/console_prov/main/app_main.c +++ b/examples/provisioning/console_prov/main/app_main.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -21,55 +21,44 @@ #include "app_prov.h" +#define EXAMPLE_AP_RECONN_ATTEMPTS CONFIG_AP_RECONN_ATTEMPTS + static const char *TAG = "app"; -static esp_err_t event_handler(void *ctx, system_event_t *event) +static void event_handler(void* arg, esp_event_base_t event_base, + int event_id, void* event_data) { - /* Invoke Provisioning event handler first */ - app_prov_event_handler(ctx, event); + static int s_retry_num = 0; - 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: + 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_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_start() ); + /* 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)); + + /* Start Wi-Fi in station mode with credentials set during provisioning */ + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_start()); } -void app_main() +static void start_console_provisioning() { /* Security version */ int security = 0; @@ -89,11 +78,24 @@ void app_main() pop = &app_pop; #endif + ESP_ERROR_CHECK(app_prov_start_console_provisioning(security, pop)); +} + +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()); + + /* Initialize Wi-Fi with default config */ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); /* Check if device is provisioned */ bool provisioned; @@ -105,10 +107,10 @@ void app_main() if (provisioned == false) { /* If not provisioned, start provisioning via console */ ESP_LOGI(TAG, "Starting console provisioning"); - app_prov_start_console_provisioning(security, pop); + start_console_provisioning(); } else { /* Else start as station with credentials set during provisioning */ ESP_LOGI(TAG, "Starting WiFi station"); - wifi_init_sta(NULL); + wifi_init_sta(); } } diff --git a/examples/provisioning/console_prov/main/app_prov.c b/examples/provisioning/console_prov/main/app_prov.c index 83c4e4e055..ce3e520430 100644 --- a/examples/provisioning/console_prov/main/app_prov.c +++ b/examples/provisioning/console_prov/main/app_prov.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,9 @@ static const char *TAG = "app_prov"; +/* Handler for catching WiFi events */ +static void app_prov_event_handler(void* handler_arg, esp_event_base_t base, int id, void* data); + /* Handlers for wifi_config provisioning endpoint */ extern wifi_prov_config_handlers_t wifi_prov_handlers; @@ -99,6 +103,10 @@ static void app_prov_stop_service(void) protocomm_console_stop(g_prov->pc); /* Delete protocomm instance */ protocomm_delete(g_prov->pc); + + /* Remove event handler */ + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, app_prov_event_handler); + esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, app_prov_event_handler); } /* Task spawned by timer callback */ @@ -126,33 +134,24 @@ static void _stop_prov_cb(void * arg) xTaskCreate(&stop_prov_task, "stop_prov", 2048, NULL, tskIDLE_PRIORITY, NULL); } -/* Event handler for starting/stopping provisioning. - * To be called from within the context of the main - * event handler. - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) +/* Event handler for starting/stopping provisioning */ +static void app_prov_event_handler(void* handler_arg, esp_event_base_t event_base, + int event_id, void* event_data) { - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - /* If pointer to provisioning application data is NULL - * then provisioning is not running, therefore return without - * error */ + * then provisioning is not running */ if (!g_prov) { - return ESP_OK; + return; } - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { ESP_LOGI(TAG, "STA Start"); /* Once configuration is received through protocomm, * device is started as station. Once station starts, * wait for connection to establish with configured * host SSID and password */ g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; - break; - - case SYSTEM_EVENT_STA_GOT_IP: + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ESP_LOGI(TAG, "STA Got IP"); /* Station got IP. That means configuration is successful. * Schedule timer to stop provisioning app after 30 seconds. */ @@ -160,16 +159,16 @@ esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) if (g_prov && g_prov->timer) { esp_timer_start_once(g_prov->timer, 30000*1000U); } - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { ESP_LOGE(TAG, "STA Disconnected"); /* Station couldn't connect to configured host SSID */ g_prov->wifi_state = WIFI_PROV_STA_DISCONNECTED; - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); + + wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data; + ESP_LOGE(TAG, "Disconnect reason : %d", disconnected->reason); /* Set code corresponding to the reason for disconnection */ - switch (info->disconnected.reason) { + switch (disconnected->reason) { case WIFI_REASON_AUTH_EXPIRE: case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: case WIFI_REASON_BEACON_TIMEOUT: @@ -189,12 +188,7 @@ esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; esp_wifi_connect(); } - break; - - default: - break; } - return ESP_OK; } esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state) @@ -229,17 +223,6 @@ esp_err_t app_prov_is_provisioned(bool *provisioned) nvs_flash_erase(); #endif - if (nvs_flash_init() != ESP_OK) { - ESP_LOGE(TAG, "Failed to init NVS"); - return ESP_FAIL; - } - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - if (esp_wifi_init(&cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to init wifi"); - return ESP_FAIL; - } - /* Get WiFi Station configuration */ wifi_config_t wifi_cfg; if (esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_cfg) != ESP_OK) { @@ -256,12 +239,6 @@ esp_err_t app_prov_is_provisioned(bool *provisioned) esp_err_t app_prov_configure_sta(wifi_config_t *wifi_cfg) { - /* Initialize WiFi with default config */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - if (esp_wifi_init(&cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to init WiFi"); - return ESP_FAIL; - } /* Configure WiFi as station */ if (esp_wifi_set_mode(WIFI_MODE_STA) != ESP_OK) { ESP_LOGE(TAG, "Failed to set WiFi mode"); @@ -324,6 +301,18 @@ esp_err_t app_prov_start_console_provisioning(int security, const protocomm_secu return err; } + err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, app_prov_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register WiFi event handler"); + return err; + } + + err = esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, app_prov_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register IP event handler"); + return err; + } + /* Start provisioning service through console */ err = app_prov_start_service(); if (err != ESP_OK) { diff --git a/examples/provisioning/console_prov/main/app_prov.h b/examples/provisioning/console_prov/main/app_prov.h index c1ac7c3ee5..c6e026bc0a 100644 --- a/examples/provisioning/console_prov/main/app_prov.h +++ b/examples/provisioning/console_prov/main/app_prov.h @@ -42,21 +42,6 @@ esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state); */ esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reason); -/** - * @brief Event handler for provisioning app - * - * This is called from the main event handler and controls the - * provisioning application, depeding on WiFi events - * - * @param[in] ctx Event context data - * @param[in] event Event info - * - * @return - * - ESP_OK : Event handled successfully - * - ESP_FAIL : Failed to start server on event AP start - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event); - /** * @brief Checks if device is provisioned * * diff --git a/examples/provisioning/custom_config/main/Kconfig.projbuild b/examples/provisioning/custom_config/main/Kconfig.projbuild index 5a929966d7..2718e834c0 100644 --- a/examples/provisioning/custom_config/main/Kconfig.projbuild +++ b/examples/provisioning/custom_config/main/Kconfig.projbuild @@ -1,16 +1,16 @@ menu "Example Configuration" config SOFTAP_SSID - string "WiFi SSID" + string "Wi-Fi SSID" default "myssid" help SSID (network name) for the example to connect to. config SOFTAP_PASS - string "WiFi Password" + string "Wi-Fi Password" default "mypassword" help - WiFi password (WPA or WPA2) for the example to use. + Wi-Fi password (WPA or WPA2) for the example to use. config USE_SEC_1 bool @@ -47,6 +47,12 @@ menu "Example Configuration" prompt "Reset provisioned status of the device" help 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. + Provisioned status is determined by the Wi-Fi STA configuration, saved on the NVS. + + config 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 17bb29aecd..583894e767 100644 --- a/examples/provisioning/custom_config/main/app_main.c +++ b/examples/provisioning/custom_config/main/app_main.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -21,55 +21,44 @@ #include "app_prov.h" +#define EXAMPLE_AP_RECONN_ATTEMPTS CONFIG_AP_RECONN_ATTEMPTS + static const char *TAG = "app"; -static esp_err_t event_handler(void *ctx, system_event_t *event) +static void event_handler(void* arg, esp_event_base_t event_base, + int event_id, void* event_data) { - /* Invoke Provisioning event handler first */ - app_prov_event_handler(ctx, event); + static int s_retry_num = 0; - 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: + 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_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_start() ); + /* 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)); + + /* Start Wi-Fi in station mode with credentials set during provisioning */ + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_start()); } -void app_main() +static void start_softap_provisioning() { /* Security version */ int security = 0; @@ -89,11 +78,25 @@ void app_main() pop = &app_pop; #endif + ESP_ERROR_CHECK(app_prov_start_softap_provisioning( + CONFIG_SOFTAP_SSID, CONFIG_SOFTAP_PASS, security, pop)); +} + +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()); + + /* Initialize Wi-Fi with default config */ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); /* Check if device is provisioned */ bool provisioned; @@ -105,11 +108,10 @@ void app_main() if (provisioned == false) { /* If not provisioned, start provisioning via soft AP */ ESP_LOGI(TAG, "Starting WiFi SoftAP provisioning"); - app_prov_start_softap_provisioning(CONFIG_SOFTAP_SSID, CONFIG_SOFTAP_PASS, - security, pop); + start_softap_provisioning(); } else { /* Start WiFi station with credentials set during provisioning */ ESP_LOGI(TAG, "Starting WiFi station"); - wifi_init_sta(NULL); + wifi_init_sta(); } } diff --git a/examples/provisioning/custom_config/main/app_prov.c b/examples/provisioning/custom_config/main/app_prov.c index 6ed3df19a0..e7bb4086c8 100644 --- a/examples/provisioning/custom_config/main/app_prov.c +++ b/examples/provisioning/custom_config/main/app_prov.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,9 @@ static const char *TAG = "app_prov"; +/* Handler for catching WiFi events */ +static void app_prov_event_handler(void* handler_arg, esp_event_base_t base, int id, void* data); + /* Handlers for provisioning endpoints */ extern wifi_prov_config_handlers_t wifi_prov_handlers; extern custom_prov_config_handler_t custom_prov_handler; @@ -114,6 +118,10 @@ static void app_prov_stop_service(void) protocomm_httpd_stop(g_prov->pc); /* Delete protocomm instance */ protocomm_delete(g_prov->pc); + + /* Remove event handler */ + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, app_prov_event_handler); + esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, app_prov_event_handler); } /* Task spawned by timer callback */ @@ -142,33 +150,24 @@ static void _stop_prov_cb(void * arg) xTaskCreate(&stop_prov_task, "stop_prov", 2048, NULL, tskIDLE_PRIORITY, NULL); } -/* Event handler for starting/stopping provisioning. - * To be called from within the context of the main - * event handler. - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) +/* Event handler for starting/stopping provisioning */ +static void app_prov_event_handler(void* handler_arg, esp_event_base_t event_base, + int event_id, void* event_data) { - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - /* If pointer to provisioning application data is NULL - * then provisioning is not running, therefore return without - * error */ + * then provisioning is not running */ if (!g_prov) { - return ESP_OK; + return; } - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { ESP_LOGI(TAG, "STA Start"); - /* Once configuration is received by protocomm server, - * device is restarted as both AP and Station. - * Once station starts, wait for connection to - * establish with configured host SSID and password */ + /* Once configuration is received through protocomm, + * device is started as station. Once station starts, + * wait for connection to establish with configured + * host SSID and password */ g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; - break; - - case SYSTEM_EVENT_STA_GOT_IP: + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ESP_LOGI(TAG, "STA Got IP"); /* Station got IP. That means configuration is successful. * Schedule timer to stop provisioning app after 30 seconds. */ @@ -185,16 +184,16 @@ esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) * signaling a failure in provisioning. */ esp_timer_start_once(g_prov->timer, 30000*1000U); } - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { ESP_LOGE(TAG, "STA Disconnected"); /* Station couldn't connect to configured host SSID */ g_prov->wifi_state = WIFI_PROV_STA_DISCONNECTED; - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); + + wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data; + ESP_LOGE(TAG, "Disconnect reason : %d", disconnected->reason); /* Set code corresponding to the reason for disconnection */ - switch (info->disconnected.reason) { + switch (disconnected->reason) { case WIFI_REASON_AUTH_EXPIRE: case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: case WIFI_REASON_BEACON_TIMEOUT: @@ -214,12 +213,7 @@ esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; esp_wifi_connect(); } - break; - - default: - break; } - return ESP_OK; } esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state) @@ -248,25 +242,15 @@ esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reaso esp_err_t app_prov_is_provisioned(bool *provisioned) { + *provisioned = false; + #ifdef CONFIG_RESET_PROVISIONED nvs_flash_erase(); #endif - if (nvs_flash_init() != ESP_OK) { - ESP_LOGE(TAG, "Failed to init NVS"); - return ESP_FAIL; - } - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - if (esp_wifi_init(&cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to init wifi"); - return ESP_FAIL; - } - /* Get WiFi Station configuration */ wifi_config_t wifi_cfg; if (esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_cfg) != ESP_OK) { - *provisioned = false; return ESP_FAIL; } @@ -311,14 +295,6 @@ esp_err_t app_prov_configure_sta(wifi_config_t *wifi_cfg) static esp_err_t start_wifi_ap(const char *ssid, const char *pass) { - /* Initialize WiFi with default configuration */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - esp_err_t err = esp_wifi_init(&cfg); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to init WiFi : %d", err); - return err; - } - /* Build WiFi configuration for AP mode */ wifi_config_t wifi_config = { .ap = { @@ -338,7 +314,7 @@ static esp_err_t start_wifi_ap(const char *ssid, const char *pass) } /* Start WiFi in AP mode with configuration built above */ - err = esp_wifi_set_mode(WIFI_MODE_AP); + esp_err_t err = esp_wifi_set_mode(WIFI_MODE_AP); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to set WiFi mode : %d", err); return err; @@ -374,7 +350,7 @@ esp_err_t app_prov_start_softap_provisioning(const char *ssid, const char *pass, return ESP_ERR_NO_MEM; } - /* Initialise app data */ + /* Initialize app data */ g_prov->pop = pop; g_prov->security = security; @@ -391,6 +367,18 @@ esp_err_t app_prov_start_softap_provisioning(const char *ssid, const char *pass, return err; } + err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, app_prov_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register WiFi event handler"); + return err; + } + + err = esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, app_prov_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register IP event handler"); + return err; + } + /* Start WiFi softAP with specified ssid and password */ err = start_wifi_ap(ssid, pass); if (err != ESP_OK) { diff --git a/examples/provisioning/custom_config/main/app_prov.h b/examples/provisioning/custom_config/main/app_prov.h index a36c3aff8f..b575100bf0 100644 --- a/examples/provisioning/custom_config/main/app_prov.h +++ b/examples/provisioning/custom_config/main/app_prov.h @@ -43,21 +43,6 @@ esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state); */ esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reason); -/** - * @brief Event handler for provisioning app - * - * This is called from the main event handler and controls the - * provisioning application, depeding on WiFi events - * - * @param[in] ctx Event context data - * @param[in] event Event info - * - * @return - * - ESP_OK : Event handled successfully - * - ESP_FAIL : Failed to start server on event AP start - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event); - /** * @brief Checks if device is provisioned * * diff --git a/examples/provisioning/softap_prov/main/Kconfig.projbuild b/examples/provisioning/softap_prov/main/Kconfig.projbuild index 45593106b1..8f7da88ae9 100644 --- a/examples/provisioning/softap_prov/main/Kconfig.projbuild +++ b/examples/provisioning/softap_prov/main/Kconfig.projbuild @@ -7,17 +7,17 @@ menu "Example Configuration" Set SoftAP SSID as PROV_. config SOFTAP_SSID - string "WiFi SSID" + string "Wi-Fi SSID" default "PROV_SSID" depends on !SOFTAP_SSID_SET_MAC help SSID (network name) for the example to connect to. config SOFTAP_PASS - string "WiFi Password" + string "Wi-Fi Password" default "PROV_PASS" help - WiFi password (WPA or WPA2) for the example to use. + Wi-Fi password (WPA or WPA2) for the example to use. config USE_SEC_1 bool @@ -48,6 +48,12 @@ menu "Example Configuration" prompt "Reset provisioned status of the device" help 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. + Provisioned status is determined by the Wi-Fi STA configuration, saved on the NVS. + + config 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 65a100e4d7..4037f5091a 100644 --- a/examples/provisioning/softap_prov/main/app_main.c +++ b/examples/provisioning/softap_prov/main/app_main.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -21,55 +21,44 @@ #include "app_prov.h" +#define EXAMPLE_AP_RECONN_ATTEMPTS CONFIG_AP_RECONN_ATTEMPTS + static const char *TAG = "app"; -static esp_err_t event_handler(void *ctx, system_event_t *event) +static void event_handler(void* arg, esp_event_base_t event_base, + int event_id, void* event_data) { - /* Invoke Provisioning event handler first */ - app_prov_event_handler(ctx, event); + static int s_retry_num = 0; - 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: + 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_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_start() ); + /* 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)); + + /* Start Wi-Fi in station mode with credentials set during provisioning */ + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_start()); } -void app_main() +static void start_softap_provisioning() { /* Security version */ int security = 0; @@ -89,23 +78,6 @@ void app_main() pop = &app_pop; #endif - /* Initialize networking stack */ - tcpip_adapter_init(); - - /* Set our event handling */ - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); - - /* Check if device is provisioned */ - bool provisioned; - if (app_prov_is_provisioned(&provisioned) != ESP_OK) { - ESP_LOGE(TAG, "Error getting device provisioning state"); - return; - } - - if (provisioned == false) { - /* If not provisioned, start provisioning via soft AP */ - ESP_LOGI(TAG, "Starting WiFi SoftAP provisioning"); - const char *ssid = NULL; #ifdef CONFIG_SOFTAP_SSID @@ -121,11 +93,40 @@ void app_main() ssid = ssid_with_mac; #endif - app_prov_start_softap_provisioning(ssid, CONFIG_SOFTAP_PASS, - security, pop); + ESP_ERROR_CHECK(app_prov_start_softap_provisioning( + ssid, CONFIG_SOFTAP_PASS, security, pop)); +} + +void app_main() +{ + /* Initialize networking stack */ + tcpip_adapter_init(); + + /* 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()); + + /* Initialize Wi-Fi with default config */ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + /* Check if device is provisioned */ + bool provisioned; + if (app_prov_is_provisioned(&provisioned) != ESP_OK) { + ESP_LOGE(TAG, "Error getting device provisioning state"); + return; + } + + if (provisioned == false) { + /* If not provisioned, start provisioning via soft AP */ + ESP_LOGI(TAG, "Starting WiFi SoftAP provisioning"); + start_softap_provisioning(); } else { /* Start WiFi station with credentials set during provisioning */ ESP_LOGI(TAG, "Starting WiFi station"); - wifi_init_sta(NULL); + wifi_init_sta(); } } diff --git a/examples/provisioning/softap_prov/main/app_prov.c b/examples/provisioning/softap_prov/main/app_prov.c index 79c1e0da0c..2d625edce0 100644 --- a/examples/provisioning/softap_prov/main/app_prov.c +++ b/examples/provisioning/softap_prov/main/app_prov.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,9 @@ static const char *TAG = "app_prov"; +/* Handler for catching WiFi events */ +static void app_prov_event_handler(void* handler_arg, esp_event_base_t base, int id, void* data); + /* Handlers for wifi_config provisioning endpoint */ extern wifi_prov_config_handlers_t wifi_prov_handlers; @@ -100,6 +104,10 @@ static void app_prov_stop_service(void) protocomm_httpd_stop(g_prov->pc); /* Delete protocomm instance */ protocomm_delete(g_prov->pc); + + /* Remove event handler */ + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, app_prov_event_handler); + esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, app_prov_event_handler); } /* Task spawned by timer callback */ @@ -128,33 +136,24 @@ static void _stop_prov_cb(void * arg) xTaskCreate(&stop_prov_task, "stop_prov", 2048, NULL, tskIDLE_PRIORITY, NULL); } -/* Event handler for starting/stopping provisioning. - * To be called from within the context of the main - * event handler. - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) +/* Event handler for starting/stopping provisioning */ +static void app_prov_event_handler(void* handler_arg, esp_event_base_t event_base, + int event_id, void* event_data) { - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - /* If pointer to provisioning application data is NULL - * then provisioning is not running, therefore return without - * error */ + * then provisioning is not running */ if (!g_prov) { - return ESP_OK; + return; } - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { ESP_LOGI(TAG, "STA Start"); - /* Once configuration is received by protocomm server, - * device is restarted as both AP and Station. - * Once station starts, wait for connection to - * establish with configured host SSID and password */ + /* Once configuration is received through protocomm, + * device is started as station. Once station starts, + * wait for connection to establish with configured + * host SSID and password */ g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; - break; - - case SYSTEM_EVENT_STA_GOT_IP: + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ESP_LOGI(TAG, "STA Got IP"); /* Station got IP. That means configuration is successful. * Schedule timer to stop provisioning app after 30 seconds. */ @@ -171,16 +170,16 @@ esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) * signaling a failure in provisioning. */ esp_timer_start_once(g_prov->timer, 30000*1000U); } - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { ESP_LOGE(TAG, "STA Disconnected"); /* Station couldn't connect to configured host SSID */ g_prov->wifi_state = WIFI_PROV_STA_DISCONNECTED; - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); + + wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data; + ESP_LOGE(TAG, "Disconnect reason : %d", disconnected->reason); /* Set code corresponding to the reason for disconnection */ - switch (info->disconnected.reason) { + switch (disconnected->reason) { case WIFI_REASON_AUTH_EXPIRE: case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: case WIFI_REASON_BEACON_TIMEOUT: @@ -200,12 +199,7 @@ esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; esp_wifi_connect(); } - break; - - default: - break; } - return ESP_OK; } esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state) @@ -240,17 +234,6 @@ esp_err_t app_prov_is_provisioned(bool *provisioned) nvs_flash_erase(); #endif - if (nvs_flash_init() != ESP_OK) { - ESP_LOGE(TAG, "Failed to init NVS"); - return ESP_FAIL; - } - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - if (esp_wifi_init(&cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to init wifi"); - return ESP_FAIL; - } - /* Get WiFi Station configuration */ wifi_config_t wifi_cfg; if (esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_cfg) != ESP_OK) { @@ -298,14 +281,6 @@ esp_err_t app_prov_configure_sta(wifi_config_t *wifi_cfg) static esp_err_t start_wifi_ap(const char *ssid, const char *pass) { - /* Initialize WiFi with default configuration */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - esp_err_t err = esp_wifi_init(&cfg); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to init WiFi : %d", err); - return err; - } - /* Build WiFi configuration for AP mode */ wifi_config_t wifi_config = { .ap = { @@ -325,7 +300,7 @@ static esp_err_t start_wifi_ap(const char *ssid, const char *pass) } /* Start WiFi in AP mode with configuration built above */ - err = esp_wifi_set_mode(WIFI_MODE_AP); + esp_err_t err = esp_wifi_set_mode(WIFI_MODE_AP); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to set WiFi mode : %d", err); return err; @@ -378,6 +353,18 @@ esp_err_t app_prov_start_softap_provisioning(const char *ssid, const char *pass, return err; } + err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, app_prov_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register WiFi event handler"); + return err; + } + + err = esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, app_prov_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register IP event handler"); + return err; + } + /* Start WiFi softAP with specified ssid and password */ err = start_wifi_ap(ssid, pass); if (err != ESP_OK) { diff --git a/examples/provisioning/softap_prov/main/app_prov.h b/examples/provisioning/softap_prov/main/app_prov.h index ec196585a0..312d00e409 100644 --- a/examples/provisioning/softap_prov/main/app_prov.h +++ b/examples/provisioning/softap_prov/main/app_prov.h @@ -42,21 +42,6 @@ esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state); */ esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reason); -/** - * @brief Event handler for provisioning app - * - * This is called from the main event handler and controls the - * provisioning application, depeding on WiFi events - * - * @param[in] ctx Event context data - * @param[in] event Event info - * - * @return - * - ESP_OK : Event handled successfully - * - ESP_FAIL : Failed to start server on event AP start - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event); - /** * @brief Checks if device is provisioned * * diff --git a/examples/provisioning/softap_prov/softap_prov_test.py b/examples/provisioning/softap_prov/softap_prov_test.py index b8d8d9c7f1..e54ef23bec 100644 --- a/examples/provisioning/softap_prov/softap_prov_test.py +++ b/examples/provisioning/softap_prov/softap_prov_test.py @@ -64,7 +64,6 @@ def test_examples_provisioning_softap(env, extra_data): # Parse IP address of STA dut1.expect("Starting WiFi SoftAP provisioning", timeout=60) - dut1.expect("SoftAP started", timeout=30) [ssid, password] = dut1.expect(re.compile(r"SoftAP Provisioning started with SSID '(\S+)', Password '(\S+)'"), timeout=30) iface = wifi_tools.get_wiface_name()