diff --git a/libraries/WiFiProv/examples/WiFiProv/README.md b/libraries/WiFiProv/examples/WiFiProv/README.md index bae3eadf297..70da0052c3d 100644 --- a/libraries/WiFiProv/examples/WiFiProv/README.md +++ b/libraries/WiFiProv/examples/WiFiProv/README.md @@ -1,116 +1,120 @@ # 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 -* function pointer : choose the mode of transfer - * provSchemeBLE - Using BLE - * provSchemeSoftAP - Using SoftAP - -* security : choose 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. +- Function pointer: Choose the mode of transfer + - `provSchemeBLE` - Using BLE + - `provSchemeSoftAP` - Using SoftAP + +- `security`: Choose the security type + - `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 - * BLE : - - 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: + - `WIFI_PROV_EVENT_HANDLER_NONE` - * SoftAp : - - WIFI_PROV_EVENT_HANDLER_NONE +- `pop`: String used for authentication. -* 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, - 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02, } +``` +{ 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, 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 - * scheme = WIFI_PROV_SCHEME_SOFTAP - * scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE - * security = WIFI_PROV_SECURITY_1 - * pop = "abcd1234" - * service_name = "PROV_XXX" - * service_key = NULL - * uuid = NULL +**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_event_handler = WIFI_PROV_EVENT_HANDLER_NONE` +- `security = WIFI_PROV_SECURITY_1` +- `pop = "abcd1234"` +- `service_name = "PROV_XXX"` +- `service_key = NULL` +- `uuid = NULL` +- `reset_provisioned = false` -# Log Output -* Enable debuger : [ Tools -> Core Debug Level -> Info ] +## Flashing +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 -https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/provisioning/wifi_provisioning.html#provisioning-tools +## Log Output +- 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 - service_name : PROV_XXX - password : 123456789 - pop : abcd1234 + service_name: PROV_XXX + password: 123456789 + pop: abcd1234 Provisioning started -Give Credentials of your access point using " Android app " +Give Credentials of your access point using "Android app" Received Wi-Fi credentials - SSID : GIONEE M2 - Password : 123456789 + SSID: GIONEE M2 + Password: 123456789 -Connected IP address : 192.168.43.120 +Connected IP address: 192.168.43.120 Provisioning Successful Provisioning Ends - ``` -## Provisioning using BLE - +### Provisioning using BLE ``` [I][WiFiProv.cpp:115] beginProvision(): Starting AP using BLE - service_name : PROV_XXX - pop : abcd1234 + service_name: PROV_XXX + pop: abcd1234 Provisioning started -Give Credentials of your access point using " Android app " +Give Credentials of your access point using "Android app" Received Wi-Fi credentials - SSID : GIONEE M2 - Password : 123456789 + SSID: GIONEE M2 + Password: 123456789 -Connected IP address : 192.168.43.120 +Connected IP address: 192.168.43.120 Provisioning Successful Provisioning Ends - ``` -## Credentials are available on 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 +### Credentials are available on the device ``` +[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 diff --git a/libraries/WiFiProv/examples/WiFiProv/WiFiProv.ino b/libraries/WiFiProv/examples/WiFiProv/WiFiProv.ino index 9d6de5f00f3..28c470f7241 100644 --- a/libraries/WiFiProv/examples/WiFiProv/WiFiProv.ino +++ b/libraries/WiFiProv/examples/WiFiProv/WiFiProv.ino @@ -1,5 +1,23 @@ +/* +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 "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) { switch (sys_event->event_id) { @@ -11,9 +29,9 @@ void SysProvEvent(arduino_event_t *sys_event) Serial.println("\nDisconnected. Connecting to the AP again... "); break; 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; - case ARDUINO_EVENT_PROV_CRED_RECV: { + case ARDUINO_EVENT_PROV_CRED_RECV: { Serial.println("\nReceived Wi-Fi credentials"); Serial.print("\tSSID : "); Serial.println((const char *) sys_event->event_info.prov_cred_recv.ssid); @@ -21,12 +39,12 @@ void SysProvEvent(arduino_event_t *sys_event) Serial.println((char const *) sys_event->event_info.prov_cred_recv.password); 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"); - 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"); 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; } case ARDUINO_EVENT_PROV_CRED_SUCCESS: @@ -42,15 +60,26 @@ void SysProvEvent(arduino_event_t *sys_event) void setup() { 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); -#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 - 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 + + #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() { diff --git a/libraries/WiFiProv/src/WiFiProv.cpp b/libraries/WiFiProv/src/WiFiProv.cpp index d5a2cb0e4c3..8acb684993b 100644 --- a/libraries/WiFiProv/src/WiFiProv.cpp +++ b/libraries/WiFiProv/src/WiFiProv.cpp @@ -26,6 +26,9 @@ #include #include #include +#if __has_include("qrcode.h") + #include "qrcode.h" +#endif #include #if CONFIG_BLUEDROID_ENABLED @@ -66,7 +69,7 @@ static void get_device_service_name(prov_scheme_t prov_scheme, char *service_nam #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; static char service_name_temp[32]; @@ -107,10 +110,13 @@ void WiFiProvClass :: beginProvision(prov_scheme_t prov_scheme, scheme_handler_t log_e("wifi_prov_mgr_init failed!"); return; } - if(wifi_prov_mgr_is_provisioned(&provisioned) != ESP_OK){ - log_e("wifi_prov_mgr_is_provisioned failed!"); - wifi_prov_mgr_deinit(); - return; + if(reset_provisioned){ + log_i("Resetting provisioned data."); + wifi_prov_mgr_reset_provisioning(); + }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 CONFIG_BLUEDROID_ENABLED @@ -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; diff --git a/libraries/WiFiProv/src/WiFiProv.h b/libraries/WiFiProv/src/WiFiProv.h index bbcab41a6f8..57342668770 100644 --- a/libraries/WiFiProv/src/WiFiProv.h +++ b/libraries/WiFiProv/src/WiFiProv.h @@ -47,7 +47,9 @@ class WiFiProvClass public: 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;