# Wi-Fi Provisioning

[中文]

## Overview

This component provides APIs that control the Wi-Fi provisioning service for receiving and configuring Wi-Fi credentials over SoftAP or Bluetooth LE transport via secure Protocol Communication sessions. The set of `wifi_prov_mgr_` APIs help quickly implement a provisioning service that has necessary features with minimal amount of code and sufficient flexibility.

### Initialization

`wifi_prov_mgr_init()` is called to configure and initialize the provisioning manager, and thus must be called prior to invoking any other `wifi_prov_mgr_` APIs. Note that the manager relies on other components of ESP-IDF, namely NVS, TCP/IP, Event Loop and Wi-Fi, and optionally mDNS, hence these components must be initialized beforehand. The manager can be de-initialized at any moment by making a call to `wifi_prov_mgr_deinit()`.

>     wifi_prov_mgr_config_t config = {
>         .scheme = wifi_prov_scheme_ble,
>         .scheme_event_handler = WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM
>     };

>     ESP_ERROR_CHECK( wifi_prov_mgr_init(config) );

The configuration structure `wifi_prov_mgr_config_t` has a few fields to specify the desired behavior of the manager:

> - `wifi_prov_mgr_config_t::scheme` - This is used to specify the provisioning scheme. Each scheme corresponds to one of the modes of transport supported by protocomm. Hence, support the following options:

>   > - `wifi_prov_scheme_ble` - Bluetooth LE transport and GATT Server for handling the provisioning commands.

>   > - `wifi_prov_scheme_softap` - Wi-Fi SoftAP transport and HTTP Server for handling the provisioning commands.

>   > - `wifi_prov_scheme_console` - Serial transport and console for handling the provisioning commands.

> - `wifi_prov_mgr_config_t::scheme_event_handler`: An event handler defined along with the scheme. Choosing the appropriate scheme-specific event handler allows the manager to take care of certain matters automatically. Presently, this option is not used for either the SoftAP or Console-based provisioning, but is very convenient for Bluetooth LE. To understand how, we must recall that Bluetooth requires a substantial amount of memory to function, and once the provisioning is finished, the main application may want to reclaim back this memory (or part of it) if it needs to use either Bluetooth LE or classic Bluetooth. Also, upon every future reboot of a provisioned device, this reclamation of memory needs to be performed again. To reduce this complication in using `wifi_prov_scheme_ble`, the scheme-specific handlers have been defined, and depending upon the chosen handler, the Bluetooth LE/classic Bluetooth/BTDM memory is freed automatically when the provisioning manager is de-initialized. The available options are:

>   > - `WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM` - Free both classic Bluetooth and Bluetooth LE/BTDM memory. Used when the main application does not require Bluetooth at all.

>   > - `WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE` - Free only Bluetooth LE memory. Used when main application requires classic Bluetooth.

>   > - `WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT` - Free only classic Bluetooth. Used when main application requires Bluetooth LE. In this case freeing happens right when the manager is initialized.

>   > - `WIFI_PROV_EVENT_HANDLER_NONE` - Do not use any scheme specific handler. Used when the provisioning scheme is not Bluetooth LE, i.e., using SoftAP or Console, or when main application wants to handle the memory reclaiming on its own, or needs both Bluetooth LE and classic Bluetooth to function.

> - `wifi_prov_mgr_config_t::app_event_handler` (Deprecated) - It is now recommended to catch `WIFI_PROV_EVENT` that is emitted to the default event loop handler. See definition of `wifi_prov_cb_event_t` for the list of events that are generated by the provisioning service. Here is an excerpt showing some of the provisioning events:

>     static void event_handler(void* arg, esp_event_base_t event_base,
>                               int 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");
>                     break;
>                 }
>                 case WIFI_PROV_CRED_SUCCESS:
>                     ESP_LOGI(TAG, "Provisioning successful");
>                     break;
>                 case WIFI_PROV_END:
>                     /* De-initialize manager once provisioning is finished */
>                     wifi_prov_mgr_deinit();
>                     break;
>                 default:
>                     break;
>             }
>         }
>     }

The manager can be de-initialized at any moment by making a call to `wifi_prov_mgr_deinit()`.

### Check the Provisioning State

Whether the device is provisioned or not can be checked at runtime by calling `wifi_prov_mgr_is_provisioned()`. This internally checks if the Wi-Fi credentials are stored in NVS.

Note that presently the manager does not have its own NVS namespace for storage of Wi-Fi credentials, instead it relies on the `esp_wifi_` APIs to set and get the credentials stored in NVS from the default location.

If the provisioning state needs to be reset, any of the following approaches may be taken:

> - The associated part of NVS partition has to be erased manually

> - The main application must implement some logic to call `esp_wifi_` APIs for erasing the credentials at runtime

> - The main application must implement some logic to force start the provisioning irrespective of the provisioning state

>     bool provisioned = false;
>     ESP_ERROR_CHECK( wifi_prov_mgr_is_provisioned(&provisioned) );

### Start the Provisioning Service

At the time of starting provisioning we need to specify a service name and the corresponding key, that is to say:

> - A Wi-Fi SoftAP SSID and a passphrase, respectively, when the scheme is `wifi_prov_scheme_softap`.

> - Bluetooth LE device name with the service key ignored when the scheme is `wifi_prov_scheme_ble`.

Also, since internally the manager uses `protocomm`, we have the option of choosing one of the security features provided by it:

> - Security 1 is secure communication which consists of a prior handshake involving X25519 key exchange along with authentication using a proof of possession `pop`, followed by AES-CTR for encryption or decryption of subsequent messages.

> - Security 0 is simply plain text communication. In this case the `pop` is simply ignored.

See Unified Provisioning for details about the security features.

