1
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
43
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
86
87
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
148
152
154
155
208
209
210
216
217
218
219
220
221
222
223
224
225
226
232
233
234
235
238
239
240
244
245
246
247
248
249
250
251
255
256
271
272
275
276
277
278
279
280
305
306
307
308
309
310
311
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
349
350
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
380
381
382
383
384
385
386
389
390
391
392
393
394
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
417
418
419
422
423
424
425
426
427
428
429
430
431
436
437
442
443
448
449
450
451
452
453
454
455
461
462
463
464
465
466
467
468
469
470
471
472
473
479
480
483
484
485
486
491
492
493
495
496
497
498
499
500
501
505
506
507
510
511
512
513
514
515
516
517
518
519
520
521
523
524
525
526
527
528
529
530
531
532
533
534
535
536
540
541
542
543
544
545
546
547
548
553
554
/* ... */
#include <stdio.h>
#include <string.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/event_groups.h>
#include <esp_log.h>
#include <esp_wifi.h>
#include <esp_event.h>
#include <nvs_flash.h>
#include <wifi_provisioning/manager.h>10 includes
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
#include <wifi_provisioning/scheme_ble.h>
#endif
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP
#include <wifi_provisioning/scheme_softap.h>
#endif
#include "qrcode.h"
static const char *TAG = "app";
#if CONFIG_EXAMPLE_PROV_SECURITY_VERSION_2
#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE
#define EXAMPLE_PROV_SEC2_USERNAME "wifiprov"
#define EXAMPLE_PROV_SEC2_PWD "abcd1234"
/* ... */
static const char sec2_salt[] = {
0x03, 0x6e, 0xe0, 0xc7, 0xbc, 0xb9, 0xed, 0xa8, 0x4c, 0x9e, 0xac, 0x97, 0xd9, 0x3d, 0xec, 0xf4
}{...};
static const char sec2_verifier[] = {
0x7c, 0x7c, 0x85, 0x47, 0x65, 0x08, 0x94, 0x6d, 0xd6, 0x36, 0xaf, 0x37, 0xd7, 0xe8, 0x91, 0x43,
0x78, 0xcf, 0xfd, 0x61, 0x6c, 0x59, 0xd2, 0xf8, 0x39, 0x08, 0x12, 0x72, 0x38, 0xde, 0x9e, 0x24,
0xa4, 0x70, 0x26, 0x1c, 0xdf, 0xa9, 0x03, 0xc2, 0xb2, 0x70, 0xe7, 0xb1, 0x32, 0x24, 0xda, 0x11,
0x1d, 0x97, 0x18, 0xdc, 0x60, 0x72, 0x08, 0xcc, 0x9a, 0xc9, 0x0c, 0x48, 0x27, 0xe2, 0xae, 0x89,
0xaa, 0x16, 0x25, 0xb8, 0x04, 0xd2, 0x1a, 0x9b, 0x3a, 0x8f, 0x37, 0xf6, 0xe4, 0x3a, 0x71, 0x2e,
0xe1, 0x27, 0x86, 0x6e, 0xad, 0xce, 0x28, 0xff, 0x54, 0x46, 0x60, 0x1f, 0xb9, 0x96, 0x87, 0xdc,
0x57, 0x40, 0xa7, 0xd4, 0x6c, 0xc9, 0x77, 0x54, 0xdc, 0x16, 0x82, 0xf0, 0xed, 0x35, 0x6a, 0xc4,
0x70, 0xad, 0x3d, 0x90, 0xb5, 0x81, 0x94, 0x70, 0xd7, 0xbc, 0x65, 0xb2, 0xd5, 0x18, 0xe0, 0x2e,
0xc3, 0xa5, 0xf9, 0x68, 0xdd, 0x64, 0x7b, 0xb8, 0xb7, 0x3c, 0x9c, 0xfc, 0x00, 0xd8, 0x71, 0x7e,
0xb7, 0x9a, 0x7c, 0xb1, 0xb7, 0xc2, 0xc3, 0x18, 0x34, 0x29, 0x32, 0x43, 0x3e, 0x00, 0x99, 0xe9,
0x82, 0x94, 0xe3, 0xd8, 0x2a, 0xb0, 0x96, 0x29, 0xb7, 0xdf, 0x0e, 0x5f, 0x08, 0x33, 0x40, 0x76,
0x52, 0x91, 0x32, 0x00, 0x9f, 0x97, 0x2c, 0x89, 0x6c, 0x39, 0x1e, 0xc8, 0x28, 0x05, 0x44, 0x17,
0x3f, 0x68, 0x02, 0x8a, 0x9f, 0x44, 0x61, 0xd1, 0xf5, 0xa1, 0x7e, 0x5a, 0x70, 0xd2, 0xc7, 0x23,
0x81, 0xcb, 0x38, 0x68, 0xe4, 0x2c, 0x20, 0xbc, 0x40, 0x57, 0x76, 0x17, 0xbd, 0x08, 0xb8, 0x96,
0xbc, 0x26, 0xeb, 0x32, 0x46, 0x69, 0x35, 0x05, 0x8c, 0x15, 0x70, 0xd9, 0x1b, 0xe9, 0xbe, 0xcc,
0xa9, 0x38, 0xa6, 0x67, 0xf0, 0xad, 0x50, 0x13, 0x19, 0x72, 0x64, 0xbf, 0x52, 0xc2, 0x34, 0xe2,
0x1b, 0x11, 0x79, 0x74, 0x72, 0xbd, 0x34, 0x5b, 0xb1, 0xe2, 0xfd, 0x66, 0x73, 0xfe, 0x71, 0x64,
0x74, 0xd0, 0x4e, 0xbc, 0x51, 0x24, 0x19, 0x40, 0x87, 0x0e, 0x92, 0x40, 0xe6, 0x21, 0xe7, 0x2d,
0x4e, 0x37, 0x76, 0x2f, 0x2e, 0xe2, 0x68, 0xc7, 0x89, 0xe8, 0x32, 0x13, 0x42, 0x06, 0x84, 0x84,
0x53, 0x4a, 0xb3, 0x0c, 0x1b, 0x4c, 0x8d, 0x1c, 0x51, 0x97, 0x19, 0xab, 0xae, 0x77, 0xff, 0xdb,
0xec, 0xf0, 0x10, 0x95, 0x34, 0x33, 0x6b, 0xcb, 0x3e, 0x84, 0x0f, 0xb9, 0xd8, 0x5f, 0xb8, 0xa0,
0xb8, 0x55, 0x53, 0x3e, 0x70, 0xf7, 0x18, 0xf5, 0xce, 0x7b, 0x4e, 0xbf, 0x27, 0xce, 0xce, 0xa8,
0xb3, 0xbe, 0x40, 0xc5, 0xc5, 0x32, 0x29, 0x3e, 0x71, 0x64, 0x9e, 0xde, 0x8c, 0xf6, 0x75, 0xa1,
0xe6, 0xf6, 0x53, 0xc8, 0x31, 0xa8, 0x78, 0xde, 0x50, 0x40, 0xf7, 0x62, 0xde, 0x36, 0xb2, 0xba
}{...};
/* ... */#endif
static esp_err_t example_get_sec2_salt(const char **salt, uint16_t *salt_len) {
#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE
ESP_LOGI(TAG, "Development mode: using hard coded salt");
*salt = sec2_salt;
*salt_len = sizeof(sec2_salt);
return ESP_OK;/* ... */
#elif CONFIG_EXAMPLE_PROV_SEC2_PROD_MODE
ESP_LOGE(TAG, "Not implemented!");
return ESP_FAIL;/* ... */
#endif
}{ ... }
static esp_err_t example_get_sec2_verifier(const char **verifier, uint16_t *verifier_len) {
#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE
ESP_LOGI(TAG, "Development mode: using hard coded verifier");
*verifier = sec2_verifier;
*verifier_len = sizeof(sec2_verifier);
return ESP_OK;/* ... */
#elif CONFIG_EXAMPLE_PROV_SEC2_PROD_MODE
ESP_LOGE(TAG, "Not implemented!");
return ESP_FAIL;/* ... */
#endif
}{ ... }
#endif/* ... */
const int WIFI_CONNECTED_EVENT = BIT0;
static EventGroupHandle_t wifi_event_group;
#define PROV_QR_VERSION "v1"
#define PROV_TRANSPORT_SOFTAP "softap"
#define PROV_TRANSPORT_BLE "ble"
#define QRCODE_BASE_URL "https://espressif.github.io/esp-jumpstart/qrcode.html"
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == WIFI_PROV_EVENT) {
switch (event_id) {
case WIFI_PROV_START:
ESP_LOGI(TAG, "Provisioning started");
break;...
case WIFI_PROV_CRED_RECV: {
wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)event_data;
ESP_LOGI(TAG, "Received Wi-Fi credentials"
"\n\tSSID : %s\n\tPassword : %s",
(const char *) wifi_sta_cfg->ssid,
(const char *) wifi_sta_cfg->password);
break;
}{...}
... case WIFI_PROV_CRED_FAIL: {
wifi_prov_sta_fail_reason_t *reason = (wifi_prov_sta_fail_reason_t *)event_data;
ESP_LOGE(TAG, "Provisioning failed!\n\tReason : %s"
"\n\tPlease reset to factory and retry provisioning",
(*reason == WIFI_PROV_STA_AUTH_ERROR) ?
"Wi-Fi station authentication failed" : "Wi-Fi access-point not found");
#ifdef CONFIG_EXAMPLE_RESET_PROV_MGR_ON_FAILURE
/* ... */
wifi_prov_mgr_reset_sm_state_on_failure();/* ... */
#endif
break;
}{...}
... case WIFI_PROV_CRED_SUCCESS:
ESP_LOGI(TAG, "Provisioning successful");
break;...
case WIFI_PROV_END:
wifi_prov_mgr_deinit();
break;...
default:
break;...
}{...}
}{...} else if (event_base == WIFI_EVENT) {
switch (event_id) {
case WIFI_EVENT_STA_START:
esp_wifi_connect();
break;...
case WIFI_EVENT_STA_DISCONNECTED:
ESP_LOGI(TAG, "Disconnected. Connecting to the AP again...");
esp_wifi_connect();
break;
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP...
case WIFI_EVENT_AP_STACONNECTED:
ESP_LOGI(TAG, "SoftAP transport: Connected!");
break;...
case WIFI_EVENT_AP_STADISCONNECTED:
ESP_LOGI(TAG, "SoftAP transport: Disconnected!");
break;/* ... */
#endif
default:
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, "Connected with IP Address:" IPSTR, IP2STR(&event->ip_info.ip));
xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_EVENT);
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
}{...} else if (event_base == PROTOCOMM_TRANSPORT_BLE_EVENT) {
switch (event_id) {
case PROTOCOMM_TRANSPORT_BLE_CONNECTED:
ESP_LOGI(TAG, "BLE transport: Connected!");
break;...
case PROTOCOMM_TRANSPORT_BLE_DISCONNECTED:
ESP_LOGI(TAG, "BLE transport: Disconnected!");
break;...
default:
break;...
}{...}
#endif
}{...} else if (event_base == PROTOCOMM_SECURITY_SESSION_EVENT) {
switch (event_id) {
case PROTOCOMM_SECURITY_SESSION_SETUP_OK:
ESP_LOGI(TAG, "Secured session established!");
break;...
case PROTOCOMM_SECURITY_SESSION_INVALID_SECURITY_PARAMS:
ESP_LOGE(TAG, "Received invalid security parameters for establishing secure session!");
break;...
case PROTOCOMM_SECURITY_SESSION_CREDENTIALS_MISMATCH:
ESP_LOGE(TAG, "Received incorrect username and/or PoP for establishing secure session!");
break;...
default:
break;...
}{...}
}{...}
}{ ... }
static void wifi_init_sta(void)
{
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_start());
}{ ... }
static void get_device_service_name(char *service_name, size_t max)
{
uint8_t eth_mac[6];
const char *ssid_prefix = "PROV_";
esp_wifi_get_mac(WIFI_IF_STA, eth_mac);
snprintf(service_name, max, "%s%02X%02X%02X",
ssid_prefix, eth_mac[3], eth_mac[4], eth_mac[5]);
}{ ... }
/* ... */
esp_err_t custom_prov_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen,
uint8_t **outbuf, ssize_t *outlen, void *priv_data)
{
if (inbuf) {
ESP_LOGI(TAG, "Received data: %.*s", inlen, (char *)inbuf);
}{...}
char response[] = "SUCCESS";
*outbuf = (uint8_t *)strdup(response);
if (*outbuf == NULL) {
ESP_LOGE(TAG, "System out of memory");
return ESP_ERR_NO_MEM;
}{...}
*outlen = strlen(response) + 1;
return ESP_OK;
}{ ... }
static void wifi_prov_print_qr(const char *name, const char *username, const char *pop, const char *transport)
{
if (!name || !transport) {
ESP_LOGW(TAG, "Cannot generate QR code payload. Data missing.");
return;
}{...}
char payload[150] = {0};
if (pop) {
#if CONFIG_EXAMPLE_PROV_SECURITY_VERSION_1
snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \
",\"pop\":\"%s\",\"transport\":\"%s\"}",
PROV_QR_VERSION, name, pop, transport);/* ... */
#elif CONFIG_EXAMPLE_PROV_SECURITY_VERSION_2
snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \
",\"username\":\"%s\",\"pop\":\"%s\",\"transport\":\"%s\"}",
PROV_QR_VERSION, name, username, pop, transport);/* ... */
#endif
}{...} else {
snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \
",\"transport\":\"%s\"}",
PROV_QR_VERSION, name, transport);
}{...}
#ifdef CONFIG_EXAMPLE_PROV_SHOW_QR
ESP_LOGI(TAG, "Scan this QR code from the provisioning application for Provisioning.");
esp_qrcode_config_t cfg = ESP_QRCODE_CONFIG_DEFAULT();
esp_qrcode_generate(&cfg, payload);/* ... */
#endif
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);
}{ ... }
#ifdef CONFIG_EXAMPLE_PROV_ENABLE_APP_CALLBACK
void wifi_prov_app_callback(void *user_data, wifi_prov_cb_event_t event, void *event_data)
{
/* ... */
switch (event) {
case WIFI_PROV_SET_STA_CONFIG: {
/* ... */
wifi_config_t *wifi_config = (wifi_config_t*)event_data;
(void) wifi_config;
break;
}{...}
... default:
break;...
}{...}
}{...}
const wifi_prov_event_handler_t wifi_prov_event_handler = {
.event_cb = wifi_prov_app_callback,
.user_data = NULL,
}{...};/* ... */
#endif
void app_main(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
/* ... */
ESP_ERROR_CHECK(nvs_flash_erase());
ESP_ERROR_CHECK(nvs_flash_init());
}{...}
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
ESP_ERROR_CHECK(esp_event_handler_register(PROTOCOMM_TRANSPORT_BLE_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
#endif
ESP_ERROR_CHECK(esp_event_handler_register(PROTOCOMM_SECURITY_SESSION_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));
esp_netif_create_default_wifi_sta();
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP
esp_netif_create_default_wifi_ap();
#endif
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
wifi_prov_mgr_config_t config = {
#ifdef CONFIG_EXAMPLE_RESET_PROV_MGR_ON_FAILURE
.wifi_prov_conn_cfg = {
.wifi_conn_attempts = CONFIG_EXAMPLE_PROV_MGR_CONNECTION_CNT,
}{...},/* ... */
#endif
/* ... */
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
.scheme = wifi_prov_scheme_ble,
#endif
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP
.scheme = wifi_prov_scheme_softap,
#endif
#ifdef CONFIG_EXAMPLE_PROV_ENABLE_APP_CALLBACK
.app_event_handler = wifi_prov_event_handler,
#endif
/* ... */
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
.scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM
#endif
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP
.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE
#endif
}{...};
/* ... */
ESP_ERROR_CHECK(wifi_prov_mgr_init(config));
bool provisioned = false;
#ifdef CONFIG_EXAMPLE_RESET_PROVISIONED
wifi_prov_mgr_reset_provisioning();
#else
ESP_ERROR_CHECK(wifi_prov_mgr_is_provisioned(&provisioned));
/* ... */
#endif
if (!provisioned) {
ESP_LOGI(TAG, "Starting provisioning");
/* ... */
char service_name[12];
get_device_service_name(service_name, sizeof(service_name));
#ifdef CONFIG_EXAMPLE_PROV_SECURITY_VERSION_1
/* ... */
wifi_prov_security_t security = WIFI_PROV_SECURITY_1;
/* ... */
const char *pop = "abcd1234";
/* ... */
wifi_prov_security1_params_t *sec_params = pop;
const char *username = NULL;
/* ... */
#elif CONFIG_EXAMPLE_PROV_SECURITY_VERSION_2
wifi_prov_security_t security = WIFI_PROV_SECURITY_2;
#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE
/* ... */
const char *username = EXAMPLE_PROV_SEC2_USERNAME;
const char *pop = EXAMPLE_PROV_SEC2_PWD;/* ... */
#elif CONFIG_EXAMPLE_PROV_SEC2_PROD_MODE
/* ... */
const char *username = NULL;
const char *pop = NULL;/* ... */
#endif
/* ... */
wifi_prov_security2_params_t sec2_params = {};
ESP_ERROR_CHECK(example_get_sec2_salt(&sec2_params.salt, &sec2_params.salt_len));
ESP_ERROR_CHECK(example_get_sec2_verifier(&sec2_params.verifier, &sec2_params.verifier_len));
wifi_prov_security2_params_t *sec_params = &sec2_params;/* ... */
#endif
/* ... */
const char *service_key = NULL;
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
/* ... */
uint8_t custom_service_uuid[] = {
/* ... */
0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf,
0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02,
}{...};
/* ... */
wifi_prov_scheme_ble_set_service_uuid(custom_service_uuid);/* ... */
#endif
/* ... */
wifi_prov_mgr_endpoint_create("custom-data");
/* ... */
#ifdef CONFIG_EXAMPLE_REPROVISIONING
wifi_prov_mgr_disable_auto_stop(1000);
#endif
ESP_ERROR_CHECK(wifi_prov_mgr_start_provisioning(security, (const void *) sec_params, service_name, service_key));
/* ... */
wifi_prov_mgr_endpoint_register("custom-data", custom_prov_data_handler, NULL);
/* ... */
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
wifi_prov_print_qr(service_name, username, pop, PROV_TRANSPORT_BLE);
#else
wifi_prov_print_qr(service_name, username, pop, PROV_TRANSPORT_SOFTAP);
#endif
}{...} else {
ESP_LOGI(TAG, "Already provisioned, starting Wi-Fi STA");
/* ... */
wifi_prov_mgr_deinit();
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
wifi_init_sta();
}{...}
xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_EVENT, true, true, portMAX_DELAY);
#if CONFIG_EXAMPLE_REPROVISIONING
while (1) {
for (int i = 0; i < 10; i++) {
ESP_LOGI(TAG, "Hello World!");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}{...}
wifi_prov_mgr_reset_sm_state_for_reprovision();
xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_EVENT, true, true, portMAX_DELAY);
}{...}
#else/* ... */
while (1) {
ESP_LOGI(TAG, "Hello World!");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}{...}
#endif/* ... */
}{ ... }