diff --git a/components/log/include/esp_log_internal.h b/components/log/include/esp_log_internal.h index 94ec3463..02dbdba6 100644 --- a/components/log/include/esp_log_internal.h +++ b/components/log/include/esp_log_internal.h @@ -16,9 +16,13 @@ #define __ESP_LOG_INTERNAL_H__ //these functions do not check level versus ESP_LOCAL_LEVEL, this should be done in esp_log.h -void esp_log_buffer_hex_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level); -void esp_log_buffer_char_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level); -void esp_log_buffer_hexdump_internal( const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level); +#define esp_log_buffer_hex_internal(...) +#define esp_log_buffer_char_internal(...) +#define esp_log_buffer_hexdump_internal(...) +/* TODO: Add the implementation of the below API's */ +// void esp_log_buffer_hex_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level); +// void esp_log_buffer_char_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level); +// void esp_log_buffer_hexdump_internal( const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level); #endif diff --git a/components/protocomm/CMakeLists.txt b/components/protocomm/CMakeLists.txt index c8effa89..78991561 100644 --- a/components/protocomm/CMakeLists.txt +++ b/components/protocomm/CMakeLists.txt @@ -11,6 +11,6 @@ set(COMPONENT_SRCS "src/common/protocomm.c" "proto-c/session.pb-c.c" "src/transports/protocomm_httpd.c") -set(COMPONENT_PRIV_REQUIRES protobuf-c mbedtls) +set(COMPONENT_PRIV_REQUIRES protobuf-c mbedtls wifi_provisioning) register_component() diff --git a/components/protocomm/component.mk b/components/protocomm/component.mk index e627511f..31b71f04 100644 --- a/components/protocomm/component.mk +++ b/components/protocomm/component.mk @@ -1,10 +1,8 @@ COMPONENT_ADD_INCLUDEDIRS := COMPONENT_SRCDIRS := -ifdef CONFIG_SSL_USING_MBEDTLS -ifdef CONFIG_MBEDTLS_CIPHER_MODE_CTR +ifdef CONFIG_ENABLE_UNIFIED_PROVISIONING COMPONENT_ADD_INCLUDEDIRS := include/common include/security include/transports COMPONENT_PRIV_INCLUDEDIRS := proto-c src/common COMPONENT_SRCDIRS := src/common src/security proto-c src/transports endif -endif diff --git a/components/wifi_provisioning/Kconfig b/components/wifi_provisioning/Kconfig new file mode 100644 index 00000000..2b641b11 --- /dev/null +++ b/components/wifi_provisioning/Kconfig @@ -0,0 +1,11 @@ +menu "Unified Provisioning" + +config ENABLE_UNIFIED_PROVISIONING + bool "Enable Unified Provisioning" + default n + select SSL_USING_MBEDTLS + select MBEDTLS_CIPHER_MODE_CTR + select MBEDTLS_ECP_C + help + This enables Unified Provisioning feature along with required components like Wifi-Provisioning, Protocomm and their mbedtls dependencies. +endmenu diff --git a/components/wifi_provisioning/component.mk b/components/wifi_provisioning/component.mk index efeb597c..5b5f985e 100644 --- a/components/wifi_provisioning/component.mk +++ b/components/wifi_provisioning/component.mk @@ -1,3 +1,8 @@ +COMPONENT_SRCDIRS := +COMPONENT_ADD_INCLUDEDIRS := + +ifdef CONFIG_ENABLE_UNIFIED_PROVISIONING COMPONENT_SRCDIRS := src proto-c COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_PRIV_INCLUDEDIRS := proto-c ../protocomm/proto-c/ +endif diff --git a/components/wifi_provisioning/include/wifi_provisioning/wifi_config.h b/components/wifi_provisioning/include/wifi_provisioning/wifi_config.h index 4058540a..115bde6e 100644 --- a/components/wifi_provisioning/include/wifi_provisioning/wifi_config.h +++ b/components/wifi_provisioning/include/wifi_provisioning/wifi_config.h @@ -16,7 +16,7 @@ #define _WIFI_PROV_CONFIG_H_ #include - +#include #ifdef __cplusplus extern "C" { #endif diff --git a/examples/provisioning/ble_prov/CMakeLists.txt b/examples/provisioning/ble_prov/CMakeLists.txt deleted file mode 100644 index 30012d3e..00000000 --- a/examples/provisioning/ble_prov/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(ble_prov) diff --git a/examples/provisioning/ble_prov/Makefile b/examples/provisioning/ble_prov/Makefile deleted file mode 100644 index ccd2a96b..00000000 --- a/examples/provisioning/ble_prov/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := ble_prov - -include $(IDF_PATH)/make/project.mk - diff --git a/examples/provisioning/ble_prov/README.md b/examples/provisioning/ble_prov/README.md deleted file mode 100644 index d6d5223a..00000000 --- a/examples/provisioning/ble_prov/README.md +++ /dev/null @@ -1,206 +0,0 @@ -# BLE based Provisioning Example - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -`ble_prov` example demonstrates the implementation and integration of various IDF components 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). - -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. - -Right after provisioning is complete, BLE is turned off and disabled to free the memory used by the BLE stack. Though, that is specific to this example, and the user can choose to keep BLE on in their own application. - -`ble_prov` uses the following components : -* `wifi_provisioning` : provides data structures and protocomm endpoint handlers for Wi-Fi configuration -* `protocomm` : for protocol based communication and secure session establishment -* `protobuf` : Google's protocol buffer library for serialization of protocomm data structures -* `bt` : ESP32 BLE stack for transport of protobuf packets - -This example can be used, as it is, for adding a provisioning service to any application intended for IoT. - -## How to use example - -### Hardware Required - -Example should be able to run on any commonly available ESP32 development board. - -### Application Required - -Provisioning applications are available for various platforms. See below - -#### Platform : Android - -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) - -#### Platform : iOS - -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) - -#### Platform : Linux / Windows / macOS - -To provision the device running this example, the `esp_prov.py` script needs to be run (found under `$IDF_PATH/tools/esp_prov`). Make sure to satisfy all the dependencies prior to running the script. - -Presently, `esp_prov` supports BLE transport only for Linux platform. For Windows/macOS it falls back to console mode and requires another application (for BLE) through which the communication can take place. - -There are various applications, specific to Windows and macOS platform which can be used. The `esp_prov` console will guide you through the provisioning process of locating the correct BLE GATT services and characteristics, the values to write, and input read values. - -### Configure the project - -``` -make menuconfig -``` - -* Set serial port under Serial Flasher Options. - -* Under Example Configuration set the following : - * Security Version (default 1) - * Proof of Possession (default "abcd1234") - -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -make -j4 flash monitor -``` - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -``` -I (550) app: Starting BLE provisioning -I (1130) app_prov: Provisioning started with BLE devname : PROV_261FCC -``` - -Make sure to note down the BLE device name (starting with PROV_) displayed in the serial monitor log (eg. PROV_261FCC). This will depend on the MAC ID and will be unique for every device. - -In a separate terminal run the `esp_prov.py` script under `$IDP_PATH/tools/esp_prov` directory (please replace `myssid` and `mypassword` with the credentials of the AP to which the device is supposed to connect to after provisioning). Assuming default example configuration : - -``` -python esp_prov.py --ssid myssid --passphrase mypassword --sec_ver 1 --pop abcd1234 --transport ble --ble_devname PROV_261FCC -``` - -Above command will perform the provisioning steps, and the monitor log should display something like this : - -``` -I (682950) app_prov_handler: WiFi Credentials Received : - ssid : myssid - password : mypassword -. -. -. -I (683130) app_prov: STA Start -I (683130) app_prov_handler: WiFi Credentials Applied -. -. -. -I (688270) app_prov_handler: Connecting state -. -. -. -I (688390) app_prov: STA Got IP -I (688390) app: got ip:192.168.43.220 -I (693410) app_prov_handler: Connected state -``` - -After sometime the provisioning app will exit and BLE will be turned off - -``` -I (718390) app_prov: Stopping provisioning -I (718670) app_prov: Provisioning stopped -``` - -## Troubleshooting - -### Provisioning failed - -It is possible that the Wi-Fi credentials provided were incorrect, or the device was not able to establish connection to the network, in which the the `esp_prov` script will notify failure (with reason) and the provisioning app will continue running, allowing the user to retry the process. Serial monitor log will display the failure along with disconnect reason : - -``` -E (39291) app_prov: STA Disconnected -E (39291) app_prov: Disconnect reason : 201 -I (39291) app_prov: STA AP Not found -I (42021) app_prov_handler: Disconnected state -``` - -### Provisioning does not start - -If the serial monitor log is different, as shown below : - -``` -I (539) app_prov: Found ssid myssid -I (539) app_prov: Found password mypassword -I (549) app: Starting WiFi station -``` - -It means the Wi-Fi credentials were already set by some other application flashed previously to your device. To erase these credentials either do full erase and then flash the example - -``` -make erase_flash -make -j4 flash monitor -``` - -Or, enable `Reset Provisioning` option under `Example Configuration` under menuconfig. But this will erase the saved Wi-Fi credentials every time the device boots, so this is not the preferred solution. - -### Unsupported platform - -If the platform requirement, for running `esp_prov` is not satisfied, then the script execution will fallback to console mode, in which case the full process (involving user inputs) will look like this : - -``` -==== Esp_Prov Version: V0.1 ==== -BLE client is running in console mode - This could be due to your platform not being supported or dependencies not being met - Please ensure all pre-requisites are met to run the full fledged client -BLECLI >> Please connect to BLE device `PROV_261FCC` manually using your tool of choice -BLECLI >> Was the device connected successfully? [y/n] y -BLECLI >> List available attributes of the connected device -BLECLI >> Is the service UUID '0000ffff-0000-1000-8000-00805f9b34fb' listed among available attributes? [y/n] y -BLECLI >> Is the characteristic UUID '0000ff53-0000-1000-8000-00805f9b34fb' listed among available attributes? [y/n] y -BLECLI >> Is the characteristic UUID '0000ff51-0000-1000-8000-00805f9b34fb' listed among available attributes? [y/n] y -BLECLI >> Is the characteristic UUID '0000ff52-0000-1000-8000-00805f9b34fb' listed among available attributes? [y/n] y - -==== Verifying protocol version ==== -BLECLI >> Write following data to characteristic with UUID '0000ff53-0000-1000-8000-00805f9b34fb' : - >> 56302e31 -BLECLI >> Enter data read from characteristic (in hex) : - << 53554343455353 -==== Verified protocol version successfully ==== - -==== Starting Session ==== -BLECLI >> Write following data to characteristic with UUID '0000ff51-0000-1000-8000-00805f9b34fb' : - >> 10015a25a201220a20ae6d9d5d1029f8c366892252d2d5a0ffa7ce1ee5829312545dd5f2aba057294d -BLECLI >> Enter data read from characteristic (in hex) : - << 10015a390801aa0134122048008bfc365fad4753dc75912e0c764d60749cb26dd609595b6fbc72e12614031a1089733af233c7448e7d7fb7963682c6d8 -BLECLI >> Write following data to characteristic with UUID '0000ff51-0000-1000-8000-00805f9b34fb' : - >> 10015a270802b2012212204051088dc294fe4621fac934a8ea22e948fcc3e8ac458aac088ce705c65dbfb9 -BLECLI >> Enter data read from characteristic (in hex) : - << 10015a270803ba01221a20c8d38059d5206a3d92642973ac6ba8ac2f6ecf2b7a3632964eb35a0f20133adb -==== Session Established ==== - -==== Sending Wifi credential to esp32 ==== -BLECLI >> Write following data to characteristic with UUID '0000ff52-0000-1000-8000-00805f9b34fb' : - >> 98471ac4019a46765c28d87df8c8ae71c1ae6cfe0bc9c615bc6d2c -BLECLI >> Enter data read from characteristic (in hex) : - << 3271f39a -==== Wifi Credentials sent successfully ==== - -==== Applying config to esp32 ==== -BLECLI >> Write following data to characteristic with UUID '0000ff52-0000-1000-8000-00805f9b34fb' : - >> 5355 -BLECLI >> Enter data read from characteristic (in hex) : - << 1664db24 -==== Apply config sent successfully ==== - -==== Wifi connection state ==== -BLECLI >> Write following data to characteristic with UUID '0000ff52-0000-1000-8000-00805f9b34fb' : - >> 290d -BLECLI >> Enter data read from characteristic (in hex) : - << 505f72a9f8521025c1964d7789c4d7edc56aedebd144e1b667bc7c0975757b80cc091aa9f3e95b06eaefbc30290fa1 -++++ WiFi state: connected ++++ -==== Provisioning was successful ==== -``` - -The write data is to be copied from the console output ```>>``` to the platform specific application and the data read from the application is to be pasted at the user input prompt ```<<``` of the console, in the format (hex) indicated in above sample log. diff --git a/examples/provisioning/ble_prov/ble_prov_test.py b/examples/provisioning/ble_prov/ble_prov_test.py deleted file mode 100644 index 537dc930..00000000 --- a/examples/provisioning/ble_prov/ble_prov_test.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2018 Espressif Systems (Shanghai) PTE LTD -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import print_function -import imp -import re -import os -import sys -import time - -# This environment variable is expected on the host machine -test_fw_path = os.getenv("TEST_FW_PATH") -if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - -# When running on local machine execute the following before running this script -# > export TEST_FW_PATH='~/esp/esp-idf/tools/tiny-test-fw' -# > make print_flash_cmd | tail -n 1 > build/download.config -# > make app bootloader - -import TinyFW -import IDF - -# Import esp_prov tool -idf_path = os.environ['IDF_PATH'] -esp_prov = imp.load_source("esp_prov", idf_path + "/tools/esp_prov/esp_prov.py") - -@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") - - # Get binary file - binary_file = os.path.join(dut1.app.binary_path, "ble_prov.bin") - bin_size = os.path.getsize(binary_file) - IDF.log_performance("ble_prov_bin_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("ble_prov_bin_size", bin_size//1024) - - # Upload binary and start testing - dut1.start_app() - - # Parse BLE devname - devname = dut1.expect(re.compile(r"(?:[\s\S]*) Provisioning started with BLE devname : (PROV_\S\S\S\S\S\S)"))[0] - print("BLE Device Alias for DUT :", devname) - - # Match additional headers sent in the request - dut1.expect("BLE Provisioning started") - - print("Starting Provisioning") - verbose = False - protover = "V0.1" - secver = 1 - pop = "abcd1234" - provmode = "ble" - ap_ssid = "myssid" - ap_password = "mypassword" - - print("Getting security") - security = esp_prov.get_security(secver, pop, verbose) - if security == None: - raise RuntimeError("Failed to get security") - - print("Getting transport") - transport = esp_prov.get_transport(provmode, None, devname) - if transport == None: - raise RuntimeError("Failed to get transport") - - print("Verifying protocol version") - if not esp_prov.version_match(transport, protover): - raise RuntimeError("Mismatch in protocol version") - - print("Starting Session") - if not esp_prov.establish_session(transport, security): - raise RuntimeError("Failed to start session") - - 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") - - print("Applying config") - if not esp_prov.apply_wifi_config(transport, security): - raise RuntimeError("Failed to send apply config") - - success = False - while True: - time.sleep(5) - print("Wi-Fi connection state") - ret = esp_prov.get_wifi_config(transport, security) - if (ret == 1): - continue - elif (ret == 0): - print("Provisioning was successful") - success = True - break - - if not success: - raise RuntimeError("Provisioning failed") - -if __name__ == '__main__': - test_examples_provisioning_ble() diff --git a/examples/provisioning/ble_prov/main/CMakeLists.txt b/examples/provisioning/ble_prov/main/CMakeLists.txt deleted file mode 100644 index 3c44a1a3..00000000 --- a/examples/provisioning/ble_prov/main/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(COMPONENT_SRCS "app_main.c" - "app_prov.c" - "app_prov_handlers.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") - -register_component() diff --git a/examples/provisioning/ble_prov/main/Kconfig.projbuild b/examples/provisioning/ble_prov/main/Kconfig.projbuild deleted file mode 100644 index b669a1e5..00000000 --- a/examples/provisioning/ble_prov/main/Kconfig.projbuild +++ /dev/null @@ -1,34 +0,0 @@ -menu "Example Configuration" - -config USE_SEC_1 - bool - default y - prompt "Use Security Version 1" - help - Security version 1 used Curve25519 key exchange for establishing - secure session between device and client during provisioning - -config USE_POP - bool - depends on USE_SEC_1 - default y - prompt "Use proof-of-possession" - help - Proof-of-possession can be optionally used to prove that the device is indeed - in possession of the user who is provisioning the device. This proof-of-possession - is internally used to generate the shared secret through key exchange. - -config POP - string "Proof-of-possession" - default "abcd1234" - depends on USE_POP - -config RESET_PROVISIONED - bool - default n - prompt "Reset provisioned status of the device" - help - This erases the NVS to reset provisioned status of the device on every reboot. - Provisioned status is determined by the WiFi STA configuration, saved on the NVS. - -endmenu diff --git a/examples/provisioning/ble_prov/main/app_main.c b/examples/provisioning/ble_prov/main/app_main.c deleted file mode 100644 index bcb11a8a..00000000 --- a/examples/provisioning/ble_prov/main/app_main.c +++ /dev/null @@ -1,114 +0,0 @@ -/* BLE based Provisioning Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "app_prov.h" - -static const char *TAG = "app"; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* Invoke Provisioning event handler first */ - app_prov_event_handler(ctx, event); - - switch(event->event_id) { - case SYSTEM_EVENT_AP_START: - ESP_LOGI(TAG, "SoftAP started"); - break; - case SYSTEM_EVENT_AP_STOP: - ESP_LOGI(TAG, "SoftAP stopped"); - break; - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:"MACSTR" join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:"MACSTR"leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - break; - default: - break; - } - return ESP_OK; -} - -static void wifi_init_sta() -{ - /* Start wifi in station mode with credentials set during provisioning */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_start() ); -} - -void app_main() -{ - /* Security version */ - int security = 0; - /* Proof of possession */ - const protocomm_security_pop_t *pop = NULL; - -#ifdef CONFIG_USE_SEC_1 - security = 1; -#endif - - /* Having proof of possession is optional */ -#ifdef CONFIG_USE_POP - const static protocomm_security_pop_t app_pop = { - .data = (uint8_t *) CONFIG_POP, - .len = (sizeof(CONFIG_POP)-1) - }; - pop = &app_pop; -#endif - - /* Initialize networking stack */ - tcpip_adapter_init(); - - /* Set our event handling */ - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); - - /* Check if device is provisioned */ - bool provisioned; - if (app_prov_is_provisioned(&provisioned) != ESP_OK) { - ESP_LOGE(TAG, "Error getting device provisioning state"); - return; - } - - if (provisioned == false) { - /* If not provisioned, start provisioning via BLE */ - ESP_LOGI(TAG, "Starting BLE provisioning"); - app_prov_start_ble_provisioning(security, pop); - } else { - /* Else start as station with credentials set during provisioning */ - ESP_LOGI(TAG, "Starting WiFi station"); - wifi_init_sta(NULL); - } -} diff --git a/examples/provisioning/ble_prov/main/app_prov.c b/examples/provisioning/ble_prov/main/app_prov.c deleted file mode 100644 index 1f927dca..00000000 --- a/examples/provisioning/ble_prov/main/app_prov.c +++ /dev/null @@ -1,370 +0,0 @@ -/* BLE based Provisioning Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "app_prov.h" - -static const char *TAG = "app_prov"; -static const char *ssid_prefix = "PROV_"; - -/* Handlers for wifi_config provisioning endpoint */ -extern wifi_prov_config_handlers_t wifi_prov_handlers; - -/** - * @brief Data relevant to provisioning application - */ -struct app_prov_data { - protocomm_t *pc; /*!< Protocomm handler */ - int security; /*!< Type of security to use with protocomm */ - const protocomm_security_pop_t *pop; /*!< Pointer to proof of possession */ - esp_timer_handle_t timer; /*!< Handle to timer */ - - /* State of WiFi Station */ - wifi_prov_sta_state_t wifi_state; - - /* Code for WiFi station disconnection (if disconnected) */ - wifi_prov_sta_fail_reason_t wifi_disconnect_reason; -}; - -/* Pointer to provisioning application data */ -static struct app_prov_data *g_prov; - -static esp_err_t app_prov_start_service(void) -{ - /* Create new protocomm instance */ - g_prov->pc = protocomm_new(); - if (g_prov->pc == NULL) { - ESP_LOGE(TAG, "Failed to create new protocomm instance"); - return ESP_FAIL; - } - - /* Endpoint UUIDs */ - protocomm_ble_name_uuid_t nu_lookup_table[] = { - {"prov-session", 0xFF51}, - {"prov-config", 0xFF52}, - {"proto-ver", 0xFF53}, - }; - - /* Config for protocomm_ble_start() */ - protocomm_ble_config_t config = { - .service_uuid = { - /* LSB <--------------------------------------- - * ---------------------------------------> MSB */ - 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, - 0x00, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - }, - .nu_lookup_count = sizeof(nu_lookup_table)/sizeof(nu_lookup_table[0]), - .nu_lookup = nu_lookup_table - }; - uint8_t eth_mac[6]; - esp_wifi_get_mac(WIFI_IF_STA, eth_mac); - snprintf(config.device_name, sizeof(config.device_name), "%s%02X%02X%02X", - ssid_prefix, eth_mac[3], eth_mac[4], eth_mac[5]); - - /* Release BT memory, as we need only BLE */ - esp_err_t err = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); - if (err) { - ESP_LOGE(TAG, "bt_controller_mem_release failed %d", err); - if (err != ESP_ERR_INVALID_STATE) { - return err; - } - } - - /* Start protocomm layer on top of BLE */ - if (protocomm_ble_start(g_prov->pc, &config) != ESP_OK) { - ESP_LOGE(TAG, "Failed to start BLE provisioning"); - return ESP_FAIL; - } - - /* Set protocomm version verification endpoint for protocol */ - protocomm_set_version(g_prov->pc, "proto-ver", "V0.1"); - - /* Set protocomm security type for endpoint */ - if (g_prov->security == 0) { - protocomm_set_security(g_prov->pc, "prov-session", &protocomm_security0, NULL); - } else if (g_prov->security == 1) { - protocomm_set_security(g_prov->pc, "prov-session", &protocomm_security1, g_prov->pop); - } - - /* Add endpoint for provisioning to set wifi station config */ - if (protocomm_add_endpoint(g_prov->pc, "prov-config", - wifi_prov_config_data_handler, - (void *) &wifi_prov_handlers) != ESP_OK) { - ESP_LOGE(TAG, "Failed to set provisioning endpoint"); - protocomm_ble_stop(g_prov->pc); - return ESP_FAIL; - } - - ESP_LOGI(TAG, "Provisioning started with BLE devname : %s", config.device_name); - return ESP_OK; -} - -static void app_prov_stop_service(void) -{ - /* Remove provisioning endpoint */ - protocomm_remove_endpoint(g_prov->pc, "prov-config"); - /* Unset provisioning security */ - protocomm_unset_security(g_prov->pc, "prov-session"); - /* Unset provisioning version endpoint */ - protocomm_unset_version(g_prov->pc, "proto-ver"); - /* Stop protocomm ble service */ - protocomm_ble_stop(g_prov->pc); - /* Delete protocomm instance */ - protocomm_delete(g_prov->pc); - - /* Release memory used by BT stack */ - esp_bt_mem_release(ESP_BT_MODE_BTDM); -} - -/* Task spawned by timer callback */ -static void stop_prov_task(void * arg) -{ - ESP_LOGI(TAG, "Stopping provisioning"); - app_prov_stop_service(); - - /* Timer not needed anymore */ - esp_timer_handle_t timer = g_prov->timer; - esp_timer_delete(timer); - g_prov->timer = NULL; - - /* Free provisioning process data */ - free(g_prov); - g_prov = NULL; - ESP_LOGI(TAG, "Provisioning stopped"); - - vTaskDelete(NULL); -} - -/* Callback to be invoked by timer */ -static void _stop_prov_cb(void * arg) -{ - xTaskCreate(&stop_prov_task, "stop_prov", 2048, NULL, tskIDLE_PRIORITY, NULL); -} - -/* Event handler for starting/stopping provisioning. - * To be called from within the context of the main - * event handler. - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - /* If pointer to provisioning application data is NULL - * then provisioning is not running, therefore return without - * error */ - if (!g_prov) { - return ESP_OK; - } - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - ESP_LOGI(TAG, "STA Start"); - /* Once configuration is received through protocomm, - * device is started as station. Once station starts, - * wait for connection to establish with configured - * host SSID and password */ - g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; - break; - - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "STA Got IP"); - /* Station got IP. That means configuration is successful. - * Schedule timer to stop provisioning app after 30 seconds. */ - g_prov->wifi_state = WIFI_PROV_STA_CONNECTED; - if (g_prov && g_prov->timer) { - esp_timer_start_once(g_prov->timer, 30000*1000U); - } - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "STA Disconnected"); - /* Station couldn't connect to configured host SSID */ - g_prov->wifi_state = WIFI_PROV_STA_DISCONNECTED; - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - - /* Set code corresponding to the reason for disconnection */ - switch (info->disconnected.reason) { - case WIFI_REASON_AUTH_EXPIRE: - case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: - case WIFI_REASON_BEACON_TIMEOUT: - case WIFI_REASON_AUTH_FAIL: - case WIFI_REASON_ASSOC_FAIL: - case WIFI_REASON_HANDSHAKE_TIMEOUT: - ESP_LOGI(TAG, "STA Auth Error"); - g_prov->wifi_disconnect_reason = WIFI_PROV_STA_AUTH_ERROR; - break; - case WIFI_REASON_NO_AP_FOUND: - ESP_LOGI(TAG, "STA AP Not found"); - g_prov->wifi_disconnect_reason = WIFI_PROV_STA_AP_NOT_FOUND; - break; - default: - /* If none of the expected reasons, - * retry connecting to host SSID */ - g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; - esp_wifi_connect(); - } - break; - - default: - break; - } - return ESP_OK; -} - -esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state) -{ - if (g_prov == NULL || state == NULL) { - return ESP_FAIL; - } - - *state = g_prov->wifi_state; - return ESP_OK; -} - -esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reason) -{ - if (g_prov == NULL || reason == NULL) { - return ESP_FAIL; - } - - if (g_prov->wifi_state != WIFI_PROV_STA_DISCONNECTED) { - return ESP_FAIL; - } - - *reason = g_prov->wifi_disconnect_reason; - return ESP_OK; -} - -esp_err_t app_prov_is_provisioned(bool *provisioned) -{ - *provisioned = false; - -#ifdef CONFIG_RESET_PROVISIONED - nvs_flash_erase(); -#endif - - if (nvs_flash_init() != ESP_OK) { - ESP_LOGE(TAG, "Failed to init NVS"); - return ESP_FAIL; - } - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - if (esp_wifi_init(&cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to init wifi"); - return ESP_FAIL; - } - - /* Get WiFi Station configuration */ - wifi_config_t wifi_cfg; - if (esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_cfg) != ESP_OK) { - return ESP_FAIL; - } - - if (strlen((const char*) wifi_cfg.sta.ssid)) { - *provisioned = true; - ESP_LOGI(TAG, "Found ssid %s", (const char*) wifi_cfg.sta.ssid); - ESP_LOGI(TAG, "Found password %s", (const char*) wifi_cfg.sta.password); - } - return ESP_OK; -} - -esp_err_t app_prov_configure_sta(wifi_config_t *wifi_cfg) -{ - /* Initialize WiFi with default config */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - if (esp_wifi_init(&cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to init WiFi"); - return ESP_FAIL; - } - /* Configure WiFi as station */ - if (esp_wifi_set_mode(WIFI_MODE_STA) != ESP_OK) { - ESP_LOGE(TAG, "Failed to set WiFi mode"); - return ESP_FAIL; - } - /* Configure WiFi station with host credentials - * provided during provisioning */ - if (esp_wifi_set_config(ESP_IF_WIFI_STA, wifi_cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to set WiFi configuration"); - return ESP_FAIL; - } - /* Start WiFi */ - if (esp_wifi_start() != ESP_OK) { - ESP_LOGE(TAG, "Failed to set WiFi configuration"); - return ESP_FAIL; - } - /* Connect to AP */ - if (esp_wifi_connect() != ESP_OK) { - ESP_LOGE(TAG, "Failed to connect WiFi"); - return ESP_FAIL; - } - - if (g_prov) { - /* Reset wifi station state for provisioning app */ - g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; - } - return ESP_OK; -} - -esp_err_t app_prov_start_ble_provisioning(int security, const protocomm_security_pop_t *pop) -{ - /* If provisioning app data present, - * means provisioning app is already running */ - if (g_prov) { - ESP_LOGI(TAG, "Invalid provisioning state"); - return ESP_FAIL; - } - - /* Allocate memory for provisioning app data */ - g_prov = (struct app_prov_data *) calloc(1, sizeof(struct app_prov_data)); - if (!g_prov) { - ESP_LOGI(TAG, "Unable to allocate prov data"); - return ESP_ERR_NO_MEM; - } - - /* Initialize app data */ - g_prov->pop = pop; - g_prov->security = security; - - /* Create timer object as a member of app data */ - esp_timer_create_args_t timer_conf = { - .callback = _stop_prov_cb, - .arg = NULL, - .dispatch_method = ESP_TIMER_TASK, - .name = "stop_ble_tm" - }; - esp_err_t err = esp_timer_create(&timer_conf, &g_prov->timer); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to create timer"); - return err; - } - - /* Start provisioning service through BLE */ - err = app_prov_start_service(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Provisioning failed to start"); - return err; - } - - ESP_LOGI(TAG, "BLE Provisioning started"); - return ESP_OK; -} diff --git a/examples/provisioning/ble_prov/main/app_prov.h b/examples/provisioning/ble_prov/main/app_prov.h deleted file mode 100644 index 01b9ba07..00000000 --- a/examples/provisioning/ble_prov/main/app_prov.h +++ /dev/null @@ -1,96 +0,0 @@ -/* BLE based Provisioning Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#pragma once - -#include - -#include -#include - -/** - * @brief Get state of WiFi Station during provisioning - * - * @note WiFi is initially configured as AP, when - * provisioning starts. After provisioning data - * is provided by user, the WiFi is reconfigured - * to run as both AP and Station. - * - * @param[out] state Pointer to wifi_prov_sta_state_t variable to be filled - * - * @return - * - ESP_OK : Successfully retrieved wifi state - * - ESP_FAIL : Provisioning app not running - */ -esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state); - -/** - * @brief Get reason code in case of WiFi station - * disconnection during provisioning - * -* @param[out] reason Pointer to wifi_prov_sta_fail_reason_t variable to be filled - * - * @return - * - ESP_OK : Successfully retrieved wifi disconnect reason - * - ESP_FAIL : Provisioning app not running - */ -esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reason); - -/** - * @brief Event handler for provisioning app - * - * This is called from the main event handler and controls the - * provisioning application, depeding on WiFi events - * - * @param[in] ctx Event context data - * @param[in] event Event info - * - * @return - * - ESP_OK : Event handled successfully - * - ESP_FAIL : Failed to start server on event AP start - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event); - -/** - * @brief Checks if device is provisioned - * * - * @param[out] provisioned True if provisioned, else false - * - * @return - * - ESP_OK : Retrieved provision state successfully - * - ESP_FAIL : Failed to retrieve provision state - */ -esp_err_t app_prov_is_provisioned(bool *provisioned); - -/** - * @brief Runs WiFi as Station - * - * Configures the WiFi station mode to connect to the - * SSID and password specified in config structure, - * and starts WiFi to run as station - * - * @param[in] wifi_cfg Pointer to WiFi cofiguration structure - * - * @return - * - ESP_OK : WiFi configured and started successfully - * - ESP_FAIL : Failed to set configuration - */ -esp_err_t app_prov_configure_sta(wifi_config_t *wifi_cfg); - -/** - * @brief Start provisioning via Bluetooth - * - * @param[in] security Security mode - * @param[in] pop Pointer to proof of possession (NULL if not present) - * - * @return - * - ESP_OK : Provisioning started successfully - * - ESP_FAIL : Failed to start - */ -esp_err_t app_prov_start_ble_provisioning(int security, const protocomm_security_pop_t *pop); diff --git a/examples/provisioning/ble_prov/main/app_prov_handlers.c b/examples/provisioning/ble_prov/main/app_prov_handlers.c deleted file mode 100644 index 4a0c0d99..00000000 --- a/examples/provisioning/ble_prov/main/app_prov_handlers.c +++ /dev/null @@ -1,128 +0,0 @@ -/* SoftAP based Provisioning Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -/* This file is mostly a boiler-plate code that applications can use without much change */ - -#include -#include -#include -#include - -#include -#include - -#include - -#include "app_prov.h" - -static const char* TAG = "app_prov_handler"; - -/* Provide definition of wifi_prov_ctx_t */ -struct wifi_prov_ctx { - wifi_config_t wifi_cfg; -}; - -static wifi_config_t *get_config(wifi_prov_ctx_t **ctx) -{ - return (*ctx ? &(*ctx)->wifi_cfg : NULL); -} - -static wifi_config_t *new_config(wifi_prov_ctx_t **ctx) -{ - free(*ctx); - (*ctx) = (wifi_prov_ctx_t *) calloc(1, sizeof(wifi_prov_ctx_t)); - return get_config(ctx); -} - -static void free_config(wifi_prov_ctx_t **ctx) -{ - free(*ctx); - *ctx = NULL; -} - -static esp_err_t get_status_handler(wifi_prov_config_get_data_t *resp_data, wifi_prov_ctx_t **ctx) -{ - /* Initialize to zero */ - memset(resp_data, 0, sizeof(wifi_prov_config_get_data_t)); - - if (app_prov_get_wifi_state(&resp_data->wifi_state) != ESP_OK) { - ESP_LOGW(TAG, "Prov app not running"); - return ESP_FAIL; - } - - if (resp_data->wifi_state == WIFI_PROV_STA_CONNECTED) { - ESP_LOGI(TAG, "Connected state"); - - /* IP Addr assigned to STA */ - tcpip_adapter_ip_info_t ip_info; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info); - char *ip_addr = ip4addr_ntoa(&ip_info.ip); - strcpy(resp_data->conn_info.ip_addr, ip_addr); - - /* AP information to which STA is connected */ - wifi_ap_record_t ap_info; - esp_wifi_sta_get_ap_info(&ap_info); - memcpy(resp_data->conn_info.bssid, (char *)ap_info.bssid, sizeof(ap_info.bssid)); - memcpy(resp_data->conn_info.ssid, (char *)ap_info.ssid, sizeof(ap_info.ssid)); - resp_data->conn_info.channel = ap_info.primary; - resp_data->conn_info.auth_mode = ap_info.authmode; - } else if (resp_data->wifi_state == WIFI_PROV_STA_DISCONNECTED) { - ESP_LOGI(TAG, "Disconnected state"); - - /* If disconnected, convey reason */ - app_prov_get_wifi_disconnect_reason(&resp_data->fail_reason); - } else { - ESP_LOGI(TAG, "Connecting state"); - } - return ESP_OK; -} - -static esp_err_t set_config_handler(const wifi_prov_config_set_data_t *req_data, wifi_prov_ctx_t **ctx) -{ - wifi_config_t *wifi_cfg = get_config(ctx); - if (wifi_cfg) { - free_config(ctx); - } - - wifi_cfg = new_config(ctx); - if (!wifi_cfg) { - ESP_LOGE(TAG, "Unable to alloc wifi config"); - return ESP_FAIL; - } - - ESP_LOGI(TAG, "WiFi Credentials Received : \n\tssid %s \n\tpassword %s", - req_data->ssid, req_data->password); - memcpy((char *) wifi_cfg->sta.ssid, req_data->ssid, - strnlen(req_data->ssid, sizeof(wifi_cfg->sta.ssid))); - memcpy((char *) wifi_cfg->sta.password, req_data->password, - strnlen(req_data->password, sizeof(wifi_cfg->sta.password))); - return ESP_OK; -} - -static esp_err_t apply_config_handler(wifi_prov_ctx_t **ctx) -{ - wifi_config_t *wifi_cfg = get_config(ctx); - if (!wifi_cfg) { - ESP_LOGE(TAG, "WiFi config not set"); - return ESP_FAIL; - } - - app_prov_configure_sta(wifi_cfg); - ESP_LOGI(TAG, "WiFi Credentials Applied"); - - free_config(ctx); - return ESP_OK; -} - -wifi_prov_config_handlers_t wifi_prov_handlers = { - .get_status_handler = get_status_handler, - .set_config_handler = set_config_handler, - .apply_config_handler = apply_config_handler, - .ctx = NULL -}; diff --git a/examples/provisioning/ble_prov/main/component.mk b/examples/provisioning/ble_prov/main/component.mk deleted file mode 100644 index 61f8990c..00000000 --- a/examples/provisioning/ble_prov/main/component.mk +++ /dev/null @@ -1,8 +0,0 @@ -# -# Main component makefile. -# -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a -# in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# diff --git a/examples/provisioning/ble_prov/partitions.csv b/examples/provisioning/ble_prov/partitions.csv deleted file mode 100644 index e382463f..00000000 --- a/examples/provisioning/ble_prov/partitions.csv +++ /dev/null @@ -1,5 +0,0 @@ -# Name, Type, SubType, Offset, Size, Flags -# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild -nvs, data, nvs, 0x9000, 0x6000, -phy_init, data, phy, 0xf000, 0x1000, -factory, app, factory, 0x10000, 1200000, diff --git a/examples/provisioning/ble_prov/sdkconfig.defaults b/examples/provisioning/ble_prov/sdkconfig.defaults deleted file mode 100644 index 47e57831..00000000 --- a/examples/provisioning/ble_prov/sdkconfig.defaults +++ /dev/null @@ -1,10 +0,0 @@ -# Override some defaults so BT stack is enabled and -CONFIG_BT_ENABLED=y -CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y -CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY= -CONFIG_BTDM_CONTROLLER_MODE_BTDM= - -# Binary is larger than default size -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/examples/provisioning/console_prov/CMakeLists.txt b/examples/provisioning/console_prov/CMakeLists.txt deleted file mode 100644 index 65420058..00000000 --- a/examples/provisioning/console_prov/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(console_prov) diff --git a/examples/provisioning/console_prov/Makefile b/examples/provisioning/console_prov/Makefile deleted file mode 100644 index c84ccd93..00000000 --- a/examples/provisioning/console_prov/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := console_prov - -include $(IDF_PATH)/make/project.mk - diff --git a/examples/provisioning/console_prov/README.md b/examples/provisioning/console_prov/README.md deleted file mode 100644 index cb7551c6..00000000 --- a/examples/provisioning/console_prov/README.md +++ /dev/null @@ -1,212 +0,0 @@ -# Console based Provisioning Example - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -`console_prov` example demonstrates the implementation and integration of various IDF components for building a console based provisioning application. - -For this example UART console 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). - -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. - -Right after provisioning is complete, the UART console is deactivated. - -`console_prov` uses the following components : -* `wifi_provisioning` : provides data structures and protocomm endpoint handlers for Wi-Fi configuration -* `protocomm` : for protocol based communication and secure session establishment -* `protobuf` : Google's protocol buffer library for serialization of protocomm data structures - -This example can be used, as it is, for adding a provisioning service to any application intended for IoT. But it is more suitable for debugging protocomm and provisioning related components and feature additions. - -## How to use example - -### Hardware Required - -Example should be able to run on any commonly available ESP32 development board. - -### Application Required - -To provision the device running this example, the `esp_prov.py` script needs to be run (found under `$IDF_PATH/tools/esp_prov`). This feature of `esp_prov` should work on all platforms, given the dependencies are satisfied. - -### Configure the project - -``` -make menuconfig -``` - -* Set serial port under Serial Flasher Options. - -* Under Example Configuration set the following : - * Security Version (default 1) - * Proof of Possession (default "abcd1234") - -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -make -j4 flash monitor -``` - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -``` -I (388) app: Starting console provisioning -I (398) app_prov: Console provisioning started -. -. -. ->> -``` - -In a separate terminal run the `esp_prov.py` script under `$IDP_PATH/tools/esp_prov` directory (please replace `myssid` and `mypassword` with the credentials of the AP to which the device is supposed to connect to after provisioning). Assuming default example configuration, the script should be run as follows : - -``` -python esp_prov.py --ssid myssid --passphrase mypassword --sec_ver 1 --pop abcd1234 --transport console -``` - -A console will open up and the `Client->Device` commands have to be copied manually to the serial monitor console prompt : - -``` -==== Esp_Prov Version: V0.1 ==== - -==== Verifying protocol version ==== -Client->Device msg : proto-ver 0 56302e31 -Enter device->client msg : -``` - -On pasting the command on the serial monitor console, a `Device->Client` message will appear for each command : - -``` ->> proto-ver 0 56302e31 -53554343455353 -``` - -Copy this message back to the `esp_prov` console for proceeding to the next command : - -``` -==== Verifying protocol version ==== -Client->Device msg : proto-ver 0 56302e31 -Enter device->client msg : 53554343455353 -==== Verified protocol version successfully ==== - -==== Starting Session ==== -Client->Device msg : prov-session 0 10015a25a201220a20677106cc2f5b2acb5d8da26f0ad443df006daa1cd5bb3d75a8324d81ec5ef970 -Enter device->client msg : -``` - -This process keeps on till the device gets provisioned. - -Note that the commands are in the following format : - -``` - -``` - -This is helpful in understanding the provisioning process and the order in which the endpoints are communicated with. - -The full execution sequence of `esp_prov`, as seen on the console, is shown here : - -``` -==== Esp_Prov Version: V0.1 ==== - -==== Verifying protocol version ==== -Client->Device msg : proto-ver 0 56302e31 -Enter device->client msg : 53554343455353 -==== Verified protocol version successfully ==== - -==== Starting Session ==== -Client->Device msg : prov-session 0 10015a25a201220a20677106cc2f5b2acb5d8da26f0ad443df006daa1cd5bb3d75a8324d81ec5ef970 -Enter device->client msg : 10015a390801aa013412207566f4de191f600ea42de5c2b1df73f1f16685c2edb43d7c3ffc83d6b81ff61b1a103db6476536a88db10b7e0a172d4adef8 -Client->Device msg : prov-session 0 10015a270802b20122122084ca311e51c904a94f8a249c049f7aed33b39671cc11f0b92b15b299ef5653b7 -Enter device->client msg : 10015a270803ba01221a203246230190d5c1f5d94c01b56ac8cace1086cfb2d937a4a46cb6c79db7a35a8b -==== Session Established ==== - -==== Sending Wifi credential to esp32 ==== -Client->Device msg : prov-config 0 8f0c8cb6f2d53c4cc53b29be8ba1aac3edbb1dead39117c34687d6 -Enter device->client msg : 2e1f0eb0 -==== Wifi Credentials sent successfully ==== - -==== Applying config to esp32 ==== -Client->Device msg : prov-config 0 e8df -Enter device->client msg : 245c83f0 -==== Apply config sent successfully ==== - -==== Wifi connection state ==== -Client->Device msg : prov-config 0 2d36 -Enter device->client msg : 1b38a7411b6e2608aae50a6571807e04a6e90520b3b1e3c1e5b38cea4b9022e56485b92ff84289df218311972a42eb -++++ WiFi state: connected ++++ -==== Provisioning was successful ==== -``` - -The serial monitor console, for above sequence of commands, would look like : - -``` ->> proto-ver 0 56302e31 -53554343455353 ->> prov-session 0 10015a25a201220a20677106cc2f5b2acb5d8da26f0ad443df006daa1cd5bb3d75a8324d81ec5ef970 -10015a390801aa013412207566f4de191f600ea42de5c2b1df73f1f16685c2edb43d7c3ffc83d6b81ff61b1a103db6476536a88db10b7e0a172d4adef8 ->> prov-session 0 10015a270802b20122122084ca311e51c904a94f8a249c049f7aed33b39671cc11f0b92b15b299ef5653b7 -10015a270803ba01221a203246230190d5c1f5d94c01b56ac8cace1086cfb2d937a4a46cb6c79db7a35a8b ->> prov-config 0 8f0c8cb6f2d53c4cc53b29be8ba1aac3edbb1dead39117c34687d6 -I (1073738) app_prov_handler: WiFi Credentials Received : - ssid : myssid - password : mypassword - -2e1f0eb0 ->> prov-config 0 e8df -I (1084218) app_prov_handler: WiFi Credentials Applied - -245c83f0 ->> prov-config 0 2d36 -I (1089728) app_prov: STA Got IP -I (1089728) app: got ip:192.168.43.220 -I (1099698) app_prov_handler: Connected state - -1b38a7411b6e2608aae50a6571807e04a6e90520b3b1e3c1e5b38cea4b9022e56485b92ff84289df218311972a42eb ->> -``` - -After sometime the provisioning app will exit and UART console will be stopped - -``` -I (1119728) app_prov: Stopping provisioning -I (1119728) protocomm_console: Stopping console... -I (1119728) app_prov: Provisioning stopped -I (1119748) protocomm_console: Console stopped -``` - -## Troubleshooting - -### Provisioning failed - -It is possible that the Wi-Fi credentials provided were incorrect, or the device was not able to establish connection to the network, in which the the `esp_prov` script will notify failure (with reason) and the provisioning app will continue running, allowing the user to retry the process. Serial monitor log will display the failure along with disconnect reason : - -``` -E (39291) app_prov: STA Disconnected -E (39291) app_prov: Disconnect reason : 201 -I (39291) app_prov: STA AP Not found -I (42021) app_prov_handler: Disconnected state -``` - -### Provisioning does not start - -If the serial monitor log is different, as shown below : - -``` -I (539) app_prov: Found ssid myssid -I (539) app_prov: Found password mypassword -I (549) app: Starting WiFi station -``` - -It means the Wi-Fi credentials were already set by some other application flashed previously to your device. To erase these credentials either do full erase and then flash the example - -``` -make erase_flash -make -j4 flash monitor -``` - -Or, enable `Reset Provisioning` option under `Example Configuration` under menuconfig. But this will erase the saved Wi-Fi credentials every time the device boots, so this is not the preferred solution. diff --git a/examples/provisioning/console_prov/main/CMakeLists.txt b/examples/provisioning/console_prov/main/CMakeLists.txt deleted file mode 100644 index 3c44a1a3..00000000 --- a/examples/provisioning/console_prov/main/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(COMPONENT_SRCS "app_main.c" - "app_prov.c" - "app_prov_handlers.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") - -register_component() diff --git a/examples/provisioning/console_prov/main/Kconfig.projbuild b/examples/provisioning/console_prov/main/Kconfig.projbuild deleted file mode 100644 index b669a1e5..00000000 --- a/examples/provisioning/console_prov/main/Kconfig.projbuild +++ /dev/null @@ -1,34 +0,0 @@ -menu "Example Configuration" - -config USE_SEC_1 - bool - default y - prompt "Use Security Version 1" - help - Security version 1 used Curve25519 key exchange for establishing - secure session between device and client during provisioning - -config USE_POP - bool - depends on USE_SEC_1 - default y - prompt "Use proof-of-possession" - help - Proof-of-possession can be optionally used to prove that the device is indeed - in possession of the user who is provisioning the device. This proof-of-possession - is internally used to generate the shared secret through key exchange. - -config POP - string "Proof-of-possession" - default "abcd1234" - depends on USE_POP - -config RESET_PROVISIONED - bool - default n - prompt "Reset provisioned status of the device" - help - This erases the NVS to reset provisioned status of the device on every reboot. - Provisioned status is determined by the WiFi STA configuration, saved on the NVS. - -endmenu diff --git a/examples/provisioning/console_prov/main/app_main.c b/examples/provisioning/console_prov/main/app_main.c deleted file mode 100644 index 9edfdd2e..00000000 --- a/examples/provisioning/console_prov/main/app_main.c +++ /dev/null @@ -1,114 +0,0 @@ -/* Console based Provisioning Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "app_prov.h" - -static const char *TAG = "app"; - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* Invoke Provisioning event handler first */ - app_prov_event_handler(ctx, event); - - switch(event->event_id) { - case SYSTEM_EVENT_AP_START: - ESP_LOGI(TAG, "SoftAP started"); - break; - case SYSTEM_EVENT_AP_STOP: - ESP_LOGI(TAG, "SoftAP stopped"); - break; - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:"MACSTR" join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:"MACSTR"leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - break; - default: - break; - } - return ESP_OK; -} - -static void wifi_init_sta() -{ - /* Start wifi in station mode with credentials set during provisioning */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_start() ); -} - -void app_main() -{ - /* Security version */ - int security = 0; - /* Proof of possession */ - const protocomm_security_pop_t *pop = NULL; - -#ifdef CONFIG_USE_SEC_1 - security = 1; -#endif - - /* Having proof of possession is optional */ -#ifdef CONFIG_USE_POP - const static protocomm_security_pop_t app_pop = { - .data = (uint8_t *) CONFIG_POP, - .len = (sizeof(CONFIG_POP)-1) - }; - pop = &app_pop; -#endif - - /* Initialize networking stack */ - tcpip_adapter_init(); - - /* Set our event handling */ - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); - - /* Check if device is provisioned */ - bool provisioned; - if (app_prov_is_provisioned(&provisioned) != ESP_OK) { - ESP_LOGE(TAG, "Error getting device provisioning state"); - return; - } - - if (provisioned == false) { - /* If not provisioned, start provisioning via console */ - ESP_LOGI(TAG, "Starting console provisioning"); - app_prov_start_console_provisioning(security, pop); - } else { - /* Else start as station with credentials set during provisioning */ - ESP_LOGI(TAG, "Starting WiFi station"); - wifi_init_sta(NULL); - } -} diff --git a/examples/provisioning/console_prov/main/app_prov.c b/examples/provisioning/console_prov/main/app_prov.c deleted file mode 100644 index 83c4e4e0..00000000 --- a/examples/provisioning/console_prov/main/app_prov.c +++ /dev/null @@ -1,336 +0,0 @@ -/* Console based Provisioning Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "app_prov.h" - -static const char *TAG = "app_prov"; - -/* Handlers for wifi_config provisioning endpoint */ -extern wifi_prov_config_handlers_t wifi_prov_handlers; - -/** - * @brief Data relevant to provisioning application - */ -struct app_prov_data { - protocomm_t *pc; /*!< Protocomm handler */ - int security; /*!< Type of security to use with protocomm */ - const protocomm_security_pop_t *pop; /*!< Pointer to proof of possession */ - esp_timer_handle_t timer; /*!< Handle to timer */ - - /* State of WiFi Station */ - wifi_prov_sta_state_t wifi_state; - - /* Code for WiFi station disconnection (if disconnected) */ - wifi_prov_sta_fail_reason_t wifi_disconnect_reason; -}; - -/* Pointer to provisioning application data */ -static struct app_prov_data *g_prov; - -static esp_err_t app_prov_start_service(void) -{ - /* Create new protocomm instance */ - g_prov->pc = protocomm_new(); - if (g_prov->pc == NULL) { - ESP_LOGE(TAG, "Failed to create new protocomm instance"); - return ESP_FAIL; - } - - /* Config for protocomm_console_start() */ - protocomm_console_config_t config = PROTOCOMM_CONSOLE_DEFAULT_CONFIG(); - - /* Start protocomm using console */ - if (protocomm_console_start(g_prov->pc, &config) != ESP_OK) { - ESP_LOGE(TAG, "Failed to start console provisioning"); - return ESP_FAIL; - } - - /* Set protocomm version verification endpoint for protocol */ - protocomm_set_version(g_prov->pc, "proto-ver", "V0.1"); - - /* Set protocomm security type for endpoint */ - if (g_prov->security == 0) { - protocomm_set_security(g_prov->pc, "prov-session", &protocomm_security0, NULL); - } else if (g_prov->security == 1) { - protocomm_set_security(g_prov->pc, "prov-session", &protocomm_security1, g_prov->pop); - } - - /* Add endpoint for provisioning to set wifi station config */ - if (protocomm_add_endpoint(g_prov->pc, "prov-config", - wifi_prov_config_data_handler, - (void *) &wifi_prov_handlers) != ESP_OK) { - ESP_LOGE(TAG, "Failed to set provisioning endpoint"); - protocomm_console_stop(g_prov->pc); - return ESP_FAIL; - } - - ESP_LOGI(TAG, "Provisioning started"); - return ESP_OK; -} - -static void app_prov_stop_service(void) -{ - /* Remove provisioning endpoint */ - protocomm_remove_endpoint(g_prov->pc, "prov-config"); - /* Unset provisioning security */ - protocomm_unset_security(g_prov->pc, "prov-session"); - /* Unset provisioning version endpoint */ - protocomm_unset_version(g_prov->pc, "proto-ver"); - /* Stop protocomm console service */ - protocomm_console_stop(g_prov->pc); - /* Delete protocomm instance */ - protocomm_delete(g_prov->pc); -} - -/* Task spawned by timer callback */ -static void stop_prov_task(void * arg) -{ - ESP_LOGI(TAG, "Stopping provisioning"); - app_prov_stop_service(); - - /* Timer not needed anymore */ - esp_timer_handle_t timer = g_prov->timer; - esp_timer_delete(timer); - g_prov->timer = NULL; - - /* Free provisioning process data */ - free(g_prov); - g_prov = NULL; - ESP_LOGI(TAG, "Provisioning stopped"); - - vTaskDelete(NULL); -} - -/* Callback to be invoked by timer */ -static void _stop_prov_cb(void * arg) -{ - xTaskCreate(&stop_prov_task, "stop_prov", 2048, NULL, tskIDLE_PRIORITY, NULL); -} - -/* Event handler for starting/stopping provisioning. - * To be called from within the context of the main - * event handler. - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - /* If pointer to provisioning application data is NULL - * then provisioning is not running, therefore return without - * error */ - if (!g_prov) { - return ESP_OK; - } - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - ESP_LOGI(TAG, "STA Start"); - /* Once configuration is received through protocomm, - * device is started as station. Once station starts, - * wait for connection to establish with configured - * host SSID and password */ - g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; - break; - - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "STA Got IP"); - /* Station got IP. That means configuration is successful. - * Schedule timer to stop provisioning app after 30 seconds. */ - g_prov->wifi_state = WIFI_PROV_STA_CONNECTED; - if (g_prov && g_prov->timer) { - esp_timer_start_once(g_prov->timer, 30000*1000U); - } - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGE(TAG, "STA Disconnected"); - /* Station couldn't connect to configured host SSID */ - g_prov->wifi_state = WIFI_PROV_STA_DISCONNECTED; - ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason); - - /* Set code corresponding to the reason for disconnection */ - switch (info->disconnected.reason) { - case WIFI_REASON_AUTH_EXPIRE: - case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: - case WIFI_REASON_BEACON_TIMEOUT: - case WIFI_REASON_AUTH_FAIL: - case WIFI_REASON_ASSOC_FAIL: - case WIFI_REASON_HANDSHAKE_TIMEOUT: - ESP_LOGI(TAG, "STA Auth Error"); - g_prov->wifi_disconnect_reason = WIFI_PROV_STA_AUTH_ERROR; - break; - case WIFI_REASON_NO_AP_FOUND: - ESP_LOGI(TAG, "STA AP Not found"); - g_prov->wifi_disconnect_reason = WIFI_PROV_STA_AP_NOT_FOUND; - break; - default: - /* If none of the expected reasons, - * retry connecting to host SSID */ - g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; - esp_wifi_connect(); - } - break; - - default: - break; - } - return ESP_OK; -} - -esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state) -{ - if (g_prov == NULL || state == NULL) { - return ESP_FAIL; - } - - *state = g_prov->wifi_state; - return ESP_OK; -} - -esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reason) -{ - if (g_prov == NULL || reason == NULL) { - return ESP_FAIL; - } - - if (g_prov->wifi_state != WIFI_PROV_STA_DISCONNECTED) { - return ESP_FAIL; - } - - *reason = g_prov->wifi_disconnect_reason; - return ESP_OK; -} - -esp_err_t app_prov_is_provisioned(bool *provisioned) -{ - *provisioned = false; - -#ifdef CONFIG_RESET_PROVISIONED - nvs_flash_erase(); -#endif - - if (nvs_flash_init() != ESP_OK) { - ESP_LOGE(TAG, "Failed to init NVS"); - return ESP_FAIL; - } - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - if (esp_wifi_init(&cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to init wifi"); - return ESP_FAIL; - } - - /* Get WiFi Station configuration */ - wifi_config_t wifi_cfg; - if (esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_cfg) != ESP_OK) { - return ESP_FAIL; - } - - if (strlen((const char*) wifi_cfg.sta.ssid)) { - *provisioned = true; - ESP_LOGI(TAG, "Found ssid %s", (const char*) wifi_cfg.sta.ssid); - ESP_LOGI(TAG, "Found password %s", (const char*) wifi_cfg.sta.password); - } - return ESP_OK; -} - -esp_err_t app_prov_configure_sta(wifi_config_t *wifi_cfg) -{ - /* Initialize WiFi with default config */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - if (esp_wifi_init(&cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to init WiFi"); - return ESP_FAIL; - } - /* Configure WiFi as station */ - if (esp_wifi_set_mode(WIFI_MODE_STA) != ESP_OK) { - ESP_LOGE(TAG, "Failed to set WiFi mode"); - return ESP_FAIL; - } - /* Configure WiFi station with host credentials - * provided during provisioning */ - if (esp_wifi_set_config(ESP_IF_WIFI_STA, wifi_cfg) != ESP_OK) { - ESP_LOGE(TAG, "Failed to set WiFi configuration"); - return ESP_FAIL; - } - /* Start WiFi */ - if (esp_wifi_start() != ESP_OK) { - ESP_LOGE(TAG, "Failed to set WiFi configuration"); - return ESP_FAIL; - } - /* Connect to AP */ - if (esp_wifi_connect() != ESP_OK) { - ESP_LOGE(TAG, "Failed to connect WiFi"); - return ESP_FAIL; - } - - if (g_prov) { - /* Reset wifi station state for provisioning app */ - g_prov->wifi_state = WIFI_PROV_STA_CONNECTING; - } - return ESP_OK; -} - -esp_err_t app_prov_start_console_provisioning(int security, const protocomm_security_pop_t *pop) -{ - /* If provisioning app data present, - * means provisioning app is already running */ - if (g_prov) { - ESP_LOGI(TAG, "Invalid provisioning state"); - return ESP_FAIL; - } - - /* Allocate memory for provisioning app data */ - g_prov = (struct app_prov_data *) calloc(1, sizeof(struct app_prov_data)); - if (!g_prov) { - ESP_LOGI(TAG, "Unable to allocate prov data"); - return ESP_ERR_NO_MEM; - } - - /* Initialize app data */ - g_prov->pop = pop; - g_prov->security = security; - - /* Create timer object as a member of app data */ - esp_timer_create_args_t timer_conf = { - .callback = _stop_prov_cb, - .arg = NULL, - .dispatch_method = ESP_TIMER_TASK, - .name = "stop_console_tm" - }; - esp_err_t err = esp_timer_create(&timer_conf, &g_prov->timer); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to create timer"); - return err; - } - - /* Start provisioning service through console */ - err = app_prov_start_service(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Provisioning failed to start"); - return err; - } - - ESP_LOGI(TAG, "Console provisioning started"); - return ESP_OK; -} diff --git a/examples/provisioning/console_prov/main/app_prov.h b/examples/provisioning/console_prov/main/app_prov.h deleted file mode 100644 index c1ac7c3e..00000000 --- a/examples/provisioning/console_prov/main/app_prov.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Console based Provisioning Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#pragma once - -#include - -#include -#include - -/** - * @brief Get state of WiFi Station during provisioning - * - * @note WiFi is initially configured as AP, when - * provisioning starts. After provisioning data - * is provided by user, the WiFi is reconfigured - * to run as both AP and Station. - * - * @param[out] state Pointer to wifi_prov_sta_state_t variable to be filled - * - * @return - * - ESP_OK : Successfully retrieved wifi state - * - ESP_FAIL : Provisioning app not running - */ -esp_err_t app_prov_get_wifi_state(wifi_prov_sta_state_t* state); - -/** - * @brief Get reason code in case of WiFi station - * disconnection during provisioning - * -* @param[out] reason Pointer to wifi_prov_sta_fail_reason_t variable to be filled - * - * @return - * - ESP_OK : Successfully retrieved wifi disconnect reason - * - ESP_FAIL : Provisioning app not running - */ -esp_err_t app_prov_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t* reason); - -/** - * @brief Event handler for provisioning app - * - * This is called from the main event handler and controls the - * provisioning application, depeding on WiFi events - * - * @param[in] ctx Event context data - * @param[in] event Event info - * - * @return - * - ESP_OK : Event handled successfully - * - ESP_FAIL : Failed to start server on event AP start - */ -esp_err_t app_prov_event_handler(void *ctx, system_event_t *event); - -/** - * @brief Checks if device is provisioned - * * - * @param[out] provisioned True if provisioned, else false - * - * @return - * - ESP_OK : Retrieved provision state successfully - * - ESP_FAIL : Failed to retrieve provision state - */ -esp_err_t app_prov_is_provisioned(bool *provisioned); - -/** - * @brief Runs WiFi as Station - * - * Configures the WiFi station mode to connect to the - * SSID and password specified in config structure, - * and starts WiFi to run as station - * - * @param[in] wifi_cfg Pointer to WiFi cofiguration structure - * - * @return - * - ESP_OK : WiFi configured and started successfully - * - ESP_FAIL : Failed to set configuration - */ -esp_err_t app_prov_configure_sta(wifi_config_t *wifi_cfg); - -/** - * @brief Start provisioning via Console - * - * @param[in] security Security mode - * @param[in] pop Pointer to proof of possession (NULL if not present) - * - * @return - * - ESP_OK : Provisioning started successfully - * - ESP_FAIL : Failed to start - */ -esp_err_t app_prov_start_console_provisioning(int security, const protocomm_security_pop_t *pop); diff --git a/examples/provisioning/console_prov/main/app_prov_handlers.c b/examples/provisioning/console_prov/main/app_prov_handlers.c deleted file mode 100644 index 49c29739..00000000 --- a/examples/provisioning/console_prov/main/app_prov_handlers.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Console based Provisioning Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -/* This file is mostly a boiler-plate code that applications can use without much change */ - -#include -#include -#include -#include - -#include -#include - -#include - -#include "app_prov.h" - -static const char* TAG = "app_prov_handler"; - -/* Provide definition of wifi_prov_ctx_t */ -struct wifi_prov_ctx { - wifi_config_t wifi_cfg; -}; - -static wifi_config_t *get_config(wifi_prov_ctx_t **ctx) -{ - return (*ctx ? &(*ctx)->wifi_cfg : NULL); -} - -static wifi_config_t *new_config(wifi_prov_ctx_t **ctx) -{ - free(*ctx); - (*ctx) = (wifi_prov_ctx_t *) calloc(1, sizeof(wifi_prov_ctx_t)); - return get_config(ctx); -} - -static void free_config(wifi_prov_ctx_t **ctx) -{ - free(*ctx); - *ctx = NULL; -} - -static esp_err_t get_status_handler(wifi_prov_config_get_data_t *resp_data, wifi_prov_ctx_t **ctx) -{ - /* Initialize to zero */ - memset(resp_data, 0, sizeof(wifi_prov_config_get_data_t)); - - if (app_prov_get_wifi_state(&resp_data->wifi_state) != ESP_OK) { - ESP_LOGW(TAG, "Prov app not running"); - return ESP_FAIL; - } - - if (resp_data->wifi_state == WIFI_PROV_STA_CONNECTED) { - ESP_LOGI(TAG, "Connected state"); - - /* IP Addr assigned to STA */ - tcpip_adapter_ip_info_t ip_info; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info); - char *ip_addr = ip4addr_ntoa(&ip_info.ip); - strcpy(resp_data->conn_info.ip_addr, ip_addr); - - /* AP information to which STA is connected */ - wifi_ap_record_t ap_info; - esp_wifi_sta_get_ap_info(&ap_info); - memcpy(resp_data->conn_info.bssid, (char *)ap_info.bssid, sizeof(ap_info.bssid)); - memcpy(resp_data->conn_info.ssid, (char *)ap_info.ssid, sizeof(ap_info.ssid)); - resp_data->conn_info.channel = ap_info.primary; - resp_data->conn_info.auth_mode = ap_info.authmode; - } else if (resp_data->wifi_state == WIFI_PROV_STA_DISCONNECTED) { - ESP_LOGI(TAG, "Disconnected state"); - - /* If disconnected, convey reason */ - app_prov_get_wifi_disconnect_reason(&resp_data->fail_reason); - } else { - ESP_LOGI(TAG, "Connecting state"); - } - return ESP_OK; -} - -static esp_err_t set_config_handler(const wifi_prov_config_set_data_t *req_data, wifi_prov_ctx_t **ctx) -{ - wifi_config_t *wifi_cfg = get_config(ctx); - if (wifi_cfg) { - free_config(ctx); - } - - wifi_cfg = new_config(ctx); - if (!wifi_cfg) { - ESP_LOGE(TAG, "Unable to alloc wifi config"); - return ESP_FAIL; - } - - ESP_LOGI(TAG, "WiFi Credentials Received : \n\tssid %s \n\tpassword %s", - req_data->ssid, req_data->password); - memcpy((char *) wifi_cfg->sta.ssid, req_data->ssid, - strnlen(req_data->ssid, sizeof(wifi_cfg->sta.ssid))); - memcpy((char *) wifi_cfg->sta.password, req_data->password, - strnlen(req_data->password, sizeof(wifi_cfg->sta.password))); - return ESP_OK; -} - -static esp_err_t apply_config_handler(wifi_prov_ctx_t **ctx) -{ - wifi_config_t *wifi_cfg = get_config(ctx); - if (!wifi_cfg) { - ESP_LOGE(TAG, "WiFi config not set"); - return ESP_FAIL; - } - - app_prov_configure_sta(wifi_cfg); - ESP_LOGI(TAG, "WiFi Credentials Applied"); - - free_config(ctx); - return ESP_OK; -} - -wifi_prov_config_handlers_t wifi_prov_handlers = { - .get_status_handler = get_status_handler, - .set_config_handler = set_config_handler, - .apply_config_handler = apply_config_handler, - .ctx = NULL -}; diff --git a/examples/provisioning/console_prov/main/component.mk b/examples/provisioning/console_prov/main/component.mk deleted file mode 100644 index 61f8990c..00000000 --- a/examples/provisioning/console_prov/main/component.mk +++ /dev/null @@ -1,8 +0,0 @@ -# -# Main component makefile. -# -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a -# in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# diff --git a/examples/provisioning/custom_config/components/custom_provisioning/include/custom_provisioning/custom_config.h b/examples/provisioning/custom_config/components/custom_provisioning/include/custom_provisioning/custom_config.h index a9b6214a..e76c808e 100644 --- a/examples/provisioning/custom_config/components/custom_provisioning/include/custom_provisioning/custom_config.h +++ b/examples/provisioning/custom_config/components/custom_provisioning/include/custom_provisioning/custom_config.h @@ -14,6 +14,7 @@ #ifndef _CUSTOM_PROV_CONFIG_H_ #define _CUSTOM_PROV_CONFIG_H_ +#include /** * @brief Custom config data received by device diff --git a/examples/provisioning/custom_config/main/app_prov.c b/examples/provisioning/custom_config/main/app_prov.c index 6ed3df19..f183f644 100644 --- a/examples/provisioning/custom_config/main/app_prov.c +++ b/examples/provisioning/custom_config/main/app_prov.c @@ -14,6 +14,9 @@ #include #include +#include +#include +#include #include #include #include diff --git a/examples/provisioning/custom_config/sdkconfig.defaults b/examples/provisioning/custom_config/sdkconfig.defaults new file mode 100644 index 00000000..17ac268d --- /dev/null +++ b/examples/provisioning/custom_config/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_ENABLE_UNIFIED_PROVISIONING=y diff --git a/examples/provisioning/softap_prov/main/app_prov.c b/examples/provisioning/softap_prov/main/app_prov.c index 79c1e0da..69aed5a5 100644 --- a/examples/provisioning/softap_prov/main/app_prov.c +++ b/examples/provisioning/softap_prov/main/app_prov.c @@ -14,6 +14,9 @@ #include #include +#include +#include +#include #include #include #include diff --git a/examples/provisioning/softap_prov/sdkconfig.defaults b/examples/provisioning/softap_prov/sdkconfig.defaults new file mode 100644 index 00000000..17ac268d --- /dev/null +++ b/examples/provisioning/softap_prov/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_ENABLE_UNIFIED_PROVISIONING=y diff --git a/examples/provisioning/softap_prov/softap_prov_test.py b/examples/provisioning/softap_prov/softap_prov_test.py deleted file mode 100644 index d986847d..00000000 --- a/examples/provisioning/softap_prov/softap_prov_test.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2018 Espressif Systems (Shanghai) PTE LTD -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import print_function -import imp -import re -import os -import sys -import time - -# This environment variable is expected on the host machine -test_fw_path = os.getenv("TEST_FW_PATH") -if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - -# When running on local machine execute the following before running this script -# > export TEST_FW_PATH='~/esp/esp-idf/tools/tiny-test-fw' -# > make print_flash_cmd | tail -n 1 > build/download.config -# > make app bootloader - -import TinyFW -import IDF - -# Import esp_prov tool -idf_path = os.environ['IDF_PATH'] -esp_prov = imp.load_source("esp_prov", idf_path + "/tools/esp_prov/esp_prov.py") -wifi_tools = imp.load_source("wifi_tools", idf_path + "/examples/provisioning/softap_prov/utils/wifi_tools.py") - -@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") - - # Get binary file - binary_file = os.path.join(dut1.app.binary_path, "softap_prov.bin") - bin_size = os.path.getsize(binary_file) - IDF.log_performance("softap_prov_bin_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("softap_prov_bin_size", bin_size//1024) - - # Upload binary and start testing - dut1.start_app() - - # Parse IP address of STA - dut1.expect("Starting WiFi SoftAP provisioning") - dut1.expect("SoftAP started") - [ssid, password] = dut1.expect(re.compile(r"(?:[\s\S]*)SoftAP Provisioning started with SSID '(\S+)', Password '(\S+)'")) - - iface = wifi_tools.get_wiface_name() - if iface == None: - raise RuntimeError("Failed to get Wi-Fi interface on host") - print("Interface name : " + iface) - print("SoftAP SSID : " + ssid) - print("SoftAP Password : " + password) - - ctrl = wifi_tools.wpa_cli(iface, reset_on_exit = True) - print("Connecting to DUT SoftAP...") - ip = ctrl.connect(ssid, password) - print("Connected to DUT SoftAP") - - print("Starting Provisioning") - verbose = False - protover = "V0.1" - secver = 1 - pop = "abcd1234" - provmode = "softap" - ap_ssid = "myssid" - ap_password = "mypassword" - softap_endpoint = ip.split('.')[0] + "." + ip.split('.')[1]+ "." + ip.split('.')[2] + ".1:80" - - print("Getting security") - security = esp_prov.get_security(secver, pop, verbose) - if security == None: - raise RuntimeError("Failed to get security") - - print("Getting transport") - transport = esp_prov.get_transport(provmode, softap_endpoint, None) - if transport == None: - raise RuntimeError("Failed to get transport") - - print("Verifying protocol version") - if not esp_prov.version_match(transport, protover): - raise RuntimeError("Mismatch in protocol version") - - print("Starting Session") - if not esp_prov.establish_session(transport, security): - raise RuntimeError("Failed to start session") - - 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") - - print("Applying config") - if not esp_prov.apply_wifi_config(transport, security): - raise RuntimeError("Failed to send apply config") - - success = False - while True: - time.sleep(5) - print("Wi-Fi connection state") - ret = esp_prov.get_wifi_config(transport, security) - if (ret == 1): - continue - elif (ret == 0): - print("Provisioning was successful") - success = True - break - - if not success: - raise RuntimeError("Provisioning failed") - -if __name__ == '__main__': - test_examples_provisioning_softap() diff --git a/tools/esp_prov/README.md b/tools/esp_prov/README.md index 9d7a0e91..98f54f77 100644 --- a/tools/esp_prov/README.md +++ b/tools/esp_prov/README.md @@ -1,24 +1,26 @@ # ESP Provisioning Tool # NAME -`esp_prov` - A python based utility for testing the provisioning examples over a host +`esp_prov` - A python based utility for testing the provisioning examples over a host using Httpd on a soft AP interface. # SYNOPSIS ``` -python esp_prov.py --transport < mode of provisioning : softap \ ble \ console > --ssid < AP SSID > --passphrase < AP Password > --sec_ver < Security version 0 / 1 > [ Optional parameters... ] +python esp_prov.py --ssid < AP SSID > --passphrase < AP Password > --sec_ver < Security version 0 / 1 > [ Optional parameters... ] ``` # DESCRIPTION +For SoftAP + HTTPD based provisioning. This assumes that the device is running in Wi-Fi SoftAP mode and hosts an HTTP server supporting specific endpoint URIs. Also client needs to connect to the device softAP network before running `esp_prov`. + Usage of `esp-prov` assumes that the provisioning app has specific protocomm endpoints active. These endpoints are active in the provisioning examples and accept specific protobuf data structures: -| Endpoint Name | URI (HTTP server on ip:port) | UUID (BLE) | Description | -|---------------|------------------------------|--------------------------------------|-----------------------------------------------------------| -| prov-session | http://ip:port/prov-session | 0000ff51-0000-1000-8000-00805f9b34fb | Security endpoint used for session establishment | -| prov-config | http://ip:port/prov-config | 0000ff52-0000-1000-8000-00805f9b34fb | Endpoint used for configuring Wi-Fi credentials on device | -| proto-ver | http://ip:port/proto-ver | 0000ff53-0000-1000-8000-00805f9b34fb | Version endpoint for checking protocol compatibility | -| custom-config | http://ip:port/custom-config | NA | Optional endpoint for configuring custom credentials | +| Endpoint Name | URI (HTTP server on ip:port) | Description | +|---------------|------------------------------|-----------------------------------------------------------| +| prov-session | http://ip:port/prov-session | Security endpoint used for session establishment | +| prov-config | http://ip:port/prov-config | Endpoint used for configuring Wi-Fi credentials on device | +| proto-ver | http://ip:port/proto-ver | Version endpoint for checking protocol compatibility | +| custom-config | http://ip:port/custom-config | Optional endpoint for configuring custom credentials | # PARAMETERS @@ -28,15 +30,6 @@ Usage of `esp-prov` assumes that the provisioning app has specific protocomm end * `--verbose`, `-v` Sets the verbosity level of output log -* `--transport ` - Three options are available: - * `softap` - For SoftAP + HTTPD based provisioning. This assumes that the device is running in Wi-Fi SoftAP mode and hosts an HTTP server supporting specific endpoint URIs. Also client needs to connect to the device softAP network before running `esp_prov` - * `ble` - For BLE based provisioning (Linux support only. In Windows/macOS it redirects to console). This assumes that the provisioning endpoints are active on the device with specific BLE service UUIDs - * `console` - For debugging via console based provisioning. The client->device commands are printed to STDOUT and device->client messages are accepted via STDIN. This is to be used when device is accepting provisioning commands on UART console. - * `--ssid ` For specifying the SSID of the Wi-Fi AP to which the device is to connect after provisioning @@ -57,9 +50,6 @@ Usage of `esp-prov` assumes that the provisioning app has specific protocomm end * `--softap_endpoint ` (Optional) (Default `192.168.4.1:80`) For specifying the IP and port of the HTTP server on which provisioning app is running. The client must connect to the device SoftAP prior to running `esp_prov` -* `--ble_devname ` (Optional) - For specifying name of the BLE device to which connection is to be established prior to starting provisioning process. This is only used when `--transport ble` is specified, else it is ignored. Since connection with BLE is supported only on Linux, so this option is again ignored for other platforms - * `--custom_config` (Optional) This flag assumes the provisioning app has an endpoint called `custom-config`. Use `--custom_info` and `--custom_ver` options to specify the fields accepted by this endpoint @@ -71,12 +61,10 @@ Usage of `esp-prov` assumes that the provisioning app has specific protocomm end # AVAILABILITY -`esp_prov` is intended as a cross-platform tool, but currently BLE communication functionality is only available on Linux (via BlueZ and DBus) +`esp_prov` is intended as a cross-platform tool. For android, a provisioning tool along with source code is available [here](https://github.com/espressif/esp-idf-provisioning-android) -On macOS and Windows, running with `--transport ble` option falls back to console mode, ie. write data and target UUID are printed to STDOUT and read data is input through STDIN. Users are free to use their app of choice to connect to the BLE device, send the write data to the target characteristic and read from it. - ## Dependencies This requires the following python libraries to run (included in requirements.txt): @@ -87,23 +75,13 @@ This requires the following python libraries to run (included in requirements.tx Run `pip install -r $IDF_PATH/tools/esp_prov/requirements.txt` Note : -* The packages listed in requirements.txt are limited only to the ones needed AFTER fully satisfying the requirements of ESP-IDF -* BLE communication is only supported on Linux (via Bluez and DBus), therefore, the dependencies for this have been made optional - -## Optional Dependencies (Linux Only) - -These dependencies are for enabling communication with BLE devices using Bluez and DBus on Linux: -* `dbus-python` - -Run `pip install -r $IDF_PATH/tools/esp_prov/requirements_linux_extra.txt` +* The packages listed in requirements.txt are limited only to the ones needed AFTER fully satisfying the requirements of ESP8266_RTOS_SDK # EXAMPLE USAGE Please refer to the README.md files with the examples present under `$IDF_PATH/examples/provisioning/`, namely: -* `ble_prov` * `softap_prov` * `custom_config` -* `console_prov` Each of these examples use specific options of the `esp_prov` tool and give an overview to simple as well as advanced usage scenarios. diff --git a/tools/esp_prov/esp_prov.py b/tools/esp_prov/esp_prov.py index 0ea172da..44306153 100644 --- a/tools/esp_prov/esp_prov.py +++ b/tools/esp_prov/esp_prov.py @@ -36,21 +36,11 @@ def get_security(secver, pop=None, verbose=False): return security.Security0(verbose) return None -def get_transport(sel_transport, softap_endpoint=None, ble_devname=None): +def get_transport(sel_transport, softap_endpoint=None): try: tp = None if (sel_transport == 'softap'): tp = transport.Transport_Softap(softap_endpoint) - elif (sel_transport == 'ble'): - tp = transport.Transport_BLE(devname = ble_devname, - service_uuid = '0000ffff-0000-1000-8000-00805f9b34fb', - nu_lookup = { - 'prov-session': 'ff51', - 'prov-config' : 'ff52', - 'proto-ver' : 'ff53' - }) - elif (sel_transport == 'console'): - tp = transport.Transport_Console() return tp except RuntimeError as e: print(e) @@ -134,12 +124,7 @@ if __name__ == '__main__': parser.add_argument("--softap_endpoint", dest = 'softap_endpoint', type = str, help = ", http(s):// shouldn't be included", default = '192.168.4.1:80') - - parser.add_argument("--ble_devname", dest = 'ble_devname', type = str, - help = "BLE Device Name", default = '') - - parser.add_argument("--transport", dest = 'provmode', type = str, - help = "provisioning mode i.e console or softap or ble", default = 'softap') + parser.add_argument("--custom_config", help="Provision Custom Configuration", action = "store_true") @@ -159,7 +144,7 @@ if __name__ == '__main__': print("---- Invalid Security Version ----") exit(1) - transport = get_transport(args.provmode, args.softap_endpoint, args.ble_devname) + transport = get_transport('softap', args.softap_endpoint) if transport == None: print("---- Invalid provisioning mode ----") exit(2) diff --git a/tools/esp_prov/requirements_linux_extra.txt b/tools/esp_prov/requirements_linux_extra.txt deleted file mode 100644 index 555438cc..00000000 --- a/tools/esp_prov/requirements_linux_extra.txt +++ /dev/null @@ -1 +0,0 @@ -dbus-python diff --git a/tools/esp_prov/transport/__init__.py b/tools/esp_prov/transport/__init__.py index 0b519d8f..445a2ad3 100644 --- a/tools/esp_prov/transport/__init__.py +++ b/tools/esp_prov/transport/__init__.py @@ -13,6 +13,4 @@ # limitations under the License. # -from .transport_console import * from .transport_softap import * -from .transport_ble import * diff --git a/tools/esp_prov/transport/ble_cli.py b/tools/esp_prov/transport/ble_cli.py deleted file mode 100644 index d8b2dff8..00000000 --- a/tools/esp_prov/transport/ble_cli.py +++ /dev/null @@ -1,202 +0,0 @@ -# Copyright 2018 Espressif Systems (Shanghai) PTE LTD -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -from __future__ import print_function -from builtins import input - -import platform - -import utils - -fallback = True - -# Check if platform is Linux and required packages are installed -# else fallback to console mode -if platform.system() == 'Linux': - try: - import dbus - import dbus.mainloop.glib - import time - fallback = False - except: - pass - -#-------------------------------------------------------------------- - -# BLE client (Linux Only) using Bluez and DBus -class BLE_Bluez_Client: - def connect(self, devname, iface, srv_uuid): - self.devname = devname - self.srv_uuid = srv_uuid - self.device = None - self.adapter = None - self.adapter_props = None - self.services = None - - dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) - bus = dbus.SystemBus() - manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.freedesktop.DBus.ObjectManager") - objects = manager.GetManagedObjects() - - for path, interfaces in objects.items(): - adapter = interfaces.get("org.bluez.Adapter1") - if adapter != None: - if path.endswith(iface): - self.adapter = dbus.Interface(bus.get_object("org.bluez", path), "org.bluez.Adapter1") - self.adapter_props = dbus.Interface(bus.get_object("org.bluez", path), "org.freedesktop.DBus.Properties") - break - - if self.adapter == None: - raise RuntimeError("Bluetooth adapter not found") - - self.adapter_props.Set("org.bluez.Adapter1", "Powered", dbus.Boolean(1)) - self.adapter.StartDiscovery() - - retry = 10 - while (retry > 0): - try: - if self.device == None: - print("Connecting...") - # Wait for device to be discovered - time.sleep(5) - self._connect_() - print("Connected") - print("Getting Services...") - # Wait for services to be discovered - time.sleep(5) - self._get_services_() - return True - except Exception as e: - print(e) - retry -= 1 - print("Retries left", retry) - continue - self.adapter.StopDiscovery() - return False - - def _connect_(self): - bus = dbus.SystemBus() - manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.freedesktop.DBus.ObjectManager") - objects = manager.GetManagedObjects() - dev_path = None - for path, interfaces in objects.items(): - if "org.bluez.Device1" not in interfaces.keys(): - continue - if interfaces["org.bluez.Device1"].get("Name") == self.devname: - dev_path = path - break - - if dev_path == None: - raise RuntimeError("BLE device not found") - - try: - self.device = bus.get_object("org.bluez", dev_path) - self.device.Connect(dbus_interface='org.bluez.Device1') - except Exception as e: - print(e) - self.device = None - raise RuntimeError("BLE device could not connect") - - def _get_services_(self): - bus = dbus.SystemBus() - manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.freedesktop.DBus.ObjectManager") - objects = manager.GetManagedObjects() - srv_path = None - for path, interfaces in objects.items(): - if "org.bluez.GattService1" not in interfaces.keys(): - continue - if path.startswith(self.device.object_path): - service = bus.get_object("org.bluez", path) - uuid = service.Get('org.bluez.GattService1', 'UUID', - dbus_interface='org.freedesktop.DBus.Properties') - if uuid == self.srv_uuid: - srv_path = path - break - - if srv_path == None: - raise RuntimeError("Provisioning service not found") - - self.characteristics = dict() - for path, interfaces in objects.items(): - if "org.bluez.GattCharacteristic1" not in interfaces.keys(): - continue - if path.startswith(srv_path): - chrc = bus.get_object("org.bluez", path) - uuid = chrc.Get('org.bluez.GattCharacteristic1', 'UUID', - dbus_interface='org.freedesktop.DBus.Properties') - self.characteristics[uuid] = chrc - - def has_characteristic(self, uuid): - if uuid in self.characteristics.keys(): - return True - return False - - def disconnect(self): - if self.device: - self.device.Disconnect(dbus_interface='org.bluez.Device1') - if self.adapter: - self.adapter.RemoveDevice(self.device) - if self.adapter_props: - self.adapter_props.Set("org.bluez.Adapter1", "Powered", dbus.Boolean(0)) - - def send_data(self, characteristic_uuid, data): - try: - path = self.characteristics[characteristic_uuid] - except KeyError: - raise RuntimeError("Invalid characteristic : " + characteristic_uuid) - path.WriteValue([ord(c) for c in data], {}, dbus_interface='org.bluez.GattCharacteristic1') - return ''.join(chr(b) for b in path.ReadValue({}, dbus_interface='org.bluez.GattCharacteristic1')) - -#-------------------------------------------------------------------- - -# Console based BLE client for Cross Platform support -class BLE_Console_Client: - def connect(self, devname, iface, srv_uuid): - print("BLE client is running in console mode") - print("\tThis could be due to your platform not being supported or dependencies not being met") - print("\tPlease ensure all pre-requisites are met to run the full fledged client") - print("BLECLI >> Please connect to BLE device `" + devname + "` manually using your tool of choice") - resp = input("BLECLI >> Was the device connected successfully? [y/n] ") - if resp != 'Y' and resp != 'y': - return False - print("BLECLI >> List available attributes of the connected device") - resp = input("BLECLI >> Is the service UUID '" + srv_uuid + "' listed among available attributes? [y/n] ") - if resp != 'Y' and resp != 'y': - return False - return True - - def has_characteristic(self, uuid): - resp = input("BLECLI >> Is the characteristic UUID '" + uuid + "' listed among available attributes? [y/n] ") - if resp != 'Y' and resp != 'y': - return False - return True - - def disconnect(self): - pass - - def send_data(self, characteristic_uuid, data): - print("BLECLI >> Write following data to characteristic with UUID '" + characteristic_uuid + "' :") - print("\t>> " + utils.str_to_hexstr(data)) - print("BLECLI >> Enter data read from characteristic (in hex) :") - resp = input("\t<< ") - return utils.hexstr_to_str(resp) - -#-------------------------------------------------------------------- - -# Function to get client instance depending upon platform -def get_client(): - if fallback: - return BLE_Console_Client() - return BLE_Bluez_Client() diff --git a/tools/esp_prov/transport/transport_ble.py b/tools/esp_prov/transport/transport_ble.py deleted file mode 100644 index 20cb144f..00000000 --- a/tools/esp_prov/transport/transport_ble.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2018 Espressif Systems (Shanghai) PTE LTD -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -from __future__ import print_function - -from .transport import * - -from . import ble_cli - -class Transport_BLE(Transport): - def __init__(self, devname, service_uuid, nu_lookup): - # Expect service UUID like '0000ffff-0000-1000-8000-00805f9b34fb' - for name in nu_lookup.keys(): - # Calculate characteristic UUID for each endpoint - nu_lookup[name] = service_uuid[:4] + '{:02x}'.format( - int(nu_lookup[name], 16) & int(service_uuid[4:8], 16)) + service_uuid[8:] - self.name_uuid_lookup = nu_lookup - - # Get BLE client module - self.cli = ble_cli.get_client() - - # Use client to connect to BLE device and bind to service - if not self.cli.connect(devname = devname, iface = 'hci0', srv_uuid = service_uuid): - raise RuntimeError("Failed to initialize transport") - - # Check if expected characteristics are provided by the service - for name in self.name_uuid_lookup.keys(): - if not self.cli.has_characteristic(self.name_uuid_lookup[name]): - raise RuntimeError("'" + name + "' endpoint not found") - - def __del__(self): - # Make sure device is disconnected before application gets closed - try: - self.disconnect() - except: - pass - - def disconnect(self): - self.cli.disconnect() - - def send_data(self, ep_name, data): - # Write (and read) data to characteristic corresponding to the endpoint - if ep_name not in self.name_uuid_lookup.keys(): - raise RuntimeError("Invalid endpoint : " + ep_name) - return self.cli.send_data(self.name_uuid_lookup[ep_name], data) diff --git a/tools/esp_prov/transport/transport_console.py b/tools/esp_prov/transport/transport_console.py deleted file mode 100644 index 82308306..00000000 --- a/tools/esp_prov/transport/transport_console.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2018 Espressif Systems (Shanghai) PTE LTD -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -from __future__ import print_function -from builtins import input - -import utils - -from .transport import * - -class Transport_Console(Transport): - - def send_data(self, path, data, session_id = 0): - print("Client->Device msg :", path, session_id, utils.str_to_hexstr(data)) - try: - resp = input("Enter device->client msg : ") - except Exception as err: - print("error:", err) - return None - return utils.hexstr_to_str(resp)