>     const char *service_name = "my_device";
>     const char *service_key  = "password";

>     wifi_prov_security_t security = WIFI_PROV_SECURITY_1;
>     const char *pop = "abcd1234";

>     ESP_ERROR_CHECK( wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key) );

The provisioning service automatically finishes only if it receives valid Wi-Fi AP credentials followed by successful connection of device to the AP with IP obtained. Regardless of that, the provisioning service can be stopped at any moment by making a call to `wifi_prov_mgr_stop_provisioning()`.

Note

If the device fails to connect with the provided credentials, it does not accept new credentials anymore, but the provisioning service keeps on running, only to convey failure to the client, until the device is restarted. Upon restart, the provisioning state turns out to be true this time, as credentials are found in NVS, but the device does fail again to connect with those same credentials, unless an AP with the matching credentials somehow does become available. This situation can be fixed by resetting the credentials in NVS or force starting the provisioning service. This has been explained above in Check the Provisioning State.

### Waiting for Completion

Typically, the main application waits for the provisioning to finish, then de-initializes the manager to free up resources, and finally starts executing its own logic.

There are two ways for making this possible. The simpler way is to use a blocking call to `wifi_prov_mgr_wait()`.

>     // Start provisioning service
>     ESP_ERROR_CHECK( wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key) );

>     // Wait for service to complete
>     wifi_prov_mgr_wait();

>     // Finally de-initialize the manager
>     wifi_prov_mgr_deinit();

The other way is to use the default event loop handler to catch `WIFI_PROV_EVENT` and call `wifi_prov_mgr_deinit()` when event ID is `WIFI_PROV_END`:

>     static void event_handler(void* arg, esp_event_base_t event_base,
>                               int event_id, void* event_data)
>     {
>         if (event_base == WIFI_PROV_EVENT && event_id == WIFI_PROV_END) {
>             /* De-initialize the manager once the provisioning is finished */
>             wifi_prov_mgr_deinit();
>         }
>     }

### User Side Implementation

When the service is started, the device to be provisioned is identified by the advertised service name, which, depending upon the selected transport, is either the Bluetooth LE device name or the SoftAP SSID.

When using SoftAP transport, for allowing service discovery, mDNS must be initialized before starting provisioning. In this case, the host name set by the main application is used, and the service type is internally set to `_esp_wifi_prov`.

When using Bluetooth LE transport, a custom 128-bit UUID should be set using `wifi_prov_scheme_ble_set_service_uuid()`. This UUID is to be included in the Bluetooth LE advertisement and corresponds to the primary GATT service that provides provisioning endpoints as GATT characteristics. Each GATT characteristic is formed using the primary service UUID as the base, with different auto-assigned 12th and 13th bytes, presumably counting from the 0th byte. Since an endpoint characteristic UUID is auto-assigned, it should not be used to identify the endpoint. Instead, client-side applications should identify the endpoints by reading the User Characteristic Description (`0x2901`) descriptor for each characteristic, which contains the endpoint name of the characteristic. For example, if the service UUID is set to `55cc035e-fb27-4f80-be02-3c60828b7451`, each endpoint characteristic is assigned a UUID like `55cc____-fb27-4f80-be02-3c60828b7451`, with unique values at the 12th and 13th bytes.

Once connected to the device, the provisioning-related protocomm endpoints can be identified as follows:

Endpoints Provided by the Provisioning Service
Endpoint Name i.e., Bluetooth LE + GATT Server | URI, i.e., SoftAP + HTTP Server + mDNS | Description
--- | --- | ---
prov-session | http://<mdns-hostname>.local/prov-session | Security endpoint used for session establishment
prov-scan | http://wifi-prov.local/prov-scan | the endpoint used for starting Wi-Fi scan and receiving scan results
prov-ctrl | http://wifi-prov.local/prov-ctrl | the endpoint used for controlling Wi-Fi provisioning state
prov-config | http://<mdns-hostname>.local/prov-config | the endpoint used for configuring Wi-Fi credentials on device
proto-ver | http://<mdns-hostname>.local/proto-ver | the endpoint for retrieving version info

Immediately after connecting, the client application may fetch the version/capabilities information from the `proto-ver` endpoint. All communications to this endpoint are unencrypted, hence necessary information, which may be relevant for deciding compatibility, can be retrieved before establishing a secure session. The response is in JSON format and looks like : `prov: { ver: v1.1, sec_ver: 1, sec_patch_ver: 0, cap: [no_pop] }, my_app: { ver: 1.345, cap: [cloud, local_ctrl] },....`.

Here label `prov` provides:

> - provisioning service version `ver`

> - security version `sec_ver`

> - security patch version `sec_patch_ver` (default is 0)

> - capabilities `cap`

For now, only the `no_pop` capability is supported, which indicates that the service does not require proof of possession for authentication. Any application-related version or capabilities are given by other labels, e.g., `my_app` in this example. These additional fields are set using `wifi_prov_mgr_set_app_info()`.

Important

Client must take into account both the `sec_ver` and `sec_patch_ver` fields, as these are used to determine the security scheme to be used for the session establishment.

User side applications need to implement the signature handshaking required for establishing and authenticating secure protocomm sessions as per the security scheme configured for use, which is not needed when the manager is configured to use protocomm security 0.

See Unified Provisioning for more details about the secure handshake and encryption used. Applications must use the `.proto` files found under protocomm/proto, which define the Protobuf message structures supported by `prov-session` endpoint.

Once a session is established, Wi-Fi credentials are configured using the following set of `wifi_config` commands, serialized as Protobuf messages with the corresponding `.proto` files that can be found under wifi_provisioning/proto:

