Unverified Commit 82227e6d authored by Tomáš Pilný's avatar Tomáš Pilný Committed by GitHub

Provisioning fix and upgrades (#8209)

* Added printQR function to library

* Upgraded example

* Upgraded README

* Safegueard for qrcode.h include

* Updated Safegueard for qrcode.h include
parent 0034a438
# Provisioning for Arduino # Provisioning for Arduino
This sketch implements provisioning using various IDF components This sketch implements provisioning using various IDF components.
# Description ## Description
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). This example allows Arduino users to choose either BLE or SOFTAP as the mode of transport for provisioning-related communication between the device (to be provisioned) and the client (owner of the device).
# APIs introduced for provisioning ## APIs introduced for provisioning
## WiFi.onEvent() ### WiFi.onEvent()
Using this API user can register to receive WiFi Events and Provisioning Events Using this API, users can register to receive WiFi Events and Provisioning Events.
## WiFi.beginProvision() ### WiFi.beginProvision()
WiFi.beginProvision(void ( * scheme_cb)(), 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); ```
WiFi.beginProvision(void (*scheme_cb)(), 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);
```
#### Parameters passed #### Parameters passed
* function pointer : choose the mode of transfer - Function pointer: Choose the mode of transfer
* provSchemeBLE - Using BLE - `provSchemeBLE` - Using BLE
* provSchemeSoftAP - Using SoftAP - `provSchemeSoftAP` - Using SoftAP
* security : choose security type - `security`: Choose the security type
* 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. - `WIFI_PROV_SECURITY_1` - Enables secure communication with a secure handshake using key exchange and proof of possession (pop), and encryption/decryption of messages.
- `WIFI_PROV_SECURITY_0` - Does not provide application-level security, allowing plain text communication.
* WIFI_PROV_SECURITY_0 - It do not provide application level security, it involve simply plain text communication. - `scheme_event_handler`: Specify the handlers according to the chosen mode
- BLE:
- `WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM` - Used when the application doesn't need BT and BLE after provisioning is finished.
- `WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE` - Used when the application doesn't need BLE to be active after provisioning is finished.
- `WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT` - Used when the application doesn't need BT to be active after provisioning is finished.
* scheme_event_handler : specify the handlers according to the mode chosen - SoftAP:
* BLE : - `WIFI_PROV_EVENT_HANDLER_NONE`
- 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
- 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
- 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
* SoftAp : - `pop`: String used for authentication.
- WIFI_PROV_EVENT_HANDLER_NONE
* pop : It is the string that is used to provide the authentication. - `service_name`: Specify the service name for the device. If not specified, the default chosen name is `PROV_XXX`, where XXX represents the last 3 bytes of the MAC address.
* service_name : Specify service name for the device, if it is not specified then default chosen name is PROV_XXX where XXX are the last 3 bytes of the MAC address. - `service_key`: Specify the service key. If the chosen mode of provisioning is BLE, the `service_key` is always NULL.
* service_key : Specify service key, if chosen mode of provisioning is BLE then service_key is always NULL - `uuid`: Users can specify their own 128-bit UUID while provisioning using BLE. If not specified, the default value is:
* uuid : user can specify there own 128 bit UUID while provisioning using BLE, if not specified then default value taken is ```
- { 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, { 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02 }
0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02, } ```
# NOTE - `reset_provisioned`: Resets previously provisioned data before initializing. Using this prevents problem when the device automatically connects to previously connected WiFi and therefore cannot be found.
* If none of the parameters are specified in beginProvision then default provisioning takes place using SoftAP with **NOTE:** If none of the parameters are specified in `beginProvision`, default provisioning takes place using SoftAP with the following settings:
* scheme = WIFI_PROV_SCHEME_SOFTAP - `scheme = WIFI_PROV_SCHEME_SOFTAP`
* scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE - `scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE`
* security = WIFI_PROV_SECURITY_1 - `security = WIFI_PROV_SECURITY_1`
* pop = "abcd1234" - `pop = "abcd1234"`
* service_name = "PROV_XXX" - `service_name = "PROV_XXX"`
* service_key = NULL - `service_key = NULL`
* uuid = NULL - `uuid = NULL`
- `reset_provisioned = false`
# Log Output ## Flashing
* Enable debuger : [ Tools -> Core Debug Level -> Info ] This sketch takes up a lot of space for the app and may not be able to flash with default setting on some chips.
If you see Error like this: "Sketch too big"
In Arduino IDE go to: Tools > Partition scheme > chose anything that has more than 1.4MB APP for example `No OTA (2MB APP/2MB SPIFFS)`
# Provisioning Tools ## Log Output
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/provisioning/wifi_provisioning.html#provisioning-tools - To enable debugging: Go to Tools -> Core Debug Level -> Info.
# Example output ## Provisioning Tools
[Provisioning Tools](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/provisioning/wifi_provisioning.html#provisioning-tools)
## Provisioning using SoftAP ## Example Output
### Provisioning using SoftAP
``` ```
[I][WiFiProv.cpp:117] beginProvision(): Starting AP using SOFTAP [I][WiFiProv.cpp:117] beginProvision(): Starting AP using SOFTAP
service_name : PROV_XXX service_name: PROV_XXX
password : 123456789 password: 123456789
pop : abcd1234 pop: abcd1234
Provisioning started Provisioning started
Give Credentials of your access point using " Android app " Give Credentials of your access point using "Android app"
Received Wi-Fi credentials Received Wi-Fi credentials
SSID : GIONEE M2 SSID: GIONEE M2
Password : 123456789 Password: 123456789
Connected IP address : 192.168.43.120 Connected IP address: 192.168.43.120
Provisioning Successful Provisioning Successful
Provisioning Ends Provisioning Ends
``` ```
## Provisioning using BLE ### Provisioning using BLE
``` ```
[I][WiFiProv.cpp:115] beginProvision(): Starting AP using BLE [I][WiFiProv.cpp:115] beginProvision(): Starting AP using BLE
service_name : PROV_XXX service_name: PROV_XXX
pop : abcd1234 pop: abcd1234
Provisioning started Provisioning started
Give Credentials of your access point using " Android app " Give Credentials of your access point using "Android app"
Received Wi-Fi credentials Received Wi-Fi credentials
SSID : GIONEE M2 SSID: GIONEE M2
Password : 123456789 Password: 123456789
Connected IP address : 192.168.43.120 Connected IP address: 192.168.43.120
Provisioning Successful Provisioning Successful
Provisioning Ends Provisioning Ends
``` ```
## Credentials are available on device ### Credentials are available on the device
```
[I][WiFiProv.cpp:146] beginProvision(): Aleardy Provisioned, starting Wi-Fi STA
[I][WiFiProv.cpp:150] beginProvision(): SSID : Wce*****
[I][WiFiProv.cpp:152] beginProvision(): CONNECTING TO THE ACCESS POINT :
Connected IP address : 192.168.43.120
``` ```
[I][WiFiProv.cpp:146] beginProvision(): Already Provisioned, starting Wi-Fi STA
[I][WiFiProv.cpp:150] beginProvision(): SSID: Wce*****
[I][WiFiProv.cpp:152] beginProvision(): CONNECTING TO THE ACCESS POINT:
Connected IP address: 192.168.43.120
```
\ No newline at end of file
/*
Please read README.md file in this folder, or on the web:
https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFiProv/examples/WiFiProv
Note: This sketch takes up a lot of space for the app and may not be able to flash with default setting on some chips.
If you see Error like this: "Sketch too big"
In Arduino IDE go to: Tools > Partition scheme > chose anything that has more than 1.4MB APP
- for example "No OTA (2MB APP/2MB SPIFFS)"
*/
#include "WiFiProv.h" #include "WiFiProv.h"
#include "WiFi.h" #include "WiFi.h"
// #define USE_SOFT_AP // Uncomment if you want to enforce using Soft AP method instead of BLE
const char * pop = "abcd1234"; // Proof of possession - otherwise called a PIN - string provided by the device, entered by user in the phone app
const char * service_name = "PROV_123"; // Name of your device (the Espressif apps expects by default device name starting with "Prov_")
const char * service_key = NULL; // Password used for SofAP method (NULL = no password needed)
bool reset_provisioned = true; // When true the library will automatically delete previously provisioned data.
void SysProvEvent(arduino_event_t *sys_event) void SysProvEvent(arduino_event_t *sys_event)
{ {
switch (sys_event->event_id) { switch (sys_event->event_id) {
...@@ -11,9 +29,9 @@ void SysProvEvent(arduino_event_t *sys_event) ...@@ -11,9 +29,9 @@ void SysProvEvent(arduino_event_t *sys_event)
Serial.println("\nDisconnected. Connecting to the AP again... "); Serial.println("\nDisconnected. Connecting to the AP again... ");
break; break;
case ARDUINO_EVENT_PROV_START: case ARDUINO_EVENT_PROV_START:
Serial.println("\nProvisioning started\nGive Credentials of your access point using \" Android app \""); Serial.println("\nProvisioning started\nGive Credentials of your access point using smartphone app");
break; break;
case ARDUINO_EVENT_PROV_CRED_RECV: { case ARDUINO_EVENT_PROV_CRED_RECV: {
Serial.println("\nReceived Wi-Fi credentials"); Serial.println("\nReceived Wi-Fi credentials");
Serial.print("\tSSID : "); Serial.print("\tSSID : ");
Serial.println((const char *) sys_event->event_info.prov_cred_recv.ssid); Serial.println((const char *) sys_event->event_info.prov_cred_recv.ssid);
...@@ -21,12 +39,12 @@ void SysProvEvent(arduino_event_t *sys_event) ...@@ -21,12 +39,12 @@ void SysProvEvent(arduino_event_t *sys_event)
Serial.println((char const *) sys_event->event_info.prov_cred_recv.password); Serial.println((char const *) sys_event->event_info.prov_cred_recv.password);
break; break;
} }
case ARDUINO_EVENT_PROV_CRED_FAIL: { case ARDUINO_EVENT_PROV_CRED_FAIL: {
Serial.println("\nProvisioning failed!\nPlease reset to factory and retry provisioning\n"); Serial.println("\nProvisioning failed!\nPlease reset to factory and retry provisioning\n");
if(sys_event->event_info.prov_fail_reason == WIFI_PROV_STA_AUTH_ERROR) if(sys_event->event_info.prov_fail_reason == WIFI_PROV_STA_AUTH_ERROR)
Serial.println("\nWi-Fi AP password incorrect"); Serial.println("\nWi-Fi AP password incorrect");
else else
Serial.println("\nWi-Fi AP not found....Add API \" nvs_flash_erase() \" before beginProvision()"); Serial.println("\nWi-Fi AP not found....Add API \" nvs_flash_erase() \" before beginProvision()");
break; break;
} }
case ARDUINO_EVENT_PROV_CRED_SUCCESS: case ARDUINO_EVENT_PROV_CRED_SUCCESS:
...@@ -42,15 +60,26 @@ void SysProvEvent(arduino_event_t *sys_event) ...@@ -42,15 +60,26 @@ void SysProvEvent(arduino_event_t *sys_event)
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
//Sample uuid that user can pass during provisioning using BLE
/* uint8_t uuid[16] = {0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf,
0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02 };*/
WiFi.onEvent(SysProvEvent); WiFi.onEvent(SysProvEvent);
#if CONFIG_IDF_TARGET_ESP32 && CONFIG_BLUEDROID_ENABLED
WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, "abcd1234", "Prov_123"); #if CONFIG_IDF_TARGET_ESP32 && CONFIG_BLUEDROID_ENABLED && not USE_SOFT_AP
Serial.println("Begin Provisioning using BLE");
// Sample uuid that user can pass during provisioning using BLE
uint8_t uuid[16] = {0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf,
0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02 };
WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name, service_key, uuid, reset_provisioned);
#else #else
WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, "abcd1234", "Prov_123"); Serial.println("Begin Provisioning using Soft AP");
WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name, service_key);
#endif #endif
#if CONFIG_BLUEDROID_ENABLED && not USE_SOFT_AP
log_d("ble qr");
WiFiProv.printQR(service_name, pop, "ble");
#else
log_d("wifi qr");
WiFiProv.printQR(service_name, pop, "softap");
#endif
} }
void loop() { void loop() {
......
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
#include <esp_wifi.h> #include <esp_wifi.h>
#include <esp_event.h> #include <esp_event.h>
#include <esp32-hal.h> #include <esp32-hal.h>
#if __has_include("qrcode.h")
#include "qrcode.h"
#endif
#include <nvs_flash.h> #include <nvs_flash.h>
#if CONFIG_BLUEDROID_ENABLED #if CONFIG_BLUEDROID_ENABLED
...@@ -66,7 +69,7 @@ static void get_device_service_name(prov_scheme_t prov_scheme, char *service_nam ...@@ -66,7 +69,7 @@ static void get_device_service_name(prov_scheme_t prov_scheme, char *service_nam
#endif #endif
} }
void WiFiProvClass :: beginProvision(prov_scheme_t prov_scheme, scheme_handler_t scheme_handler, wifi_prov_security_t security, const char * pop, const char *service_name, const char *service_key, uint8_t * uuid) void WiFiProvClass :: beginProvision(prov_scheme_t prov_scheme, scheme_handler_t scheme_handler, wifi_prov_security_t security, const char * pop, const char *service_name, const char *service_key, uint8_t * uuid, bool reset_provisioned)
{ {
bool provisioned = false; bool provisioned = false;
static char service_name_temp[32]; static char service_name_temp[32];
...@@ -107,10 +110,13 @@ void WiFiProvClass :: beginProvision(prov_scheme_t prov_scheme, scheme_handler_t ...@@ -107,10 +110,13 @@ void WiFiProvClass :: beginProvision(prov_scheme_t prov_scheme, scheme_handler_t
log_e("wifi_prov_mgr_init failed!"); log_e("wifi_prov_mgr_init failed!");
return; return;
} }
if(wifi_prov_mgr_is_provisioned(&provisioned) != ESP_OK){ if(reset_provisioned){
log_e("wifi_prov_mgr_is_provisioned failed!"); log_i("Resetting provisioned data.");
wifi_prov_mgr_deinit(); wifi_prov_mgr_reset_provisioning();
return; }else if(wifi_prov_mgr_is_provisioned(&provisioned) != ESP_OK){
log_e("wifi_prov_mgr_is_provisioned failed!");
wifi_prov_mgr_deinit();
return;
} }
if(provisioned == false) { if(provisioned == false) {
#if CONFIG_BLUEDROID_ENABLED #if CONFIG_BLUEDROID_ENABLED
...@@ -158,4 +164,30 @@ void WiFiProvClass :: beginProvision(prov_scheme_t prov_scheme, scheme_handler_t ...@@ -158,4 +164,30 @@ void WiFiProvClass :: beginProvision(prov_scheme_t prov_scheme, scheme_handler_t
} }
} }
// Copied from IDF example
void WiFiProvClass :: printQR(const char *name, const char *pop, const char *transport){
if (!name || !transport) {
log_w("Cannot generate QR code payload. Data missing.");
return;
}
char payload[150] = {0};
if (pop) {
snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \
",\"pop\":\"%s\",\"transport\":\"%s\"}",
"v1", name, pop, transport);
} else {
snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \
",\"transport\":\"%s\"}",
"v1", name, transport);
}
#if __has_include("qrcode.h")
log_i("Scan this QR code from the provisioning application for Provisioning.");
esp_qrcode_config_t cfg = ESP_QRCODE_CONFIG_DEFAULT();
esp_qrcode_generate(&cfg, payload);
#else
log_i("If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s", "https://espressif.github.io/esp-jumpstart/qrcode.html", payload);
log_i("If you are using Arduino as IDF component, install ESP Rainmaker:\nhttps://github.com/espressif/esp-rainmaker");
#endif
}
WiFiProvClass WiFiProv; WiFiProvClass WiFiProv;
...@@ -47,7 +47,9 @@ class WiFiProvClass ...@@ -47,7 +47,9 @@ class WiFiProvClass
public: public:
void beginProvision(prov_scheme_t prov_scheme = WIFI_PROV_SCHEME_SOFTAP, scheme_handler_t scheme_handler = WIFI_PROV_SCHEME_HANDLER_NONE, void beginProvision(prov_scheme_t prov_scheme = WIFI_PROV_SCHEME_SOFTAP, scheme_handler_t scheme_handler = WIFI_PROV_SCHEME_HANDLER_NONE,
wifi_prov_security_t security = WIFI_PROV_SECURITY_1, const char * pop = "abcd1234", const char * service_name = NULL, const char * service_key = NULL, uint8_t *uuid = NULL); wifi_prov_security_t security = WIFI_PROV_SECURITY_1, const char * pop = "abcd1234", const char * service_name = NULL,
const char * service_key = NULL, uint8_t *uuid = NULL, bool reset_provisioned = false);
void printQR(const char *name, const char *pop, const char *transport);
}; };
extern WiFiProvClass WiFiProv; extern WiFiProvClass WiFiProv;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment