1 /* DPP Enrollee 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 #include <string.h>
10 #include "freertos/FreeRTOS.h"
11 #include "freertos/task.h"
12 #include "freertos/event_groups.h"
13 #include "esp_system.h"
14 #include "esp_wifi.h"
15 #include "esp_event.h"
16 #include "esp_dpp.h"
17 #include "esp_log.h"
18 #include "nvs_flash.h"
19 #include "qrcode.h"
20 
21 #ifdef CONFIG_ESP_DPP_LISTEN_CHANNEL
22 #define EXAMPLE_DPP_LISTEN_CHANNEL_LIST     CONFIG_ESP_DPP_LISTEN_CHANNEL_LIST
23 #else
24 #define EXAMPLE_DPP_LISTEN_CHANNEL_LIST     "6"
25 #endif
26 
27 #ifdef CONFIG_ESP_DPP_BOOTSTRAPPING_KEY
28 #define EXAMPLE_DPP_BOOTSTRAPPING_KEY   CONFIG_ESP_DPP_BOOTSTRAPPING_KEY
29 #else
30 #define EXAMPLE_DPP_BOOTSTRAPPING_KEY   0
31 #endif
32 
33 #ifdef CONFIG_ESP_DPP_DEVICE_INFO
34 #define EXAMPLE_DPP_DEVICE_INFO      CONFIG_ESP_DPP_DEVICE_INFO
35 #else
36 #define EXAMPLE_DPP_DEVICE_INFO      0
37 #endif
38 
39 static const char *TAG = "wifi dpp-enrollee";
40 wifi_config_t s_dpp_wifi_config;
41 
42 static int s_retry_num = 0;
43 
44 /* FreeRTOS event group to signal when we are connected*/
45 static EventGroupHandle_t s_dpp_event_group;
46 
47 #define DPP_CONNECTED_BIT  BIT0
48 #define DPP_CONNECT_FAIL_BIT     BIT1
49 #define DPP_AUTH_FAIL_BIT           BIT2
50 
event_handler(void * arg,esp_event_base_t event_base,int32_t event_id,void * event_data)51 static void event_handler(void *arg, esp_event_base_t event_base,
52                           int32_t event_id, void *event_data)
53 {
54     if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
55         ESP_ERROR_CHECK(esp_supp_dpp_start_listen());
56         ESP_LOGI(TAG, "Started listening for DPP Authentication");
57     } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
58         if (s_retry_num < 5) {
59             esp_wifi_connect();
60             s_retry_num++;
61             ESP_LOGI(TAG, "retry to connect to the AP");
62         } else {
63             xEventGroupSetBits(s_dpp_event_group, DPP_CONNECT_FAIL_BIT);
64         }
65         ESP_LOGI(TAG, "connect to the AP fail");
66     } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
67         ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
68         ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
69         s_retry_num = 0;
70         xEventGroupSetBits(s_dpp_event_group, DPP_CONNECTED_BIT);
71     }
72 }
73 
dpp_enrollee_event_cb(esp_supp_dpp_event_t event,void * data)74 void dpp_enrollee_event_cb(esp_supp_dpp_event_t event, void *data)
75 {
76     switch (event) {
77     case ESP_SUPP_DPP_URI_READY:
78         if (data != NULL) {
79             esp_qrcode_config_t cfg = ESP_QRCODE_CONFIG_DEFAULT();
80 
81             ESP_LOGI(TAG, "Scan below QR Code to configure the enrollee:\n");
82             esp_qrcode_generate(&cfg, (const char *)data);
83         }
84         break;
85     case ESP_SUPP_DPP_CFG_RECVD:
86         memcpy(&s_dpp_wifi_config, data, sizeof(s_dpp_wifi_config));
87         esp_wifi_set_config(ESP_IF_WIFI_STA, &s_dpp_wifi_config);
88         ESP_LOGI(TAG, "DPP Authentication successful, connecting to AP : %s",
89                  s_dpp_wifi_config.sta.ssid);
90         s_retry_num = 0;
91         esp_wifi_connect();
92         break;
93     case ESP_SUPP_DPP_FAIL:
94         if (s_retry_num < 5) {
95             ESP_LOGI(TAG, "DPP Auth failed (Reason: %s), retry...", esp_err_to_name((int)data));
96             ESP_ERROR_CHECK(esp_supp_dpp_start_listen());
97             s_retry_num++;
98         } else {
99             xEventGroupSetBits(s_dpp_event_group, DPP_AUTH_FAIL_BIT);
100         }
101         break;
102     default:
103         break;
104     }
105 }
106 
dpp_enrollee_init(void)107 void dpp_enrollee_init(void)
108 {
109     s_dpp_event_group = xEventGroupCreate();
110 
111     ESP_ERROR_CHECK(esp_netif_init());
112 
113     ESP_ERROR_CHECK(esp_event_loop_create_default());
114     esp_netif_create_default_wifi_sta();
115 
116     ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
117     ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
118 
119     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
120     ESP_ERROR_CHECK(esp_wifi_init(&cfg));
121 
122     ESP_ERROR_CHECK(esp_supp_dpp_init(dpp_enrollee_event_cb));
123     /* Currently only supported method is QR Code */
124     ESP_ERROR_CHECK(esp_supp_dpp_bootstrap_gen(EXAMPLE_DPP_LISTEN_CHANNEL_LIST, DPP_BOOTSTRAP_QR_CODE,
125                     EXAMPLE_DPP_BOOTSTRAPPING_KEY, EXAMPLE_DPP_DEVICE_INFO));
126 
127     ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
128     ESP_ERROR_CHECK(esp_wifi_start());
129 
130     /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
131      * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
132     EventBits_t bits = xEventGroupWaitBits(s_dpp_event_group,
133                                            DPP_CONNECTED_BIT | DPP_CONNECT_FAIL_BIT | DPP_AUTH_FAIL_BIT,
134                                            pdFALSE,
135                                            pdFALSE,
136                                            portMAX_DELAY);
137 
138     /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
139      * happened. */
140     if (bits & DPP_CONNECTED_BIT) {
141         ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
142                  s_dpp_wifi_config.sta.ssid, s_dpp_wifi_config.sta.password);
143     } else if (bits & DPP_CONNECT_FAIL_BIT) {
144         ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
145                  s_dpp_wifi_config.sta.ssid, s_dpp_wifi_config.sta.password);
146     } else if (bits & DPP_AUTH_FAIL_BIT) {
147         ESP_LOGI(TAG, "DPP Authentication failed after %d retries", s_retry_num);
148     } else {
149         ESP_LOGE(TAG, "UNEXPECTED EVENT");
150     }
151 
152     esp_supp_dpp_deinit();
153     ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler));
154     ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler));
155     vEventGroupDelete(s_dpp_event_group);
156 }
157 
app_main(void)158 void app_main(void)
159 {
160     //Initialize NVS
161     esp_err_t ret = nvs_flash_init();
162     if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
163         ESP_ERROR_CHECK(nvs_flash_erase());
164         ret = nvs_flash_init();
165     }
166     ESP_ERROR_CHECK(ret);
167 
168     dpp_enrollee_init();
169 }
170