> - `get_status` - For querying the Wi-Fi connection status. The device responds with a status which is one of connecting, connected or disconnected. If the status is disconnected, a disconnection reason is also to be included in the status response.

> - `set_config` - For setting the Wi-Fi connection credentials.

> - `apply_config` - For applying the credentials saved during `set_config` and starting the Wi-Fi station.

After session establishment, the client can also request Wi-Fi scan results from the device. The results returned is a list of AP SSIDs, sorted in descending order of signal strength. This allows client applications to display APs nearby to the device at the time of provisioning, and users can select one of the SSIDs and provide the password which is then sent using the `wifi_config` commands described above. The `wifi_scan` endpoint supports the following protobuf commands :

> - `scan_start` - For starting Wi-Fi scan with various options:

>   > - `blocking` (input) - If true, the command returns only when the scanning is finished.

>   > - `passive` (input) - If true, the scan is started in passive mode, which may be slower, instead of active mode.

>   > - `group_channels` (input) - This specifies whether to scan all channels in one go when zero, or perform scanning of channels in groups, with 120 ms delay between scanning of consecutive groups, and the value of this parameter sets the number of channels in each group. This is useful when transport mode is SoftAP, where scanning all channels in one go may not give the Wi-Fi driver enough time to send out beacons, and hence may cause disconnection with any connected stations. When scanning in groups, the manager waits for at least 120 ms after completing the scan on a group of channels, and thus allows the driver to send out the beacons. For example, given that the total number of Wi-Fi channels is 14, then setting `group_channels` to 3 creates 5 groups, with each group having 3 channels, except the last one which has 14 % 3 = 2 channels. So, when the scan is started, the first 3 channels will be scanned, followed by a 120 ms delay, and then the next 3 channels, and so on, until all the 14 channels have been scanned.One may need to adjust this parameter as having only a few channels in a group may increase the overall scan time, while having too many may again cause disconnection. Usually, a value of 4 should work for most cases. Note that for any other mode of transport, e.g., Bluetooth LE, this can be safely set to 0, and hence achieve the shortest overall scanning time.

>   > - `period_ms` (input) - The scan parameter specifying how long to wait on each channel.

> - `scan_status` - It gives the status of scanning process:

>   > - `scan_finished` (output) - When the scan has finished, this returns true.

>   > - `result_count` (output) - This gives the total number of results obtained till now. If the scan is yet happening, this number keeps on updating.

> - `scan_result` - For fetching the scan results. This can be called even if the scan is still on going.

>   > - `start_index` (input) - Where the index starts from to fetch the entries from the results list.

>   > - `count` (input) - The number of entries to fetch from the starting index.

>   > - `entries` (output) - The list of entries returned. Each entry consists of `ssid`, `channel` and `rssi` information.

The client can also control the provisioning state of the device using `wifi_ctrl` endpoint. The `wifi_ctrl` endpoint supports the following protobuf commands:

> - `ctrl_reset` - Resets internal state machine of the device and clears provisioned credentials only in case of provisioning failures.

> - `ctrl_reprov` - Resets internal state machine of the device and clears provisioned credentials only in case the device is to be provisioned again for new credentials after a previous successful provisioning.

### Additional Endpoints

In case users want to have some additional protocomm endpoints customized to their requirements, this is done in two steps. First is creation of an endpoint with a specific name, and the second step is the registration of a handler for this endpoint. See Protocol Communication for the function signature of an endpoint handler. A custom endpoint must be created after initialization and before starting the provisioning service. Whereas, the protocomm handler is registered for this endpoint only after starting the provisioning service. Note that in the custom endpoint handler function, memory for the response of such protocomm endpoints should be allocated using heap as it gets freed by the protocomm layer once it has been sent by the transport layer.

>     wifi_prov_mgr_init(config);
>     wifi_prov_mgr_endpoint_create("custom-endpoint");
>     wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key);
>     wifi_prov_mgr_endpoint_register("custom-endpoint", custom_ep_handler, custom_ep_data);

When the provisioning service stops, the endpoint is unregistered automatically.

One can also choose to call `wifi_prov_mgr_endpoint_unregister()` to manually deactivate an endpoint at runtime. This can also be used to deactivate the internal endpoints used by the provisioning service.

### When/How to Stop the Provisioning Service?

The default behavior is that once the device successfully connects using the Wi-Fi credentials set by the `apply_config` command, the provisioning service stops, and Bluetooth LE or SoftAP turns off, automatically after responding to the next `get_status` command. If `get_status` command is not received by the device, the service stops after a 30 s timeout.

On the other hand, if device is not able to connect using the provided Wi-Fi credentials, due to incorrect SSID or passphrase, the service keeps running, and `get_status` keeps responding with disconnected status and reason for disconnection. Any further attempts to provide another set of Wi-Fi credentials, are to be rejected. These credentials are preserved, unless the provisioning service is force started, or NVS erased.

If this default behavior is not desired, it can be disabled by calling `wifi_prov_mgr_disable_auto_stop()`. Now the provisioning service stops only after an explicit call to `wifi_prov_mgr_stop_provisioning()`, which returns immediately after scheduling a task for stopping the service. The service stops after a certain delay and `WIFI_PROV_END` event gets emitted. This delay is specified by the argument to `wifi_prov_mgr_disable_auto_stop()`.

The customized behavior is useful for applications which want the provisioning service to be stopped some time after the Wi-Fi connection is successfully established. For example, if the application requires the device to connect to some cloud service and obtain another set of credentials, and exchange these credentials over a custom protocomm endpoint, then after successfully doing so, stop the provisioning service by calling `wifi_prov_mgr_stop_provisioning()` inside the protocomm handler itself. The right amount of delay ensures that the transport resources are freed only after the response from the protocomm handler reaches the client side application.

## Application Examples

