├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── doc ├── module.png ├── wiring.png └── wiring.vsdx ├── main ├── CMakeLists.txt ├── Kconfig.projbuild ├── ble_server.c ├── ble_server.h ├── component.mk ├── main.h ├── spp_task.c ├── spp_task.h └── spp_vfs_acceptor.c ├── sdkconfig ├── sdkconfig.defaults ├── test ├── ble_test.py └── bt_echo.py └── www ├── css └── test.css ├── favicon.ico ├── index.html └── js └── test.js /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's CMakeLists 2 | # in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(bt_spp_vfs_acceptor_demo) 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ESP32 classic bluetooth to serial port bridge 2 | 3 | (C) 2018, Oleg Volkov 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 3. The name of the author may not be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := bt_spp_serial_bridge 7 | 8 | COMPONENT_ADD_INCLUDEDIRS := components/include 9 | 10 | include $(IDF_PATH)/make/project.mk 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esp32-bt-serial 2 | ESP32 dual mode bluetooth to serial port bridge 3 | 4 | ## Motivation 5 | 6 | Most existing bluetooth bridges are based on the Bluecore 4 chip. It is pretty old and has issues while working with baud rates higher than default 115200. The hardware flow control implementation on this family of devices seems to be the kind of the software one. The RTS signal may be delayed by an arbitrary amount of time so that working on baud rates higher than default leads to random buffer overflow and data lost unless you always transferring small chunks of data fitting entirely onto the receiver buffer. 7 | 8 | The ESP32 on the other hand provides an excellent platform for BT to UART bridge implementation. It even supports working in classic BT and BT low energy (BLE) modes simultaneously. This project was developed in attempt to create flexible wireless communication solution for some embedded controller. Typically it needs fast interface for commands and responses with option for using it for firmware update. Such communication channel is best implemented over classic Bluetooth link. The BLE channel has its own benefits though. The host side of the BLE connection may be implemented in web page using web BLE API. Such approach allows you to write code once and run it in the browser on all popular desktop and mobile platforms such as Windows, Linux, Android and iOS. Since BLE channel is slow its best suited for controller monitoring. Currently this project implements it in one direction only transmitting data from controller to monitoring application. 9 | 10 | ## Configuring 11 | 12 | The bridge has connection indicator output, serial data RX/TX lines and flow control lines RTS/CTS, the last one is optional and is not enabled by default. All pin locations can be configured by running *make menuconfig*. Besides one can configure UART baud rate, buffer size and bluetooth device name prefix. The full device name consists of the user defined prefix followed by 6 symbols derived from the device MAC address. Such scheme is convenient in case you have more than one device since it provides the way to distinguish them. The supported serial baud rates are in the range from 9600 to 1843200 with 921600 being the default since it matches the baud rate of the bluetooth channel itself. So further increasing baud rate has no practical sense. 13 | 14 | ## Flashing 15 | 16 | Unless you have dev kit with USB programmer included you will need some minimal wiring made to the ESP32 module to be able to flash it. The following figure shows an example of such setup with programming connections shown in blue. The connections providing interface to your system are shown in black. 17 | ![ESP32 module wiring](https://github.com/olegv142/esp32-bt-serial/blob/master/doc/wiring.png) 18 | You can use virtually any USB-serial bridge capable of working at 115200 baud. The IO0 pin should be connected to the ground while powering up the module in order to turn it onto serial programming mode. After that you can issue *make flash* command in the project directory and wait for the flashing completion. Then turn off power, disconnect programming circuit and enjoy using your brand new bluetooth serial bridge. 19 | 20 | ## Connections 21 | 22 | You can use hardware flow control CTS/RTS lines or ignore them depending on your system design details. Basically not using RTS line is safe if packets you are sending to the module's RXD line are not exceeding 128 bytes. The CTS line usage is completely up to your implementation of the serial data receiver. If you are not going to use CTS line you should either connect it to the ground or disable at firmware build stage by means of *make menuconfig*. The EN line plays the role of the reset to the module. Low level on this line turns the module onto the reset state with low power consumption. In case you are not going to use this line it should be pulled up. The pull up resistors on the TXD and RTS lines are needed to prevent them from floating during module boot. 23 | 24 | ## Alternative settings 25 | 26 | Pulling low nALT input pin (IO4 by default) while powering on activates alternative settings for baud rate and device name. It may be handy in case you need separate settings for flashing firmware for example. With this application in mind the serial protocol in alt mode does not use hardware flow control but does transmit even parity bit (to be compatible with STM32 boot-loader) though it may be disabled in config. Leave nALT pin floating if alternative setting are not required. 27 | 28 | While in alternative mode the ALT indicator pin (IO32 by default) is pulled high. Otherwise it is left in high impedance state. Such behavior is handy in case the alternative mode is used for upgrading firmware of the controller that is normally driving EN input. If ALT indicator pin is connected to EN input it will keep ESP32 module active while upgrading firmware of the controller. 29 | 30 | ## BLE adapter 31 | 32 | The BLE communication channel uses separate BLE_RXD data input. It expects even parity bit by default though it may be disabled in config. Hardware flow control is not used. 33 | The BLE transmits data received from serial input by updating 'characteristic' since BLE has no notion of the serial communication channel at all. Updates are delivered to monitoring application which subscribes to them. In theory this mechanism is inherently unreliable since the update may be lost. Though reliable update delivery is possible (its called 'indication') the web BLE API does not support such mechanism. 34 | 35 | To control updates delivery the BLE adapter inserts sequence tag as the first symbol of the characteristic value. The sequence tag is assigned a values from 16 characters sequence 'a', 'b', .. 'p'. The next update uses next letter as sequence tag. The 'p' letter is followed by the 'a' again. The sequence tag symbol is followed by the data to be transmitted. The receiving application may use sequence tags to detect lost chunks of data transmitted or just ignore them. An example web page receiving BLE data with sequence tags validation may be found in *www* folder. 36 | 37 | If you don't need BLE communication channel it may be disabled completely by setting Bluetooth controller mode to *BR/EDR Only* instead of *Dual Mode* in *Components config*. 38 | 39 | ## Testing 40 | 41 | The *test* folder contains two python2 scripts for classic BT and BLE channels testing. The *bt_echo.py* sends random data to the given BT device and expects to receive the same data in response. To run this test one should enable CTS flow control and connect RX-TX and RTS-CTS pins so the adapter will send the same data back. The *ble_test.py* sends randomly generated messages to given serial port which should be connected to BLE_RXD input. The web page in *www* folder receives such data and validates it. It prints data received as well as the total count / the number of corrupt fragments and messages. The test web page is also available at address https://olegv142.github.io/esp32-bt-serial/www/ 42 | 43 | ## Troubleshooting 44 | 45 | The ESP32 module is using the same serial channel used for programming to print error and debug messages. So if anything goes wrong you can attach the programming circuit without grounding the IO0 pin and monitor debug messages during module boot. 46 | 47 | ## Power consumption 48 | 49 | 35mA in idle state, 110mA while transferring data at maximum rate. A little more than average but you have got high data rate and excellent range. 50 | 51 | ## Range 52 | 53 | Exceptional. Several timer better than with anything based on the Bluecore chips. I've got stable connection with 10 meters distance and 2 concrete walls in between. 54 | 55 | ## Known issues 56 | 57 | Working in classic BT and BLE modes simultaneously is tricky since they use the same transceiver and the same frequency band. So the frequency band should be shared between them properly which apparently is not always done by esp-idf framework. An attempt to connect to the adapter using classic BT while BLE is already paired with monitoring application and sending data to it may fail. The BT stack on windows host may even loose the ability to connect to this adapter till the system reboot. On the other hand the BLE pairing while classic BT connection is established is always possible. 58 | 59 | I had to carefully choose BLE advertising flags to make adapter working on various operating systems. The BR_EDR_NOT_SUPPORTED flag is set since setting dual mode flag breaks ability to connect to device on Linux. This is the only flag set on advertising packet since setting connectivity flag leads to listing two devices with identical names on attempt to pair with adapter from Windows host. 60 | 61 | ## Building 62 | 63 | The code can be built with esp-idf version 3.2.5. Later versions of esp-idf need code modifications to build and work properly. Yet newer versions of esp-idf don't improve stability in any way so I decided to keep code based on older version. 64 | 65 | ## Useful links 66 | 67 | Flexible dual role BLE to serial bridge for Arduino using ESP32 https://github.com/olegv142/esp32-ble 68 | 69 | Example of the BLE receiver implemented in web page: https://github.com/enspectr/ble-term 70 | 71 | Ethernet to serial adapter based on ESP32: https://github.com/olegv142/esp32-eth-serial 72 | 73 | Esp-idf installation instructions: https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html 74 | -------------------------------------------------------------------------------- /doc/module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegv142/esp32-bt-serial/3d3e1818b5c388518944f9ad9347f1c20373bb74/doc/module.png -------------------------------------------------------------------------------- /doc/wiring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegv142/esp32-bt-serial/3d3e1818b5c388518944f9ad9347f1c20373bb74/doc/wiring.png -------------------------------------------------------------------------------- /doc/wiring.vsdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegv142/esp32-bt-serial/3d3e1818b5c388518944f9ad9347f1c20373bb74/doc/wiring.vsdx -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "spp_vfs_acceptor.c" 2 | "spp_task.c") 3 | set(COMPONENT_ADD_INCLUDEDIRS ".") 4 | 5 | register_component() 6 | -------------------------------------------------------------------------------- /main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "BT-UART Bridge Configuration" 2 | 3 | config CONNECTED_LED_GPIO 4 | int "Connected indicator GPIO number" 5 | range 0 34 6 | default 5 7 | help 8 | GPIO number (IOxx) for connected status indication. 9 | 10 | config UART_TX_GPIO 11 | int "UART TX GPIO number" 12 | range 0 34 13 | default 25 14 | help 15 | GPIO number (IOxx) for serial data TX output. 16 | 17 | config UART_RX_GPIO 18 | int "UART RX GPIO number" 19 | range 0 34 20 | default 26 21 | help 22 | GPIO number (IOxx) for serial data RX input. 23 | 24 | config UART_RTS_GPIO 25 | int "UART RTS GPIO number" 26 | range 0 34 27 | default 27 28 | help 29 | GPIO number (IOxx) for serial data RTS output. Low level enables data reception from RX line. 30 | 31 | config UART_CTS_GPIO 32 | depends on UART_CTS_EN 33 | int "UART CTS GPIO number" 34 | range 0 34 35 | default 14 36 | help 37 | GPIO number (IOxx) for serial data CTS input. Low level enables data transmission to TX line. 38 | 39 | config UART_CTS_EN 40 | bool "UART CTS enable" 41 | default n 42 | help 43 | Enable using CTS input. Low level on this pin enables data transmission to TX line. 44 | 45 | config UART_BITRATE 46 | int "UART baud rate" 47 | range 9600 1843200 48 | default 921600 49 | help 50 | UART data transfer rate in bits per second. 51 | 52 | config UART_BITRATE_ALT 53 | int "UART alternative baud rate" 54 | range 9600 1843200 55 | default 115200 56 | help 57 | UART alternative mode data transfer rate in bits per second. 58 | 59 | config UART_TX_BUFF_SIZE 60 | int "UART transmit buffer size (KB)" 61 | range 0 64 62 | default 17 63 | help 64 | UART transmit data buffer size in kilobytes. 65 | 66 | config UART_RX_BUFF_SIZE 67 | int "UART receive buffer size (KB)" 68 | range 1 64 69 | default 17 70 | help 71 | UART receive data buffer size in kilobytes. 72 | 73 | config DEV_NAME_PREFIX 74 | string "Bluetooth device name prefix" 75 | default "EnSpectr-" 76 | help 77 | The fixed part of the bluetooth device name. It will be followed by serial number based on the MAC address. 78 | 79 | config DEV_NAME_PREFIX_ALT 80 | string "Bluetooth alternative device name prefix" 81 | default "EnSpectrPw-" 82 | help 83 | The fixed part of the alternative bluetooth device name. It will be followed by serial number based on the MAC address. 84 | 85 | config ALT_SWITCH_GPIO 86 | int "UART alternative mode switch GPIO number" 87 | range 0 34 88 | default 4 89 | help 90 | GPIO number (IOxx) for alternative mode switch. Pulled low it will engage alternative settings for device name and baud rate. 91 | 92 | config ALT_INDICATOR_GPIO 93 | int "UART alternative mode indicator GPIO number" 94 | range 0 34 95 | default 32 96 | help 97 | GPIO number (IOxx) for alternative mode indicator. Its pulled high while in alternative mode or kept in high impedance state otherwise. 98 | 99 | config ALT_UART_PARITY 100 | bool "UART use parity in alternative mode" 101 | default y 102 | help 103 | Enable UART parity in alternative mode. If enabled the UART port uses even parity in alternative mode. 104 | 105 | config DEV_NAME_BLE 106 | depends on BTDM_CONTROLLER_MODE_BTDM 107 | string "Bluetooth LE device name" 108 | default "EsPw" 109 | help 110 | The name of the bluetooth LE device. It will be followed by serial number based on the MAC address. Its shown by web BLE applications only. 111 | 112 | config BLE_UART_RX_GPIO 113 | depends on BTDM_CONTROLLER_MODE_BTDM 114 | int "BLE UART RX GPIO number" 115 | range 0 34 116 | default 33 117 | help 118 | GPIO number (IOxx) for BLE UART RX input. 119 | 120 | config BLE_UART_BITRATE 121 | depends on BTDM_CONTROLLER_MODE_BTDM 122 | int "BLE UART baud rate" 123 | range 9600 1843200 124 | default 19200 125 | help 126 | BLE UART data transfer rate in bits per second. 127 | 128 | config BLE_UART_PARITY 129 | depends on BTDM_CONTROLLER_MODE_BTDM 130 | bool "BLE adapter use parity" 131 | default y 132 | help 133 | Enable BLE adapter parity. If enabled the BLE UART port expects even parity. 134 | 135 | endmenu 136 | -------------------------------------------------------------------------------- /main/ble_server.c: -------------------------------------------------------------------------------- 1 | /* 2 | This example code is in the Public Domain (or CC0 licensed, at your option.) 3 | 4 | Unless required by applicable law or agreed to in writing, this 5 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 6 | CONDITIONS OF ANY KIND, either express or implied. 7 | */ 8 | 9 | 10 | #include "ble_server.h" 11 | 12 | #ifdef BLE_ADAPTER_EN 13 | 14 | #include "freertos/FreeRTOS.h" 15 | #include "freertos/task.h" 16 | #include "freertos/event_groups.h" 17 | #include "esp_system.h" 18 | #include "esp_log.h" 19 | #include "nvs_flash.h" 20 | #include "esp_bt.h" 21 | #include "driver/uart.h" 22 | 23 | #include "esp_gap_ble_api.h" 24 | #include "esp_gatts_api.h" 25 | #include "esp_bt_defs.h" 26 | #include "esp_bt_main.h" 27 | #include "main.h" 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #define GATTS_TABLE_TAG "GATTS_SPP" 34 | 35 | // Attributes State Machine 36 | enum{ 37 | SPP_IDX_SVC, 38 | SPP_IDX_SPP_DATA_NOTIFY_CHAR, 39 | SPP_IDX_SPP_DATA_NTY_VAL, 40 | SPP_IDX_SPP_DATA_NTF_CFG, 41 | 42 | SPP_IDX_NB, 43 | }; 44 | 45 | #define SPP_PROFILE_NUM 1 46 | #define SPP_PROFILE_APP_IDX 0 47 | #define ESP_SPP_APP_ID 0x56 48 | #define SPP_SVC_INST_ID 0 49 | #define SPP_DATA_MAX_LEN (512) 50 | 51 | // SPP Service 52 | static const uint16_t spp_service_uuid = 0xFFE0; 53 | // Characteristic UUID 54 | #define ESP_GATT_UUID_SPP_DATA_NOTIFY 0xFFE1 55 | 56 | #define BLE_ADV_NAME CONFIG_DEV_NAME_BLE 57 | #define BLE_ADV_NAME_LEN (sizeof(BLE_ADV_NAME)-1) 58 | #define BLE_ADV_NAME_OFF 15 59 | 60 | static uint8_t spp_adv_data[BLE_ADV_NAME_OFF+BLE_ADV_NAME_LEN+DEV_NAME_SUFF_LEN] = { 61 | 0x02, 0x01, 0x04, // flags 62 | 0x03, 0x03, 0xe0, 0xff, // service UID 63 | 0x05, 0x12, 0x20, 0x00, 0x40, 0x00, // conn interval range 64 | 1+BLE_ADV_NAME_LEN+DEV_NAME_SUFF_LEN, 0x09, 65 | // [BLE_ADV_NAME_OFF..] BLE_ADV_NAME + suffix 66 | }; 67 | 68 | #define BLE_UART_NUM UART_NUM_2 69 | #ifdef CONFIG_BLE_UART_PARITY 70 | #define BLE_UART_PARITY UART_PARITY_EVEN 71 | #else 72 | #define BLE_UART_PARITY UART_PARITY_DISABLE 73 | #endif 74 | 75 | static uint16_t spp_mtu_size = 23; 76 | static uint8_t spp_seq = 0; 77 | static uint8_t spp_seq_max = 15; 78 | static uint16_t spp_conn_id = 0xffff; 79 | static esp_gatt_if_t spp_gatts_if = 0xff; 80 | QueueHandle_t spp_uart_queue = NULL; 81 | 82 | static bool enable_data_ntf = false; 83 | static bool is_connected = false; 84 | static esp_bd_addr_t spp_remote_bda = {0x0,}; 85 | 86 | static uint16_t spp_handle_table[SPP_IDX_NB]; 87 | 88 | static esp_ble_adv_params_t spp_adv_params = { 89 | .adv_int_min = 0x20, 90 | .adv_int_max = 0x40, 91 | .adv_type = ADV_TYPE_IND, 92 | .own_addr_type = BLE_ADDR_TYPE_PUBLIC, 93 | .channel_map = ADV_CHNL_ALL, 94 | .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, 95 | }; 96 | 97 | struct gatts_profile_inst { 98 | esp_gatts_cb_t gatts_cb; 99 | uint16_t gatts_if; 100 | uint16_t app_id; 101 | uint16_t conn_id; 102 | uint16_t service_handle; 103 | esp_gatt_srvc_id_t service_id; 104 | uint16_t char_handle; 105 | esp_bt_uuid_t char_uuid; 106 | esp_gatt_perm_t perm; 107 | esp_gatt_char_prop_t property; 108 | uint16_t descr_handle; 109 | esp_bt_uuid_t descr_uuid; 110 | }; 111 | 112 | static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); 113 | 114 | /* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */ 115 | static struct gatts_profile_inst spp_profile_tab[SPP_PROFILE_NUM] = { 116 | [SPP_PROFILE_APP_IDX] = { 117 | .gatts_cb = gatts_profile_event_handler, 118 | .gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */ 119 | }, 120 | }; 121 | 122 | /* 123 | * SPP PROFILE ATTRIBUTES 124 | **************************************************************************************** 125 | */ 126 | 127 | #define CHAR_DECLARATION_SIZE (sizeof(uint8_t)) 128 | static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE; 129 | static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE; 130 | static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; 131 | 132 | static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY; 133 | 134 | // SPP Service - data notify characteristic, notify&read 135 | static const uint16_t spp_data_notify_uuid = ESP_GATT_UUID_SPP_DATA_NOTIFY; 136 | static const uint8_t spp_data_notify_val[20] = {0x00}; 137 | static const uint8_t spp_data_notify_ccc[2] = {0x00, 0x00}; 138 | 139 | // Full HRS Database Description - Used to add attributes into the database 140 | static const esp_gatts_attr_db_t spp_gatt_db[SPP_IDX_NB] = 141 | { 142 | //SPP - Service Declaration 143 | [SPP_IDX_SVC] = 144 | {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ, 145 | sizeof(spp_service_uuid), sizeof(spp_service_uuid), (uint8_t *)&spp_service_uuid}}, 146 | 147 | //SPP - data notify characteristic Declaration 148 | [SPP_IDX_SPP_DATA_NOTIFY_CHAR] = 149 | {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, 150 | CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}}, 151 | 152 | //SPP - data notify characteristic Value 153 | [SPP_IDX_SPP_DATA_NTY_VAL] = 154 | {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_data_notify_uuid, ESP_GATT_PERM_READ, 155 | SPP_DATA_MAX_LEN, sizeof(spp_data_notify_val), (uint8_t *)spp_data_notify_val}}, 156 | 157 | //SPP - data notify characteristic - Client Characteristic Configuration Descriptor 158 | [SPP_IDX_SPP_DATA_NTF_CFG] = 159 | {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE, 160 | sizeof(uint16_t),sizeof(spp_data_notify_ccc), (uint8_t *)spp_data_notify_ccc}}, 161 | }; 162 | 163 | static uint8_t find_char_and_desr_index(uint16_t handle) 164 | { 165 | uint8_t error = 0xff; 166 | 167 | for(int i = 0; i < SPP_IDX_NB ; i++){ 168 | if(handle == spp_handle_table[i]){ 169 | return i; 170 | } 171 | } 172 | 173 | return error; 174 | } 175 | 176 | void uart_task(void *pvParameters) 177 | { 178 | for (;;) { 179 | // Waiting for UART event. 180 | uart_event_t event; 181 | if (xQueueReceive(spp_uart_queue, (void*)&event, (portTickType)portMAX_DELAY)) { 182 | switch (event.type) { 183 | //Event of UART receving data 184 | case UART_DATA: 185 | if (event.size) { 186 | uint8_t * const buff = (uint8_t*)malloc(1 + event.size); 187 | if (buff == NULL) { 188 | ESP_LOGE(GATTS_TABLE_TAG, "%s malloc.1 failed", __func__); 189 | break; 190 | } 191 | uart_read_bytes(BLE_UART_NUM, buff + 1, event.size, portMAX_DELAY); 192 | if (!is_connected) { 193 | ESP_LOGW(GATTS_TABLE_TAG, "%s not connected", __func__); 194 | } else if (!enable_data_ntf) { 195 | ESP_LOGW(GATTS_TABLE_TAG, "%s notify not enabled", __func__); 196 | } else { 197 | uint16_t const max_payload = spp_mtu_size - 3; 198 | uint16_t const max_chunk = max_payload - 1; 199 | int const nchunks = (event.size + max_chunk - 1) / max_chunk; 200 | int remain = event.size; 201 | ESP_LOGD(GATTS_TABLE_TAG, "%s %u / %u", __func__, event.size, max_chunk); 202 | for (int i = 0; i < nchunks; ++i) { 203 | int const chunk = remain <= max_chunk ? remain : max_chunk; 204 | uint8_t first_tag = 'a'; 205 | buff[i*max_chunk] = first_tag + spp_seq; 206 | if (++spp_seq > spp_seq_max) 207 | spp_seq = 0; 208 | esp_ble_gatts_send_indicate(spp_gatts_if, spp_conn_id, spp_handle_table[SPP_IDX_SPP_DATA_NTY_VAL], 1 + chunk, &buff[i*max_chunk], false); 209 | } 210 | } 211 | free(buff); 212 | } 213 | break; 214 | default: 215 | break; 216 | } 217 | } 218 | } 219 | vTaskDelete(NULL); 220 | } 221 | 222 | static void spp_uart_init(void) 223 | { 224 | uart_config_t uart_config = { 225 | .baud_rate = CONFIG_BLE_UART_BITRATE, 226 | .data_bits = UART_DATA_8_BITS, 227 | .parity = BLE_UART_PARITY, 228 | .stop_bits = UART_STOP_BITS_1, 229 | .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, 230 | .rx_flow_ctrl_thresh = UART_FIFO_LEN - 4, 231 | }; 232 | 233 | // Set UART parameters 234 | ESP_ERROR_CHECK(uart_param_config(BLE_UART_NUM, &uart_config)); 235 | // Set UART pins 236 | ESP_ERROR_CHECK(uart_set_pin(BLE_UART_NUM, UART_PIN_NO_CHANGE, CONFIG_BLE_UART_RX_GPIO, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); 237 | // Install UART driver, and get the queue. 238 | ESP_ERROR_CHECK(uart_driver_install(BLE_UART_NUM, 4096, 8192, 10, &spp_uart_queue, 0)); 239 | xTaskCreate(uart_task, "uTask", 2048, (void*)BLE_UART_NUM, 8, NULL); 240 | } 241 | 242 | static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) 243 | { 244 | esp_err_t err; 245 | ESP_LOGI(GATTS_TABLE_TAG, "GAP_EVT, event %d", event); 246 | 247 | switch (event) { 248 | case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: 249 | esp_ble_gap_start_advertising(&spp_adv_params); 250 | break; 251 | case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: 252 | // advertising start complete event to indicate advertising start successfully or failed 253 | if((err = param->adv_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) { 254 | ESP_LOGE(GATTS_TABLE_TAG, "Advertising start failed: %s", esp_err_to_name(err)); 255 | } 256 | break; 257 | default: 258 | break; 259 | } 260 | } 261 | 262 | static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) 263 | { 264 | esp_ble_gatts_cb_param_t *p_data = (esp_ble_gatts_cb_param_t *) param; 265 | uint8_t res = 0xff; 266 | 267 | ESP_LOGD(GATTS_TABLE_TAG, "event = %x", event); 268 | switch (event) { 269 | case ESP_GATTS_REG_EVT: 270 | ESP_LOGI(GATTS_TABLE_TAG, "%s %d", __func__, __LINE__); 271 | esp_ble_gap_set_device_name(get_device_name()); 272 | esp_ble_gap_config_adv_data_raw((uint8_t *)spp_adv_data, sizeof(spp_adv_data)); 273 | esp_ble_gatts_create_attr_tab(spp_gatt_db, gatts_if, SPP_IDX_NB, SPP_SVC_INST_ID); 274 | break; 275 | case ESP_GATTS_READ_EVT: 276 | break; 277 | case ESP_GATTS_WRITE_EVT: 278 | res = find_char_and_desr_index(p_data->write.handle); 279 | if (p_data->write.is_prep == false){ 280 | ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_WRITE_EVT : handle = %d", res); 281 | if (res == SPP_IDX_SPP_DATA_NTF_CFG) { 282 | if(p_data->write.len == 2 && p_data->write.value[1] == 0x00) { 283 | if (p_data->write.value[0] == 0x01) { 284 | ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_WRITE_EVT : notification enabled"); 285 | enable_data_ntf = true; 286 | } else if (p_data->write.value[0] == 0x00) { 287 | ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_WRITE_EVT : notification disabled"); 288 | enable_data_ntf = false; 289 | } 290 | } 291 | } 292 | } 293 | break; 294 | case ESP_GATTS_EXEC_WRITE_EVT: 295 | break; 296 | case ESP_GATTS_MTU_EVT: 297 | spp_mtu_size = p_data->mtu.mtu; 298 | ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_MTU_EVT mtu = %d", spp_mtu_size); 299 | break; 300 | case ESP_GATTS_CONF_EVT: 301 | case ESP_GATTS_UNREG_EVT: 302 | case ESP_GATTS_DELETE_EVT: 303 | case ESP_GATTS_START_EVT: 304 | case ESP_GATTS_STOP_EVT: 305 | break; 306 | case ESP_GATTS_CONNECT_EVT: 307 | spp_conn_id = p_data->connect.conn_id; 308 | spp_gatts_if = gatts_if; 309 | is_connected = true; 310 | memcpy(&spp_remote_bda,&p_data->connect.remote_bda,sizeof(esp_bd_addr_t)); 311 | break; 312 | case ESP_GATTS_DISCONNECT_EVT: 313 | is_connected = false; 314 | enable_data_ntf = false; 315 | esp_ble_gap_start_advertising(&spp_adv_params); 316 | break; 317 | case ESP_GATTS_OPEN_EVT: 318 | case ESP_GATTS_CANCEL_OPEN_EVT: 319 | case ESP_GATTS_CLOSE_EVT: 320 | case ESP_GATTS_LISTEN_EVT: 321 | case ESP_GATTS_CONGEST_EVT: 322 | break; 323 | case ESP_GATTS_CREAT_ATTR_TAB_EVT:{ 324 | ESP_LOGI(GATTS_TABLE_TAG, "The number handle =%x",param->add_attr_tab.num_handle); 325 | if (param->add_attr_tab.status != ESP_GATT_OK){ 326 | ESP_LOGE(GATTS_TABLE_TAG, "Create attribute table failed, error code=0x%x", param->add_attr_tab.status); 327 | } 328 | else if (param->add_attr_tab.num_handle != SPP_IDX_NB){ 329 | ESP_LOGE(GATTS_TABLE_TAG, "Create attribute table abnormally, num_handle (%d) doesn't equal to HRS_IDX_NB(%d)", param->add_attr_tab.num_handle, SPP_IDX_NB); 330 | } 331 | else { 332 | memcpy(spp_handle_table, param->add_attr_tab.handles, sizeof(spp_handle_table)); 333 | esp_ble_gatts_start_service(spp_handle_table[SPP_IDX_SVC]); 334 | } 335 | break; 336 | } 337 | default: 338 | break; 339 | } 340 | } 341 | 342 | static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) 343 | { 344 | ESP_LOGD(GATTS_TABLE_TAG, "EVT %d, gatts if %d", event, gatts_if); 345 | 346 | /* If event is register event, store the gatts_if for each profile */ 347 | if (event == ESP_GATTS_REG_EVT) { 348 | if (param->reg.status == ESP_GATT_OK) { 349 | spp_profile_tab[SPP_PROFILE_APP_IDX].gatts_if = gatts_if; 350 | } else { 351 | ESP_LOGI(GATTS_TABLE_TAG, "Reg app failed, app_id %04x, status %d",param->reg.app_id, param->reg.status); 352 | return; 353 | } 354 | } 355 | 356 | do { 357 | int idx; 358 | for (idx = 0; idx < SPP_PROFILE_NUM; idx++) { 359 | if (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */ 360 | gatts_if == spp_profile_tab[idx].gatts_if) { 361 | if (spp_profile_tab[idx].gatts_cb) { 362 | spp_profile_tab[idx].gatts_cb(event, gatts_if, param); 363 | } 364 | } 365 | } 366 | } while (0); 367 | } 368 | 369 | void ble_server_init(void) 370 | { 371 | for (int i = 0; i < BLE_ADV_NAME_LEN; ++i) 372 | spp_adv_data[BLE_ADV_NAME_OFF+i] = BLE_ADV_NAME[i]; 373 | get_device_name_suff((char*)&spp_adv_data[BLE_ADV_NAME_OFF+BLE_ADV_NAME_LEN]); 374 | 375 | esp_ble_gatts_register_callback(gatts_event_handler); 376 | esp_ble_gap_register_callback(gap_event_handler); 377 | esp_ble_gatts_app_register(ESP_SPP_APP_ID); 378 | 379 | spp_uart_init(); 380 | } 381 | 382 | #endif 383 | -------------------------------------------------------------------------------- /main/ble_server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sdkconfig.h" 4 | 5 | #ifdef CONFIG_BTDM_CONTROLLER_MODE_BTDM 6 | #define BLE_ADAPTER_EN 7 | #endif 8 | 9 | #ifdef BLE_ADAPTER_EN 10 | 11 | void ble_server_init(void); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | -------------------------------------------------------------------------------- /main/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | const char* get_device_name(void); 4 | 5 | #define DEV_NAME_SUFF_LEN 6 6 | 7 | void get_device_name_suff(char buff[DEV_NAME_SUFF_LEN]); 8 | -------------------------------------------------------------------------------- /main/spp_task.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include "freertos/xtensa_api.h" 19 | #include "freertos/FreeRTOSConfig.h" 20 | #include "freertos/FreeRTOS.h" 21 | #include "freertos/queue.h" 22 | #include "freertos/task.h" 23 | #include "esp_log.h" 24 | #include "spp_task.h" 25 | 26 | static void spp_task_task_handler(void *arg); 27 | static bool spp_task_send_msg(spp_task_msg_t *msg); 28 | static void spp_task_work_dispatched(spp_task_msg_t *msg); 29 | 30 | static xQueueHandle spp_task_task_queue = NULL; 31 | static xTaskHandle spp_task_task_handle = NULL; 32 | 33 | bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_params, int param_len, spp_task_copy_cb_t p_copy_cback) 34 | { 35 | ESP_LOGD(SPP_TASK_TAG, "%s event 0x%x, param len %d", __func__, event, param_len); 36 | 37 | spp_task_msg_t msg; 38 | memset(&msg, 0, sizeof(spp_task_msg_t)); 39 | 40 | msg.sig = SPP_TASK_SIG_WORK_DISPATCH; 41 | msg.event = event; 42 | msg.cb = p_cback; 43 | 44 | if (param_len == 0) { 45 | return spp_task_send_msg(&msg); 46 | } else if (p_params && param_len > 0) { 47 | if ((msg.param = malloc(param_len)) != NULL) { 48 | memcpy(msg.param, p_params, param_len); 49 | /* check if caller has provided a copy callback to do the deep copy */ 50 | if (p_copy_cback) { 51 | p_copy_cback(&msg, msg.param, p_params); 52 | } 53 | return spp_task_send_msg(&msg); 54 | } 55 | } 56 | 57 | return false; 58 | } 59 | 60 | static bool spp_task_send_msg(spp_task_msg_t *msg) 61 | { 62 | if (msg == NULL) { 63 | return false; 64 | } 65 | 66 | if (xQueueSend(spp_task_task_queue, msg, 10 / portTICK_RATE_MS) != pdTRUE) { 67 | ESP_LOGE(SPP_TASK_TAG, "%s xQueue send failed", __func__); 68 | return false; 69 | } 70 | return true; 71 | } 72 | 73 | static void spp_task_work_dispatched(spp_task_msg_t *msg) 74 | { 75 | if (msg->cb) { 76 | msg->cb(msg->event, msg->param); 77 | } 78 | } 79 | 80 | static void spp_task_task_handler(void *arg) 81 | { 82 | spp_task_msg_t msg; 83 | for (;;) { 84 | if (pdTRUE == xQueueReceive(spp_task_task_queue, &msg, (portTickType)portMAX_DELAY)) { 85 | ESP_LOGD(SPP_TASK_TAG, "%s, sig 0x%x, 0x%x", __func__, msg.sig, msg.event); 86 | switch (msg.sig) { 87 | case SPP_TASK_SIG_WORK_DISPATCH: 88 | spp_task_work_dispatched(&msg); 89 | break; 90 | default: 91 | ESP_LOGW(SPP_TASK_TAG, "%s, unhandled sig: %d", __func__, msg.sig); 92 | break; 93 | } 94 | 95 | if (msg.param) { 96 | free(msg.param); 97 | } 98 | } 99 | } 100 | } 101 | 102 | void spp_task_task_start_up(void) 103 | { 104 | spp_task_task_queue = xQueueCreate(10, sizeof(spp_task_msg_t)); 105 | xTaskCreate(spp_task_task_handler, "SPPAppT", 2048, NULL, 10, spp_task_task_handle); 106 | return; 107 | } 108 | 109 | void spp_task_task_shut_down(void) 110 | { 111 | if (spp_task_task_handle) { 112 | vTaskDelete(spp_task_task_handle); 113 | spp_task_task_handle = NULL; 114 | } 115 | if (spp_task_task_queue) { 116 | vQueueDelete(spp_task_task_queue); 117 | spp_task_task_queue = NULL; 118 | } 119 | } 120 | 121 | void spp_wr_task_start_up(spp_wr_task_cb_t p_cback, int fd) 122 | { 123 | xTaskCreate(p_cback, "write_read", 2048, (void *)fd, 5, NULL); 124 | } 125 | 126 | void spp_wr_task_shut_down(void) 127 | { 128 | vTaskDelete(NULL); 129 | } 130 | -------------------------------------------------------------------------------- /main/spp_task.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef __SPP_TASK_H__ 16 | #define __SPP_TASK_H__ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #define SPP_TASK_TAG "SPP_TASK" 23 | 24 | #define SPP_TASK_SIG_WORK_DISPATCH (0x01) 25 | 26 | /** 27 | * @brief handler for the dispatched work 28 | */ 29 | typedef void (* spp_task_cb_t) (uint16_t event, void *param); 30 | 31 | /* message to be sent */ 32 | typedef struct { 33 | uint16_t sig; /*!< signal to spp_task_task */ 34 | uint16_t event; /*!< message event id */ 35 | spp_task_cb_t cb; /*!< context switch callback */ 36 | void *param; /*!< parameter area needs to be last */ 37 | } spp_task_msg_t; 38 | 39 | /** 40 | * @brief parameter deep-copy function to be customized 41 | */ 42 | typedef void (* spp_task_copy_cb_t) (spp_task_msg_t *msg, void *p_dest, void *p_src); 43 | 44 | /** 45 | * @brief work dispatcher for the application task 46 | */ 47 | bool spp_task_work_dispatch(spp_task_cb_t p_cback, uint16_t event, void *p_params, int param_len, spp_task_copy_cb_t p_copy_cback); 48 | 49 | void spp_task_task_start_up(void); 50 | 51 | void spp_task_task_shut_down(void); 52 | 53 | 54 | /** 55 | * @brief handler for write and read 56 | */ 57 | typedef void (* spp_wr_task_cb_t) (void *fd); 58 | 59 | void spp_wr_task_start_up(spp_wr_task_cb_t p_cback, int fd); 60 | 61 | void spp_wr_task_shut_down(void); 62 | 63 | #endif ///__SPP_TASK_H__ -------------------------------------------------------------------------------- /main/spp_vfs_acceptor.c: -------------------------------------------------------------------------------- 1 | /* 2 | This example code is in the Public Domain (or CC0 licensed, at your option.) 3 | 4 | Unless required by applicable law or agreed to in writing, this 5 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 6 | CONDITIONS OF ANY KIND, either express or implied. 7 | */ 8 | 9 | /**************************************************************************** 10 | * 11 | * This file is for bt_spp_vfs_acceptor demo. It can create servers, wait for connected and receive data. 12 | * run bt_spp_vfs_acceptor demo, the bt_spp_vfs_initiator demo will automatically connect the bt_spp_vfs_acceptor demo, 13 | * then receive data. 14 | * 15 | ****************************************************************************/ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "nvs.h" 22 | #include "nvs_flash.h" 23 | #include "freertos/FreeRTOS.h" 24 | #include "freertos/task.h" 25 | #include "driver/uart.h" 26 | #include "esp_log.h" 27 | #include "esp_bt.h" 28 | #include "esp_bt_main.h" 29 | #include "esp_gap_bt_api.h" 30 | #include "esp_bt_device.h" 31 | #include "esp_spp_api.h" 32 | #include "spp_task.h" 33 | #include "main.h" 34 | 35 | #include "time.h" 36 | #include "sys/time.h" 37 | 38 | #include "esp_vfs.h" 39 | #include "sys/unistd.h" 40 | 41 | #include "ble_server.h" 42 | 43 | #define SPP_TAG "SPP_ACCEPTOR" 44 | #define SPP_SERVER_NAME "SPP_SERVER" 45 | 46 | #define BT_DEV_NAME_PREFIX CONFIG_DEV_NAME_PREFIX 47 | #define BT_DEV_NAME_PREFIX_LEN (sizeof(BT_DEV_NAME_PREFIX) - 1) 48 | 49 | #define BT_DEV_NAME_PREFIX_ALT CONFIG_DEV_NAME_PREFIX_ALT 50 | #define BT_DEV_NAME_PREFIX_LEN_ALT (sizeof(BT_DEV_NAME_PREFIX_ALT) - 1) 51 | 52 | #define BT_CONNECTED_GPIO CONFIG_CONNECTED_LED_GPIO 53 | #define BT_UART_TX_GPIO CONFIG_UART_TX_GPIO 54 | #define BT_UART_RX_GPIO CONFIG_UART_RX_GPIO 55 | #define BT_UART_RTS_GPIO CONFIG_UART_RTS_GPIO 56 | 57 | #define BT_LED_CONNECTED 0 58 | #define BT_LED_DISCONNECTED 1 59 | 60 | #define BT_UART_BITRATE CONFIG_UART_BITRATE 61 | #define BT_UART_BITRATE_ALT CONFIG_UART_BITRATE_ALT 62 | 63 | #define BT_ALT_SWITCH_GPIO CONFIG_ALT_SWITCH_GPIO 64 | #define BT_ALT_INDICATOR_GPIO CONFIG_ALT_INDICATOR_GPIO 65 | 66 | #ifdef CONFIG_UART_CTS_EN 67 | #define BT_UART_FLOWCTRL UART_HW_FLOWCTRL_CTS_RTS 68 | #define BT_UART_CTS_GPIO CONFIG_UART_CTS_GPIO 69 | #else 70 | #define BT_UART_FLOWCTRL UART_HW_FLOWCTRL_RTS 71 | #define BT_UART_CTS_GPIO UART_PIN_NO_CHANGE 72 | #endif 73 | 74 | #define BT_UART_FLOWCTRL_ALT UART_HW_FLOWCTRL_DISABLE 75 | #ifdef CONFIG_ALT_UART_PARITY 76 | #define BT_UART_PARITY_ALT UART_PARITY_EVEN 77 | #else 78 | #define BT_UART_PARITY_ALT UART_HW_FLOWCTRL_DISABLE 79 | #endif 80 | 81 | #define BT_UART_RX_BUF_SZ (1024 * CONFIG_UART_RX_BUFF_SIZE) 82 | #define BT_UART_TX_BUF_SZ (1024 * CONFIG_UART_TX_BUFF_SIZE) 83 | 84 | static const esp_spp_mode_t esp_spp_mode = ESP_SPP_MODE_VFS; 85 | 86 | static const esp_spp_sec_t sec_mask = ESP_SPP_SEC_AUTHENTICATE; 87 | static const esp_spp_role_t role_slave = ESP_SPP_ROLE_SLAVE; 88 | 89 | #define SPP_BUFF_SZ 100 90 | static uint8_t spp_buff[SPP_BUFF_SZ]; 91 | 92 | static bool alt_settings; 93 | 94 | #define BT_UART UART_NUM_1 95 | 96 | static int uart_to_bt(int bt_fd, TickType_t ticks_to_wait) 97 | { 98 | int size = uart_read_bytes(BT_UART, spp_buff, SPP_BUFF_SZ, ticks_to_wait); 99 | if (size <= 0) { 100 | return 0; 101 | } 102 | ESP_LOGD(SPP_TAG, "UART -> %d bytes", size); 103 | uint8_t* ptr = spp_buff; 104 | int remain = size; 105 | while (remain > 0) 106 | { 107 | int res = write(bt_fd, ptr, remain); 108 | if (res < 0) { 109 | return -1; 110 | } 111 | if (res == 0) { 112 | vTaskDelay(1); 113 | continue; 114 | } 115 | ESP_LOGD(SPP_TAG, "BT <- %d bytes", res); 116 | remain -= res; 117 | ptr += res; 118 | } 119 | return size; 120 | } 121 | 122 | static void spp_read_handle(void * param) 123 | { 124 | int fd = (int)param; 125 | 126 | ESP_LOGI(SPP_TAG, "BT connected, %u bytes free", heap_caps_get_free_size(MALLOC_CAP_DEFAULT)); 127 | gpio_set_level(BT_CONNECTED_GPIO, BT_LED_CONNECTED); 128 | uart_flush(BT_UART); 129 | 130 | TickType_t ticks_to_wait = 1; 131 | 132 | for (;;) 133 | { 134 | // Send available data from UART to BT first 135 | for (;;) { 136 | int tx_size = uart_to_bt(fd, ticks_to_wait); 137 | if (tx_size < 0) 138 | goto disconnected; 139 | if (!tx_size) 140 | break; 141 | ticks_to_wait = 0; 142 | } 143 | // Try receive data from BT 144 | int const size = read(fd, spp_buff, SPP_BUFF_SZ); 145 | if (size < 0) { 146 | goto disconnected; 147 | } 148 | if (size > 0) { 149 | ESP_LOGD(SPP_TAG, "BT -> %d bytes -> UART", size); 150 | uart_write_bytes(BT_UART, (const char *)spp_buff, size); 151 | ticks_to_wait = 0; 152 | } else 153 | ticks_to_wait = 1; 154 | } 155 | 156 | disconnected: 157 | ESP_LOGI(SPP_TAG, "BT disconnected"); 158 | gpio_set_level(BT_CONNECTED_GPIO, BT_LED_DISCONNECTED); 159 | spp_wr_task_shut_down(); 160 | } 161 | 162 | static inline char hex_digit(uint8_t v) 163 | { 164 | return v < 10 ? '0' + v : 'A' + v - 10; 165 | } 166 | 167 | static inline char byte_signature(uint8_t v) 168 | { 169 | return hex_digit((v & 0xf) ^ (v >> 4)); 170 | } 171 | 172 | void get_device_name_suff(char buff[DEV_NAME_SUFF_LEN]) 173 | { 174 | const uint8_t * mac = esp_bt_dev_get_address(); 175 | for (int i = 0; i < DEV_NAME_SUFF_LEN; ++i) { 176 | buff[i] = byte_signature(mac[i]); 177 | } 178 | } 179 | 180 | static const char* bt_get_dev_name(void) 181 | { 182 | static char dev_name[BT_DEV_NAME_PREFIX_LEN + DEV_NAME_SUFF_LEN + 1] = BT_DEV_NAME_PREFIX; 183 | get_device_name_suff(&dev_name[BT_DEV_NAME_PREFIX_LEN]); 184 | dev_name[BT_DEV_NAME_PREFIX_LEN + DEV_NAME_SUFF_LEN] = 0; 185 | ESP_LOGI(SPP_TAG, "Device name is %s", dev_name); 186 | return dev_name; 187 | } 188 | 189 | static const char* bt_get_alt_dev_name(void) 190 | { 191 | static char dev_name[BT_DEV_NAME_PREFIX_LEN_ALT + DEV_NAME_SUFF_LEN + 1] = BT_DEV_NAME_PREFIX_ALT; 192 | get_device_name_suff(&dev_name[BT_DEV_NAME_PREFIX_LEN_ALT]); 193 | dev_name[BT_DEV_NAME_PREFIX_LEN_ALT + DEV_NAME_SUFF_LEN] = 0; 194 | ESP_LOGI(SPP_TAG, "Device name (alt) is %s", dev_name); 195 | return dev_name; 196 | } 197 | 198 | const char* get_device_name(void) 199 | { 200 | return alt_settings ? bt_get_alt_dev_name() : bt_get_dev_name(); 201 | } 202 | 203 | static void esp_spp_cb(uint16_t e, void *p) 204 | { 205 | esp_spp_cb_event_t event = e; 206 | esp_spp_cb_param_t *param = p; 207 | 208 | switch (event) { 209 | case ESP_SPP_INIT_EVT: 210 | ESP_LOGI(SPP_TAG, "ESP_SPP_INIT_EVT"); 211 | ESP_ERROR_CHECK(esp_bt_dev_set_device_name(get_device_name())); 212 | esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); 213 | esp_spp_start_srv(sec_mask,role_slave, 0, SPP_SERVER_NAME); 214 | break; 215 | case ESP_SPP_DISCOVERY_COMP_EVT: 216 | ESP_LOGI(SPP_TAG, "ESP_SPP_DISCOVERY_COMP_EVT"); 217 | break; 218 | case ESP_SPP_OPEN_EVT: 219 | ESP_LOGI(SPP_TAG, "ESP_SPP_OPEN_EVT"); 220 | break; 221 | case ESP_SPP_CLOSE_EVT: 222 | ESP_LOGI(SPP_TAG, "ESP_SPP_CLOSE_EVT"); 223 | break; 224 | case ESP_SPP_START_EVT: 225 | ESP_LOGI(SPP_TAG, "ESP_SPP_START_EVT"); 226 | break; 227 | case ESP_SPP_CL_INIT_EVT: 228 | ESP_LOGI(SPP_TAG, "ESP_SPP_CL_INIT_EVT"); 229 | break; 230 | case ESP_SPP_SRV_OPEN_EVT: 231 | ESP_LOGI(SPP_TAG, "ESP_SPP_SRV_OPEN_EVT"); 232 | spp_wr_task_start_up(spp_read_handle, param->srv_open.fd); 233 | break; 234 | default: 235 | break; 236 | } 237 | } 238 | 239 | static void esp_spp_stack_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) 240 | { 241 | spp_task_work_dispatch(esp_spp_cb, event, param, sizeof(esp_spp_cb_param_t), NULL); 242 | } 243 | 244 | void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) 245 | { 246 | switch (event) { 247 | case ESP_BT_GAP_AUTH_CMPL_EVT:{ 248 | if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { 249 | ESP_LOGI(SPP_TAG, "authentication success: %s", param->auth_cmpl.device_name); 250 | esp_log_buffer_hex(SPP_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN); 251 | } else { 252 | ESP_LOGE(SPP_TAG, "authentication failed, status:%d", param->auth_cmpl.stat); 253 | } 254 | break; 255 | } 256 | case ESP_BT_GAP_PIN_REQ_EVT:{ 257 | ESP_LOGI(SPP_TAG, "ESP_BT_GAP_PIN_REQ_EVT min_16_digit:%d", param->pin_req.min_16_digit); 258 | if (param->pin_req.min_16_digit) { 259 | ESP_LOGI(SPP_TAG, "Input pin code: 0000 0000 0000 0000"); 260 | esp_bt_pin_code_t pin_code = {0}; 261 | esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code); 262 | } else { 263 | ESP_LOGI(SPP_TAG, "Input pin code: 1234"); 264 | esp_bt_pin_code_t pin_code; 265 | pin_code[0] = '1'; 266 | pin_code[1] = '2'; 267 | pin_code[2] = '3'; 268 | pin_code[3] = '4'; 269 | esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code); 270 | } 271 | break; 272 | } 273 | case ESP_BT_GAP_CFM_REQ_EVT: 274 | ESP_LOGI(SPP_TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); 275 | esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); 276 | break; 277 | case ESP_BT_GAP_KEY_NOTIF_EVT: 278 | ESP_LOGI(SPP_TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey); 279 | break; 280 | case ESP_BT_GAP_KEY_REQ_EVT: 281 | ESP_LOGI(SPP_TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); 282 | break; 283 | default: 284 | ESP_LOGI(SPP_TAG, "event: %d", event); 285 | break; 286 | } 287 | return; 288 | } 289 | 290 | void app_main() 291 | { 292 | /* Configure GPIO mux */ 293 | gpio_pad_select_gpio(BT_ALT_SWITCH_GPIO); 294 | gpio_set_direction(BT_ALT_SWITCH_GPIO, GPIO_MODE_INPUT); 295 | gpio_set_pull_mode(BT_ALT_SWITCH_GPIO, GPIO_PULLUP_ONLY); 296 | 297 | gpio_pad_select_gpio(BT_CONNECTED_GPIO); 298 | gpio_set_direction(BT_CONNECTED_GPIO, GPIO_MODE_OUTPUT_OD); 299 | gpio_set_level(BT_CONNECTED_GPIO, BT_LED_DISCONNECTED); 300 | 301 | alt_settings = !gpio_get_level(BT_ALT_SWITCH_GPIO); 302 | if (alt_settings) { 303 | gpio_pad_select_gpio(BT_ALT_INDICATOR_GPIO); 304 | gpio_set_level(BT_ALT_INDICATOR_GPIO, 1); 305 | gpio_set_direction(BT_ALT_INDICATOR_GPIO, GPIO_MODE_OUTPUT); 306 | } 307 | 308 | /* Configure UART */ 309 | uart_config_t uart_config = { 310 | .baud_rate = alt_settings ? BT_UART_BITRATE_ALT : BT_UART_BITRATE, 311 | .data_bits = UART_DATA_8_BITS, 312 | .parity = alt_settings ? BT_UART_PARITY_ALT : UART_PARITY_DISABLE, 313 | .stop_bits = UART_STOP_BITS_1, 314 | .flow_ctrl = alt_settings ? BT_UART_FLOWCTRL_ALT : BT_UART_FLOWCTRL, 315 | .rx_flow_ctrl_thresh = UART_FIFO_LEN - 4 316 | }; 317 | 318 | ESP_ERROR_CHECK(uart_param_config(BT_UART, &uart_config)); 319 | ESP_ERROR_CHECK(uart_set_pin(BT_UART, BT_UART_TX_GPIO, BT_UART_RX_GPIO, BT_UART_RTS_GPIO, BT_UART_CTS_GPIO)); 320 | ESP_ERROR_CHECK(uart_driver_install(BT_UART, BT_UART_RX_BUF_SZ, BT_UART_TX_BUF_SZ, 0, NULL, 0)); 321 | 322 | esp_err_t ret = nvs_flash_init(); 323 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { 324 | ESP_ERROR_CHECK(nvs_flash_erase()); 325 | ret = nvs_flash_init(); 326 | } 327 | ESP_ERROR_CHECK( ret ); 328 | 329 | #ifndef BLE_ADAPTER_EN 330 | ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE)); 331 | #endif 332 | 333 | esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); 334 | if (esp_bt_controller_init(&bt_cfg) != ESP_OK) { 335 | ESP_LOGE(SPP_TAG, "%s initialize controller failed", __func__); 336 | return; 337 | } 338 | 339 | #ifndef BLE_ADAPTER_EN 340 | #define BT_MODE ESP_BT_MODE_CLASSIC_BT 341 | #else 342 | #define BT_MODE ESP_BT_MODE_BTDM 343 | #endif 344 | 345 | if (esp_bt_controller_enable(BT_MODE) != ESP_OK) { 346 | ESP_LOGE(SPP_TAG, "%s enable controller failed", __func__); 347 | return; 348 | } 349 | 350 | if (esp_bluedroid_init() != ESP_OK) { 351 | ESP_LOGE(SPP_TAG, "%s initialize bluedroid failed", __func__); 352 | return; 353 | } 354 | 355 | if (esp_bluedroid_enable() != ESP_OK) { 356 | ESP_LOGE(SPP_TAG, "%s enable bluedroid failed", __func__); 357 | return; 358 | } 359 | 360 | if (esp_bt_gap_register_callback(esp_bt_gap_cb) != ESP_OK) { 361 | ESP_LOGE(SPP_TAG, "%s gap register failed: %s\n", __func__, esp_err_to_name(ret)); 362 | return; 363 | } 364 | 365 | if (esp_spp_register_callback(esp_spp_stack_cb) != ESP_OK) { 366 | ESP_LOGE(SPP_TAG, "%s spp register failed", __func__); 367 | return; 368 | } 369 | esp_spp_vfs_register(); 370 | spp_task_task_start_up(); 371 | 372 | if (esp_spp_init(esp_spp_mode) != ESP_OK) { 373 | ESP_LOGE(SPP_TAG, "%s spp init failed", __func__); 374 | return; 375 | } 376 | 377 | /* Set default parameters for Secure Simple Pairing */ 378 | esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; 379 | esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_IO; 380 | esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); 381 | 382 | /* 383 | * Set default parameters for Legacy Pairing 384 | * Use variable pin, input pin code when pairing 385 | */ 386 | esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE; 387 | esp_bt_pin_code_t pin_code; 388 | esp_bt_gap_set_pin(pin_type, 0, pin_code); 389 | 390 | #ifdef BLE_ADAPTER_EN 391 | ble_server_init(); 392 | #endif 393 | } 394 | 395 | -------------------------------------------------------------------------------- /sdkconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Automatically generated file; DO NOT EDIT. 3 | # Espressif IoT Development Framework Configuration 4 | # 5 | CONFIG_IDF_TARGET="esp32" 6 | 7 | # 8 | # SDK tool configuration 9 | # 10 | CONFIG_TOOLPREFIX="xtensa-esp32-elf-" 11 | CONFIG_PYTHON="python" 12 | CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y 13 | 14 | # 15 | # Bootloader config 16 | # 17 | CONFIG_LOG_BOOTLOADER_LEVEL_NONE= 18 | CONFIG_LOG_BOOTLOADER_LEVEL_ERROR= 19 | CONFIG_LOG_BOOTLOADER_LEVEL_WARN= 20 | CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y 21 | CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= 22 | CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= 23 | CONFIG_LOG_BOOTLOADER_LEVEL=3 24 | CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= 25 | CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y 26 | CONFIG_BOOTLOADER_FACTORY_RESET= 27 | CONFIG_BOOTLOADER_APP_TEST= 28 | CONFIG_BOOTLOADER_WDT_ENABLE=y 29 | CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE= 30 | CONFIG_BOOTLOADER_WDT_TIME_MS=9000 31 | 32 | # 33 | # Security features 34 | # 35 | CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT= 36 | CONFIG_SECURE_BOOT_ENABLED= 37 | CONFIG_FLASH_ENCRYPTION_ENABLED= 38 | 39 | # 40 | # Serial flasher config 41 | # 42 | CONFIG_ESPTOOLPY_PORT="/dev/ttyUSB0" 43 | CONFIG_ESPTOOLPY_BAUD_115200B=y 44 | CONFIG_ESPTOOLPY_BAUD_230400B= 45 | CONFIG_ESPTOOLPY_BAUD_921600B= 46 | CONFIG_ESPTOOLPY_BAUD_2MB= 47 | CONFIG_ESPTOOLPY_BAUD_OTHER= 48 | CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 49 | CONFIG_ESPTOOLPY_BAUD=115200 50 | CONFIG_ESPTOOLPY_COMPRESSED=y 51 | CONFIG_FLASHMODE_QIO= 52 | CONFIG_FLASHMODE_QOUT= 53 | CONFIG_FLASHMODE_DIO=y 54 | CONFIG_FLASHMODE_DOUT= 55 | CONFIG_ESPTOOLPY_FLASHMODE="dio" 56 | CONFIG_ESPTOOLPY_FLASHFREQ_80M= 57 | CONFIG_ESPTOOLPY_FLASHFREQ_40M=y 58 | CONFIG_ESPTOOLPY_FLASHFREQ_26M= 59 | CONFIG_ESPTOOLPY_FLASHFREQ_20M= 60 | CONFIG_ESPTOOLPY_FLASHFREQ="40m" 61 | CONFIG_ESPTOOLPY_FLASHSIZE_1MB= 62 | CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y 63 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB= 64 | CONFIG_ESPTOOLPY_FLASHSIZE_8MB= 65 | CONFIG_ESPTOOLPY_FLASHSIZE_16MB= 66 | CONFIG_ESPTOOLPY_FLASHSIZE="2MB" 67 | CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y 68 | CONFIG_ESPTOOLPY_BEFORE_RESET=y 69 | CONFIG_ESPTOOLPY_BEFORE_NORESET= 70 | CONFIG_ESPTOOLPY_BEFORE="default_reset" 71 | CONFIG_ESPTOOLPY_AFTER_RESET=y 72 | CONFIG_ESPTOOLPY_AFTER_NORESET= 73 | CONFIG_ESPTOOLPY_AFTER="hard_reset" 74 | CONFIG_MONITOR_BAUD_9600B= 75 | CONFIG_MONITOR_BAUD_57600B= 76 | CONFIG_MONITOR_BAUD_115200B=y 77 | CONFIG_MONITOR_BAUD_230400B= 78 | CONFIG_MONITOR_BAUD_921600B= 79 | CONFIG_MONITOR_BAUD_2MB= 80 | CONFIG_MONITOR_BAUD_OTHER= 81 | CONFIG_MONITOR_BAUD_OTHER_VAL=115200 82 | CONFIG_MONITOR_BAUD=115200 83 | 84 | # 85 | # BT-UART Bridge Configuration 86 | # 87 | CONFIG_CONNECTED_LED_GPIO=5 88 | CONFIG_UART_TX_GPIO=25 89 | CONFIG_UART_RX_GPIO=26 90 | CONFIG_UART_RTS_GPIO=27 91 | CONFIG_UART_CTS_EN= 92 | CONFIG_UART_BITRATE=921600 93 | CONFIG_UART_BITRATE_ALT=115200 94 | CONFIG_UART_TX_BUFF_SIZE=17 95 | CONFIG_UART_RX_BUFF_SIZE=17 96 | CONFIG_DEV_NAME_PREFIX="EnSpectr-" 97 | CONFIG_DEV_NAME_PREFIX_ALT="EnSpectrPw-" 98 | CONFIG_ALT_SWITCH_GPIO=4 99 | CONFIG_ALT_INDICATOR_GPIO=32 100 | CONFIG_ALT_UART_PARITY=y 101 | CONFIG_DEV_NAME_BLE="EsPw" 102 | CONFIG_BLE_UART_RX_GPIO=33 103 | CONFIG_BLE_UART_BITRATE=19200 104 | CONFIG_BLE_UART_PARITY=y 105 | 106 | # 107 | # Partition Table 108 | # 109 | CONFIG_PARTITION_TABLE_SINGLE_APP=y 110 | CONFIG_PARTITION_TABLE_TWO_OTA= 111 | CONFIG_PARTITION_TABLE_CUSTOM= 112 | CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" 113 | CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" 114 | CONFIG_PARTITION_TABLE_OFFSET=0x8000 115 | CONFIG_PARTITION_TABLE_MD5=y 116 | 117 | # 118 | # Compiler options 119 | # 120 | CONFIG_OPTIMIZATION_LEVEL_DEBUG=y 121 | CONFIG_OPTIMIZATION_LEVEL_RELEASE= 122 | CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y 123 | CONFIG_OPTIMIZATION_ASSERTIONS_SILENT= 124 | CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED= 125 | CONFIG_CXX_EXCEPTIONS= 126 | CONFIG_STACK_CHECK_NONE=y 127 | CONFIG_STACK_CHECK_NORM= 128 | CONFIG_STACK_CHECK_STRONG= 129 | CONFIG_STACK_CHECK_ALL= 130 | CONFIG_STACK_CHECK= 131 | CONFIG_WARN_WRITE_STRINGS= 132 | CONFIG_DISABLE_GCC8_WARNINGS= 133 | 134 | # 135 | # Component config 136 | # 137 | 138 | # 139 | # Application Level Tracing 140 | # 141 | CONFIG_ESP32_APPTRACE_DEST_TRAX= 142 | CONFIG_ESP32_APPTRACE_DEST_NONE=y 143 | CONFIG_ESP32_APPTRACE_ENABLE= 144 | CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y 145 | CONFIG_AWS_IOT_SDK= 146 | 147 | # 148 | # Bluetooth 149 | # 150 | CONFIG_BT_ENABLED=y 151 | 152 | # 153 | # Bluetooth controller 154 | # 155 | CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY= 156 | CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY= 157 | CONFIG_BTDM_CONTROLLER_MODE_BTDM=y 158 | CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=3 159 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN=2 160 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN=0 161 | CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=3 162 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=2 163 | CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 164 | CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y 165 | CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1= 166 | CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 167 | CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y 168 | CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4= 169 | 170 | # 171 | # MODEM SLEEP Options 172 | # 173 | CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=y 174 | CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG=y 175 | CONFIG_BTDM_MODEM_SLEEP_MODE_EVED= 176 | CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL=y 177 | CONFIG_BLE_SCAN_DUPLICATE=y 178 | CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR=y 179 | CONFIG_SCAN_DUPLICATE_BY_ADV_DATA= 180 | CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR= 181 | CONFIG_SCAN_DUPLICATE_TYPE=0 182 | CONFIG_DUPLICATE_SCAN_CACHE_SIZE=200 183 | CONFIG_BLE_MESH_SCAN_DUPLICATE_EN= 184 | CONFIG_BLUEDROID_ENABLED=y 185 | CONFIG_BLUEDROID_PINNED_TO_CORE_0=y 186 | CONFIG_BLUEDROID_PINNED_TO_CORE_1= 187 | CONFIG_BLUEDROID_PINNED_TO_CORE=0 188 | CONFIG_BTC_TASK_STACK_SIZE=3072 189 | CONFIG_BLUEDROID_MEM_DEBUG= 190 | CONFIG_CLASSIC_BT_ENABLED=y 191 | CONFIG_A2DP_ENABLE= 192 | CONFIG_BT_SPP_ENABLED=y 193 | CONFIG_HFP_ENABLE= 194 | CONFIG_GATTS_ENABLE=y 195 | CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL= 196 | CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y 197 | CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 198 | CONFIG_GATTC_ENABLE=y 199 | CONFIG_GATTC_CACHE_NVS_FLASH= 200 | CONFIG_BLE_SMP_ENABLE=y 201 | CONFIG_BT_STACK_NO_LOG= 202 | 203 | # 204 | # BT DEBUG LOG LEVEL 205 | # 206 | CONFIG_HCI_TRACE_LEVEL_NONE= 207 | CONFIG_HCI_TRACE_LEVEL_ERROR= 208 | CONFIG_HCI_TRACE_LEVEL_WARNING=y 209 | CONFIG_HCI_TRACE_LEVEL_API= 210 | CONFIG_HCI_TRACE_LEVEL_EVENT= 211 | CONFIG_HCI_TRACE_LEVEL_DEBUG= 212 | CONFIG_HCI_TRACE_LEVEL_VERBOSE= 213 | CONFIG_HCI_INITIAL_TRACE_LEVEL=2 214 | CONFIG_BTM_TRACE_LEVEL_NONE= 215 | CONFIG_BTM_TRACE_LEVEL_ERROR= 216 | CONFIG_BTM_TRACE_LEVEL_WARNING=y 217 | CONFIG_BTM_TRACE_LEVEL_API= 218 | CONFIG_BTM_TRACE_LEVEL_EVENT= 219 | CONFIG_BTM_TRACE_LEVEL_DEBUG= 220 | CONFIG_BTM_TRACE_LEVEL_VERBOSE= 221 | CONFIG_BTM_INITIAL_TRACE_LEVEL=2 222 | CONFIG_L2CAP_TRACE_LEVEL_NONE= 223 | CONFIG_L2CAP_TRACE_LEVEL_ERROR= 224 | CONFIG_L2CAP_TRACE_LEVEL_WARNING=y 225 | CONFIG_L2CAP_TRACE_LEVEL_API= 226 | CONFIG_L2CAP_TRACE_LEVEL_EVENT= 227 | CONFIG_L2CAP_TRACE_LEVEL_DEBUG= 228 | CONFIG_L2CAP_TRACE_LEVEL_VERBOSE= 229 | CONFIG_L2CAP_INITIAL_TRACE_LEVEL=2 230 | CONFIG_RFCOMM_TRACE_LEVEL_NONE= 231 | CONFIG_RFCOMM_TRACE_LEVEL_ERROR= 232 | CONFIG_RFCOMM_TRACE_LEVEL_WARNING=y 233 | CONFIG_RFCOMM_TRACE_LEVEL_API= 234 | CONFIG_RFCOMM_TRACE_LEVEL_EVENT= 235 | CONFIG_RFCOMM_TRACE_LEVEL_DEBUG= 236 | CONFIG_RFCOMM_TRACE_LEVEL_VERBOSE= 237 | CONFIG_RFCOMM_INITIAL_TRACE_LEVEL=2 238 | CONFIG_SDP_TRACE_LEVEL_NONE= 239 | CONFIG_SDP_TRACE_LEVEL_ERROR= 240 | CONFIG_SDP_TRACE_LEVEL_WARNING=y 241 | CONFIG_SDP_TRACE_LEVEL_API= 242 | CONFIG_SDP_TRACE_LEVEL_EVENT= 243 | CONFIG_SDP_TRACE_LEVEL_DEBUG= 244 | CONFIG_SDP_TRACE_LEVEL_VERBOSE= 245 | CONFIG_SDP_INITIAL_TRACE_LEVEL=2 246 | CONFIG_GAP_TRACE_LEVEL_NONE= 247 | CONFIG_GAP_TRACE_LEVEL_ERROR= 248 | CONFIG_GAP_TRACE_LEVEL_WARNING=y 249 | CONFIG_GAP_TRACE_LEVEL_API= 250 | CONFIG_GAP_TRACE_LEVEL_EVENT= 251 | CONFIG_GAP_TRACE_LEVEL_DEBUG= 252 | CONFIG_GAP_TRACE_LEVEL_VERBOSE= 253 | CONFIG_GAP_INITIAL_TRACE_LEVEL=2 254 | CONFIG_BNEP_TRACE_LEVEL_NONE= 255 | CONFIG_BNEP_TRACE_LEVEL_ERROR= 256 | CONFIG_BNEP_TRACE_LEVEL_WARNING=y 257 | CONFIG_BNEP_TRACE_LEVEL_API= 258 | CONFIG_BNEP_TRACE_LEVEL_EVENT= 259 | CONFIG_BNEP_TRACE_LEVEL_DEBUG= 260 | CONFIG_BNEP_TRACE_LEVEL_VERBOSE= 261 | CONFIG_BNEP_INITIAL_TRACE_LEVEL=2 262 | CONFIG_PAN_TRACE_LEVEL_NONE= 263 | CONFIG_PAN_TRACE_LEVEL_ERROR= 264 | CONFIG_PAN_TRACE_LEVEL_WARNING=y 265 | CONFIG_PAN_TRACE_LEVEL_API= 266 | CONFIG_PAN_TRACE_LEVEL_EVENT= 267 | CONFIG_PAN_TRACE_LEVEL_DEBUG= 268 | CONFIG_PAN_TRACE_LEVEL_VERBOSE= 269 | CONFIG_PAN_INITIAL_TRACE_LEVEL=2 270 | CONFIG_A2D_TRACE_LEVEL_NONE= 271 | CONFIG_A2D_TRACE_LEVEL_ERROR= 272 | CONFIG_A2D_TRACE_LEVEL_WARNING=y 273 | CONFIG_A2D_TRACE_LEVEL_API= 274 | CONFIG_A2D_TRACE_LEVEL_EVENT= 275 | CONFIG_A2D_TRACE_LEVEL_DEBUG= 276 | CONFIG_A2D_TRACE_LEVEL_VERBOSE= 277 | CONFIG_A2D_INITIAL_TRACE_LEVEL=2 278 | CONFIG_AVDT_TRACE_LEVEL_NONE= 279 | CONFIG_AVDT_TRACE_LEVEL_ERROR= 280 | CONFIG_AVDT_TRACE_LEVEL_WARNING=y 281 | CONFIG_AVDT_TRACE_LEVEL_API= 282 | CONFIG_AVDT_TRACE_LEVEL_EVENT= 283 | CONFIG_AVDT_TRACE_LEVEL_DEBUG= 284 | CONFIG_AVDT_TRACE_LEVEL_VERBOSE= 285 | CONFIG_AVDT_INITIAL_TRACE_LEVEL=2 286 | CONFIG_AVCT_TRACE_LEVEL_NONE= 287 | CONFIG_AVCT_TRACE_LEVEL_ERROR= 288 | CONFIG_AVCT_TRACE_LEVEL_WARNING=y 289 | CONFIG_AVCT_TRACE_LEVEL_API= 290 | CONFIG_AVCT_TRACE_LEVEL_EVENT= 291 | CONFIG_AVCT_TRACE_LEVEL_DEBUG= 292 | CONFIG_AVCT_TRACE_LEVEL_VERBOSE= 293 | CONFIG_AVCT_INITIAL_TRACE_LEVEL=2 294 | CONFIG_AVRC_TRACE_LEVEL_NONE= 295 | CONFIG_AVRC_TRACE_LEVEL_ERROR= 296 | CONFIG_AVRC_TRACE_LEVEL_WARNING=y 297 | CONFIG_AVRC_TRACE_LEVEL_API= 298 | CONFIG_AVRC_TRACE_LEVEL_EVENT= 299 | CONFIG_AVRC_TRACE_LEVEL_DEBUG= 300 | CONFIG_AVRC_TRACE_LEVEL_VERBOSE= 301 | CONFIG_AVRC_INITIAL_TRACE_LEVEL=2 302 | CONFIG_MCA_TRACE_LEVEL_NONE= 303 | CONFIG_MCA_TRACE_LEVEL_ERROR= 304 | CONFIG_MCA_TRACE_LEVEL_WARNING=y 305 | CONFIG_MCA_TRACE_LEVEL_API= 306 | CONFIG_MCA_TRACE_LEVEL_EVENT= 307 | CONFIG_MCA_TRACE_LEVEL_DEBUG= 308 | CONFIG_MCA_TRACE_LEVEL_VERBOSE= 309 | CONFIG_MCA_INITIAL_TRACE_LEVEL=2 310 | CONFIG_HID_TRACE_LEVEL_NONE= 311 | CONFIG_HID_TRACE_LEVEL_ERROR= 312 | CONFIG_HID_TRACE_LEVEL_WARNING=y 313 | CONFIG_HID_TRACE_LEVEL_API= 314 | CONFIG_HID_TRACE_LEVEL_EVENT= 315 | CONFIG_HID_TRACE_LEVEL_DEBUG= 316 | CONFIG_HID_TRACE_LEVEL_VERBOSE= 317 | CONFIG_HID_INITIAL_TRACE_LEVEL=2 318 | CONFIG_APPL_TRACE_LEVEL_NONE= 319 | CONFIG_APPL_TRACE_LEVEL_ERROR= 320 | CONFIG_APPL_TRACE_LEVEL_WARNING=y 321 | CONFIG_APPL_TRACE_LEVEL_API= 322 | CONFIG_APPL_TRACE_LEVEL_EVENT= 323 | CONFIG_APPL_TRACE_LEVEL_DEBUG= 324 | CONFIG_APPL_TRACE_LEVEL_VERBOSE= 325 | CONFIG_APPL_INITIAL_TRACE_LEVEL=2 326 | CONFIG_GATT_TRACE_LEVEL_NONE= 327 | CONFIG_GATT_TRACE_LEVEL_ERROR= 328 | CONFIG_GATT_TRACE_LEVEL_WARNING=y 329 | CONFIG_GATT_TRACE_LEVEL_API= 330 | CONFIG_GATT_TRACE_LEVEL_EVENT= 331 | CONFIG_GATT_TRACE_LEVEL_DEBUG= 332 | CONFIG_GATT_TRACE_LEVEL_VERBOSE= 333 | CONFIG_GATT_INITIAL_TRACE_LEVEL=2 334 | CONFIG_SMP_TRACE_LEVEL_NONE= 335 | CONFIG_SMP_TRACE_LEVEL_ERROR= 336 | CONFIG_SMP_TRACE_LEVEL_WARNING=y 337 | CONFIG_SMP_TRACE_LEVEL_API= 338 | CONFIG_SMP_TRACE_LEVEL_EVENT= 339 | CONFIG_SMP_TRACE_LEVEL_DEBUG= 340 | CONFIG_SMP_TRACE_LEVEL_VERBOSE= 341 | CONFIG_SMP_INITIAL_TRACE_LEVEL=2 342 | CONFIG_BTIF_TRACE_LEVEL_NONE= 343 | CONFIG_BTIF_TRACE_LEVEL_ERROR= 344 | CONFIG_BTIF_TRACE_LEVEL_WARNING=y 345 | CONFIG_BTIF_TRACE_LEVEL_API= 346 | CONFIG_BTIF_TRACE_LEVEL_EVENT= 347 | CONFIG_BTIF_TRACE_LEVEL_DEBUG= 348 | CONFIG_BTIF_TRACE_LEVEL_VERBOSE= 349 | CONFIG_BTIF_INITIAL_TRACE_LEVEL=2 350 | CONFIG_BTC_TRACE_LEVEL_NONE= 351 | CONFIG_BTC_TRACE_LEVEL_ERROR= 352 | CONFIG_BTC_TRACE_LEVEL_WARNING=y 353 | CONFIG_BTC_TRACE_LEVEL_API= 354 | CONFIG_BTC_TRACE_LEVEL_EVENT= 355 | CONFIG_BTC_TRACE_LEVEL_DEBUG= 356 | CONFIG_BTC_TRACE_LEVEL_VERBOSE= 357 | CONFIG_BTC_INITIAL_TRACE_LEVEL=2 358 | CONFIG_OSI_TRACE_LEVEL_NONE= 359 | CONFIG_OSI_TRACE_LEVEL_ERROR= 360 | CONFIG_OSI_TRACE_LEVEL_WARNING=y 361 | CONFIG_OSI_TRACE_LEVEL_API= 362 | CONFIG_OSI_TRACE_LEVEL_EVENT= 363 | CONFIG_OSI_TRACE_LEVEL_DEBUG= 364 | CONFIG_OSI_TRACE_LEVEL_VERBOSE= 365 | CONFIG_OSI_INITIAL_TRACE_LEVEL=2 366 | CONFIG_BLUFI_TRACE_LEVEL_NONE= 367 | CONFIG_BLUFI_TRACE_LEVEL_ERROR= 368 | CONFIG_BLUFI_TRACE_LEVEL_WARNING=y 369 | CONFIG_BLUFI_TRACE_LEVEL_API= 370 | CONFIG_BLUFI_TRACE_LEVEL_EVENT= 371 | CONFIG_BLUFI_TRACE_LEVEL_DEBUG= 372 | CONFIG_BLUFI_TRACE_LEVEL_VERBOSE= 373 | CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 374 | CONFIG_BT_ACL_CONNECTIONS=4 375 | CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST= 376 | CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY= 377 | CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK= 378 | CONFIG_SMP_ENABLE=y 379 | CONFIG_BT_RESERVE_DRAM=0xdb5c 380 | 381 | # 382 | # Driver configurations 383 | # 384 | 385 | # 386 | # ADC configuration 387 | # 388 | CONFIG_ADC_FORCE_XPD_FSM= 389 | CONFIG_ADC2_DISABLE_DAC=y 390 | 391 | # 392 | # SPI configuration 393 | # 394 | CONFIG_SPI_MASTER_IN_IRAM= 395 | CONFIG_SPI_MASTER_ISR_IN_IRAM=y 396 | CONFIG_SPI_SLAVE_IN_IRAM= 397 | CONFIG_SPI_SLAVE_ISR_IN_IRAM=y 398 | 399 | # 400 | # ESP32-specific 401 | # 402 | CONFIG_IDF_TARGET_ESP32=y 403 | CONFIG_ESP32_DEFAULT_CPU_FREQ_80= 404 | CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y 405 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240= 406 | CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160 407 | CONFIG_SPIRAM_SUPPORT= 408 | CONFIG_MEMMAP_TRACEMEM= 409 | CONFIG_MEMMAP_TRACEMEM_TWOBANKS= 410 | CONFIG_ESP32_TRAX= 411 | CONFIG_TRACEMEM_RESERVE_DRAM=0x0 412 | 413 | # 414 | # Core dump 415 | # 416 | CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH= 417 | CONFIG_ESP32_ENABLE_COREDUMP_TO_UART= 418 | CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y 419 | CONFIG_ESP32_ENABLE_COREDUMP= 420 | CONFIG_TWO_UNIVERSAL_MAC_ADDRESS= 421 | CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y 422 | CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 423 | CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 424 | CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 425 | CONFIG_MAIN_TASK_STACK_SIZE=3584 426 | CONFIG_IPC_TASK_STACK_SIZE=1024 427 | CONFIG_TIMER_TASK_STACK_SIZE=3584 428 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y 429 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF= 430 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR= 431 | CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF= 432 | CONFIG_NEWLIB_STDIN_LINE_ENDING_LF= 433 | CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y 434 | CONFIG_NEWLIB_NANO_FORMAT= 435 | CONFIG_CONSOLE_UART_DEFAULT=y 436 | CONFIG_CONSOLE_UART_CUSTOM= 437 | CONFIG_CONSOLE_UART_NONE= 438 | CONFIG_CONSOLE_UART_NUM=0 439 | CONFIG_CONSOLE_UART_BAUDRATE=115200 440 | CONFIG_ULP_COPROC_ENABLED= 441 | CONFIG_ULP_COPROC_RESERVE_MEM=0 442 | CONFIG_ESP32_PANIC_PRINT_HALT= 443 | CONFIG_ESP32_PANIC_PRINT_REBOOT=y 444 | CONFIG_ESP32_PANIC_SILENT_REBOOT= 445 | CONFIG_ESP32_PANIC_GDBSTUB= 446 | CONFIG_ESP32_DEBUG_OCDAWARE=y 447 | CONFIG_ESP32_DEBUG_STUBS_ENABLE=y 448 | CONFIG_INT_WDT=y 449 | CONFIG_INT_WDT_TIMEOUT_MS=300 450 | CONFIG_INT_WDT_CHECK_CPU1=y 451 | CONFIG_TASK_WDT=y 452 | CONFIG_TASK_WDT_PANIC= 453 | CONFIG_TASK_WDT_TIMEOUT_S=5 454 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y 455 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y 456 | CONFIG_BROWNOUT_DET=y 457 | CONFIG_BROWNOUT_DET_LVL_SEL_0=y 458 | CONFIG_BROWNOUT_DET_LVL_SEL_1= 459 | CONFIG_BROWNOUT_DET_LVL_SEL_2= 460 | CONFIG_BROWNOUT_DET_LVL_SEL_3= 461 | CONFIG_BROWNOUT_DET_LVL_SEL_4= 462 | CONFIG_BROWNOUT_DET_LVL_SEL_5= 463 | CONFIG_BROWNOUT_DET_LVL_SEL_6= 464 | CONFIG_BROWNOUT_DET_LVL_SEL_7= 465 | CONFIG_BROWNOUT_DET_LVL=0 466 | CONFIG_REDUCE_PHY_TX_POWER=y 467 | CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y 468 | CONFIG_ESP32_TIME_SYSCALL_USE_RTC= 469 | CONFIG_ESP32_TIME_SYSCALL_USE_FRC1= 470 | CONFIG_ESP32_TIME_SYSCALL_USE_NONE= 471 | CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y 472 | CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL= 473 | CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC= 474 | CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256= 475 | CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 476 | CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 477 | CONFIG_ESP32_XTAL_FREQ_40=y 478 | CONFIG_ESP32_XTAL_FREQ_26= 479 | CONFIG_ESP32_XTAL_FREQ_AUTO= 480 | CONFIG_ESP32_XTAL_FREQ=40 481 | CONFIG_DISABLE_BASIC_ROM_CONSOLE= 482 | CONFIG_ESP_TIMER_PROFILING= 483 | CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= 484 | CONFIG_ESP_ERR_TO_NAME_LOOKUP=y 485 | 486 | # 487 | # Wi-Fi 488 | # 489 | CONFIG_SW_COEXIST_ENABLE=y 490 | CONFIG_SW_COEXIST_PREFERENCE_WIFI= 491 | CONFIG_SW_COEXIST_PREFERENCE_BT= 492 | CONFIG_SW_COEXIST_PREFERENCE_BALANCE=y 493 | CONFIG_SW_COEXIST_PREFERENCE_VALUE=2 494 | CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 495 | CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 496 | CONFIG_ESP32_WIFI_STATIC_TX_BUFFER= 497 | CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y 498 | CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 499 | CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 500 | CONFIG_ESP32_WIFI_CSI_ENABLED= 501 | CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y 502 | CONFIG_ESP32_WIFI_TX_BA_WIN=6 503 | CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y 504 | CONFIG_ESP32_WIFI_RX_BA_WIN=6 505 | CONFIG_ESP32_WIFI_NVS_ENABLED=y 506 | CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y 507 | CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= 508 | CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 509 | 510 | # 511 | # PHY 512 | # 513 | CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y 514 | CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION= 515 | CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 516 | CONFIG_ESP32_PHY_MAX_TX_POWER=20 517 | 518 | # 519 | # Power Management 520 | # 521 | CONFIG_PM_ENABLE= 522 | 523 | # 524 | # ADC-Calibration 525 | # 526 | CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y 527 | CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y 528 | CONFIG_ADC_CAL_LUT_ENABLE=y 529 | 530 | # 531 | # Event Loop Library 532 | # 533 | CONFIG_EVENT_LOOP_PROFILING= 534 | 535 | # 536 | # ESP HTTP client 537 | # 538 | CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y 539 | 540 | # 541 | # HTTP Server 542 | # 543 | CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 544 | CONFIG_HTTPD_MAX_URI_LEN=512 545 | 546 | # 547 | # Ethernet 548 | # 549 | CONFIG_DMA_RX_BUF_NUM=10 550 | CONFIG_DMA_TX_BUF_NUM=10 551 | CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE=y 552 | CONFIG_EMAC_CHECK_LINK_PERIOD_MS=2000 553 | CONFIG_EMAC_TASK_PRIORITY=20 554 | CONFIG_EMAC_TASK_STACK_SIZE=3072 555 | 556 | # 557 | # FAT Filesystem support 558 | # 559 | CONFIG_FATFS_CODEPAGE_DYNAMIC= 560 | CONFIG_FATFS_CODEPAGE_437=y 561 | CONFIG_FATFS_CODEPAGE_720= 562 | CONFIG_FATFS_CODEPAGE_737= 563 | CONFIG_FATFS_CODEPAGE_771= 564 | CONFIG_FATFS_CODEPAGE_775= 565 | CONFIG_FATFS_CODEPAGE_850= 566 | CONFIG_FATFS_CODEPAGE_852= 567 | CONFIG_FATFS_CODEPAGE_855= 568 | CONFIG_FATFS_CODEPAGE_857= 569 | CONFIG_FATFS_CODEPAGE_860= 570 | CONFIG_FATFS_CODEPAGE_861= 571 | CONFIG_FATFS_CODEPAGE_862= 572 | CONFIG_FATFS_CODEPAGE_863= 573 | CONFIG_FATFS_CODEPAGE_864= 574 | CONFIG_FATFS_CODEPAGE_865= 575 | CONFIG_FATFS_CODEPAGE_866= 576 | CONFIG_FATFS_CODEPAGE_869= 577 | CONFIG_FATFS_CODEPAGE_932= 578 | CONFIG_FATFS_CODEPAGE_936= 579 | CONFIG_FATFS_CODEPAGE_949= 580 | CONFIG_FATFS_CODEPAGE_950= 581 | CONFIG_FATFS_CODEPAGE=437 582 | CONFIG_FATFS_LFN_NONE=y 583 | CONFIG_FATFS_LFN_HEAP= 584 | CONFIG_FATFS_LFN_STACK= 585 | CONFIG_FATFS_FS_LOCK=0 586 | CONFIG_FATFS_TIMEOUT_MS=10000 587 | CONFIG_FATFS_PER_FILE_CACHE=y 588 | 589 | # 590 | # Modbus configuration 591 | # 592 | CONFIG_MB_UART_RXD=22 593 | CONFIG_MB_UART_TXD=23 594 | CONFIG_MB_UART_RTS=18 595 | CONFIG_MB_QUEUE_LENGTH=20 596 | CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 597 | CONFIG_MB_SERIAL_BUF_SIZE=256 598 | CONFIG_MB_SERIAL_TASK_PRIO=10 599 | CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT= 600 | CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 601 | CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 602 | CONFIG_MB_CONTROLLER_STACK_SIZE=4096 603 | CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 604 | CONFIG_MB_TIMER_PORT_ENABLED=y 605 | CONFIG_MB_TIMER_GROUP=0 606 | CONFIG_MB_TIMER_INDEX=0 607 | 608 | # 609 | # FreeRTOS 610 | # 611 | CONFIG_FREERTOS_UNICORE= 612 | CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF 613 | CONFIG_FREERTOS_CORETIMER_0=y 614 | CONFIG_FREERTOS_CORETIMER_1= 615 | CONFIG_FREERTOS_HZ=100 616 | CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y 617 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE= 618 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL= 619 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y 620 | CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK= 621 | CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y 622 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 623 | CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y 624 | CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE= 625 | CONFIG_FREERTOS_ASSERT_DISABLE= 626 | CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 627 | CONFIG_FREERTOS_ISR_STACKSIZE=1536 628 | CONFIG_FREERTOS_LEGACY_HOOKS= 629 | CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 630 | CONFIG_SUPPORT_STATIC_ALLOCATION= 631 | CONFIG_TIMER_TASK_PRIORITY=1 632 | CONFIG_TIMER_TASK_STACK_DEPTH=2048 633 | CONFIG_TIMER_QUEUE_LENGTH=10 634 | CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 635 | CONFIG_FREERTOS_USE_TRACE_FACILITY= 636 | CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS= 637 | CONFIG_FREERTOS_DEBUG_INTERNALS= 638 | CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y 639 | 640 | # 641 | # Heap memory debugging 642 | # 643 | CONFIG_HEAP_POISONING_DISABLED=y 644 | CONFIG_HEAP_POISONING_LIGHT= 645 | CONFIG_HEAP_POISONING_COMPREHENSIVE= 646 | CONFIG_HEAP_TRACING= 647 | 648 | # 649 | # libsodium 650 | # 651 | CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y 652 | 653 | # 654 | # Log output 655 | # 656 | CONFIG_LOG_DEFAULT_LEVEL_NONE= 657 | CONFIG_LOG_DEFAULT_LEVEL_ERROR= 658 | CONFIG_LOG_DEFAULT_LEVEL_WARN= 659 | CONFIG_LOG_DEFAULT_LEVEL_INFO=y 660 | CONFIG_LOG_DEFAULT_LEVEL_DEBUG= 661 | CONFIG_LOG_DEFAULT_LEVEL_VERBOSE= 662 | CONFIG_LOG_DEFAULT_LEVEL=3 663 | CONFIG_LOG_COLORS=y 664 | 665 | # 666 | # LWIP 667 | # 668 | CONFIG_L2_TO_L3_COPY= 669 | CONFIG_LWIP_IRAM_OPTIMIZATION= 670 | CONFIG_LWIP_MAX_SOCKETS=10 671 | CONFIG_USE_ONLY_LWIP_SELECT= 672 | CONFIG_LWIP_SO_REUSE=y 673 | CONFIG_LWIP_SO_REUSE_RXTOALL=y 674 | CONFIG_LWIP_SO_RCVBUF= 675 | CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 676 | CONFIG_LWIP_IP_FRAG= 677 | CONFIG_LWIP_IP_REASSEMBLY= 678 | CONFIG_LWIP_STATS= 679 | CONFIG_LWIP_ETHARP_TRUST_IP_MAC= 680 | CONFIG_ESP_GRATUITOUS_ARP=y 681 | CONFIG_GARP_TMR_INTERVAL=60 682 | CONFIG_TCPIP_RECVMBOX_SIZE=32 683 | CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y 684 | CONFIG_LWIP_DHCP_RESTORE_LAST_IP= 685 | 686 | # 687 | # DHCP server 688 | # 689 | CONFIG_LWIP_DHCPS_LEASE_UNIT=60 690 | CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 691 | CONFIG_LWIP_AUTOIP= 692 | CONFIG_LWIP_NETIF_LOOPBACK=y 693 | CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 694 | 695 | # 696 | # TCP 697 | # 698 | CONFIG_LWIP_MAX_ACTIVE_TCP=16 699 | CONFIG_LWIP_MAX_LISTENING_TCP=16 700 | CONFIG_TCP_MAXRTX=12 701 | CONFIG_TCP_SYNMAXRTX=6 702 | CONFIG_TCP_MSS=1436 703 | CONFIG_TCP_MSL=60000 704 | CONFIG_TCP_SND_BUF_DEFAULT=5744 705 | CONFIG_TCP_WND_DEFAULT=5744 706 | CONFIG_TCP_RECVMBOX_SIZE=6 707 | CONFIG_TCP_QUEUE_OOSEQ=y 708 | CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= 709 | CONFIG_TCP_OVERSIZE_MSS=y 710 | CONFIG_TCP_OVERSIZE_QUARTER_MSS= 711 | CONFIG_TCP_OVERSIZE_DISABLE= 712 | 713 | # 714 | # UDP 715 | # 716 | CONFIG_LWIP_MAX_UDP_PCBS=16 717 | CONFIG_UDP_RECVMBOX_SIZE=6 718 | CONFIG_TCPIP_TASK_STACK_SIZE=3072 719 | CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y 720 | CONFIG_TCPIP_TASK_AFFINITY_CPU0= 721 | CONFIG_TCPIP_TASK_AFFINITY_CPU1= 722 | CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF 723 | CONFIG_PPP_SUPPORT= 724 | 725 | # 726 | # ICMP 727 | # 728 | CONFIG_LWIP_MULTICAST_PING= 729 | CONFIG_LWIP_BROADCAST_PING= 730 | 731 | # 732 | # LWIP RAW API 733 | # 734 | CONFIG_LWIP_MAX_RAW_PCBS=16 735 | 736 | # 737 | # mbedTLS 738 | # 739 | CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y 740 | CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC= 741 | CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC= 742 | CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 743 | CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN= 744 | CONFIG_MBEDTLS_DEBUG= 745 | CONFIG_MBEDTLS_HARDWARE_AES=y 746 | CONFIG_MBEDTLS_HARDWARE_MPI= 747 | CONFIG_MBEDTLS_HARDWARE_SHA= 748 | CONFIG_MBEDTLS_HAVE_TIME=y 749 | CONFIG_MBEDTLS_HAVE_TIME_DATE= 750 | CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y 751 | CONFIG_MBEDTLS_TLS_SERVER_ONLY= 752 | CONFIG_MBEDTLS_TLS_CLIENT_ONLY= 753 | CONFIG_MBEDTLS_TLS_DISABLED= 754 | CONFIG_MBEDTLS_TLS_SERVER=y 755 | CONFIG_MBEDTLS_TLS_CLIENT=y 756 | CONFIG_MBEDTLS_TLS_ENABLED=y 757 | 758 | # 759 | # TLS Key Exchange Methods 760 | # 761 | CONFIG_MBEDTLS_PSK_MODES= 762 | CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y 763 | CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y 764 | CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y 765 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y 766 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y 767 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y 768 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y 769 | CONFIG_MBEDTLS_SSL_RENEGOTIATION=y 770 | CONFIG_MBEDTLS_SSL_PROTO_SSL3= 771 | CONFIG_MBEDTLS_SSL_PROTO_TLS1=y 772 | CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y 773 | CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y 774 | CONFIG_MBEDTLS_SSL_PROTO_DTLS= 775 | CONFIG_MBEDTLS_SSL_ALPN=y 776 | CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y 777 | 778 | # 779 | # Symmetric Ciphers 780 | # 781 | CONFIG_MBEDTLS_AES_C=y 782 | CONFIG_MBEDTLS_CAMELLIA_C= 783 | CONFIG_MBEDTLS_DES_C= 784 | CONFIG_MBEDTLS_RC4_DISABLED=y 785 | CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT= 786 | CONFIG_MBEDTLS_RC4_ENABLED= 787 | CONFIG_MBEDTLS_BLOWFISH_C= 788 | CONFIG_MBEDTLS_XTEA_C= 789 | CONFIG_MBEDTLS_CCM_C=y 790 | CONFIG_MBEDTLS_GCM_C=y 791 | CONFIG_MBEDTLS_RIPEMD160_C= 792 | 793 | # 794 | # Certificates 795 | # 796 | CONFIG_MBEDTLS_PEM_PARSE_C=y 797 | CONFIG_MBEDTLS_PEM_WRITE_C=y 798 | CONFIG_MBEDTLS_X509_CRL_PARSE_C=y 799 | CONFIG_MBEDTLS_X509_CSR_PARSE_C=y 800 | CONFIG_MBEDTLS_ECP_C=y 801 | CONFIG_MBEDTLS_ECDH_C=y 802 | CONFIG_MBEDTLS_ECDSA_C=y 803 | CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y 804 | CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y 805 | CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y 806 | CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y 807 | CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y 808 | CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y 809 | CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y 810 | CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y 811 | CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y 812 | CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y 813 | CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y 814 | CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y 815 | CONFIG_MBEDTLS_ECP_NIST_OPTIM=y 816 | 817 | # 818 | # mDNS 819 | # 820 | CONFIG_MDNS_MAX_SERVICES=10 821 | 822 | # 823 | # ESP-MQTT Configurations 824 | # 825 | CONFIG_MQTT_PROTOCOL_311=y 826 | CONFIG_MQTT_TRANSPORT_SSL=y 827 | CONFIG_MQTT_TRANSPORT_WEBSOCKET=y 828 | CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y 829 | CONFIG_MQTT_USE_CUSTOM_CONFIG= 830 | CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED= 831 | CONFIG_MQTT_CUSTOM_OUTBOX= 832 | 833 | # 834 | # NVS 835 | # 836 | 837 | # 838 | # OpenSSL 839 | # 840 | CONFIG_OPENSSL_DEBUG= 841 | CONFIG_OPENSSL_ASSERT_DO_NOTHING=y 842 | CONFIG_OPENSSL_ASSERT_EXIT= 843 | 844 | # 845 | # PThreads 846 | # 847 | CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 848 | CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 849 | CONFIG_PTHREAD_STACK_MIN=768 850 | 851 | # 852 | # SPI Flash driver 853 | # 854 | CONFIG_SPI_FLASH_VERIFY_WRITE= 855 | CONFIG_SPI_FLASH_ENABLE_COUNTERS= 856 | CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y 857 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y 858 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS= 859 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED= 860 | 861 | # 862 | # SPIFFS Configuration 863 | # 864 | CONFIG_SPIFFS_MAX_PARTITIONS=3 865 | 866 | # 867 | # SPIFFS Cache Configuration 868 | # 869 | CONFIG_SPIFFS_CACHE=y 870 | CONFIG_SPIFFS_CACHE_WR=y 871 | CONFIG_SPIFFS_CACHE_STATS= 872 | CONFIG_SPIFFS_PAGE_CHECK=y 873 | CONFIG_SPIFFS_GC_MAX_RUNS=10 874 | CONFIG_SPIFFS_GC_STATS= 875 | CONFIG_SPIFFS_PAGE_SIZE=256 876 | CONFIG_SPIFFS_OBJ_NAME_LEN=32 877 | CONFIG_SPIFFS_USE_MAGIC=y 878 | CONFIG_SPIFFS_USE_MAGIC_LENGTH=y 879 | CONFIG_SPIFFS_META_LENGTH=4 880 | CONFIG_SPIFFS_USE_MTIME=y 881 | 882 | # 883 | # Debug Configuration 884 | # 885 | CONFIG_SPIFFS_DBG= 886 | CONFIG_SPIFFS_API_DBG= 887 | CONFIG_SPIFFS_GC_DBG= 888 | CONFIG_SPIFFS_CACHE_DBG= 889 | CONFIG_SPIFFS_CHECK_DBG= 890 | CONFIG_SPIFFS_TEST_VISUALISATION= 891 | 892 | # 893 | # TCP/IP Adapter 894 | # 895 | CONFIG_IP_LOST_TIMER_INTERVAL=120 896 | CONFIG_TCPIP_LWIP=y 897 | 898 | # 899 | # Unity unit testing library 900 | # 901 | CONFIG_UNITY_ENABLE_FLOAT=y 902 | CONFIG_UNITY_ENABLE_DOUBLE=y 903 | CONFIG_UNITY_ENABLE_COLOR= 904 | CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y 905 | CONFIG_UNITY_ENABLE_FIXTURE= 906 | 907 | # 908 | # Virtual file system 909 | # 910 | CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y 911 | CONFIG_SUPPORT_TERMIOS=y 912 | 913 | # 914 | # Wear Levelling 915 | # 916 | CONFIG_WL_SECTOR_SIZE_512= 917 | CONFIG_WL_SECTOR_SIZE_4096=y 918 | CONFIG_WL_SECTOR_SIZE=4096 919 | -------------------------------------------------------------------------------- /sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | # Override some defaults so BT stack is enabled 2 | # and WiFi disabled by default in this example 3 | CONFIG_BT_ENABLED=y 4 | CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY= 5 | CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY=y 6 | CONFIG_BTDM_CONTROLLER_MODE_BTDM= 7 | CONFIG_CLASSIC_BT_ENABLED=y 8 | CONFIG_WIFI_ENABLED=n 9 | CONFIG_BT_SPP_ENABLED=y 10 | CONFIG_LOG_DEFAULT_LEVEL_WARN=y 11 | -------------------------------------------------------------------------------- /test/ble_test.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import random 4 | import serial 5 | from serial import Serial 6 | 7 | serial_baud_rate = 19200 8 | serial_parity = serial.PARITY_EVEN 9 | 10 | max_len = 512 11 | msg_delay = .1 12 | 13 | random.seed() 14 | 15 | def random_str(sz): 16 | buff = '' 17 | for i in range(sz): 18 | v = random.randrange(ord('A'), ord('Z') + 1) 19 | buff += chr(v) 20 | return buff 21 | 22 | def read_resp(com, tout=1): 23 | resp = b'' 24 | dline = time.time() + tout 25 | while True: 26 | r = com.read(max_len) 27 | if r: 28 | resp += r 29 | if resp[-1] == term_chr: 30 | return resp 31 | continue 32 | if time.time() > dline: 33 | return resp 34 | 35 | total_bytes = 0 36 | start = time.time() 37 | 38 | with Serial(sys.argv[1], baudrate=serial_baud_rate, parity=serial_parity, timeout=.1) as com: 39 | try: 40 | while True: 41 | s = random_str(random.randrange(1, max_len)) 42 | msg = '#' + s + '_' + s 43 | com.write(msg) 44 | resp = read_resp(com) 45 | total_bytes += len(msg) + len(resp) 46 | print '.', 47 | time.sleep(msg_delay) 48 | except KeyboardInterrupt: 49 | now = time.time() 50 | print '\n%u bytes transferred (%u bytes/sec)' % (total_bytes, int(total_bytes/(now-start))) 51 | pass 52 | -------------------------------------------------------------------------------- /test/bt_echo.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import bluetooth 3 | import random 4 | import time 5 | 6 | max_msg_len = 17*1024 7 | max_msg_offset = 1024 8 | msg_buff = None 9 | idle_delay = .001 10 | 11 | def msg_init(): 12 | global msg_buff 13 | msg_buff = bytearray(random.randrange(256) for _ in xrange(max_msg_offset + max_msg_len)) 14 | 15 | def msg_random(): 16 | len = random.randrange(max_msg_len+1) 17 | off = random.randrange(max_msg_offset+1) 18 | return str(msg_buff[off:off+len]) 19 | 20 | def find_address(dev_name): 21 | dev_list = bluetooth.discover_devices(lookup_names = True) 22 | for (addr, name) in dev_list: 23 | if name == dev_name: 24 | return addr 25 | return None 26 | 27 | def receive(sock, size, tout = 5.): 28 | chunks, sz = [], size 29 | deadline = None 30 | while sz > 0: 31 | data = sock.recv(sz) 32 | if not data: 33 | if deadline is None: 34 | deadline = time.time() + tout 35 | elif time.time() > deadline: 36 | raise RuntimeError('receive timeout, %u out of %u bytes received' % (size - sz, size)) 37 | time.sleep(idle_delay) 38 | continue 39 | chunk_sz = len(data) 40 | if chunk_sz == size: 41 | return data 42 | deadline = None 43 | chunks.append(data) 44 | sz -= chunk_sz 45 | return ''.join(chunks) 46 | 47 | def chk_resp(msg, resp): 48 | if msg == resp: 49 | return True 50 | print >> sys.stderr, 'bad response:' 51 | cnt = 0 52 | for i, sent in enumerate(msg): 53 | if sent != resp[i]: 54 | print >> sys.stderr, '[%u] sent %02x, recv %02x' % (i, ord(sent), ord(resp[i])) 55 | cnt += 1 56 | print >> sys.stderr, '%u of %u bytes mismatched' % (cnt, len(msg)) 57 | return False 58 | 59 | def do_test(addr): 60 | sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) 61 | sock.connect((addr, 1)) 62 | sock.setblocking(False) 63 | 64 | print >> sys.stderr, 'connected' 65 | 66 | msg_init() 67 | start = time.time() 68 | bytes = 0 69 | 70 | while True: 71 | msg = msg_random() 72 | sock.send(msg) 73 | msg_len = len(msg) 74 | resp = receive(sock, msg_len) 75 | assert len(resp) == msg_len 76 | if not chk_resp(msg, resp): 77 | break 78 | bytes += msg_len 79 | print >> sys.stderr, '.', 80 | if bytes > 1000000: 81 | now = time.time() 82 | print >> sys.stderr 83 | print >> sys.stderr, int(bytes * 8 / (now - start)), 'bits/sec' 84 | bytes, start = 0, now 85 | 86 | if __name__ == '__main__': 87 | args = sys.argv[1:] 88 | if not args: 89 | print >> sys.stderr, 'device name argument is required' 90 | sys.exit(1) 91 | dev_name = args[0] 92 | addr = find_address(dev_name) 93 | if not addr: 94 | print >> sys.stderr, 'not found' 95 | sys.exit(-1) 96 | if '--lookup' in args[1:]: 97 | print addr 98 | sys.exit(0) 99 | do_test(addr) 100 | -------------------------------------------------------------------------------- /www/css/test.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: sans-serif; 3 | } 4 | 5 | table { 6 | border: 0; 7 | } 8 | 9 | td { 10 | padding: .1em; 11 | } 12 | 13 | textarea { 14 | width: 100%; 15 | } 16 | -------------------------------------------------------------------------------- /www/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegv142/esp32-bt-serial/3d3e1818b5c388518944f9ad9347f1c20373bb74/www/favicon.ico -------------------------------------------------------------------------------- /www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BLE test 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
chunks tot/bad:msgs tot/bad:
0 / 00 / 0
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /www/js/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (() => { 4 | 5 | const bt_btn = document.getElementById('bt-btn'); 6 | const rx_msg = document.getElementById('rx-msg'); 7 | const chunks = document.getElementById('chunks'); 8 | const msgs = document.getElementById('msgs'); 9 | const rx_msg_max = parseInt(rx_msg.getAttribute('rows')); 10 | 11 | const bt_svc_id = 0xFFE0; 12 | const bt_char_id = 0xFFE1; 13 | 14 | let total_chunks = 0; 15 | let bad_chunks = 0; 16 | let total_msgs = 0; 17 | let bad_msgs = 0; 18 | 19 | let bt_char = null; 20 | let rx_msgs = []; 21 | let last_tag = null; 22 | let msg_buff = null; 23 | let msg_start = '#'; 24 | let msg_center = '_'; 25 | 26 | function initPage() 27 | { 28 | if (!navigator.bluetooth) { 29 | document.body.innerHTML = '
The Bluetooth is not supported in this browser. Please try another one.
'; 30 | return; 31 | } 32 | bt_btn.onclick = onConnect; 33 | } 34 | 35 | function showMessage(msg) 36 | { 37 | if (rx_msgs.length >= rx_msg_max) 38 | rx_msgs.shift(); 39 | rx_msgs.push(msg); 40 | console.log('rx:', msg); 41 | rx_msg.textContent = rx_msgs.join('\n'); 42 | } 43 | 44 | function onDisconnection(event) 45 | { 46 | const device = event.target; 47 | console.log(device.name + ' bluetooth device disconnected'); 48 | rx_msg.disabled = true; 49 | bt_char = null; 50 | connectTo(device); 51 | } 52 | 53 | function on_new_msg(msg) 54 | { 55 | total_msgs += 1; 56 | if (msg.length % 2) { 57 | console.log('invalid message length (' + msg.length + '): ' + msg) 58 | bad_msgs += 1; 59 | return; 60 | } 61 | if (msg.slice(msg.length/2, msg.length/2+1) != msg_center) { 62 | console.log('invalid message : ' + msg) 63 | bad_msgs += 1; 64 | return; 65 | } 66 | if (msg.slice(1, msg.length/2) != msg.slice(msg.length/2 + 1)) { 67 | console.log('corrupt message : ' + msg) 68 | bad_msgs += 1; 69 | return; 70 | } 71 | } 72 | 73 | function on_new_chunk(msg) 74 | { 75 | const tag = msg.charCodeAt(0) - 'a'.charCodeAt(0); 76 | let bad_chunk = false; 77 | if (last_tag !== null) { 78 | let next_tag = last_tag + 1; 79 | if (next_tag > 15) 80 | next_tag = 0; 81 | if (tag != next_tag) 82 | bad_chunk = true; 83 | } 84 | last_tag = tag; 85 | 86 | if (bad_chunk) { 87 | bad_chunks += 1; 88 | bad_msgs += 1; 89 | msg_buff = null; 90 | } 91 | 92 | let start = 1, off = 1; 93 | for (;;) { 94 | const i = msg.indexOf(msg_start, off); 95 | if (i >= 0) { 96 | if (msg_buff !== null) 97 | on_new_msg(msg_buff + msg.slice(start, i)); 98 | msg_buff = ''; 99 | start = i; 100 | off = i + 1; 101 | } else { 102 | msg_buff += msg.slice(start); 103 | break; 104 | } 105 | } 106 | 107 | showMessage(msg); 108 | total_chunks += 1; 109 | 110 | chunks.innerHTML = total_chunks + ' / ' + bad_chunks; 111 | msgs.innerHTML = total_msgs + ' / ' + bad_msgs; 112 | } 113 | 114 | function onValueChanged(event) 115 | { 116 | const value = event.target.value; 117 | let msg = ''; 118 | for (let i = 0; i < value.byteLength; i++) { 119 | const c = value.getUint8(i); 120 | msg += String.fromCharCode(c); 121 | } 122 | on_new_chunk(msg); 123 | } 124 | 125 | function onBTConnected(device, characteristic) 126 | { 127 | console.log(device.name, 'connected'); 128 | characteristic.addEventListener('characteristicvaluechanged', onValueChanged); 129 | device.addEventListener('gattserverdisconnected', onDisconnection); 130 | rx_msg.disabled = false; 131 | bt_char = characteristic; 132 | } 133 | 134 | function connectTo(device) 135 | { 136 | device.gatt.connect(). 137 | then((server) => { 138 | console.log(device.name, 'GATT server connected, getting service...'); 139 | return server.getPrimaryService(bt_svc_id); 140 | }). 141 | then((service) => { 142 | console.log(device.name, 'service found, getting characteristic...'); 143 | return service.getCharacteristic(bt_char_id); 144 | }). 145 | then((characteristic) => { 146 | console.log(device.name, 'characteristic found'); 147 | return characteristic.startNotifications().then( 148 | () => { 149 | onBTConnected(device, characteristic); 150 | }, 151 | (err) => { 152 | console.log('Failed to subscribe to ' + device.name + ':', err.message); 153 | return Promise.reject(err); 154 | } 155 | ); 156 | }) 157 | .catch((err) => { 158 | console.log('Failed to connect to ' + device.name + ':', err.message); 159 | setTimeout(() => { connectTo(device); }, 500); 160 | }); 161 | } 162 | 163 | function doConnect(devname) 164 | { 165 | console.log('doConnect', devname); 166 | bt_btn.disabled = true; 167 | let filters = [{services: [bt_svc_id]}]; 168 | if (devname) { 169 | filters.push({name: devname}); 170 | } 171 | return navigator.bluetooth.requestDevice({ 172 | filters: filters, 173 | }). 174 | then((device) => { 175 | console.log(device.name, 'selected'); 176 | connectTo(device); 177 | }) 178 | .catch((err) => { 179 | console.log('Failed to discover BT devices'); 180 | bt_btn.disabled = false; 181 | }); 182 | } 183 | 184 | function onConnect(event) 185 | { 186 | console.log('onConnect'); 187 | doConnect(); 188 | } 189 | 190 | initPage(); 191 | 192 | })(); 193 | 194 | --------------------------------------------------------------------------------