Merge branch 'feature/prov_mgr_event_loop' into 'master'

Wi-Fi Provisioning : Add support for esp_event

See merge request espressif/esp-idf!4857
This commit is contained in:
Mahavir Jain
2019-07-07 13:40:18 +08:00
4 changed files with 182 additions and 191 deletions

View File

@@ -23,6 +23,8 @@
extern "C" { extern "C" {
#endif #endif
ESP_EVENT_DECLARE_BASE(WIFI_PROV_EVENT);
/** /**
* @brief Events generated by manager * @brief Events generated by manager
* *
@@ -489,14 +491,17 @@ void wifi_prov_mgr_endpoint_unregister(const char *ep_name);
* provisioning manager's internal state machine depending on * provisioning manager's internal state machine depending on
* incoming Wi-Fi events * incoming Wi-Fi events
* *
* @note : This function is DEPRECATED, because events are now
* handled internally using the event loop library, esp_event.
* Calling this will do nothing and simply return ESP_OK.
*
* @param[in] ctx Event context data * @param[in] ctx Event context data
* @param[in] event Event info * @param[in] event Event info
* *
* @return * @return
* - ESP_OK : Event handled successfully * - ESP_OK : Event handled successfully
* - ESP_ERR_FAIL : This event cannot be handled
*/ */
esp_err_t wifi_prov_mgr_event_handler(void *ctx, system_event_t *event); esp_err_t wifi_prov_mgr_event_handler(void *ctx, system_event_t *event) __attribute__ ((deprecated));
/** /**
* @brief Get state of Wi-Fi Station during provisioning * @brief Get state of Wi-Fi Station during provisioning

View File

@@ -40,6 +40,8 @@
static const char *TAG = "wifi_prov_mgr"; static const char *TAG = "wifi_prov_mgr";
ESP_EVENT_DEFINE_BASE(WIFI_PROV_EVENT);
typedef enum { typedef enum {
WIFI_PROV_STATE_IDLE, WIFI_PROV_STATE_IDLE,
WIFI_PROV_STATE_STARTING, WIFI_PROV_STATE_STARTING,
@@ -155,7 +157,7 @@ static struct wifi_prov_mgr_ctx *prov_ctx;
* *
* NOTE: This function should be called only after ensuring that the * NOTE: This function should be called only after ensuring that the
* context is valid and the control mutex is locked. */ * context is valid and the control mutex is locked. */
static void execute_event_cb(wifi_prov_cb_event_t event_id, void *event_data) static void execute_event_cb(wifi_prov_cb_event_t event_id, void *event_data, size_t event_data_size)
{ {
ESP_LOGD(TAG, "execute_event_cb : %d", event_id); ESP_LOGD(TAG, "execute_event_cb : %d", event_id);
@@ -180,6 +182,12 @@ static void execute_event_cb(wifi_prov_cb_event_t event_id, void *event_data)
app_cb(app_data, event_id, event_data); app_cb(app_data, event_id, event_data);
} }
if (esp_event_post(WIFI_PROV_EVENT, event_id,
event_data, event_data_size,
portMAX_DELAY) != ESP_OK) {
ESP_LOGE(TAG, "Failed to post event %d to default event loop", event_id);
}
ACQUIRE_LOCK(prov_ctx_lock); ACQUIRE_LOCK(prov_ctx_lock);
} }
} }
@@ -255,6 +263,10 @@ static cJSON* wifi_prov_get_info_json(void)
return full_info_json; return full_info_json;
} }
/* Declare the internal event handler */
static void wifi_prov_mgr_event_handler_internal(void* arg, esp_event_base_t event_base,
int event_id, void* event_data);
static esp_err_t wifi_prov_mgr_start_service(const char *service_name, const char *service_key) static esp_err_t wifi_prov_mgr_start_service(const char *service_name, const char *service_key)
{ {
const wifi_prov_scheme_t *scheme = &prov_ctx->mgr_config.scheme; const wifi_prov_scheme_t *scheme = &prov_ctx->mgr_config.scheme;
@@ -284,7 +296,9 @@ static esp_err_t wifi_prov_mgr_start_service(const char *service_name, const cha
/* Set version information / capabilities of provisioning service and application */ /* Set version information / capabilities of provisioning service and application */
cJSON *version_json = wifi_prov_get_info_json(); cJSON *version_json = wifi_prov_get_info_json();
ret = protocomm_set_version(prov_ctx->pc, "proto-ver", cJSON_Print(version_json)); char *version_str = cJSON_Print(version_json);
ret = protocomm_set_version(prov_ctx->pc, "proto-ver", version_str);
free(version_str);
cJSON_Delete(version_json); cJSON_Delete(version_json);
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to set version endpoint"); ESP_LOGE(TAG, "Failed to set version endpoint");
@@ -355,6 +369,31 @@ static esp_err_t wifi_prov_mgr_start_service(const char *service_name, const cha
return ret; return ret;
} }
/* Register global event handler */
ret = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
wifi_prov_mgr_event_handler_internal, NULL);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register WiFi event handler");
free(prov_ctx->wifi_scan_handlers);
free(prov_ctx->wifi_prov_handlers);
scheme->prov_stop(prov_ctx->pc);
protocomm_delete(prov_ctx->pc);
return ret;
}
ret = esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
wifi_prov_mgr_event_handler_internal, NULL);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register IP event handler");
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID,
wifi_prov_mgr_event_handler_internal);
free(prov_ctx->wifi_scan_handlers);
free(prov_ctx->wifi_prov_handlers);
scheme->prov_stop(prov_ctx->pc);
protocomm_delete(prov_ctx->pc);
return ret;
}
ESP_LOGI(TAG, "Provisioning started with service name : %s ", ESP_LOGI(TAG, "Provisioning started with service name : %s ",
service_name ? service_name : "<NULL>"); service_name ? service_name : "<NULL>");
return ESP_OK; return ESP_OK;
@@ -549,6 +588,12 @@ static bool wifi_prov_mgr_stop_service(bool blocking)
prov_ctx->ap_list_sorted[i] = NULL; prov_ctx->ap_list_sorted[i] = NULL;
} }
/* Remove event handler */
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID,
wifi_prov_mgr_event_handler_internal);
esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP,
wifi_prov_mgr_event_handler_internal);
if (blocking) { if (blocking) {
/* Run the cleanup without launching a separate task. Also the /* Run the cleanup without launching a separate task. Also the
* WIFI_PROV_END event is not emitted in this case */ * WIFI_PROV_END event is not emitted in this case */
@@ -734,17 +779,20 @@ static esp_err_t update_wifi_scan_results(void)
return ret; return ret;
} }
/* Event handler for starting/stopping provisioning. /* DEPRECATED : Event handler for starting/stopping provisioning.
* To be called from within the context of the main * To be called from within the context of the main
* event handler */ * event handler */
esp_err_t wifi_prov_mgr_event_handler(void *ctx, system_event_t *event) esp_err_t wifi_prov_mgr_event_handler(void *ctx, system_event_t *event)
{ {
/* For accessing reason codes in case of disconnection */ return ESP_OK;
system_event_info_t *info = &event->event_info; }
static void wifi_prov_mgr_event_handler_internal(
void* arg, esp_event_base_t event_base, int event_id, void* event_data)
{
if (!prov_ctx_lock) { if (!prov_ctx_lock) {
ESP_LOGE(TAG, "Provisioning manager not initialized"); ESP_LOGE(TAG, "Provisioning manager not initialized");
return ESP_ERR_INVALID_STATE; return;
} }
ACQUIRE_LOCK(prov_ctx_lock); ACQUIRE_LOCK(prov_ctx_lock);
@@ -753,12 +801,13 @@ esp_err_t wifi_prov_mgr_event_handler(void *ctx, system_event_t *event)
* return with error to allow the global handler to act */ * return with error to allow the global handler to act */
if (!prov_ctx) { if (!prov_ctx) {
RELEASE_LOCK(prov_ctx_lock); RELEASE_LOCK(prov_ctx_lock);
return ESP_ERR_INVALID_STATE; return;
} }
/* If scan completed then update scan result */ /* If scan completed then update scan result */
if (prov_ctx->prov_state == WIFI_PROV_STATE_STARTED && if (prov_ctx->prov_state == WIFI_PROV_STATE_STARTED &&
event->event_id == SYSTEM_EVENT_SCAN_DONE) { event_base == WIFI_EVENT &&
event_id == WIFI_EVENT_SCAN_DONE) {
update_wifi_scan_results(); update_wifi_scan_results();
} }
@@ -766,22 +815,18 @@ esp_err_t wifi_prov_mgr_event_handler(void *ctx, system_event_t *event)
* Wi-Fi STA is yet to complete trying the connection */ * Wi-Fi STA is yet to complete trying the connection */
if (prov_ctx->prov_state != WIFI_PROV_STATE_CRED_RECV) { if (prov_ctx->prov_state != WIFI_PROV_STATE_CRED_RECV) {
RELEASE_LOCK(prov_ctx_lock); RELEASE_LOCK(prov_ctx_lock);
return ESP_OK; return;
} }
esp_err_t ret = ESP_OK; if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
switch (event->event_id) { ESP_LOGI(TAG, "STA Start");
case SYSTEM_EVENT_STA_START:
ESP_LOGD(TAG, "STA Start");
/* Once configuration is received through protocomm, /* Once configuration is received through protocomm,
* device is started as station. Once station starts, * device is started as station. Once station starts,
* wait for connection to establish with configured * wait for connection to establish with configured
* host SSID and password */ * host SSID and password */
prov_ctx->wifi_state = WIFI_PROV_STA_CONNECTING; prov_ctx->wifi_state = WIFI_PROV_STA_CONNECTING;
break; } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ESP_LOGI(TAG, "STA Got IP");
case SYSTEM_EVENT_STA_GOT_IP:
ESP_LOGD(TAG, "STA Got IP");
/* Station got IP. That means configuration is successful. */ /* Station got IP. That means configuration is successful. */
prov_ctx->wifi_state = WIFI_PROV_STA_CONNECTED; prov_ctx->wifi_state = WIFI_PROV_STA_CONNECTED;
prov_ctx->prov_state = WIFI_PROV_STATE_SUCCESS; prov_ctx->prov_state = WIFI_PROV_STATE_SUCCESS;
@@ -794,28 +839,27 @@ esp_err_t wifi_prov_mgr_event_handler(void *ctx, system_event_t *event)
} }
/* Execute user registered callback handler */ /* Execute user registered callback handler */
execute_event_cb(WIFI_PROV_CRED_SUCCESS, NULL); execute_event_cb(WIFI_PROV_CRED_SUCCESS, NULL, 0);
break; } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
ESP_LOGE(TAG, "STA Disconnected");
case SYSTEM_EVENT_STA_DISCONNECTED:
ESP_LOGD(TAG, "STA Disconnected");
/* Station couldn't connect to configured host SSID */ /* Station couldn't connect to configured host SSID */
prov_ctx->wifi_state = WIFI_PROV_STA_DISCONNECTED; prov_ctx->wifi_state = WIFI_PROV_STA_DISCONNECTED;
ESP_LOGD(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 */ /* Set code corresponding to the reason for disconnection */
switch (info->disconnected.reason) { switch (disconnected->reason) {
case WIFI_REASON_AUTH_EXPIRE: case WIFI_REASON_AUTH_EXPIRE:
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
case WIFI_REASON_BEACON_TIMEOUT:
case WIFI_REASON_AUTH_FAIL: case WIFI_REASON_AUTH_FAIL:
case WIFI_REASON_ASSOC_FAIL: case WIFI_REASON_ASSOC_EXPIRE:
case WIFI_REASON_HANDSHAKE_TIMEOUT: case WIFI_REASON_HANDSHAKE_TIMEOUT:
ESP_LOGD(TAG, "STA Auth Error"); ESP_LOGE(TAG, "STA Auth Error");
prov_ctx->wifi_disconnect_reason = WIFI_PROV_STA_AUTH_ERROR; prov_ctx->wifi_disconnect_reason = WIFI_PROV_STA_AUTH_ERROR;
break; break;
case WIFI_REASON_NO_AP_FOUND: case WIFI_REASON_NO_AP_FOUND:
ESP_LOGD(TAG, "STA AP Not found"); ESP_LOGE(TAG, "STA AP Not found");
prov_ctx->wifi_disconnect_reason = WIFI_PROV_STA_AP_NOT_FOUND; prov_ctx->wifi_disconnect_reason = WIFI_PROV_STA_AP_NOT_FOUND;
break; break;
default: default:
@@ -831,20 +875,11 @@ esp_err_t wifi_prov_mgr_event_handler(void *ctx, system_event_t *event)
prov_ctx->prov_state = WIFI_PROV_STATE_FAIL; prov_ctx->prov_state = WIFI_PROV_STATE_FAIL;
wifi_prov_sta_fail_reason_t reason = prov_ctx->wifi_disconnect_reason; wifi_prov_sta_fail_reason_t reason = prov_ctx->wifi_disconnect_reason;
/* Execute user registered callback handler */ /* Execute user registered callback handler */
execute_event_cb(WIFI_PROV_CRED_FAIL, (void *)&reason); execute_event_cb(WIFI_PROV_CRED_FAIL, (void *)&reason, sizeof(reason));
} }
break;
default:
/* This event is not intended to be handled by this handler.
* Return ESP_FAIL to signal global event handler to take
* control */
ret = ESP_FAIL;
break;
} }
RELEASE_LOCK(prov_ctx_lock); RELEASE_LOCK(prov_ctx_lock);
return ret;
} }
esp_err_t wifi_prov_mgr_wifi_scan_start(bool blocking, bool passive, esp_err_t wifi_prov_mgr_wifi_scan_start(bool blocking, bool passive,
@@ -1125,7 +1160,7 @@ esp_err_t wifi_prov_mgr_configure_sta(wifi_config_t *wifi_cfg)
prov_ctx->wifi_state = WIFI_PROV_STA_CONNECTING; prov_ctx->wifi_state = WIFI_PROV_STA_CONNECTING;
prov_ctx->prov_state = WIFI_PROV_STATE_CRED_RECV; prov_ctx->prov_state = WIFI_PROV_STATE_CRED_RECV;
/* Execute user registered callback handler */ /* Execute user registered callback handler */
execute_event_cb(WIFI_PROV_CRED_RECV, (void *)&wifi_cfg->sta); execute_event_cb(WIFI_PROV_CRED_RECV, (void *)&wifi_cfg->sta, sizeof(wifi_cfg->sta));
RELEASE_LOCK(prov_ctx_lock); RELEASE_LOCK(prov_ctx_lock);
return ESP_OK; return ESP_OK;
@@ -1230,7 +1265,7 @@ exit:
} }
free(prov_ctx); free(prov_ctx);
} else { } else {
execute_event_cb(WIFI_PROV_INIT, NULL); execute_event_cb(WIFI_PROV_INIT, NULL, 0);
} }
RELEASE_LOCK(prov_ctx_lock); RELEASE_LOCK(prov_ctx_lock);
return ret; return ret;
@@ -1322,6 +1357,7 @@ void wifi_prov_mgr_deinit(void)
if (app_cb) { if (app_cb) {
app_cb(app_data, WIFI_PROV_DEINIT, NULL); app_cb(app_data, WIFI_PROV_DEINIT, NULL);
} }
esp_event_post(WIFI_PROV_EVENT, WIFI_PROV_DEINIT, NULL, 0, portMAX_DELAY);
} }
esp_err_t wifi_prov_mgr_start_provisioning(wifi_prov_security_t security, const char *pop, esp_err_t wifi_prov_mgr_start_provisioning(wifi_prov_security_t security, const char *pop,
@@ -1442,7 +1478,7 @@ esp_err_t wifi_prov_mgr_start_provisioning(wifi_prov_security_t security, const
if (ret == ESP_OK) { if (ret == ESP_OK) {
prov_ctx->prov_state = WIFI_PROV_STATE_STARTED; prov_ctx->prov_state = WIFI_PROV_STATE_STARTED;
/* Execute user registered callback handler */ /* Execute user registered callback handler */
execute_event_cb(WIFI_PROV_START, NULL); execute_event_cb(WIFI_PROV_START, NULL, 0);
goto exit; goto exit;
} }

View File

@@ -19,11 +19,7 @@ Initialization
wifi_prov_mgr_config_t config = { wifi_prov_mgr_config_t config = {
.scheme = wifi_prov_scheme_ble, .scheme = wifi_prov_scheme_ble,
.scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM, .scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM
.app_event_handler = {
.event_cb = prov_event_handler,
.user_data = NULL
}
}; };
ESP_ERR_CHECK( wifi_prov_mgr_init(config) ); ESP_ERR_CHECK( wifi_prov_mgr_init(config) );
@@ -44,20 +40,17 @@ The configuration structure ``wifi_prov_mgr_config_t`` has a few fields to speci
* ``WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT`` - Free only classic BT. Used when main application requires BLE. In this case freeing happens right when the manager is initialized. * ``WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT`` - Free only classic BT. Used when main application requires BLE. In this case freeing happens right when the manager is initialized.
* ``WIFI_PROV_EVENT_HANDLER_NONE`` - Don't use any scheme specific handler. Used when provisioning scheme is not BLE (i.e. SoftAP or Console), or when main application wants to handle the memory reclaiming on its own, or needs both BLE and classic BT to function. * ``WIFI_PROV_EVENT_HANDLER_NONE`` - Don't use any scheme specific handler. Used when provisioning scheme is not BLE (i.e. SoftAP or Console), or when main application wants to handle the memory reclaiming on its own, or needs both BLE and classic BT to function.
* `app_event_handler` : Application specific event handler which can be used to execute specific calls depending on the state of the provisioning service. This is to be set to a function of the form ``void app_event_handler(void *user_data, wifi_prov_cb_event_t event, void *event_data)`` along with any user data to be made available at the time of handling. This can also be set to ``WIFI_PROV_EVENT_HANDLER_NONE`` if not used. See definition of ``wifi_prov_cb_event_t`` for the list of events that are generated by the provisioning service. Following is a snippet showing a typical application specific provisioning event handler along with usage of the ``event_data`` parameter : * `app_event_handler` (Deprecated) : It is now recommended to catch ``WIFI_PROV_EVENT``s that are emitted to the default event loop handler. See definition of ``wifi_prov_cb_event_t`` for the list of events that are generated by the provisioning service. Here is an excerpt showing some of the provisioning events:
.. highlight:: c .. highlight:: c
:: ::
void prov_event_handler(void *user_data, static void event_handler(void* arg, esp_event_base_t event_base,
wifi_prov_cb_event_t event, int event_id, void* event_data)
void *event_data)
{ {
switch (event) { if (event_base == WIFI_PROV_EVENT) {
case WIFI_PROV_INIT: switch (event_id) {
ESP_LOGI(TAG, "Manager initialized");
break;
case WIFI_PROV_START: case WIFI_PROV_START:
ESP_LOGI(TAG, "Provisioning started"); ESP_LOGI(TAG, "Provisioning started");
break; break;
@@ -71,25 +64,26 @@ The configuration structure ``wifi_prov_mgr_config_t`` has a few fields to speci
} }
case WIFI_PROV_CRED_FAIL: { case WIFI_PROV_CRED_FAIL: {
wifi_prov_sta_fail_reason_t *reason = (wifi_prov_sta_fail_reason_t *)event_data; wifi_prov_sta_fail_reason_t *reason = (wifi_prov_sta_fail_reason_t *)event_data;
ESP_LOGE(TAG, "Provisioning failed : %s", ESP_LOGE(TAG, "Provisioning failed!\n\tReason : %s"
"\n\tPlease reset to factory and retry provisioning",
(*reason == WIFI_PROV_STA_AUTH_ERROR) ? (*reason == WIFI_PROV_STA_AUTH_ERROR) ?
"Wi-Fi AP password incorrect" : "Wi-Fi station authentication failed" : "Wi-Fi access-point not found");
"Wi-Fi AP not found");
break; break;
} }
case WIFI_PROV_CRED_SUCCESS: case WIFI_PROV_CRED_SUCCESS:
ESP_LOGI(TAG, "Provisioning successful"); ESP_LOGI(TAG, "Provisioning successful");
break; break;
case WIFI_PROV_END: case WIFI_PROV_END:
ESP_LOGI(TAG, "Provisioning stopped"); /* De-initialize manager once provisioning is finished */
break; wifi_prov_mgr_deinit();
case WIFI_PROV_DEINIT:
ESP_LOGI(TAG, "Manager de-initialized");
break; break;
default: default:
break; break;
} }
} }
}
The manager can be de-initialized at any moment by making a call to :cpp:func:`wifi_prov_mgr_deinit()`.
.. _wifi-prov-check-state: .. _wifi-prov-check-state:
@@ -114,30 +108,6 @@ If provisioning state needs to be reset, any of the following approaches may be
ESP_ERR_CHECK( wifi_prov_mgr_is_provisioned(&provisioned) ); ESP_ERR_CHECK( wifi_prov_mgr_is_provisioned(&provisioned) );
Event Loop Handling
^^^^^^^^^^^^^^^^^^^
Presently Wi-Fi provisioning manager cannot directly catch external system events, hence it is necessary to explicitly call :cpp:func:`wifi_prov_mgr_event_handler()` from inside the global event loop handler. See the following snippet :
.. highlight:: c
::
static esp_err_t global_event_loop_handler(void *ctx, system_event_t *event)
{
/* Pass event information to provisioning manager so that it can
* maintain its internal state depending upon the system event */
wifi_prov_mgr_event_handler(ctx, event);
/* Event handling logic for main application */
switch (event->event_id) {
.....
.....
.....
}
return ESP_OK;
}
Start Provisioning Service Start Provisioning Service
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -194,21 +164,18 @@ There are two ways for making this possible. The simpler way is to use a blockin
wifi_prov_mgr_deinit(); wifi_prov_mgr_deinit();
The other way is to use the application specific event handler which is to be configured during initialization, as explained above in :ref:`wifi-prov-mgr-init`. The other way is to use the default event loop handler to catch ``WIFI_PROV_EVENT``s and call :cpp:func:`wifi_prov_mgr_deinit()` when event ID is ``WIFI_PROV_END``:
.. highlight:: c .. highlight:: c
:: ::
void prov_event_handler(void *user_data, wifi_prov_cb_event_t event, void *event_data) static void event_handler(void* arg, esp_event_base_t event_base,
int event_id, void* event_data)
{ {
switch (event) { if (event_base == WIFI_PROV_EVENT && event_id == WIFI_PROV_END) {
case WIFI_PROV_END: /* De-initialize manager once provisioning is finished */
// De-initialize manager once provisioning is finished
wifi_prov_mgr_deinit(); wifi_prov_mgr_deinit();
break;
default:
break;
} }
} }

View File

@@ -16,7 +16,7 @@
#include <esp_log.h> #include <esp_log.h>
#include <esp_wifi.h> #include <esp_wifi.h>
#include <esp_event_loop.h> #include <esp_event.h>
#include <nvs_flash.h> #include <nvs_flash.h>
#include <wifi_provisioning/manager.h> #include <wifi_provisioning/manager.h>
@@ -30,48 +30,19 @@ const int WIFI_CONNECTED_EVENT = BIT0;
static EventGroupHandle_t wifi_event_group; static EventGroupHandle_t wifi_event_group;
/* Event handler for catching system events */ /* Event handler for catching system events */
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)
{ {
/* Pass event information to provisioning manager so that it can if (event_base == WIFI_PROV_EVENT) {
* maintain its internal state depending upon the system event */ switch (event_id) {
wifi_prov_mgr_event_handler(ctx, event);
/* Global event handling */
switch (event->event_id) {
case SYSTEM_EVENT_STA_START:
esp_wifi_connect();
break;
case SYSTEM_EVENT_STA_GOT_IP:
ESP_LOGI(TAG, "Connected with IP Address:%s",
ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_EVENT);
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
ESP_LOGI(TAG, "Disconnected. Connecting to the AP again...");
esp_wifi_connect();
break;
default:
break;
}
return ESP_OK;
}
/* Event handler for catching provisioning manager events */
static void prov_event_handler(void *user_data,
wifi_prov_cb_event_t event, void *event_data)
{
switch (event) {
case WIFI_PROV_START: case WIFI_PROV_START:
ESP_LOGI(TAG, "Provisioning started"); ESP_LOGI(TAG, "Provisioning started");
break; break;
case WIFI_PROV_CRED_RECV: { case WIFI_PROV_CRED_RECV: {
wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)event_data; wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)event_data;
/* If SSID length is exactly 32 bytes, null termination
* will not be present, so explicitly obtain the length */
size_t ssid_len = strnlen((const char *)wifi_sta_cfg->ssid, sizeof(wifi_sta_cfg->ssid));
ESP_LOGI(TAG, "Received Wi-Fi credentials" ESP_LOGI(TAG, "Received Wi-Fi credentials"
"\n\tSSID : %.*s\n\tPassword : %s", "\n\tSSID : %s\n\tPassword : %s",
ssid_len, (const char *) wifi_sta_cfg->ssid, (const char *) wifi_sta_cfg->ssid,
(const char *) wifi_sta_cfg->password); (const char *) wifi_sta_cfg->password);
break; break;
} }
@@ -80,7 +51,7 @@ static void prov_event_handler(void *user_data,
ESP_LOGE(TAG, "Provisioning failed!\n\tReason : %s" ESP_LOGE(TAG, "Provisioning failed!\n\tReason : %s"
"\n\tPlease reset to factory and retry provisioning", "\n\tPlease reset to factory and retry provisioning",
(*reason == WIFI_PROV_STA_AUTH_ERROR) ? (*reason == WIFI_PROV_STA_AUTH_ERROR) ?
"Wi-Fi AP password incorrect" : "Wi-Fi AP not found"); "Wi-Fi station authentication failed" : "Wi-Fi access-point not found");
break; break;
} }
case WIFI_PROV_CRED_SUCCESS: case WIFI_PROV_CRED_SUCCESS:
@@ -93,10 +64,22 @@ static void prov_event_handler(void *user_data,
default: default:
break; break;
} }
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} 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, "Connected with IP Address:%s", ip4addr_ntoa(&event->ip_info.ip));
/* Signal main application to continue execution */
xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_EVENT);
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
ESP_LOGI(TAG, "Disconnected. Connecting to the AP again...");
esp_wifi_connect();
}
} }
static void wifi_init_sta() static void wifi_init_sta()
{ {
/* Start Wi-Fi in station mode */
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_start()); ESP_ERROR_CHECK(esp_wifi_start());
} }
@@ -123,11 +106,18 @@ void app_main()
ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(nvs_flash_init());
} }
/* Initialize TCP/IP and the event loop */ /* Initialize TCP/IP */
tcpip_adapter_init(); tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
/* Initialize the event loop */
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_event_group = xEventGroupCreate(); wifi_event_group = xEventGroupCreate();
/* Register our event handler for Wi-Fi, IP and Provisioning related events */
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
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));
/* Initialize Wi-Fi */ /* Initialize Wi-Fi */
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK(esp_wifi_init(&cfg));
@@ -146,14 +136,7 @@ void app_main()
* appropriate scheme specific event handler allows the manager * appropriate scheme specific event handler allows the manager
* to take care of this automatically. This can be set to * to take care of this automatically. This can be set to
* WIFI_PROV_EVENT_HANDLER_NONE when using wifi_prov_scheme_softap*/ * WIFI_PROV_EVENT_HANDLER_NONE when using wifi_prov_scheme_softap*/
.scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM, .scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM
/* Do we want an application specific handler be executed on
* various provisioning related events */
.app_event_handler = {
.event_cb = prov_event_handler,
.user_data = NULL
}
}; };
/* Initialize provisioning manager with the /* Initialize provisioning manager with the
@@ -219,7 +202,7 @@ void app_main()
/* Uncomment the following to wait for the provisioning to finish and then release /* Uncomment the following to wait for the provisioning to finish and then release
* the resources of the manager. Since in this case de-initialization is triggered * the resources of the manager. Since in this case de-initialization is triggered
* by the configured prov_event_handler(), we don't need to call the following */ * by the default event loop handler, we don't need to call the following */
// wifi_prov_mgr_wait(); // wifi_prov_mgr_wait();
// wifi_prov_mgr_deinit(); // wifi_prov_mgr_deinit();
} else { } else {