For complete example implementation see provisioning/wifi_prov_mgr.

## Provisioning Tools

Provisioning applications are available for various platforms, along with source code:

- Android:

    - Bluetooth LE Provisioning app on Play Store.

    - SoftAP Provisioning app on Play Store.

    - Source code on GitHub: esp-idf-provisioning-android.

- iOS:

    - Bluetooth LE Provisioning app on App Store.

    - SoftAP Provisioning app on App Store.

    - Source code on GitHub: esp-idf-provisioning-ios.

- Linux/MacOS/Windows: tools/esp_prov, a Python-based command-line tool for provisioning.

The phone applications offer simple UI and are thus more user centric, while the command-line application is useful as a debugging tool for developers.

## API Reference

### Header File

- components/wifi_provisioning/include/wifi_provisioning/manager.h

- This header file can be included with:

  >     #include "wifi_provisioning/manager.h"

- This header file is a part of the API provided by the `wifi_provisioning` component. To declare that your component depends on `wifi_provisioning`, add the following to your CMakeLists.txt:

  >     REQUIRES wifi_provisioning

  > or

  >     PRIV_REQUIRES wifi_provisioning

### Functions

esp_err_t wifi_prov_mgr_init(wifi_prov_mgr_config_t config)

  Initialize provisioning manager instance.

  Configures the manager and allocates internal resources

  Configuration specifies the provisioning scheme (transport) and event handlers

  Event WIFI_PROV_INIT is emitted right after initialization is complete

  Parameters:

    config -- [in] Configuration structure

  Returns:

    - ESP_OK : Success

    - ESP_FAIL : Fail

void wifi_prov_mgr_deinit(void)

  Stop provisioning (if running) and release resource used by the manager.

  Event WIFI_PROV_DEINIT is emitted right after de-initialization is finished

  If provisioning service is still active when this API is called, it first stops the service, hence emitting WIFI_PROV_END, and then performs the de-initialization

esp_err_t wifi_prov_mgr_is_provisioned(bool *provisioned)

  Checks if device is provisioned.

  This checks if Wi-Fi credentials are present on the NVS

  The Wi-Fi credentials are assumed to be kept in the same NVS namespace as used by esp_wifi component

  If one were to call esp_wifi_set_config() directly instead of going through the provisioning process, this function will still yield true (i.e. device will be found to be provisioned)

  Note

  Calling wifi_prov_mgr_start_provisioning() automatically resets the provision state, irrespective of what the state was prior to making the call.

  Parameters:

    provisioned -- [out] True if provisioned, else false

  Returns:

    - ESP_OK : Retrieved provision state successfully

    - ESP_FAIL : Wi-Fi not initialized

    - ESP_ERR_INVALID_ARG : Null argument supplied

bool wifi_prov_mgr_is_sm_idle(void)

  Checks whether the provisioning state machine is idle.

  Returns:

    True if state machine is idle, else false

esp_err_t wifi_prov_mgr_start_provisioning(wifi_prov_security_t security, const void *wifi_prov_sec_params, const char *service_name, const char *service_key)

  Start provisioning service.

  This starts the provisioning service according to the scheme configured at the time of initialization. For scheme :

  - wifi_prov_scheme_ble : This starts protocomm_ble, which internally initializes BLE transport and starts GATT server for handling provisioning requests

  - wifi_prov_scheme_softap : This activates SoftAP mode of Wi-Fi and starts protocomm_httpd, which internally starts an HTTP server for handling provisioning requests (If mDNS is active it also starts advertising service with type _esp_wifi_prov._tcp)

  Event WIFI_PROV_START is emitted right after provisioning starts without failure

  Note

  This API will start provisioning service even if device is found to be already provisioned, i.e. wifi_prov_mgr_is_provisioned() yields true

  Parameters:

    - security -- [in] Specify which protocomm security scheme to use :

      - WIFI_PROV_SECURITY_0 : For no security

      - WIFI_PROV_SECURITY_1 : x25519 secure handshake for session establishment followed by AES-CTR encryption of provisioning messages

      - WIFI_PROV_SECURITY_2: SRP6a based authentication and key exchange followed by AES-GCM encryption/decryption of provisioning messages

    - wifi_prov_sec_params -- [in] Pointer to security params (NULL if not needed). This is not needed for protocomm security 0 This pointer should hold the struct of type wifi_prov_security1_params_t for protocomm security 1 and wifi_prov_security2_params_t for protocomm security 2 respectively. This pointer and its contents should be valid till the provisioning service is running and has not been stopped or de-inited.

    - service_name -- [in] Unique name of the service. This translates to:

      - Wi-Fi SSID when provisioning mode is softAP

      - Device name when provisioning mode is BLE

    - service_key -- [in] Key required by client to access the service (NULL if not needed). This translates to:

      - Wi-Fi password when provisioning mode is softAP

      - ignored when provisioning mode is BLE

  Returns:

    - ESP_OK : Provisioning started successfully

    - ESP_FAIL : Failed to start provisioning service

    - ESP_ERR_INVALID_STATE : Provisioning manager not initialized or already started

void wifi_prov_mgr_stop_provisioning(void)

  Stop provisioning service.

  If provisioning service is active, this API will initiate a process to stop the service and return. Once the service actually stops, the event WIFI_PROV_END will be emitted.

  If wifi_prov_mgr_deinit() is called without calling this API first, it will automatically stop the provisioning service and emit the WIFI_PROV_END, followed by WIFI_PROV_DEINIT, before returning.

  This API will generally be used along with wifi_prov_mgr_disable_auto_stop() in the scenario when the main application has registered its own endpoints, and wishes that the provisioning service is stopped only when some protocomm command from the client side application is received.

  Calling this API inside an endpoint handler, with sufficient cleanup_delay, will allow the response / acknowledgment to be sent successfully before the underlying protocomm service is stopped.

  Cleaup_delay is set when calling wifi_prov_mgr_disable_auto_stop(). If not specified, it defaults to 1000ms.

  For straightforward cases, using this API is usually not necessary as provisioning is stopped automatically once WIFI_PROV_CRED_SUCCESS is emitted. Stopping is delayed (maximum 30 seconds) thus allowing the client side application to query for Wi-Fi state, i.e. after receiving the first query and sending `Wi-Fi state connected` response the service is stopped immediately.

