34
34
#include <qrcode.h>
35
35
#include <nvs.h>
36
36
#include <nvs_flash.h>
37
+ #include <esp_timer.h>
37
38
#include "app_wifi.h"
38
39
40
+ ESP_EVENT_DEFINE_BASE (APP_WIFI_EVENT );
39
41
static const char * TAG = "app_wifi" ;
40
42
static const int WIFI_CONNECTED_EVENT = BIT0 ;
41
43
static EventGroupHandle_t wifi_event_group ;
@@ -49,6 +51,12 @@ static EventGroupHandle_t wifi_event_group;
49
51
#define CREDENTIALS_NAMESPACE "rmaker_creds"
50
52
#define RANDOM_NVS_KEY "random"
51
53
54
+ #define POP_STR_SIZE 9
55
+ static esp_timer_handle_t prov_stop_timer ;
56
+ /* Timeout period in minutes */
57
+ #define APP_WIFI_PROV_TIMEOUT_PERIOD CONFIG_APP_WIFI_PROV_TIMEOUT_PERIOD
58
+ /* Autofetch period in micro-seconds */
59
+ static uint64_t prov_timeout_period = (APP_WIFI_PROV_TIMEOUT_PERIOD * 60 * 1000000LL );
52
60
#ifdef CONFIG_APP_WIFI_SHOW_DEMO_INTRO_TEXT
53
61
54
62
#define ESP_RAINMAKER_GITHUB_EXAMPLES_PATH "https://github.com/espressif/esp-rainmaker/blob/master/examples"
@@ -94,19 +102,26 @@ static void intro_print(bool provisioned)
94
102
95
103
static void app_wifi_print_qr (const char * name , const char * pop , const char * transport )
96
104
{
97
- if (!name || !pop || ! transport ) {
105
+ if (!name || !transport ) {
98
106
ESP_LOGW (TAG , "Cannot generate QR code payload. Data missing." );
99
107
return ;
100
108
}
101
109
char payload [150 ];
102
- snprintf (payload , sizeof (payload ), "{\"ver\":\"%s\",\"name\":\"%s\"" \
103
- ",\"pop\":\"%s\",\"transport\":\"%s\"}" ,
104
- PROV_QR_VERSION , name , pop , transport );
110
+ if (pop ) {
111
+ snprintf (payload , sizeof (payload ), "{\"ver\":\"%s\",\"name\":\"%s\"" \
112
+ ",\"pop\":\"%s\",\"transport\":\"%s\"}" ,
113
+ PROV_QR_VERSION , name , pop , transport );
114
+ } else {
115
+ snprintf (payload , sizeof (payload ), "{\"ver\":\"%s\",\"name\":\"%s\"" \
116
+ ",\"transport\":\"%s\"}" ,
117
+ PROV_QR_VERSION , name , transport );
118
+ }
105
119
#ifdef CONFIG_APP_WIFI_PROV_SHOW_QR
106
120
ESP_LOGI (TAG , "Scan this QR code from the ESP RainMaker phone app for Provisioning." );
107
121
qrcode_display (payload );
108
122
#endif /* CONFIG_APP_WIFI_PROV_SHOW_QR */
109
123
ESP_LOGI (TAG , "If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s" , QRCODE_BASE_URL , payload );
124
+ esp_event_post (APP_WIFI_EVENT , APP_WIFI_EVENT_QR_DISPLAY , payload , strlen (payload ) + 1 , portMAX_DELAY );
110
125
}
111
126
112
127
/* Event handler for catching system events */
@@ -138,6 +153,11 @@ static void event_handler(void* arg, esp_event_base_t event_base,
138
153
ESP_LOGI (TAG , "Provisioning successful" );
139
154
break ;
140
155
case WIFI_PROV_END :
156
+ if (prov_stop_timer ) {
157
+ esp_timer_stop (prov_stop_timer );
158
+ esp_timer_delete (prov_stop_timer );
159
+ prov_stop_timer = NULL ;
160
+ }
141
161
/* De-initialize manager once provisioning is finished */
142
162
wifi_prov_mgr_deinit ();
143
163
break ;
@@ -212,34 +232,45 @@ static esp_err_t get_device_service_name(char *service_name, size_t max)
212
232
}
213
233
214
234
215
- static esp_err_t get_device_pop ( char * pop , size_t max , app_wifi_pop_type_t pop_type )
235
+ static char * get_device_pop ( app_wifi_pop_type_t pop_type )
216
236
{
217
- if (!pop || !max ) {
218
- return ESP_ERR_INVALID_ARG ;
237
+ if (pop_type == POP_TYPE_NONE ) {
238
+ return NULL ;
239
+ }
240
+ char * pop = calloc (1 , POP_STR_SIZE );
241
+ if (!pop ) {
242
+ ESP_LOGE (TAG , "Failed to allocate memory for PoP." );
243
+ return NULL ;
219
244
}
220
245
221
246
if (pop_type == POP_TYPE_MAC ) {
222
247
uint8_t eth_mac [6 ];
223
248
esp_err_t err = esp_wifi_get_mac (WIFI_IF_STA , eth_mac );
224
249
if (err == ESP_OK ) {
225
- snprintf (pop , max , "%02x%02x%02x%02x" , eth_mac [2 ], eth_mac [3 ], eth_mac [4 ], eth_mac [5 ]);
226
- return ESP_OK ;
250
+ snprintf (pop , POP_STR_SIZE , "%02x%02x%02x%02x" , eth_mac [2 ], eth_mac [3 ], eth_mac [4 ], eth_mac [5 ]);
251
+ return pop ;
227
252
} else {
228
- return err ;
253
+ ESP_LOGE (TAG , "Failed to get MAC address to generate PoP." );
254
+ goto pop_err ;
229
255
}
230
256
} else if (pop_type == POP_TYPE_RANDOM ) {
231
- uint8_t * nvs_random ;
257
+ uint8_t * nvs_random = NULL ;
232
258
size_t nvs_random_size = 0 ;
233
259
if ((read_random_bytes_from_nvs (& nvs_random , & nvs_random_size ) != ESP_OK ) || nvs_random_size < 4 ) {
234
- return ESP_ERR_NOT_FOUND ;
260
+ ESP_LOGE (TAG , "Failed to read random bytes from NVS to generate PoP." );
261
+ if (nvs_random ) {
262
+ free (nvs_random );
263
+ }
264
+ goto pop_err ;
235
265
} else {
236
- snprintf (pop , max , "%02x%02x%02x%02x" , nvs_random [0 ], nvs_random [1 ], nvs_random [2 ], nvs_random [3 ]);
266
+ snprintf (pop , POP_STR_SIZE , "%02x%02x%02x%02x" , nvs_random [0 ], nvs_random [1 ], nvs_random [2 ], nvs_random [3 ]);
237
267
free (nvs_random );
238
- return ESP_OK ;
268
+ return pop ;
239
269
}
240
- } else {
241
- return ESP_ERR_INVALID_ARG ;
242
270
}
271
+ pop_err :
272
+ free (pop );
273
+ return NULL ;
243
274
}
244
275
245
276
void app_wifi_init (void )
@@ -268,6 +299,35 @@ void app_wifi_init(void)
268
299
ESP_ERROR_CHECK (esp_wifi_init (& cfg ));
269
300
}
270
301
302
+ static void app_wifi_prov_stop (void * priv )
303
+ {
304
+ ESP_LOGW (TAG , "Provisioning timed out. Please reboot device to restart provisioning." );
305
+ wifi_prov_mgr_stop_provisioning ();
306
+ esp_event_post (APP_WIFI_EVENT , APP_WIFI_EVENT_PROV_TIMEOUT , NULL , 0 , portMAX_DELAY );
307
+ }
308
+
309
+ esp_err_t app_wifi_start_timer (void )
310
+ {
311
+ if (prov_timeout_period == 0 ) {
312
+ return ESP_OK ;
313
+ }
314
+ esp_timer_create_args_t prov_stop_timer_conf = {
315
+ .callback = app_wifi_prov_stop ,
316
+ .arg = NULL ,
317
+ .dispatch_method = ESP_TIMER_TASK ,
318
+ .name = "app_wifi_prov_stop_tm"
319
+ };
320
+ if (esp_timer_create (& prov_stop_timer_conf , & prov_stop_timer ) == ESP_OK ) {
321
+ esp_timer_start_once (prov_stop_timer , prov_timeout_period );
322
+ ESP_LOGI (TAG , "Provisioning will auto stop after %d minute(s)." ,
323
+ APP_WIFI_PROV_TIMEOUT_PERIOD );
324
+ return ESP_OK ;
325
+ } else {
326
+ ESP_LOGE (TAG , "Failed to create Provisioning auto stop timer." );
327
+ }
328
+ return ESP_FAIL ;
329
+ }
330
+
271
331
esp_err_t app_wifi_start (app_wifi_pop_type_t pop_type )
272
332
{
273
333
/* Configuration for the provisioning manager */
@@ -317,6 +377,12 @@ esp_err_t app_wifi_start(app_wifi_pop_type_t pop_type)
317
377
char service_name [12 ];
318
378
get_device_service_name (service_name , sizeof (service_name ));
319
379
380
+ /* What is the service key (Wi-Fi password)
381
+ * NULL = Open network
382
+ * This is ignored when scheme is wifi_prov_scheme_ble
383
+ */
384
+ const char * service_key = NULL ;
385
+
320
386
/* What is the security level that we want (0 or 1):
321
387
* - WIFI_PROV_SECURITY_0 is simply plain text communication.
322
388
* - WIFI_PROV_SECURITY_1 is secure communication which consists of secure handshake
@@ -329,19 +395,11 @@ esp_err_t app_wifi_start(app_wifi_pop_type_t pop_type)
329
395
* - this should be a string with length > 0
330
396
* - NULL if not used
331
397
*/
332
- char pop [9 ];
333
- esp_err_t err = get_device_pop (pop , sizeof (pop ), pop_type );
334
- if (err != ESP_OK ) {
335
- ESP_LOGE (TAG , "Error: %d. Failed to get PoP from NVS, Please perform Claiming." , err );
336
- return err ;
398
+ char * pop = get_device_pop (pop_type );
399
+ if ((pop_type != POP_TYPE_NONE ) && (pop == NULL )) {
400
+ return ESP_ERR_NO_MEM ;
337
401
}
338
402
339
- /* What is the service key (Wi-Fi password)
340
- * NULL = Open network
341
- * This is ignored when scheme is wifi_prov_scheme_ble
342
- */
343
- const char * service_key = NULL ;
344
-
345
403
#ifdef CONFIG_APP_WIFI_PROV_TRANSPORT_BLE
346
404
/* This step is only useful when scheme is wifi_prov_scheme_ble. This will
347
405
* set a custom 128 bit UUID which will be included in the BLE advertisement
@@ -358,7 +416,7 @@ esp_err_t app_wifi_start(app_wifi_pop_type_t pop_type)
358
416
0xb4 , 0xdf , 0x5a , 0x1c , 0x3f , 0x6b , 0xf4 , 0xbf ,
359
417
0xea , 0x4a , 0x82 , 0x03 , 0x04 , 0x90 , 0x1a , 0x02 ,
360
418
};
361
- err = wifi_prov_scheme_ble_set_service_uuid (custom_service_uuid );
419
+ esp_err_t err = wifi_prov_scheme_ble_set_service_uuid (custom_service_uuid );
362
420
if (err != ESP_OK ) {
363
421
ESP_LOGE (TAG , "wifi_prov_scheme_ble_set_service_uuid failed %d" , err );
364
422
return err ;
@@ -374,7 +432,11 @@ esp_err_t app_wifi_start(app_wifi_pop_type_t pop_type)
374
432
app_wifi_print_qr (service_name , pop , PROV_TRANSPORT_SOFTAP );
375
433
#endif /* CONFIG_APP_WIFI_PROV_TRANSPORT_BLE */
376
434
intro_print (provisioned );
377
- ESP_LOGI (TAG , "Provisioning Started. Name : %s, POP : %s" , service_name , pop );
435
+ ESP_LOGI (TAG , "Provisioning Started. Name : %s, POP : %s" , service_name , pop ? pop : "<null>" );
436
+ if (pop ) {
437
+ free (pop );
438
+ }
439
+ app_wifi_start_timer ();
378
440
} else {
379
441
ESP_LOGI (TAG , "Already provisioned, starting Wi-Fi STA" );
380
442
intro_print (provisioned );
0 commit comments