Merge branch 'feature/prov_example_restructure' into 'master'

wifi_provisioning: Example restructuring

See merge request espressif/esp-idf!6901
This commit is contained in:
Mahavir Jain 2020-03-16 15:38:11 +08:00
commit 88fd09111c
73 changed files with 208 additions and 29 deletions

View file

@ -162,4 +162,4 @@ exclude =
components/wifi_provisioning/python/wifi_config_pb2.py,
components/wifi_provisioning/python/wifi_constants_pb2.py,
components/esp_local_ctrl/python/esp_local_ctrl_pb2.py,
examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py,
examples/provisioning/legacy/custom_config/components/custom_provisioning/python/custom_config_pb2.py,

View file

@ -19,7 +19,7 @@ Note that the client still needs to establish session (only for protocomm_securi
Transport Example (SoftAP + HTTP) with Security 1
-------------------------------------------------
For complete example see :example:`provisioning/softap_prov`
For complete example see :example:`provisioning/legacy/softap_prov`
.. highlight:: c
@ -113,7 +113,7 @@ For complete example see :example:`provisioning/softap_prov`
Transport Example (BLE) with Security 0
---------------------------------------
For complete example see :example:`provisioning/ble_prov`
For complete example see :example:`provisioning/legacy/ble_prov`
.. highlight:: c

View file

@ -144,15 +144,21 @@ Sample Code
>>>>>>>>>>>
Please refer to :doc:`protocomm` and :doc:`wifi_provisioning` for API guides and code snippets on example usage.
Various use case implementations can be found as examples under :example:`provisioning`.
Application implementation can be found as an example under :example:`provisioning`.
Provisioning Tools
>>>>>>>>>>>>>>>>>>
Provisioning applications are available for various platforms, along with source code:
* Android : `esp-idf-provisioning-android <https://github.com/espressif/esp-idf-provisioning-android>`_
* iOS : `esp-idf-provisioning-ios <https://github.com/espressif/esp-idf-provisioning-ios>`_
* Android:
* `BLE Provisioning app on Play Store <https://play.google.com/store/apps/details?id=com.espressif.provble>`_.
* `SoftAP Provisioning app on Play Store <https://play.google.com/store/apps/details?id=com.espressif.provsoftap>`_.
* Source code on GitHub: `esp-idf-provisioning-android <https://github.com/espressif/esp-idf-provisioning-android>`_.
* iOS:
* `BLE Provisioning app on app store <https://apps.apple.com/in/app/esp-ble-provisioning/id1473590141>`_.
* `SoftAP Provisioning app on app Store <https://apps.apple.com/in/app/esp-softap-provisioning/id1474040630>`_.
* Source code on GitHub: `esp-idf-provisioning-ios <https://github.com/espressif/esp-idf-provisioning-ios>`_.
* Linux/MacOS/Windows : :idf:`tools/esp_prov` (a python based command line tool for provisioning)
The phone applications offer simple UI and thus more user centric, while the command line application is useful as a debugging tool for developers.

View file

@ -274,7 +274,25 @@ The customized behavior is useful for applications which want the provisioning s
Application Examples
--------------------
For complete example implementation see :example:`provisioning/manager`
For complete example implementation see :example:`provisioning/wifi_prov_mgr`
Provisioning Tools
--------------------
Provisioning applications are available for various platforms, along with source code:
* Android:
* `BLE Provisioning app on Play Store <https://play.google.com/store/apps/details?id=com.espressif.provble>`_.
* `SoftAP Provisioning app on Play Store <https://play.google.com/store/apps/details?id=com.espressif.provsoftap>`_.
* Source code on GitHub: `esp-idf-provisioning-android <https://github.com/espressif/esp-idf-provisioning-android>`_.
* iOS:
* `BLE Provisioning app on app store <https://apps.apple.com/in/app/esp-ble-provisioning/id1473590141>`_.
* `SoftAP Provisioning app on app Store <https://apps.apple.com/in/app/esp-softap-provisioning/id1474040630>`_.
* Source code on GitHub: `esp-idf-provisioning-ios <https://github.com/espressif/esp-idf-provisioning-ios>`_.
* Linux/MacOS/Windows : :idf:`tools/esp_prov` (a python based command line tool for provisioning)
The phone applications offer simple UI and thus more user centric, while the command line application is useful as a debugging tool for developers.
API Reference
-------------

View file

@ -1,6 +1,25 @@
# Provisioning Application Examples
These consist of the following examples :
This primarily consists of a single unified example wifi_prov_mgr
* wifi_prov_mgr
Abstracts out most of the complexity of Wi-Fi provisioning and allows easy switching between the SoftAP (using HTTP) and BLE transports. It also demonstrates how applications can register and use additional custom data endpoints.
Provisioning applications are available for various platforms:
* Android:
- [BLE Provisioning app on Play Store](https://play.google.com/store/apps/details?id=com.espressif.provble).
- [SoftAP Provisioning app on Play Store](https://play.google.com/store/apps/details?id=com.espressif.provsoftap).
- Source code on GitHub: [esp-idf-provisioning-android](https://github.com/espressif/esp-idf-provisioning-android).
* iOS:
- [BLE Provisioning app on app store](https://apps.apple.com/in/app/esp-ble-provisioning/id1473590141)
- [SoftAP Provisioning app on app Store](https://apps.apple.com/in/app/esp-softap-provisioning/id1474040630)
- Source code on GitHub: [esp-idf-provisioning-ios](https://github.com/espressif/esp-idf-provisioning-ios)
* For all other platforms a python based command line tool is provided under "$IDF_PATH/tools/esp_prov"
## Legacy Examples
The legacy examples require own implementation of provisioning functions and handlers. The Wi-Fi provisioning component abstracts out most of this complexity and provides a simpler interface and so, that is recommended for use. However, if you want to use lower level provisioning and protocomm APIs, you can check the these examples under legacy/ folder:
* softap_prov
Provisioning involves Wi-Fi station configuration via an HTTP server running on the device, which is initially configured to be in SoftAP mode. After provisioning, device runs in Wi-Fi station mode only and connects to the AP whose credentials were provided during provisioning.
@ -14,10 +33,4 @@ These consist of the following examples :
* custom_config
Similar to softap_prov examples, but allows for configuration of custom (device-local) information during provisioning. This is intended as an example for implementing custom provisioning schemes.
Provisioning applications are available for various platforms:
* For Android, a provisioning application along with source code is available on GitHub : [esp-idf-provisioning-android](https://github.com/espressif/esp-idf-provisioning-android)
* For iOS, a provisioning application along with source code is available on GitHub : [esp-idf-provisioning-ios](https://github.com/espressif/esp-idf-provisioning-ios)
* For all other platforms a python based command line tool is provided under "$IDF_PATH/tools/esp_prov"
Refer to the README.md files in each example directory for more information.

View file

@ -1,4 +1,6 @@
# BLE based Provisioning Example
# BLE based Provisioning Example (Legacy)
> Note: It is recommended to use the new `wifi_prov_mgr` example which is based on the simpler `wifi_provisioning` APIs. Check this example only if you wish to use lower level provisioning and protocomm APIs and want more control over the handlers.
(See the README.md file in the upper level 'examples' directory for more information about examples.)

View file

@ -29,7 +29,7 @@ esp_prov.config_throw_except = True
@ttfw_idf.idf_example_test(env_tag="Example_WIFI_BT")
def test_examples_provisioning_ble(env, extra_data):
# Acquire DUT
dut1 = env.get_dut("ble_prov", "examples/provisioning/ble_prov", dut_class=ttfw_idf.ESP32DUT)
dut1 = env.get_dut("ble_prov", "examples/provisioning/legacy/ble_prov", dut_class=ttfw_idf.ESP32DUT)
# Get binary file
binary_file = os.path.join(dut1.app.binary_path, "ble_prov.bin")

View file

@ -2,6 +2,5 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(SUPPORTED_TARGETS esp32)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(console_prov)

View file

@ -1,4 +1,6 @@
# Console based Provisioning Example
# Console based Provisioning Example (Legacy)
> Check this example only if you wish to use console based provisioning. For any real applications, it is recommended to use the new `wifi_prov_mgr` example which is based on the simpler `wifi_provisioning` APIs.
(See the README.md file in the upper level 'examples' directory for more information about examples.)

View file

@ -2,6 +2,5 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(SUPPORTED_TARGETS esp32)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(custom_config)

View file

@ -1,4 +1,6 @@
# SoftAP + HTTPD based Provisioning Example featuring Custom configuration
# SoftAP + HTTPD based Provisioning Example featuring Custom configuration (Legacy)
> Note: It is recommended to use the new `wifi_prov_mgr` example which is based on the simpler `wifi_provisioning` APIs. Check this example only if you wish to use lower level provisioning and protocomm APIs and want more control over the handlers.
(See the README.md file in the upper level 'examples' directory for more information about examples.)

View file

@ -2,6 +2,5 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(SUPPORTED_TARGETS esp32)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(softap_prov)

View file

@ -1,4 +1,6 @@
# SoftAP + HTTPD based Provisioning Example
# SoftAP + HTTPD based Provisioning Example (Legacy)
> Note: It is recommended to use the new `wifi_prov_mgr` example which is based on the simpler `wifi_provisioning` APIs. Check this example only if you wish to use lower level provisioning and protocomm APIs and want more control over the handlers.
(See the README.md file in the upper level 'examples' directory for more information about examples.)

View file

@ -30,7 +30,7 @@ esp_prov.config_throw_except = True
@ttfw_idf.idf_example_test(env_tag="Example_WIFI_BT")
def test_examples_provisioning_softap(env, extra_data):
# Acquire DUT
dut1 = env.get_dut("softap_prov", "examples/provisioning/softap_prov", dut_class=ttfw_idf.ESP32DUT)
dut1 = env.get_dut("softap_prov", "examples/provisioning/legacy/softap_prov", dut_class=ttfw_idf.ESP32DUT)
# Get binary file
binary_file = os.path.join(dut1.app.binary_path, "softap_prov.bin")

View file

@ -2,6 +2,5 @@
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(SUPPORTED_TARGETS esp32)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(wifi_prov_mgr)

View file

@ -4,7 +4,9 @@
`wifi_prov_mgr` example demonstrates the usage of `wifi_provisioning` manager component for building a provisioning application.
For this example BLE is chosen as the 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).
For this example, BLE is chosen as the default mode of transport, over which the provisioning related communication is to take place. NimBLE has been configured as the default host, but you can also switch to Bluedroid using menuconfig -> Components -> Bluetooth -> Bluetooth Host.
> Note: Since ESP32-S2 does not support BLE, the SoftAP will be the default mode of transport in that case. Even for ESP32, you can change to SoftAP transport from menuconfig.
In the provisioning process the device is configured as a Wi-Fi station with specified credentials. Once configured, the device will retain the Wi-Fi configuration, until a flash erase is performed.
@ -22,7 +24,7 @@ This example can be used, as it is, for adding a provisioning service to any app
### Hardware Required
Example should be able to run on any commonly available ESP32 development board.
Example should be able to run on any commonly available ESP32/ESP32-S2 development board.
### Application Required
@ -49,7 +51,7 @@ There are various applications, specific to Windows and macOS platform which can
```
idf.py menuconfig
```
* Set the BLE/Soft AP transport under "Example Configuration" options. ESP32-S2 will have only SoftAP option.
* Set serial port under Serial Flasher Options.
### Build and Flash
@ -157,6 +159,26 @@ Enter passphrase for MyHomeWiFiAP :
==== Provisioning was successful ====
```
### Sending Custom Data
The provisioning manager allows applications to send some custom data during provisioning, which may be
required for some other operations like connecting to some cloud service. This is achieved by creating
and registering additional endpoints using the below APIs
```
wifi_prov_mgr_endpoint_create();
wifi_prov_mgr_endpoint_register();
```
In this particular example, we have added an endpoint named "custom-data" which can be tested
by passing the `--custom_data <MyCustomData>` option to the esp\_prov tool. Following output is
expected on success:
```
==== Sending Custom data to esp32 ====
CustomData response: SUCCESS
```
## Troubleshooting
### Provisioning failed

View file

@ -0,0 +1,22 @@
menu "Example Configuration"
choice EXAMPLE_PROV_TRANSPORT
bool "Provisioning Transport"
default EXAMPLE_PROV_TRANSPORT_BLE
help
Wi-Fi provisioning component offers both, SoftAP and BLE transports. Choose any one.
config EXAMPLE_PROV_TRANSPORT_BLE
bool "BLE"
select BT_ENABLED
depends on IDF_TARGET_ESP32
config EXAMPLE_PROV_TRANSPORT_SOFTAP
bool "Soft AP"
endchoice
config EXAMPLE_PROV_TRANSPORT
int
default 1 if EXAMPLE_PROV_TRANSPORT_BLE
default 2 if EXAMPLE_PROV_TRANSPORT_SOFTAP
endmenu

View file

@ -20,8 +20,14 @@
#include <nvs_flash.h>
#include <wifi_provisioning/manager.h>
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
#include <wifi_provisioning/scheme_ble.h>
#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_BLE */
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP
#include <wifi_provisioning/scheme_softap.h>
#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP */
static const char *TAG = "app";
@ -93,6 +99,27 @@ static void get_device_service_name(char *service_name, size_t max)
ssid_prefix, eth_mac[3], eth_mac[4], eth_mac[5]);
}
/* Handler for the optional provisioning endpoint registered by the application.
* The data format can be chosen by applications. Here, we are using plain ascii text.
* Applications can choose to use other formats like protobuf, JSON, XML, etc.
*/
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; /* +1 for NULL terminating byte */
return ESP_OK;
}
void app_main(void)
{
/* Initialize NVS partition */
@ -120,6 +147,9 @@ void app_main(void)
/* Initialize Wi-Fi including netif with default config */
esp_netif_create_default_wifi_sta();
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP
esp_netif_create_default_wifi_ap();
#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP */
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
@ -127,7 +157,12 @@ void app_main(void)
wifi_prov_mgr_config_t config = {
/* What is the Provisioning Scheme that we want ?
* wifi_prov_scheme_softap or wifi_prov_scheme_ble */
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
.scheme = wifi_prov_scheme_ble,
#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_BLE */
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP
.scheme = wifi_prov_scheme_softap,
#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP */
/* Any default scheme specific event handler that you would
* like to choose. Since our example application requires
@ -137,7 +172,12 @@ void app_main(void)
* appropriate scheme specific event handler allows the manager
* to take care of this automatically. This can be set to
* WIFI_PROV_EVENT_HANDLER_NONE when using wifi_prov_scheme_softap*/
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
.scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM
#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_BLE */
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP
.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE
#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP */
};
/* Initialize provisioning manager with the
@ -181,6 +221,7 @@ void app_main(void)
*/
const char *service_key = NULL;
#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE
/* This step is only useful when scheme is wifi_prov_scheme_ble. This will
* set a custom 128 bit UUID which will be included in the BLE advertisement
* and will correspond to the primary GATT service that provides provisioning
@ -197,10 +238,23 @@ void app_main(void)
0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12
};
wifi_prov_scheme_ble_set_service_uuid(custom_service_uuid);
#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_BLE */
/* An optional endpoint that applications can create if they expect to
* get some additional custom data during provisioning workflow.
* The endpoint name can be anything of your choice.
* This call must be made before starting the provisioning.
*/
wifi_prov_mgr_endpoint_create("custom-data");
/* Start provisioning service */
ESP_ERROR_CHECK(wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key));
/* The handler for the optional endpoint created above.
* This call must be made after starting the provisioning, and only if the endpoint
* has already been created above.
*/
wifi_prov_mgr_endpoint_register("custom-data", custom_prov_data_handler, NULL);
/* Uncomment the following to wait for the provisioning to finish and then release
* the resources of the manager. Since in this case de-initialization is triggered
* by the default event loop handler, we don't need to call the following */

View file

@ -29,7 +29,7 @@ esp_prov.config_throw_except = True
@ttfw_idf.idf_example_test(env_tag="Example_WIFI_BT")
def test_examples_wifi_prov_mgr(env, extra_data):
# Acquire DUT
dut1 = env.get_dut("wifi_prov_mgr", "examples/provisioning/manager", dut_class=ttfw_idf.ESP32DUT)
dut1 = env.get_dut("wifi_prov_mgr", "examples/provisioning/wifi_prov_mgr", dut_class=ttfw_idf.ESP32DUT)
# Get binary file
binary_file = os.path.join(dut1.app.binary_path, "wifi_prov_mgr.bin")
@ -78,6 +78,10 @@ def test_examples_wifi_prov_mgr(env, extra_data):
if not esp_prov.establish_session(transport, security):
raise RuntimeError("Failed to start session")
print("Sending Custom Data")
if not esp_prov.custom_data(transport, security, "My Custom Data"):
raise RuntimeError("Failed to send custom data")
print("Sending Wifi credential to DUT")
if not esp_prov.send_wifi_config(transport, security, ap_ssid, ap_password):
raise RuntimeError("Failed to send Wi-Fi config")

View file

@ -186,6 +186,16 @@ def custom_config(tp, sec, custom_info, custom_ver):
return None
def custom_data(tp, sec, custom_data):
try:
message = prov.custom_data_request(sec, custom_data)
response = tp.send_data('custom-data', message)
return (prov.custom_data_response(sec, response) == 0)
except RuntimeError as e:
on_except(e)
return None
def scan_wifi_APs(sel_transport, tp, sec):
APs = []
group_channels = 0
@ -328,6 +338,11 @@ if __name__ == '__main__':
'If Wi-Fi scanning is supported by the provisioning service, this need not '
'be specified'))
parser.add_argument("--custom_data", dest='custom_data', type=str, default='',
help=desc_format(
'This is an optional parameter, only intended for use with '
'"examples/provisioning/wifi_prov_mgr_custom_data"'))
parser.add_argument("--custom_config", action="store_true",
help=desc_format(
'This is an optional parameter, only intended for use with '
@ -394,6 +409,13 @@ if __name__ == '__main__':
exit(5)
print("==== Custom config sent successfully ====")
if args.custom_data != '':
print("\n==== Sending Custom data to esp32 ====")
if not custom_data(obj_transport, obj_security, args.custom_data):
print("---- Error in custom data ----")
exit(5)
print("==== Custom data sent successfully ====")
if args.ssid == '':
if not has_capability(obj_transport, 'wifi_scan'):
print("---- Wi-Fi Scan List is not supported by provisioning service ----")

View file

@ -41,4 +41,4 @@ wifi_scan_pb2 = _load_source("wifi_scan_pb2", idf_path + "/components/
# custom_provisioning component related python files generated from .proto files
custom_config_pb2 = _load_source("custom_config_pb2", idf_path +
"/examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py")
"/examples/provisioning/legacy/custom_config/components/custom_provisioning/python/custom_config_pb2.py")

View file

@ -44,3 +44,17 @@ def custom_config_response(security_ctx, response_data):
cmd_resp.ParseFromString(decrypt)
print_verbose(security_ctx, "CustomConfig status " + str(cmd_resp.status))
return cmd_resp.status
def custom_data_request(security_ctx, data):
# Encrypt the custom data
enc_cmd = security_ctx.encrypt_data(data)
print_verbose(security_ctx, "Client -> Device (CustomData cmd) " + utils.str_to_hexstr(enc_cmd))
return enc_cmd
def custom_data_response(security_ctx, response_data):
# Decrypt response packet
decrypt = security_ctx.decrypt_data(tobytes(response_data))
print("CustomData response: " + str(decrypt))
return 0