void wifi_prov_mgr_wait(void)

  Wait for provisioning service to finish.

  Calling this API will block until provisioning service is stopped i.e. till event WIFI_PROV_END is emitted.

  This will not block if provisioning is not started or not initialized.

esp_err_t wifi_prov_mgr_disable_auto_stop(uint32_t cleanup_delay)

  Disable auto stopping of provisioning service upon completion.

  By default, once provisioning is complete, the provisioning service is automatically stopped, and all endpoints (along with those registered by main application) are deactivated.

  This API is useful in the case when main application wishes to close provisioning service only after it receives some protocomm command from the client side app. For example, after connecting to Wi-Fi, the device may want to connect to the cloud, and only once that is successfully, the device is said to be fully configured. But, then it is upto the main application to explicitly call wifi_prov_mgr_stop_provisioning() later when the device is fully configured and the provisioning service is no longer required.

  Note

  This must be called before executing wifi_prov_mgr_start_provisioning()

  Parameters:

    cleanup_delay -- [in] Sets the delay after which the actual cleanup of transport related resources is done after a call to wifi_prov_mgr_stop_provisioning() returns. Minimum allowed value is 100ms. If not specified, this will default to 1000ms.

  Returns:

    - ESP_OK : Success

    - ESP_ERR_INVALID_STATE : Manager not initialized or provisioning service already started

esp_err_t wifi_prov_mgr_set_app_info(const char *label, const char *version, const char **capabilities, size_t total_capabilities)

  Set application version and capabilities in the JSON data returned by proto-ver endpoint.

  This function can be called multiple times, to specify information about the various application specific services running on the device, identified by unique labels.

  The provisioning service itself registers an entry in the JSON data, by the label "prov", containing only provisioning service version and capabilities. Application services should use a label other than "prov" so as not to overwrite this.

  Note

  This must be called before executing wifi_prov_mgr_start_provisioning()

  Parameters:

    - label -- [in] String indicating the application name.

    - version -- [in] String indicating the application version. There is no constraint on format.

    - capabilities -- [in] Array of strings with capabilities. These could be used by the client side app to know the application registered endpoint capabilities

    - total_capabilities -- [in] Size of capabilities array

  Returns:

    - ESP_OK : Success

    - ESP_ERR_INVALID_STATE : Manager not initialized or provisioning service already started

    - ESP_ERR_NO_MEM : Failed to allocate memory for version string

    - ESP_ERR_INVALID_ARG : Null argument

esp_err_t wifi_prov_mgr_endpoint_create(const char *ep_name)

  Create an additional endpoint and allocate internal resources for it.

  This API is to be called by the application if it wants to create an additional endpoint. All additional endpoints will be assigned UUIDs starting from 0xFF54 and so on in the order of execution.

  protocomm handler for the created endpoint is to be registered later using wifi_prov_mgr_endpoint_register() after provisioning has started.

  Note

  This API can only be called BEFORE provisioning is started

  Note

  Additional endpoints can be used for configuring client provided parameters other than Wi-Fi credentials, that are necessary for the main application and hence must be set prior to starting the application

  Note

  After session establishment, the additional endpoints must be targeted first by the client side application before sending Wi-Fi configuration, because once Wi-Fi configuration finishes the provisioning service is stopped and hence all endpoints are unregistered

  Parameters:

    ep_name -- [in] unique name of the endpoint

  Returns:

    - ESP_OK : Success

    - ESP_FAIL : Failure

esp_err_t wifi_prov_mgr_endpoint_register(const char *ep_name, protocomm_req_handler_t handler, void *user_ctx)

  Register a handler for the previously created endpoint.

  This API can be called by the application to register a protocomm handler to any endpoint that was created using wifi_prov_mgr_endpoint_create().

  Note

  This API can only be called AFTER provisioning has started

  Note

  Additional endpoints can be used for configuring client provided parameters other than Wi-Fi credentials, that are necessary for the main application and hence must be set prior to starting the application

  Note

  After session establishment, the additional endpoints must be targeted first by the client side application before sending Wi-Fi configuration, because once Wi-Fi configuration finishes the provisioning service is stopped and hence all endpoints are unregistered

  Parameters:

    - ep_name -- [in] Name of the endpoint

    - handler -- [in] Endpoint handler function

    - user_ctx -- [in] User data

  Returns:

    - ESP_OK : Success

    - ESP_FAIL : Failure

void wifi_prov_mgr_endpoint_unregister(const char *ep_name)

  Unregister the handler for an endpoint.

  This API can be called if the application wants to selectively unregister the handler of an endpoint while the provisioning is still in progress.

  All the endpoint handlers are unregistered automatically when the provisioning stops.

  Parameters:

    ep_name -- [in] Name of the endpoint

esp_err_t wifi_prov_mgr_get_wifi_state(wifi_prov_sta_state_t *state)

  Get state of Wi-Fi Station during provisioning.

  Parameters:

    state -- [out] Pointer to wifi_prov_sta_state_t variable to be filled

  Returns:

    - ESP_OK : Successfully retrieved Wi-Fi state

    - ESP_FAIL : Provisioning app not running

