1 /* SoftAP based Provisioning Example
2
3 This example code is in the Public Domain (or CC0 licensed, at your option.)
4
5 Unless required by applicable law or agreed to in writing, this
6 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7 CONDITIONS OF ANY KIND, either express or implied.
8 */
9
10 /* This file is mostly a boiler-plate code that applications can use without much change */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <esp_err.h>
15 #include <esp_log.h>
16
17 #include <esp_wifi.h>
18 #include <esp_netif.h>
19
20 #include <wifi_provisioning/wifi_config.h>
21
22 #include "app_prov.h"
23
24 static const char* TAG = "app_prov_handler";
25
26 /* Provide definition of wifi_prov_ctx_t */
27 struct wifi_prov_ctx {
28 wifi_config_t wifi_cfg;
29 };
30
get_config(wifi_prov_ctx_t ** ctx)31 static wifi_config_t *get_config(wifi_prov_ctx_t **ctx)
32 {
33 return (*ctx ? &(*ctx)->wifi_cfg : NULL);
34 }
35
new_config(wifi_prov_ctx_t ** ctx)36 static wifi_config_t *new_config(wifi_prov_ctx_t **ctx)
37 {
38 free(*ctx);
39 (*ctx) = (wifi_prov_ctx_t *) calloc(1, sizeof(wifi_prov_ctx_t));
40 return get_config(ctx);
41 }
42
free_config(wifi_prov_ctx_t ** ctx)43 static void free_config(wifi_prov_ctx_t **ctx)
44 {
45 free(*ctx);
46 *ctx = NULL;
47 }
48
get_status_handler(wifi_prov_config_get_data_t * resp_data,wifi_prov_ctx_t ** ctx)49 static esp_err_t get_status_handler(wifi_prov_config_get_data_t *resp_data, wifi_prov_ctx_t **ctx)
50 {
51 /* Initialize to zero */
52 memset(resp_data, 0, sizeof(wifi_prov_config_get_data_t));
53
54 if (app_prov_get_wifi_state(&resp_data->wifi_state) != ESP_OK) {
55 ESP_LOGW(TAG, "Prov app not running");
56 return ESP_FAIL;
57 }
58
59 if (resp_data->wifi_state == WIFI_PROV_STA_CONNECTED) {
60 ESP_LOGI(TAG, "Connected state");
61
62 /* IP Addr assigned to STA */
63 esp_netif_ip_info_t ip_info;
64 esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ip_info);
65 esp_ip4addr_ntoa(&ip_info.ip, resp_data->conn_info.ip_addr, sizeof(resp_data->conn_info.ip_addr));
66
67 /* AP information to which STA is connected */
68 wifi_ap_record_t ap_info;
69 esp_wifi_sta_get_ap_info(&ap_info);
70 memcpy(resp_data->conn_info.bssid, (char *)ap_info.bssid, sizeof(ap_info.bssid));
71 memcpy(resp_data->conn_info.ssid, (char *)ap_info.ssid, sizeof(ap_info.ssid));
72 resp_data->conn_info.channel = ap_info.primary;
73 resp_data->conn_info.auth_mode = ap_info.authmode;
74 } else if (resp_data->wifi_state == WIFI_PROV_STA_DISCONNECTED) {
75 ESP_LOGI(TAG, "Disconnected state");
76
77 /* If disconnected, convey reason */
78 app_prov_get_wifi_disconnect_reason(&resp_data->fail_reason);
79 } else {
80 ESP_LOGI(TAG, "Connecting state");
81 }
82 return ESP_OK;
83 }
84
set_config_handler(const wifi_prov_config_set_data_t * req_data,wifi_prov_ctx_t ** ctx)85 static esp_err_t set_config_handler(const wifi_prov_config_set_data_t *req_data, wifi_prov_ctx_t **ctx)
86 {
87 wifi_config_t *wifi_cfg = get_config(ctx);
88 if (wifi_cfg) {
89 free_config(ctx);
90 }
91
92 wifi_cfg = new_config(ctx);
93 if (!wifi_cfg) {
94 ESP_LOGE(TAG, "Unable to alloc wifi config");
95 return ESP_FAIL;
96 }
97
98 ESP_LOGI(TAG, "WiFi Credentials Received : \n\tssid %s \n\tpassword %s",
99 req_data->ssid, req_data->password);
100
101 /* Using memcpy allows the max SSID length to be 32 bytes (as per 802.11 standard).
102 * But this doesn't guarantee that the saved SSID will be null terminated, because
103 * wifi_cfg->sta.ssid is also 32 bytes long (without extra 1 byte for null character).
104 * Although, this is not a matter for concern because esp_wifi library reads the SSID
105 * upto 32 bytes in absence of null termination */
106 const size_t ssid_len = strnlen(req_data->ssid, sizeof(wifi_cfg->sta.ssid));
107 /* Ensure SSID less than 32 bytes is null terminated */
108 memset(wifi_cfg->sta.ssid, 0, sizeof(wifi_cfg->sta.ssid));
109 memcpy(wifi_cfg->sta.ssid, req_data->ssid, ssid_len);
110
111 strlcpy((char *) wifi_cfg->sta.password, req_data->password, sizeof(wifi_cfg->sta.password));
112 return ESP_OK;
113 }
114
apply_config_handler(wifi_prov_ctx_t ** ctx)115 static esp_err_t apply_config_handler(wifi_prov_ctx_t **ctx)
116 {
117 wifi_config_t *wifi_cfg = get_config(ctx);
118 if (!wifi_cfg) {
119 ESP_LOGE(TAG, "WiFi config not set");
120 return ESP_FAIL;
121 }
122
123 app_prov_configure_sta(wifi_cfg);
124 ESP_LOGI(TAG, "WiFi Credentials Applied");
125
126 free_config(ctx);
127 return ESP_OK;
128 }
129
130 wifi_prov_config_handlers_t wifi_prov_handlers = {
131 .get_status_handler = get_status_handler,
132 .set_config_handler = set_config_handler,
133 .apply_config_handler = apply_config_handler,
134 .ctx = NULL
135 };
136