Skip to content

Commit 2c9b648

Browse files
Add support of unified provisioning to Arduino
1. WiFiProv.ino sketch is added that allows arduino users to do provisioning via SoftAP or BLE. WiFi.beginProvision( ) API is designed for provisioning in Arduino. 2. In WiFiProv.h provisioning class is defined. 3. WiFiProv.cpp contains implementation for provisioning class. 4. README.md file is added which contains detail information for working.
1 parent 5508689 commit 2c9b648

File tree

8 files changed

+490
-17
lines changed

8 files changed

+490
-17
lines changed

Diff for: CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ set(LIBRARY_SRCS
7171
libraries/WiFi/src/WiFi.cpp
7272
libraries/WiFi/src/WiFiGeneric.cpp
7373
libraries/WiFi/src/WiFiMulti.cpp
74+
libraries/WiFi/src/WiFiProv.cpp
7475
libraries/WiFi/src/WiFiScan.cpp
7576
libraries/WiFi/src/WiFiServer.cpp
7677
libraries/WiFi/src/WiFiSTA.cpp

Diff for: libraries/WiFi/examples/WiFiProv/README.md

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Provisioning for Arduino
2+
3+
This sketch implements provisioning using various IDF components
4+
5+
# Description
6+
7+
This example allows Arduino user to choose either BLE or SOFTAP as a mode of transport, over which the provisioning related communication is to take place, between the device (to be provisioned) and the client (owner of the device).
8+
9+
## API's introduced for provisioning
10+
11+
## WiFi.onEvent()
12+
13+
Using this API user can register to recieve WIFI Events and Provisioning Events
14+
15+
#### Parameters passed
16+
17+
A function with following signature
18+
* void SysProvEvent(system_event_t * , wifi_prov_event_t * );
19+
20+
#### structure [ wifi_prov_event_t ]
21+
22+
* wifi_prov_cb_event_t event;
23+
* void * event_data;
24+
25+
### WiFi.beginProvision()
26+
27+
WiFi.beginProvision(scheme prov_scheme, wifi_prov_scheme_event_handler_t scheme_event_handler, wifi_prov_security_t security, char * pop, char * service_name, char * service_key, uint8_t * uuid);
28+
29+
#### Parameters
30+
31+
* prov_scheme : choose the mode of transfer
32+
* WIFI_PROV_SCHEME_BLE - Using BLE
33+
* WIFI_PROV_SCHEME_SOFTAP - Using SoftAP
34+
35+
* security : choose security type
36+
* WIFI_PROV_SECURITY_1 - It allows secure communication which consists of secure handshake using key exchange and proof of possession (pop) and encryption/decryption of messages.
37+
38+
* WIFI_PROV_SECURITY_0 - It do not provide application level security, it involve simply plain text communication.
39+
40+
* scheme_event_handler : specify the handlers according to the mode chosen
41+
* BLE :
42+
- WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM - This scheme event handler is used when application doesn't need BT and BLE after provisioning is finised
43+
- WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE - This scheme event handler is used when application doesn't need BLE to be active after provisioning is finised
44+
- WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT - This scheme event handler is used when application doesn't need BT to be active after provisioning is finised
45+
46+
* SoftAp :
47+
- WIFI_PROV_EVENT_HANDLER_NONE
48+
49+
* pop : It is the string that is used to provide the authentication while provisioning
50+
51+
* service_name : Specify service name for the device while provisioning, if it is not specified then default chosen name via SoftAP is WIFI_XXX and for BLE service it is BLE_XXX where XXX is the last 3 bytes of the MAC address.
52+
53+
* service_key : Specify service key while provisioning, if chosen mode of provisioning is BLE then service_key is always NULL
54+
55+
* uuid : user can specify there own 128 bit UUID while provisioning using BLE, if not specified then default value taken is
56+
- { 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf,
57+
0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02, }
58+
59+
# NOTE
60+
61+
* If none of the parameters are specified in beginProvision then default provisioning takes place using SoftAP with
62+
* scheme = WIFI_PROV_SCHEME_SOFTAP
63+
* scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE
64+
* security = WIFI_PROV_SECURITY_1
65+
* pop = "abcd1234"
66+
* service_name = "WiFi_XXX"
67+
* service_key = NULL
68+
* uuid = NULL
69+
70+
# Log Output
71+
* Enable debuger : [ Tools -> Core Debug Level -> Info ]
72+
73+
# App required for provisioning
74+
75+
##Gihub link
76+
77+
* Android : (https://github.com/espressif/esp-idf-provisioning-android)
78+
* iOS : (https://github.com/espressif/esp-idf-provisioning-ios)
79+
80+
## These apps are available on playstore
81+
82+
* For SoftAP : ESP SoftAP Prov
83+
* For BLE : ESP BLE Prov
84+
85+
# Example output
86+
87+
## Provisioning using SoftAP
88+
89+
```
90+
[I][WiFiProv.cpp:117] beginProvision(): Starting AP using SOFTAP
91+
service_name : WIFI_XXX
92+
password : 123456789
93+
pop : abcd1234
94+
95+
Provisioning started
96+
Give Credentials of your access point using " Android app "
97+
98+
Received Wi-Fi credentials
99+
SSID : GIONEE M2
100+
Password : 123456789
101+
102+
Connected IP address : 192.168.43.120
103+
Provisioning Successful
104+
Provisioning Ends
105+
106+
```
107+
108+
## Provisioning using BLE
109+
110+
```
111+
[I][WiFiProv.cpp:115] beginProvision(): Starting AP using BLE
112+
service_name : BLE_XXX
113+
pop : abcd1234
114+
115+
Provisioning started
116+
Give Credentials of your access point using " Android app "
117+
118+
Received Wi-Fi credentials
119+
SSID : GIONEE M2
120+
Password : 123456789
121+
122+
Connected IP address : 192.168.43.120
123+
Provisioning Successful
124+
Provisioning Ends
125+
126+
```
127+
128+
## Credentials are available on device
129+
130+
```
131+
[I][WiFiProv.cpp:125] beginProvision(): Aleardy Provisioned, starting Wi-Fi STA
132+
[I][WiFiProv.cpp:126] beginProvision(): CONNECTING ACCESS POINT CREDENTIALS :
133+
[I][WiFiProv.cpp:126] beginProvision(): SSID : GIONEE M2
134+
135+
```

Diff for: libraries/WiFi/examples/WiFiProv/WiFiProv.ino

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#include "WiFi.h"
2+
void SysProvEvent(system_event_t *sys_event,wifi_prov_event_t *prov_event)
3+
{
4+
if(sys_event) {
5+
switch (sys_event->event_id) {
6+
case SYSTEM_EVENT_STA_GOT_IP:
7+
Serial.print("\nConnected IP address : ");
8+
Serial.println(ip4addr_ntoa(&sys_event->event_info.got_ip.ip_info.ip));
9+
break;
10+
case SYSTEM_EVENT_STA_DISCONNECTED:
11+
Serial.println("\nDisconnected. Connecting to the AP again... ");
12+
break;
13+
default:
14+
break;
15+
}
16+
}
17+
18+
if(prov_event) {
19+
switch (prov_event->event) {
20+
case WIFI_PROV_START:
21+
Serial.println("\nProvisioning started\nGive Credentials of your access point using \" Android app \"");
22+
break;
23+
case WIFI_PROV_CRED_RECV: {
24+
Serial.println("\nReceived Wi-Fi credentials");
25+
wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)prov_event->event_data;
26+
Serial.print("\tSSID : ");
27+
Serial.println((const char *) wifi_sta_cfg->ssid);
28+
Serial.print("\tPassword : ");
29+
Serial.println((char const *) wifi_sta_cfg->password);
30+
break;
31+
}
32+
case WIFI_PROV_CRED_FAIL: {
33+
wifi_prov_sta_fail_reason_t *reason = (wifi_prov_sta_fail_reason_t *)prov_event->event_data;
34+
Serial.println("\nProvisioning failed!\nPlease reset to factory and retry provisioning\n");
35+
if(*reason == WIFI_PROV_STA_AUTH_ERROR)
36+
Serial.println("\nWi-Fi AP password incorrect");
37+
else
38+
Serial.println("\nWi-Fi AP not found....Add API \" nvs_flash_erase() \" before beginProvision()");
39+
break;
40+
}
41+
case WIFI_PROV_CRED_SUCCESS:
42+
Serial.println("\nProvisioning Successful");
43+
break;
44+
case WIFI_PROV_END:
45+
Serial.println("\nProvisioning Ends");
46+
break;
47+
default:
48+
break;
49+
}
50+
}
51+
}
52+
53+
void setup() {
54+
Serial.begin(115200);
55+
//Sample uuid that user can pass during provisioning using BLE
56+
/* uint8_t uuid[16] = {0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf,
57+
0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02 };*/
58+
WiFi.onEvent(SysProvEvent);
59+
WiFi.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, "abcd1234", "BLE_XXX", NULL, NULL);
60+
}
61+
62+
void loop() {
63+
}

Diff for: libraries/WiFi/src/WiFi.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@
3737
#include "WiFiClient.h"
3838
#include "WiFiServer.h"
3939
#include "WiFiUdp.h"
40+
#include "WiFiProv.h"
4041

41-
class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanClass, public WiFiAPClass
42+
class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanClass, public WiFiAPClass, public WiFiProvClass
4243
{
4344
public:
4445
using WiFiGenericClass::channel;
@@ -54,8 +55,7 @@ class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanC
5455
using WiFiScanClass::BSSID;
5556
using WiFiScanClass::BSSIDstr;
5657
using WiFiScanClass::channel;
57-
58-
public:
58+
public:
5959
void printDiag(Print& dest);
6060
friend class WiFiClient;
6161
friend class WiFiServer;

Diff for: libraries/WiFi/src/WiFiGeneric.cpp

+59-13
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ extern "C" {
4242
#include "lwip/dns.h"
4343
#include "esp_ipc.h"
4444

45-
4645
} //extern "C"
4746

4847
#include "esp32-hal-log.h"
@@ -53,20 +52,42 @@ static xQueueHandle _network_event_queue;
5352
static TaskHandle_t _network_event_task_handle = NULL;
5453
static EventGroupHandle_t _network_event_group = NULL;
5554

55+
esp_err_t postToSysQueue(system_prov_event_t *data)
56+
{
57+
if (xQueueSend(_network_event_queue, &data, portMAX_DELAY) != pdPASS) {
58+
log_w("Network Event Queue Send Failed!");
59+
return ESP_FAIL;
60+
}
61+
return ESP_OK;
62+
}
63+
5664
static void _network_event_task(void * arg){
57-
system_event_t event;
65+
system_prov_event_t *data;
5866
for (;;) {
59-
if(xQueueReceive(_network_event_queue, &event, portMAX_DELAY) == pdTRUE){
60-
WiFiGenericClass::_eventCallback(arg, &event);
61-
}
67+
if(xQueueReceive(_network_event_queue, &data, portMAX_DELAY) == pdTRUE){
68+
if(data->prov_event != NULL){
69+
WiFiGenericClass::_eventCallback(arg, data->sys_event, data->prov_event);
70+
free(data->sys_event);
71+
free(data->prov_event);
72+
} else {
73+
WiFiGenericClass::_eventCallback(arg, data->sys_event, NULL);
74+
}
75+
free(data);
76+
}
6277
}
6378
vTaskDelete(NULL);
6479
_network_event_task_handle = NULL;
6580
}
6681

67-
static esp_err_t _network_event_cb(void *arg, system_event_t *event){
68-
if (xQueueSend(_network_event_queue, event, portMAX_DELAY) != pdPASS) {
69-
log_w("Network Event Queue Send Failed!");
82+
static esp_err_t _network_event_cb(void *arg, system_event_t *event){
83+
system_prov_event_t *sys_prov_data = (system_prov_event_t *)malloc(sizeof(system_prov_event_t));
84+
if(sys_prov_data == NULL) {
85+
return ESP_FAIL;
86+
}
87+
sys_prov_data->sys_event = event;
88+
sys_prov_data->prov_event = NULL;
89+
if (postToSysQueue(sys_prov_data) != ESP_OK){
90+
free(sys_prov_data);
7091
return ESP_FAIL;
7192
}
7293
return ESP_OK;
@@ -82,7 +103,7 @@ static bool _start_network_event_task(){
82103
xEventGroupSetBits(_network_event_group, WIFI_DNS_IDLE_BIT);
83104
}
84105
if(!_network_event_queue){
85-
_network_event_queue = xQueueCreate(32, sizeof(system_event_t));
106+
_network_event_queue = xQueueCreate(32, sizeof(system_prov_event_t));
86107
if(!_network_event_queue){
87108
log_e("Network Event Queue Create Failed!");
88109
return false;
@@ -144,7 +165,7 @@ static bool espWiFiStart(){
144165
_esp_wifi_started = true;
145166
system_event_t event;
146167
event.event_id = SYSTEM_EVENT_WIFI_READY;
147-
WiFiGenericClass::_eventCallback(nullptr, &event);
168+
WiFiGenericClass::_eventCallback(nullptr, &event, NULL);
148169
return true;
149170
}
150171

@@ -173,9 +194,10 @@ typedef struct WiFiEventCbList {
173194
WiFiEventCb cb;
174195
WiFiEventFuncCb fcb;
175196
WiFiEventSysCb scb;
197+
WiFiProvEventCb provcb;
176198
system_event_id_t event;
177199

178-
WiFiEventCbList() : id(current_id++), cb(NULL), fcb(NULL), scb(NULL), event(SYSTEM_EVENT_WIFI_READY) {}
200+
WiFiEventCbList() : id(current_id++), cb(NULL), fcb(NULL), scb(NULL), provcb(NULL), event(SYSTEM_EVENT_WIFI_READY) {}
179201
} WiFiEventCbList_t;
180202
wifi_event_id_t WiFiEventCbList::current_id = 1;
181203

@@ -230,6 +252,20 @@ int WiFiGenericClass::waitStatusBits(int bits, uint32_t timeout_ms){
230252
* @param cbEvent WiFiEventCb
231253
* @param event optional filter (WIFI_EVENT_MAX is all events)
232254
*/
255+
wifi_event_id_t WiFiGenericClass::onEvent(WiFiProvEventCb cbEvent, system_event_id_t event)
256+
{
257+
if(!cbEvent){
258+
return 0;
259+
}
260+
WiFiEventCbList_t newEventHandler;
261+
newEventHandler.cb = NULL;
262+
newEventHandler.fcb = NULL;
263+
newEventHandler.scb = NULL;
264+
newEventHandler.provcb = cbEvent;
265+
newEventHandler.event = event;
266+
cbEventList.push_back(newEventHandler);
267+
return newEventHandler.id;
268+
}
233269
wifi_event_id_t WiFiGenericClass::onEvent(WiFiEventCb cbEvent, system_event_id_t event)
234270
{
235271
if(!cbEvent) {
@@ -239,6 +275,7 @@ wifi_event_id_t WiFiGenericClass::onEvent(WiFiEventCb cbEvent, system_event_id_t
239275
newEventHandler.cb = cbEvent;
240276
newEventHandler.fcb = NULL;
241277
newEventHandler.scb = NULL;
278+
newEventHandler.provcb = NULL;
242279
newEventHandler.event = event;
243280
cbEventList.push_back(newEventHandler);
244281
return newEventHandler.id;
@@ -253,6 +290,7 @@ wifi_event_id_t WiFiGenericClass::onEvent(WiFiEventFuncCb cbEvent, system_event_
253290
newEventHandler.cb = NULL;
254291
newEventHandler.fcb = cbEvent;
255292
newEventHandler.scb = NULL;
293+
newEventHandler.provcb = NULL;
256294
newEventHandler.event = event;
257295
cbEventList.push_back(newEventHandler);
258296
return newEventHandler.id;
@@ -267,6 +305,7 @@ wifi_event_id_t WiFiGenericClass::onEvent(WiFiEventSysCb cbEvent, system_event_i
267305
newEventHandler.cb = NULL;
268306
newEventHandler.fcb = NULL;
269307
newEventHandler.scb = cbEvent;
308+
newEventHandler.provcb = NULL;
270309
newEventHandler.event = event;
271310
cbEventList.push_back(newEventHandler);
272311
return newEventHandler.id;
@@ -326,8 +365,11 @@ const char * system_event_names[] = { "WIFI_READY", "SCAN_DONE", "STA_START", "S
326365
const char * system_event_reasons[] = { "UNSPECIFIED", "AUTH_EXPIRE", "AUTH_LEAVE", "ASSOC_EXPIRE", "ASSOC_TOOMANY", "NOT_AUTHED", "NOT_ASSOCED", "ASSOC_LEAVE", "ASSOC_NOT_AUTHED", "DISASSOC_PWRCAP_BAD", "DISASSOC_SUPCHAN_BAD", "UNSPECIFIED", "IE_INVALID", "MIC_FAILURE", "4WAY_HANDSHAKE_TIMEOUT", "GROUP_KEY_UPDATE_TIMEOUT", "IE_IN_4WAY_DIFFERS", "GROUP_CIPHER_INVALID", "PAIRWISE_CIPHER_INVALID", "AKMP_INVALID", "UNSUPP_RSN_IE_VERSION", "INVALID_RSN_IE_CAP", "802_1X_AUTH_FAILED", "CIPHER_SUITE_REJECTED", "BEACON_TIMEOUT", "NO_AP_FOUND", "AUTH_FAIL", "ASSOC_FAIL", "HANDSHAKE_TIMEOUT", "CONNECTION_FAIL" };
327366
#define reason2str(r) ((r>176)?system_event_reasons[r-176]:system_event_reasons[r-1])
328367
#endif
329-
esp_err_t WiFiGenericClass::_eventCallback(void *arg, system_event_t *event)
368+
esp_err_t WiFiGenericClass::_eventCallback(void *arg, system_event_t *event, wifi_prov_event_t *prov_event)
330369
{
370+
if(WiFi.isProvEnabled()) {
371+
wifi_prov_mgr_event_handler(arg,event);
372+
}
331373
if(event->event_id < 26) {
332374
log_d("Event: %d - %s", event->event_id, system_event_names[event->event_id]);
333375
}
@@ -422,7 +464,7 @@ esp_err_t WiFiGenericClass::_eventCallback(void *arg, system_event_t *event)
422464
setStatusBits(ETH_CONNECTED_BIT | ETH_HAS_IP6_BIT);
423465
}
424466
}
425-
467+
426468
for(uint32_t i = 0; i < cbEventList.size(); i++) {
427469
WiFiEventCbList_t entry = cbEventList[i];
428470
if(entry.cb || entry.fcb || entry.scb) {
@@ -436,6 +478,10 @@ esp_err_t WiFiGenericClass::_eventCallback(void *arg, system_event_t *event)
436478
}
437479
}
438480
}
481+
482+
if(entry.provcb) {
483+
entry.provcb(event,prov_event);
484+
}
439485
}
440486
return ESP_OK;
441487
}

0 commit comments

Comments
 (0)