esp_err_t wifi_prov_mgr_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t *reason)

  Get reason code in case of Wi-Fi station disconnection during provisioning.

  Parameters:

    reason -- [out] Pointer to wifi_prov_sta_fail_reason_t variable to be filled

  Returns:

    - ESP_OK : Successfully retrieved Wi-Fi disconnect reason

    - ESP_FAIL : Provisioning app not running

esp_err_t wifi_prov_mgr_configure_sta(wifi_config_t *wifi_cfg)

  Runs Wi-Fi as Station with the supplied configuration.

  Configures the Wi-Fi station mode to connect to the AP with SSID and password specified in config structure and sets Wi-Fi to run as station.

  This is automatically called by provisioning service upon receiving new credentials.

  If credentials are to be supplied to the manager via a different mode other than through protocomm, then this API needs to be called.

  Event WIFI_PROV_CRED_RECV is emitted after credentials have been applied and Wi-Fi station started

  Parameters:

    wifi_cfg -- [in] Pointer to Wi-Fi configuration structure

  Returns:

    - ESP_OK : Wi-Fi configured and started successfully

    - ESP_FAIL : Failed to set configuration

esp_err_t wifi_prov_mgr_reset_provisioning(void)

  Reset Wi-Fi provisioning config.

  Calling this API will restore WiFi stack persistent settings to default values.

  Returns:

    - ESP_OK : Reset provisioning config successfully

    - ESP_FAIL : Failed to reset provisioning config

esp_err_t wifi_prov_mgr_reset_sm_state_on_failure(void)

  Reset internal state machine and clear provisioned credentials.

  This API should be used to restart provisioning ONLY in the case of provisioning failures without rebooting the device.

  Returns:

    - ESP_OK : Reset provisioning state machine successfully

    - ESP_FAIL : Failed to reset provisioning state machine

    - ESP_ERR_INVALID_STATE : Manager not initialized

esp_err_t wifi_prov_mgr_reset_sm_state_for_reprovision(void)

  Reset internal state machine and clear provisioned credentials.

  This API can be used to restart provisioning ONLY in case the device is to be provisioned again for new credentials after a previous successful provisioning without rebooting the device.

  Note

  This API can be used only if provisioning auto-stop has been disabled using wifi_prov_mgr_disable_auto_stop()

  Returns:

    - ESP_OK : Reset provisioning state machine successfully

    - ESP_FAIL : Failed to reset provisioning state machine

    - ESP_ERR_INVALID_STATE : Manager not initialized

### Structures

struct wifi_prov_event_handler_t

  Event handler that is used by the manager while provisioning service is active.

  Public Members

  wifi_prov_cb_func_t event_cb

    Callback function to be executed on provisioning events

  void *user_data

    User context data to pass as parameter to callback function

struct wifi_prov_scheme

  Structure for specifying the provisioning scheme to be followed by the manager.

  Note

  Ready to use schemes are available:

  - wifi_prov_scheme_ble : for provisioning over BLE transport + GATT server

  - wifi_prov_scheme_softap : for provisioning over SoftAP transport + HTTP server

  - wifi_prov_scheme_console : for provisioning over Serial UART transport + Console (for debugging)

  Public Members

  esp_err_t (*prov_start)(protocomm_t *pc, void *config)

    Function which is to be called by the manager when it is to start the provisioning service associated with a protocomm instance and a scheme specific configuration

  esp_err_t (*prov_stop)(protocomm_t *pc)

    Function which is to be called by the manager to stop the provisioning service previously associated with a protocomm instance

  void *(*new_config)(void)

    Function which is to be called by the manager to generate a new configuration for the provisioning service, that is to be passed to prov_start()

  void (*delete_config)(void *config)

    Function which is to be called by the manager to delete a configuration generated using new_config()

  esp_err_t (*set_config_service)(void *config, const char *service_name, const char *service_key)

    Function which is to be called by the manager to set the service name and key values in the configuration structure

  esp_err_t (*set_config_endpoint)(void *config, const char *endpoint_name, uint16_t uuid)

    Function which is to be called by the manager to set a protocomm endpoint with an identifying name and UUID in the configuration structure

  wifi_mode_t wifi_mode

    Sets mode of operation of Wi-Fi during provisioning This is set to :

    - WIFI_MODE_APSTA for SoftAP transport

    - WIFI_MODE_STA for BLE transport

struct wifi_prov_mgr_config_t

  Structure for specifying the manager configuration.

  Public Members

  wifi_prov_scheme_t scheme

    Provisioning scheme to use. Following schemes are already available:

    - wifi_prov_scheme_ble : for provisioning over BLE transport + GATT server

    - wifi_prov_scheme_softap : for provisioning over SoftAP transport + HTTP server + mDNS (optional)

    - wifi_prov_scheme_console : for provisioning over Serial UART transport + Console (for debugging)

  wifi_prov_event_handler_t scheme_event_handler

    Event handler required by the scheme for incorporating scheme specific behavior while provisioning manager is running. Various options may be provided by the scheme for setting this field. Use WIFI_PROV_EVENT_HANDLER_NONE when not used. When using scheme wifi_prov_scheme_ble, the following options are available:

    - WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM

    - WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE

    - WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT

  wifi_prov_event_handler_t app_event_handler

    Event handler that can be set for the purpose of incorporating application specific behavior. Use WIFI_PROV_EVENT_HANDLER_NONE when not used.

### Macros

WIFI_PROV_EVENT_HANDLER_NONE

  Event handler can be set to none if not used.

### Type Definitions

typedef void (*wifi_prov_cb_func_t)(void *user_data, wifi_prov_cb_event_t event, void *event_data)

typedef struct wifi_prov_scheme wifi_prov_scheme_t

  Structure for specifying the provisioning scheme to be followed by the manager.

  Note

  Ready to use schemes are available:

  - wifi_prov_scheme_ble : for provisioning over BLE transport + GATT server

  - wifi_prov_scheme_softap : for provisioning over SoftAP transport + HTTP server

  - wifi_prov_scheme_console : for provisioning over Serial UART transport + Console (for debugging)

typedef enum wifi_prov_security wifi_prov_security_t

  Security modes supported by the Provisioning Manager.

  These are same as the security modes provided by protocomm

typedef protocomm_security2_params_t wifi_prov_security2_params_t

  Security 2 params structure This needs to be passed when using WIFI_PROV_SECURITY_2.

### Enumerations

enum wifi_prov_cb_event_t

  Events generated by manager.

  These events are generated in order of declaration and, for the stretch of time between initialization and de-initialization of the manager, each event is signaled only once

  Values:

  enumerator WIFI_PROV_INIT

    Emitted when the manager is initialized

  enumerator WIFI_PROV_START

    Indicates that provisioning has started

  enumerator WIFI_PROV_CRED_RECV

    Emitted when Wi-Fi AP credentials are received via `protocomm` endpoint `wifi_config`. The event data in this case is a pointer to the corresponding `wifi_sta_config_t` structure

  enumerator WIFI_PROV_CRED_FAIL

    Emitted when device fails to connect to the AP of which the credentials were received earlier on event `WIFI_PROV_CRED_RECV`. The event data in this case is a pointer to the disconnection reason code with type `wifi_prov_sta_fail_reason_t`

  enumerator WIFI_PROV_CRED_SUCCESS

    Emitted when device successfully connects to the AP of which the credentials were received earlier on event `WIFI_PROV_CRED_RECV`

  enumerator WIFI_PROV_END

    Signals that provisioning service has stopped

  enumerator WIFI_PROV_DEINIT

    Signals that manager has been de-initialized

enum wifi_prov_security

  Security modes supported by the Provisioning Manager.

  These are same as the security modes provided by protocomm

  Values:

  enumerator WIFI_PROV_SECURITY_0

    No security (plain-text communication)

  enumerator WIFI_PROV_SECURITY_1

    This secure communication mode consists of X25519 key exchange

    - proof of possession (pop) based authentication

    - AES-CTR encryption

  enumerator WIFI_PROV_SECURITY_2

    This secure communication mode consists of SRP6a based authentication and key exchange

    - AES-GCM encryption/decryption

### Header File

- components/wifi_provisioning/include/wifi_provisioning/scheme_ble.h

- This header file can be included with:

  >     #include "wifi_provisioning/scheme_ble.h"

- This header file is a part of the API provided by the `wifi_provisioning` component. To declare that your component depends on `wifi_provisioning`, add the following to your CMakeLists.txt:

  >     REQUIRES wifi_provisioning

  > or

  >     PRIV_REQUIRES wifi_provisioning

### Functions

void wifi_prov_scheme_ble_event_cb_free_btdm(void *user_data, wifi_prov_cb_event_t event, void *event_data)

void wifi_prov_scheme_ble_event_cb_free_ble(void *user_data, wifi_prov_cb_event_t event, void *event_data)

void wifi_prov_scheme_ble_event_cb_free_bt(void *user_data, wifi_prov_cb_event_t event, void *event_data)

esp_err_t wifi_prov_scheme_ble_set_service_uuid(uint8_t *uuid128)

  Set the 128 bit GATT service UUID used for provisioning.

  This API is used to override the default 128 bit provisioning service UUID, which is 0000ffff-0000-1000-8000-00805f9b34fb.

  This must be called before starting provisioning, i.e. before making a call to wifi_prov_mgr_start_provisioning(), otherwise the default UUID will be used.

  Note

  The data being pointed to by the argument must be valid at least till provisioning is started. Upon start, the manager will store an internal copy of this UUID, and this data can be freed or invalidated afterwards.

  Parameters:

    uuid128 -- [in] A custom 128 bit UUID

  Returns:

    - ESP_OK : Success

    - ESP_ERR_INVALID_ARG : Null argument

esp_err_t wifi_prov_scheme_ble_set_mfg_data(uint8_t *mfg_data, ssize_t mfg_data_len)

  Set manufacturer specific data in scan response.

  This must be called before starting provisioning, i.e. before making a call to wifi_prov_mgr_start_provisioning().

  Note

  It is important to understand that length of custom manufacturer data should be within limits. The manufacturer data goes into scan response along with BLE device name. By default, BLE device name length is of 11 Bytes, however it can vary as per application use case. So, one has to honour the scan response data size limits i.e. (mfg_data_len + 2) < 31 - (device_name_length + 2 ). If the mfg_data length exceeds this limit, the length will be truncated.

  Parameters:

    - mfg_data -- [in] Custom manufacturer data

    - mfg_data_len -- [in] Manufacturer data length

  Returns:

    - ESP_OK : Success

    - ESP_ERR_INVALID_ARG : Null argument

esp_err_t wifi_prov_scheme_ble_set_random_addr(const uint8_t *rand_addr)

  Set Bluetooth Random address.

  This must be called before starting provisioning, i.e. before making a call to wifi_prov_mgr_start_provisioning().

  This API can be used in cases where a new identity address is to be used during provisioning. This will result in this device being treated as a new device by remote devices.

  This API is only to be called to set random address. Re-invoking this API after provisioning is started will have no effect.

  Note

  This API will change the existing BD address for the device. The address once set will remain unchanged until BLE stack tear down happens when wifi_prov_mgr_deinit is invoked.

  Parameters:

    rand_addr -- [in] The static random address to be set of length 6 bytes.

  Returns:

    - ESP_OK : Success

    - ESP_ERR_INVALID_ARG : Null argument

### Macros

WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM

WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE

WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT

### Header File

- components/wifi_provisioning/include/wifi_provisioning/scheme_softap.h

- This header file can be included with:

  >     #include "wifi_provisioning/scheme_softap.h"

- This header file is a part of the API provided by the `wifi_provisioning` component. To declare that your component depends on `wifi_provisioning`, add the following to your CMakeLists.txt:

  >     REQUIRES wifi_provisioning

  > or

  >     PRIV_REQUIRES wifi_provisioning

### Functions

void wifi_prov_scheme_softap_set_httpd_handle(void *handle)

  Provide HTTPD Server handle externally.

  Useful in cases wherein applications need the webserver for some different operations, and do not want the wifi provisioning component to start/stop a new instance.

  Note

  This API should be called before wifi_prov_mgr_start_provisioning()

  Parameters:

    handle -- [in] Handle to HTTPD server instance

### Header File

- components/wifi_provisioning/include/wifi_provisioning/scheme_console.h

- This header file can be included with:

  >     #include "wifi_provisioning/scheme_console.h"

- This header file is a part of the API provided by the `wifi_provisioning` component. To declare that your component depends on `wifi_provisioning`, add the following to your CMakeLists.txt:

  >     REQUIRES wifi_provisioning

  > or

  >     PRIV_REQUIRES wifi_provisioning

### Header File

- components/wifi_provisioning/include/wifi_provisioning/wifi_config.h

- This header file can be included with:

  >     #include "wifi_provisioning/wifi_config.h"

- This header file is a part of the API provided by the `wifi_provisioning` component. To declare that your component depends on `wifi_provisioning`, add the following to your CMakeLists.txt:

  >     REQUIRES wifi_provisioning

  > or

  >     PRIV_REQUIRES wifi_provisioning

### Functions

esp_err_t wifi_prov_config_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, uint8_t **outbuf, ssize_t *outlen, void *priv_data)

  Handler for receiving and responding to requests from master.

  This is to be registered as the `wifi_config` endpoint handler (protocomm `protocomm_req_handler_t`) using `protocomm_add_endpoint()`

### Structures

struct wifi_prov_sta_conn_info_t

  WiFi STA connected status information.

  Public Members

  char ip_addr[IP4ADDR_STRLEN_MAX]

    IP Address received by station

  char bssid[6]

    BSSID of the AP to which connection was estalished

  char ssid[33]

    SSID of the to which connection was estalished

  uint8_t channel

    Channel of the AP

  uint8_t auth_mode

    Authorization mode of the AP

struct wifi_prov_config_get_data_t

  WiFi status data to be sent in response to `get_status` request from master.

  Public Members

  wifi_prov_sta_state_t wifi_state

    WiFi state of the station

  wifi_prov_sta_fail_reason_t fail_reason

    Reason for disconnection (valid only when `wifi_state` is `WIFI_STATION_DISCONNECTED`)

  wifi_prov_sta_conn_info_t conn_info

    Connection information (valid only when `wifi_state` is `WIFI_STATION_CONNECTED`)

struct wifi_prov_config_set_data_t

  WiFi config data received by slave during `set_config` request from master.

  Public Members

  char ssid[33]

    SSID of the AP to which the slave is to be connected

  char password[64]

    Password of the AP

  char bssid[6]

    BSSID of the AP

  uint8_t channel

    Channel of the AP

struct wifi_prov_config_handlers

  Internal handlers for receiving and responding to protocomm requests from master.

  This is to be passed as priv_data for protocomm request handler (refer to `wifi_prov_config_data_handler()`) when calling `protocomm_add_endpoint()`.

  Public Members

  esp_err_t (*get_status_handler)(wifi_prov_config_get_data_t *resp_data, wifi_prov_ctx_t **ctx)

    Handler function called when connection status of the slave (in WiFi station mode) is requested

  esp_err_t (*set_config_handler)(const wifi_prov_config_set_data_t *req_data, wifi_prov_ctx_t **ctx)

    Handler function called when WiFi connection configuration (eg. AP SSID, password, etc.) of the slave (in WiFi station mode) is to be set to user provided values

  esp_err_t (*apply_config_handler)(wifi_prov_ctx_t **ctx)

    Handler function for applying the configuration that was set in `set_config_handler`. After applying the station may get connected to the AP or may fail to connect. The slave must be ready to convey the updated connection status information when `get_status_handler` is invoked again by the master.

  wifi_prov_ctx_t *ctx

    Context pointer to be passed to above handler functions upon invocation

### Type Definitions

typedef struct wifi_prov_ctx wifi_prov_ctx_t

  Type of context data passed to each get/set/apply handler function set in `wifi_prov_config_handlers` structure.

  This is passed as an opaque pointer, thereby allowing it be defined later in application code as per requirements.

typedef struct wifi_prov_config_handlers wifi_prov_config_handlers_t

  Internal handlers for receiving and responding to protocomm requests from master.

  This is to be passed as priv_data for protocomm request handler (refer to `wifi_prov_config_data_handler()`) when calling `protocomm_add_endpoint()`.

### Enumerations

enum wifi_prov_sta_state_t

  WiFi STA status for conveying back to the provisioning master.

  Values:

  enumerator WIFI_PROV_STA_CONNECTING
  enumerator WIFI_PROV_STA_CONNECTED
  enumerator WIFI_PROV_STA_DISCONNECTED

enum wifi_prov_sta_fail_reason_t

  WiFi STA connection fail reason.

  Values:

  enumerator WIFI_PROV_STA_AUTH_ERROR
  enumerator WIFI_PROV_STA_AP_NOT_FOUND

Provide feedback about this document