From 03d11913a24b2ff88488858e646fb210ec48bf8f Mon Sep 17 00:00:00 2001 From: wangcheng Date: Wed, 16 Oct 2019 10:25:00 +0800 Subject: [PATCH] ble_mesh: add ble mesh coex test example --- .../ble_mesh_coex_test/CMakeLists.txt | 8 + .../esp_ble_mesh/ble_mesh_coex_test/Makefile | 8 + .../esp_ble_mesh/ble_mesh_coex_test/README.md | 107 ++++ .../components/case/CMakeLists.txt | 12 + .../components/case/ble_unit.c | 253 ++++++++ .../components/case/ble_unit.h | 57 ++ .../components/case/component.mk | 7 + .../components/case/run_tc.c | 291 ++++++++++ .../components/case/run_tc.h | 56 ++ .../ble_mesh_coex_test/components/case/sync.c | 542 ++++++++++++++++++ .../ble_mesh_coex_test/components/case/sync.h | 122 ++++ .../components/case/test_env.c | 128 +++++ .../components/case/test_env.h | 43 ++ .../components/case/wifi_connect.c | 158 +++++ .../components/case/wifi_connect.h | 22 + .../components/case/wifi_unit.c | 187 ++++++ .../components/case/wifi_unit.h | 38 ++ .../ble_mesh_coex_test/main/CMakeLists.txt | 6 + .../ble_mesh_coex_test/main/Kconfig.projbuild | 70 +++ .../ble_mesh_coex_test/main/coex_cmd.c | 168 ++++++ .../ble_mesh_coex_test/main/coex_cmd.h | 16 + .../ble_mesh_coex_test/main/component.mk | 5 + .../ble_mesh_coex_test/main/main.c | 145 +++++ .../ble_mesh_coex_test/partitions.csv | 5 + .../ble_mesh_coex_test/sdkconfig.defaults | 110 ++++ 25 files changed, 2564 insertions(+) create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/CMakeLists.txt create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/Makefile create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/README.md create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/CMakeLists.txt create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/ble_unit.c create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/ble_unit.h create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/component.mk create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/run_tc.c create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/run_tc.h create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/sync.c create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/sync.h create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/test_env.c create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/test_env.h create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_connect.c create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_connect.h create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_unit.c create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_unit.h create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/CMakeLists.txt create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/Kconfig.projbuild create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/coex_cmd.c create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/coex_cmd.h create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/component.mk create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/main.c create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/partitions.csv create mode 100644 examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/sdkconfig.defaults diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/CMakeLists.txt b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/CMakeLists.txt new file mode 100644 index 000000000..92c0e4115 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(SUPPORTED_TARGETS esp32) +project(ble_mesh_coex_test) diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/Makefile b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/Makefile new file mode 100644 index 000000000..9e4e00a3c --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/Makefile @@ -0,0 +1,8 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := ble_mesh_coex_test + +include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/README.md b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/README.md new file mode 100644 index 000000000..7950f4c14 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/README.md @@ -0,0 +1,107 @@ +# Example of BLE Mesh and TCP Server/Client Coexistence + +This example introduces how to test the basic functions of `BLE Mesh data interface` and `TCP Server/Client Coexistence`. `BLE Mesh data interface` is GAP scanning and advertising. + +There are two working modes here: + + * In automatic mode, the program coordinates three development boards working through a synchronization mechanism. + + * In manual mode, you will work with three development boards via commands + + +## Test Preparation + +* Before running the test, you need to prepare a router and three ESP32 development boards. This Example of BLE Mesh and TCP Server/Client Coexistence has the following three items, and any of the three development boards is for running one specific item. + + * ble_dev : Run only the BLE program. + * coex_dev: Run BLE and Wi-Fi program. + * wifi_dev: Run only the Wi-Fi program. + +``Note: If you want better performance in BLE and WiFi coexistence, you should use a development board with PSRAM that could run a coexistence program. Such as ESP32_LyraT, ESP32-WROVER-B and etc.`` + +* The following structure shows the parameters you need to configure. And usually, there are two methods for configuration, i.e. configuring during initialization or configuring with the command `env`. + +```c +coex_test_env_t test_env = { +#if defined(CONFIG_EXAMPLE_MANAUL) + .ap_ssid = CONFIG_EXAMPLE_WIFI_SSID, + .ap_password = CONFIG_EXAMPLE_WIFI_PASSWORD, +#endif +#if defined(CONFIG_EXAMPLE_COEX_ROLE) + .ap_ssid = CONFIG_EXAMPLE_WIFI_SSID, + .ap_password = CONFIG_EXAMPLE_WIFI_PASSWORD, +#endif + .test_port = "8080", + .server_ip = "192.168.3.32", + .duration = "120000", + .is_start = false, +}; +``` + + +## Run Test Case Manually +Configure to Manual Mode via `Example Configuration --->run mode (manual) ` + +The meaning of the numeric argument of the command `run_tc` is as follows: + +| id | case name | description | +|:-:|:-|:-| +| 0 | wifi_tcp_tx_throughput| Test the case of Wi-Fi tcp tx, which will create a tcp client that will continuously send data to the tcp server. | +| 1 |wifi_tcp_rx_throughput| Test the case of Wi-Fi tcp rx, which will create a tcp server that will continuously receive data from the tcp client. | +| 2 | ble_adv | Test the case of BLE advertising. | +| 3 | ble_scan| Test the case of BLE Scan.| + + +### Case 1: tcp tx + scan +1. wifi_dev: run_tc -w 1 +2. coex_dev: env -s -k server_ip -v 192.168.3.34 run_tc -w 0 -b 3 +3. ble_dev : run_tc -b 2 + + +### Case 2: tcp rx + scan +1. coex_dev: run_tc -w 1 -b 3 +2. wifi_dev: env -s -k server_ip -v 192.168.3.34 run_tc -w 0 +3. ble_dev : run_tc -b 2 + +### Case 3: tcp tx + adv +1. wifi_dev: run_tc -w 1 +2. coex_dev: env -s -k server_ip -v 192.168.3.13 run_tc -w 0 -b 2 +3. ble_dev : run_tc -b 3 + + +### Case 4: tcp rx + adv +1. coex_dev: run_tc -w 1 -b 2 +2. wifi_dev: env -s -k server_ip -v 192.168.3.34 run_tc -w 0 +3. ble_dev : run_tc -b 3 + +## Run Test Case By Automation +Configure to Automatic Mode via `Example Configuration --->run mode (auto) ` + +### Coexistence device configuration +1. Select a development board as coexistence role by `Example Configuration --->select role (run device as coex role) ` +2. Select a test case by `Example Configuration --->select case `. +* There are four types of cases: + * TCP TX and BLE ADV: The TCP client will be created on the coexistence device, and bluetooth will start advertising when the Wi-Fi is running tx throughput program. + * TCP RX and BLE ADV: The TCP server will be created on the coexistence device, and bluetooth will start advertising when the Wi-Fi is running rx throughput program. + * TCP TX and BLE SCAN: The TCP client will be created on the coexistence device, and bluetooth will start scanning when the Wi-Fi is running tx throughput program. + * TCP RX and BLE SCAN: The TCP server will be created on the coexistence device, and bluetooth will start scanning when the Wi-Fi is running rx throughput program. + +### Bluetooth device configuration +1. Select a development board as bluetooth role by `select role (run device as bluetooth role) ` + +### Wi-Fi device configuration +1. Select a development board as bluetooth role by `select role (run device as wifi role) ` + + +## Coexistence Configuration +In theory, the performance of BLE and Wi-Fi coexistence will drop to half of the performance in BLE Only mode or Wi-Fi Only mode. + +* ESP32 working frequency: + * Component config ---> ESP32-specific ---> CPU frequency (240 MHz) + +* ESP32 external PSRAM + * Component config ---> ESP32-specific ---> Support for external, SPI-connected RAM + * Devices that do not support PSRAM cannot open this option! + +* ESP32 coexistence mode + * Component config ---> Wi-Fi ---> WiFi/Bluetooth coexistence performance preference (Balance) diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/CMakeLists.txt b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/CMakeLists.txt new file mode 100644 index 000000000..97d2da4f8 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/CMakeLists.txt @@ -0,0 +1,12 @@ +set(COMPONENT_SRCS "ble_unit.c" + "run_tc.c" + "sync.c" + "test_env.c" + "wifi_connect.c" + "wifi_unit.c") + +set(COMPONENT_ADD_INCLUDEDIRS .) + +set(COMPONENT_REQUIRES console nvs_flash bt) +set(SUPPORTED_TARGETS esp32) +register_component() diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/ble_unit.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/ble_unit.c new file mode 100644 index 000000000..757fb178b --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/ble_unit.c @@ -0,0 +1,253 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "ble_unit.h" +#include "sync.h" +#define TAG "BLE_UINT" + +#define GAP_TRANS_DEFAULT_SHORT_TO 50 // 50ms for events expected to reported as soon as API called + +static uint8_t default_adv_data[] = { + 0x02, 0x01, 0x06, + 0x02, 0x0a, 0xeb, 0x03, 0x03, 0xab, 0xcd +}; +static uint8_t default_scan_rsp_data[] = { + 0x0f, 0x09, 0x45, 0x53, 0x50, 0x5f, 0x47, 0x41, 0x54, 0x54, 0x53, 0x5f, 0x43, + 0x4f, 0x45, 0x58 +}; + +esp_ble_scan_params_t default_scan_param = { + .scan_type = BLE_SCAN_TYPE_ACTIVE, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, + .scan_interval = 0x100, + .scan_window = 0x100 +}; + +esp_ble_adv_params_t default_adv_param = { + .adv_int_min = 0x40, + .adv_int_max = 0x40, + .adv_type = ADV_TYPE_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, +}; + +ble_util_scan_count_t scan_count; + +static void ble_gap_event_default_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + switch (event) { + case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: { + if (param->scan_param_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(TAG, "set scan parameter failed, error status = %x", param->scan_param_cmpl.status); + } + break; + } + case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: { + if (param->adv_data_raw_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(TAG, "set row data failed, error status = %x", param->adv_data_raw_cmpl.status); + } + break; + } + case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT: { + if (param->scan_rsp_data_raw_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(TAG, "set scan response data failed, error status = %x", param->scan_rsp_data_raw_cmpl.status); + } + break; + } + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: { + if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(TAG, "Advertising start failed\n"); + } + break; + } + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: + if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(TAG, "Advertising stop failed\n"); + } + break; + case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: { + if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(TAG, "scan start failed, error status = %x", param->scan_start_cmpl.status); + } + break; + } + case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: + if (param->scan_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(TAG, "scan stop failed, error status = %x", param->scan_stop_cmpl.status); + } + break; + default: + break; + } +} + +static void ble_gap_util_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + if (sync_obj.cmd_recv != NULL) { + sync_obj.cmd_recv(param->scan_rst.ble_adv, param->scan_rst.adv_data_len); + } + + switch (event) { + case ESP_GAP_BLE_SCAN_RESULT_EVT: + switch (param->scan_rst.search_evt) { + case ESP_GAP_SEARCH_INQ_RES_EVT: + if (param->scan_rst.adv_data_len > 0 \ + && (memcmp(default_adv_data, param->scan_rst.ble_adv, sizeof(default_adv_data)) == 0)) { + scan_count.adv_count += 1; + if (scan_count.adv_count % 10 == 0) { + ESP_LOGI(TAG, "adv count:%d scan_res count %d\n", scan_count.adv_count, scan_count.scan_res_count); + } + } + + if (param->scan_rst.scan_rsp_len > 0 \ + && (memcmp(default_scan_rsp_data, (param->scan_rst.ble_adv + param->scan_rst.adv_data_len), sizeof(default_scan_rsp_data)) == 0)) { + scan_count.scan_res_count += 1; + } + break; + default: + break; + } + break; + default: + ble_gap_event_default_handler(event, param); + break; + } +} + + +esp_err_t ble_gap_util_set_adv_data(uint8_t *adv_data, uint32_t adv_data_len, uint8_t *scan_rsp_data, uint32_t scan_rsp_data_len) +{ + esp_err_t ret; + + ret = esp_ble_gap_config_adv_data_raw(adv_data, adv_data_len); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_config_adv_data_raw error, %d", ret); + return ret; + } + ret = esp_ble_gap_config_scan_rsp_data_raw(scan_rsp_data, scan_rsp_data_len); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_config_scan_rsp_data_raw error, %d", ret); + return ret; + } + return 0; +} + +esp_err_t ble_gap_util_set_default_adv_data(void) +{ + return ble_gap_util_set_adv_data(default_adv_data, sizeof(default_adv_data), default_scan_rsp_data, sizeof(default_scan_rsp_data)); +} + +esp_err_t ble_gap_util_start_adv(esp_ble_adv_params_t *adv_param) +{ + esp_err_t ret; + ret = esp_ble_gap_start_advertising(adv_param); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_start_advertising error, %d", ret); + return ret; + } + return 0; +} + +esp_err_t ble_gap_util_start_adv_default(void) +{ + esp_err_t ret; + + ret = esp_ble_gap_start_advertising(&default_adv_param); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_start_advertising error, %d", ret); + return ret; + } + return 0; +} + +esp_err_t ble_gap_util_stop_adv(void) +{ + esp_err_t ret; + ret = esp_ble_gap_stop_advertising(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_stop_advertising error, %d", ret); + return ret; + } + return 0; +} + +esp_err_t ble_gap_util_set_scan_param(esp_ble_scan_params_t *scan_param) +{ + esp_err_t ret; + ret = esp_ble_gap_set_scan_params(scan_param); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_set_scan_params error, %d", ret); + return ret; + } + return 0; +} + +esp_err_t ble_gap_util_set_default_scan_param(void) +{ + return ble_gap_util_set_scan_param(&default_scan_param); +} + +esp_err_t ble_gap_util_start_scan(uint32_t duration) +{ + esp_err_t ret; + ret = esp_ble_gap_start_scanning(duration); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_start_scanning error, %d", ret); + return ret; + } + return 0; +} + +esp_err_t ble_gap_util_stop_scan(void) +{ + esp_err_t ret; + ret = esp_ble_gap_stop_scanning(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_stop_scanning error, %d", ret); + return ret; + } + return 0; +} + + +void ble_gap_util_stop(void) +{ + ble_gap_util_stop_adv(); + ble_gap_util_stop_scan(); +} + +esp_err_t init_ble_gap_test_util(void) +{ + esp_err_t ret; + ret = esp_ble_gap_register_callback(ble_gap_util_handler); + if (ret) { + ESP_LOGE(TAG, "gap register error, error code = %x", ret); + } + return ret; +} + +void bt_test_init(void) +{ + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); + ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); + ESP_ERROR_CHECK(esp_bluedroid_init()); + ESP_ERROR_CHECK(esp_bluedroid_enable()); +} + +void bt_test_deinit(void) +{ + esp_bluedroid_disable(); + esp_bluedroid_deinit(); + esp_bt_controller_disable(); + esp_bt_controller_deinit(); +} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/ble_unit.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/ble_unit.h new file mode 100644 index 000000000..93272a91f --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/ble_unit.h @@ -0,0 +1,57 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef _BLE_UNIT_H_ +#define _BLE_UNIT_H_ +#include +#include +#include "esp_system.h" +#include "esp_timer.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_bt.h" + +#include "esp_gap_ble_api.h" +#include "esp_gatts_api.h" +#include "esp_gattc_api.h" +#include "esp_bt_defs.h" +#include "esp_bt_main.h" +#include "esp_gatt_common_api.h" + +#define BLE_TC_SCAN_REPORT_PERIOD 10000 + +typedef struct { + uint32_t adv_count; + uint32_t scan_res_count; +} ble_util_scan_count_t; + + +extern esp_bd_addr_t bt_addr; +extern ble_util_scan_count_t scan_count; +extern esp_ble_adv_params_t default_adv_param; +extern esp_ble_scan_params_t default_scan_param; + +void bt_test_init(void); +void bt_test_deinit(void); +void ble_gap_util_stop(void); + +esp_err_t ble_gap_util_set_adv_data(uint8_t *adv_data, uint32_t adv_data_len, uint8_t *scan_rsp_data, uint32_t scan_rsp_data_len); +esp_err_t ble_gap_util_set_default_adv_data(void); +esp_err_t ble_gap_util_start_adv(esp_ble_adv_params_t *adv_param); +esp_err_t ble_gap_util_start_adv_default(void); +esp_err_t ble_gap_util_stop_adv(void); + +esp_err_t ble_gap_util_set_scan_param(esp_ble_scan_params_t *scan_param); +esp_err_t ble_gap_util_set_default_scan_param(void); +esp_err_t ble_gap_util_start_scan(uint32_t duration); +esp_err_t ble_gap_util_stop_scan(void); + +esp_err_t init_ble_gap_test_util(void); + +#endif /* _BLE_UNIT_H_ */ \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/component.mk b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/component.mk new file mode 100644 index 000000000..f2fef2fee --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/component.mk @@ -0,0 +1,7 @@ +# +# Component Makefile +# + +COMPONENT_SRCDIRS := . + +COMPONENT_ADD_INCLUDEDIRS = . diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/run_tc.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/run_tc.c new file mode 100644 index 000000000..9f243dce7 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/run_tc.c @@ -0,0 +1,291 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "run_tc.h" +#include "test_env.h" +#include "wifi_unit.h" +#include "ble_unit.h" +#include "sync.h" +#include "wifi_connect.h" + +#define TAG "CASE" + +xQueueHandle xTaskQueue = 0; + +static const char *coex_get_case_env(coex_test_env_t *test_env, const char *keyword) +{ + const char *ret = NULL; + if (!strcmp(keyword, "ap_ssid")) { + ret = test_env->ap_ssid; + } else if (!strcmp(keyword, "ap_password")) { + ret = test_env->ap_password; + } else if (!strcmp(keyword, "test_port")) { + ret = test_env->test_port; + } else if (!strcmp(keyword, "server_ip")) { + ret = test_env->server_ip; + } else if (!strcmp(keyword, "duration")) { + ret = test_env->duration; + } + + return ret; +} + +static void wifi_tc_sta_throughput_timeout(void *arg) +{ + static uint32_t statistic_count = 0; + static uint64_t accumulate_speed = 0; + + uint32_t now = utils_get_system_ts(); + uint32_t *report = (uint32_t *) arg; + uint32_t last_timestamp = report[0]; + + if (now > last_timestamp) { + uint32_t speed = report[1] * 8 / (now - last_timestamp); + accumulate_speed += speed; + statistic_count += 1; + printf("speed: %d kbps average speed: %lld kbps\n", speed, accumulate_speed / statistic_count ); + report[1] = 0; + report[0] = now; + } +} + +static esp_err_t create_statistic_timer(esp_timer_handle_t *timer_hdl , uint32_t statistic_date[]) +{ + esp_err_t ret; + esp_timer_create_args_t tca = { + .callback = (esp_timer_cb_t)wifi_tc_sta_throughput_timeout, + .dispatch_method = ESP_TIMER_TASK, + .name = "TCP_STATISTIC", + }; + tca.arg = statistic_date; + ret = esp_timer_create(&tca, timer_hdl); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "statistic_timer create failed"); + return ret; + } + esp_timer_start_periodic(*timer_hdl, 1000000); //1000ms + return ret; +} + + +void wifi_tcp_tx_throught_start(void *param) +{ + esp_timer_handle_t timer_hdl = NULL; + esp_err_t ret; + int sock = -1; + uint32_t statistic_date[2] = {0}; + + const char *ssid = coex_get_case_env(param, "ap_ssid"); + const char *passwd = coex_get_case_env(param, "ap_password"); + + + wifi_util_init(); + // wifi_unit_connect_ap(ssid, passwd); + example_connect(ssid, passwd); + +#if defined(CONFIG_EXAMPLE_AUTO) + if (((coex_test_env_t *)param)->run_mutex != NULL) { + //This will be blocked by the sync timer. + xSemaphoreTake(((coex_test_env_t *)param)->run_mutex, portMAX_DELAY); + xSemaphoreGive(((coex_test_env_t *)param)->run_mutex); + } +#endif + const char *ip = coex_get_case_env(param, "server_ip"); + const char *port = coex_get_case_env(param, "test_port"); + const char *duration = coex_get_case_env(param, "duration"); + wifi_unit_client_establish(&sock, ip, port); + + ret = create_statistic_timer(&timer_hdl, statistic_date); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "statistic_timer create failed"); + goto _stop; + } + + ret = wifi_util_tcp_send(sock, 1460, 0, &statistic_date[1], atoi(duration)); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "send failed, %x", ret); + } + +_stop: + if (timer_hdl) { + esp_timer_stop(timer_hdl); + esp_timer_delete(timer_hdl); + } + + if (sock > 0) { + close(sock); + } +} + +void wifi_tcp_tx_throught_end(void) +{ + esp_wifi_disconnect(); +} + +void wifi_tcp_rx_throught_start(void *param) +{ + esp_timer_handle_t timer_hdl = NULL; + esp_err_t ret; + int sock = -1; + uint32_t statistic_date[2] = {0}; + + const char *ssid = coex_get_case_env(param, "ap_ssid"); + const char *passwd = coex_get_case_env(param, "ap_password"); + const char *port = coex_get_case_env(param, "test_port"); + const char *duration = coex_get_case_env(param, "duration"); + + wifi_util_init(); + // wifi_unit_connect_ap(ssid, passwd); + example_connect(ssid, passwd); + wifi_unit_server_establish( &sock, port); + + ret = create_statistic_timer(&timer_hdl, statistic_date); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "statistic_timer create failed"); + goto _stop; + } + ret = wifi_unit_tcp_recv(sock, duration, statistic_date); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "tcp receive failed"); + goto _stop; + } +_stop: + if (timer_hdl) { + esp_timer_stop(timer_hdl); + esp_timer_delete(timer_hdl); + } + + if (sock > 0) { + close(sock); + } +} + +void wifi_tcp_rx_throught_end(void) +{ + esp_wifi_disconnect(); +} + +void ble_adv_start(void *param) +{ + esp_err_t ret; + const char *duration = coex_get_case_env(param, "duration"); +#if defined(CONFIG_EXAMPLE_MANAUL) + bt_test_init(); +#endif + ret = ble_gap_util_set_default_adv_data(); + + if (ret != ESP_OK) { + ESP_LOGE(TAG, "failed to set adv data"); + return; + } + + ret = ble_gap_util_start_adv(&default_adv_param); + + if (ret != ESP_OK) { + ESP_LOGE(TAG, "failed to start adv"); + return; + } + + vTaskDelay(atoi(duration) / portTICK_PERIOD_MS); + +} + +void ble_adv_end(void) +{ + ble_gap_util_stop(); +} + + +void ble_scan_start(void *param) +{ + esp_err_t ret; +#if defined(CONFIG_EXAMPLE_MANAUL) + bt_test_init(); + vTaskDelay(10 / portTICK_PERIOD_MS); + init_ble_gap_test_util(); +#endif + + + ret = ble_gap_util_set_scan_param(&default_scan_param); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "set scan param fail"); + return; + } + vTaskDelay(10 / portTICK_PERIOD_MS); + + scan_count.adv_count = 0; + scan_count.scan_res_count = 0; + + ret = esp_ble_gap_start_scanning(BLE_TC_SCAN_REPORT_PERIOD); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_start_scanning error, %d", ret); + return; + } +} + +void ble_scan_end(void) +{ + ESP_LOGI(TAG, "%s \n", __func__); +} + +tc_t tc_case[] = { + DECLARE_TC(TC_WIFI_COEX_TCP_TX_THROUGHPUT, 0, wifi_tcp_tx_throught_start, wifi_tcp_tx_throught_end, (void *)&test_env), + DECLARE_TC(TC_WIFI_COEX_TCP_RX_THROUGHPUT, 1, wifi_tcp_rx_throught_start, wifi_tcp_rx_throught_end, (void *)&test_env), + DECLARE_TC(TC_BLE_COEX_ADV, 2, ble_adv_start, ble_adv_end, (void *)&test_env), + DECLARE_TC(TC_BLE_COEX_SCAN, 3, ble_scan_start, ble_scan_end, (void *)&test_env), +}; + +static void excute_case(void *arg) +{ + tc_t *run_case = (tc_t *) arg; + if (run_case && run_case->func_start != NULL) { + run_case->func_start(run_case->param_list); + } + + if (run_case && run_case->func_stop != NULL ) { + vTaskDelay(100 / portTICK_RATE_MS); + run_case->func_stop(); + } + vTaskDelete(NULL); +} + +static void run_task(void *arg) +{ + tc_t *tc_case_table = (tc_t *) arg; + run_task_msg_t msg; + + for (;;) { + if (pdTRUE == xQueueReceive(xTaskQueue, &msg, (portTickType)portMAX_DELAY)) { + if ( msg.case_id < sizeof(tc_case) / sizeof(tc_case[0]) ) { + xTaskCreatePinnedToCore(excute_case, tc_case_table->name, 4096, &tc_case_table[msg.case_id], RUN_TASK_PRIORITY, NULL, 0); + } else { + ESP_LOGW(TAG, "msg.case_id %d\n", msg.case_id); + } + + } + } + vTaskDelete(NULL); +} + + +void run_tc_init(void) +{ + xTaskQueue = xQueueCreate(RUN_TASK_QUEUE_LEN, sizeof(run_task_msg_t)); + if (!xTaskQueue) { + ESP_LOGE(TAG, "xTaskQueue create failed"); + return; + } + xTaskCreatePinnedToCore(run_task, "run_task", 4096, tc_case, RUN_TASK_PRIORITY, NULL, 0); +} + + + + + + diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/run_tc.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/run_tc.h new file mode 100644 index 000000000..1e82df683 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/run_tc.h @@ -0,0 +1,56 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __RUN_TC_H__ +#define __RUN_TC_H__ + +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" + +#define TC_NAME_LEN 63 +typedef void (*tc_func_start_t)(void *param); +typedef void (*tc_func_end_t)(void); + + +typedef struct tc { + char name[TC_NAME_LEN + 1]; + uint8_t case_id; + tc_func_start_t func_start; + tc_func_end_t func_stop; + void *param_list; +} tc_t; + + +#define TC_WIFI_COEX_TCP_TX_THROUGHPUT "TCP_COEX_TX_THROUGHPUT" +#define TC_WIFI_COEX_TCP_RX_THROUGHPUT "TCP_COEX_RX_THROUGHPUT" +#define TC_BLE_COEX_ADV "BLE_COEX_ADVERTISING" +#define TC_BLE_COEX_SCAN "BLE_COEX_SCAN" + +// run_task queue size +#define RUN_TASK_QUEUE_LEN 6 +#define RUN_TASK_PRIORITY 18 + +#define DECLARE_TC(name, id, start_func, stop_func, param_list) \ + {name, id, start_func, stop_func, param_list} + +typedef struct run_task_msg { + uint8_t case_id; +} run_task_msg_t; + +extern xQueueHandle xTaskQueue ; + +void run_tc_init(void); + +#endif /* __RUN_TC_H__ */ \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/sync.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/sync.c new file mode 100644 index 000000000..8dabe92cc --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/sync.c @@ -0,0 +1,542 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "sync.h" +#include "run_tc.h" +#include "wifi_unit.h" +#define TAG "SYNC" + +SemaphoreHandle_t client_mutex; + +struct sync_t sync_obj = { + .except_recv_wifi_id = false, + .except_recv_bt_id = false, + .recv_param_bit = 0x0, + .start_time = 0x0, + +#if defined(CONFIG_EXAMPLE_COEX_ROLE) + .state = ASSIGN_CASE, +#else + .state = WAIT_CASE, +#endif +#if defined(CONFIG_EXAMPLE_COEX_TX_ADV) + .own_wifi_case = WIFI_TCP_TX_CASE, + .own_ble_case = BLE_ADV_CASE, +#elif defined(CONFIG_EXAMPLE_COEX_RX_ADV) + .own_wifi_case = WIFI_TCP_RX_CASE, + .own_ble_case = BLE_ADV_CASE, +#elif defined(CONFIG_EXAMPLE_COEX_TX_SCAN) + .own_wifi_case = WIFI_TCP_TX_CASE, + .own_ble_case = BLE_SCAN_CASE, +#elif defined(CONFIG_EXAMPLE_COEX_RX_SCAN) + .own_wifi_case = WIFI_TCP_RX_CASE, + .own_ble_case = BLE_SCAN_CASE, +#else + .own_wifi_case = NOT_CASE, + .own_ble_case = NOT_CASE, +#endif +}; + + +auto_tc auto_tb[6] = { + {WIFI_TCP_TX_CASE, PARAMTER(0b011011)}, //need paramter: wifi_case_id ssid password server ip + {WIFI_TCP_RX_CASE, PARAMTER(0b010011)}, //need paramter: wifi_case_id ssid password + {BLE_ADV_CASE, PARAMTER(0b100000)}, //need paramter: ble_case_id + {BLE_SCAN_CASE, PARAMTER(0b100000)}, //need paramter: ble_case_id +}; + + +esp_err_t send_adv(uint8_t *raw_data, uint32_t raw_data_len) +{ + esp_err_t ret; + + esp_ble_adv_params_t adv_param = { + .adv_int_min = 0x40, + .adv_int_max = 0x40, + .adv_type = ADV_TYPE_NONCONN_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + }; + ret = esp_ble_gap_config_adv_data_raw(raw_data, raw_data_len); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_config_adv_data_raw error, %d", ret); + return ret; + } + + ret = esp_ble_gap_start_advertising(&adv_param); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_start_advertising error, %d", ret); + return ret; + } + vTaskDelay(30 / portTICK_PERIOD_MS); //every 30ms send one packet + + ret = esp_ble_gap_stop_advertising(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_stop_advertising error, %d", ret); + return ret; + } + return 0; +} + +esp_err_t send_adv_data(sync_msg *msg) +{ + send_adv((uint8_t *)msg, sizeof(sync_msg)); + return 0; +} + +void send_start_msg(uint8_t start_time) +{ + sync_msg msg = { + .length = 30, + .type = MSG_TYPE, + .head = MSG_HEAD, + .msg_id = 0x4, + .ctl = MSG_CONTINUE, + .param_bit = 0b000100 << PARAM_MAX, + .reserve = 0xff, + .data = {start_time}, + }; + send_adv_data(&msg); +} +void send_start_countdown(void) +{ + if (sync_obj.except_recv_bt_id == true && sync_obj.except_recv_wifi_id == true) { + esp_timer_stop(sync_obj.sync_timer); + esp_timer_start_once(sync_obj.sync_timer, 1000000); + sync_obj.state = START_CASE; + } +} +void send_tcp_rx_inited_msg(void) +{ + uint8_t hex_ip[4]; + uint32_t ip = wifi_util_get_ip(); + memcpy(hex_ip, &ip, sizeof(hex_ip)); + if (hex_ip[0] == 0x0) { + return; + } + sync_msg msg = { + .length = 30, + .type = MSG_TYPE, + .head = MSG_HEAD, + .msg_id = MSG_ID_WIFI_DEV_INIT_FINISH, + .ctl = MSG_CONTINUE, + .param_bit = 0b001000 << PARAM_MAX, + .reserve = 0xff, + .data = {hex_ip[0], hex_ip[1], hex_ip[2], hex_ip[3]}, + }; + send_adv_data(&msg); +} +void send_case_inited_msg(uint8_t msg_id) +{ + sync_msg msg = { + .length = 30, + .type = MSG_TYPE, + .head = MSG_HEAD, + .msg_id = msg_id, + .ctl = MSG_CONTINUE, + .param_bit = 0b000000 << PARAM_MAX, + .reserve = 0xff, + .data = {0}, + }; + send_adv_data(&msg); +} + +void assign_case_to_dev(uint8_t ble_id, uint8_t wifi_id) +{ + if ( sync_obj.own_wifi_case == WIFI_TCP_RX_CASE ) { + uint8_t hex_ip[4]; + uint32_t ip = wifi_util_get_ip(); + ESP_LOGI(TAG, "ip:%s", inet_ntoa(ip)); + memcpy(hex_ip, &ip, sizeof(hex_ip)); + if (hex_ip[0] == 0x0) { + return; + } + sync_msg msg = { + .length = 30, + .type = MSG_TYPE, + .head = MSG_HEAD, + .msg_id = 0x1, + .ctl = MSG_CONTINUE, + .param_bit = 0b111000 << PARAM_MAX, + .reserve = 0xff, + .data = {ble_id, wifi_id, hex_ip[0], hex_ip[1], hex_ip[2], hex_ip[3]}, + }; + send_adv_data(&msg); + } else if ( sync_obj.own_wifi_case == WIFI_TCP_TX_CASE ) { + sync_msg msg1 = { + .length = 30, + .type = MSG_TYPE, + .head = MSG_HEAD, + .msg_id = 0x1, + .ctl = MSG_CONTINUE, + .param_bit = 0b110000 << PARAM_MAX, + .reserve = 0xff, + .data = {ble_id, wifi_id}, + }; + send_adv_data(&msg1); + } +#if defined(CONFIG_EXAMPLE_COEX_ROLE) + if (strlen(CONFIG_EXAMPLE_WIFI_SSID) < 20) { + sync_msg msg = { + .length = 30, + .type = MSG_TYPE, + .head = MSG_HEAD, + .msg_id = 0x1, + .ctl = MSG_CONTINUE, + .param_bit = 0b000010 << PARAM_MAX, + .reserve = 0xff, + .data[0] = strlen(CONFIG_EXAMPLE_WIFI_SSID), + }; + for (uint8_t i = 0 ; i < strlen(CONFIG_EXAMPLE_WIFI_SSID); i++) { + msg.data[i + 1] = CONFIG_EXAMPLE_WIFI_SSID[i] - '0'; + } + send_adv_data(&msg); + } + + if (strlen(CONFIG_EXAMPLE_WIFI_PASSWORD) < 20) { + sync_msg msg = { + .length = 30, + .type = MSG_TYPE, + .head = MSG_HEAD, + .msg_id = 0x1, + .ctl = MSG_END, + .param_bit = 0b000001 << PARAM_MAX, + .reserve = 0xff, + .data[0] = strlen(CONFIG_EXAMPLE_WIFI_PASSWORD), + }; + for (int i = 0 ; i < strlen(CONFIG_EXAMPLE_WIFI_PASSWORD); i++) { + msg.data[i + 1] = CONFIG_EXAMPLE_WIFI_PASSWORD[i] - '0'; + } + send_adv_data(&msg); + } +#endif +} + + +void excute_case(uint8_t run_case) +{ + run_task_msg_t msg; + msg.case_id = run_case; + if (xQueueSend(xTaskQueue, &msg, portMAX_DELAY) != pdTRUE) { + ESP_LOGE(TAG, "xTaskQueue Post failed\n"); + } +} + + +void assign_test_case(void) +{ +#if defined(CONFIG_EXAMPLE_COEX_TX_ADV) + assign_case_to_dev(BLE_SCAN_CASE, WIFI_TCP_RX_CASE); +#elif defined(CONFIG_EXAMPLE_COEX_RX_ADV) + assign_case_to_dev(BLE_SCAN_CASE, WIFI_TCP_TX_CASE); +#elif defined(CONFIG_EXAMPLE_COEX_TX_SCAN) + assign_case_to_dev(BLE_ADV_CASE, WIFI_TCP_RX_CASE); +#elif defined(CONFIG_EXAMPLE_COEX_RX_SCAN) + assign_case_to_dev(BLE_ADV_CASE, WIFI_TCP_TX_CASE); +#endif +} + + +void analys_param(uint16_t param_bit, uint8_t data[], uint16_t *recv_param_bit) +{ + + uint8_t data_ptr = 0; + + for (int i = 0 ; i < PARAM_MAX; i++ ) { + switch (GET_PARAM(param_bit, 0x1000 >> i)) { + case BLE_CASE_ID: + ESP_LOGD(TAG, "BLE_CASE_ID\n"); +#if defined(CONFIG_EXAMPLE_BT_ROLE) + sync_obj.own_ble_case = data[data_ptr]; + (*recv_param_bit) |= BLE_CASE_ID; +#endif + data_ptr += 1; + break; + case WIFI_CASE_ID: + ESP_LOGD(TAG, "WIFI_CASE_ID\n"); +#if defined(CONFIG_EXAMPLE_WIFI_ROLE) + sync_obj.own_wifi_case = data[data_ptr]; + (*recv_param_bit) |= WIFI_CASE_ID; +#endif + data_ptr += 1; + break; + case START_TIME: + ESP_LOGD(TAG, "START_TIME\n"); + sync_obj.start_time = data[data_ptr]; + data_ptr += 1; + break; + case SERVER_IP: { + ESP_LOGD(TAG, "SERVER_IP\n"); + char server_ip[16]; + memset(server_ip, '0', sizeof(server_ip)); + sprintf(server_ip, "%d.%d.%d.%d", data[data_ptr], data[data_ptr + 1], data[data_ptr + 2], data[data_ptr + 3]); // size conversion + coex_set_test_env("server_ip", server_ip, sizeof(server_ip)); + coex_print_test_env(); + data_ptr += 4; + (*recv_param_bit) |= SERVER_IP; + break; + } + case WIFI_SSID: { + ESP_LOGD(TAG, "WIFI_SSID\n"); + uint8_t length = data[data_ptr]; + data_ptr += 1; + if ( length > 20) { + ESP_LOGE(TAG, "ssid length error"); + break; + } + char *ssid = malloc(length + 1); + if (ssid == NULL) { + ESP_LOGE(TAG, "%s malloc fail\n", __func__); + return ; + } + memset(ssid, '0', sizeof(length + 1)); + + for (int i = length - 1 ; i >= 0 ; i--) { + ssid[i] = data[data_ptr + i] + '0'; + } + ssid[length] = '\n'; + coex_set_test_env("ap_ssid", ssid, length); + coex_print_test_env(); + (*recv_param_bit) |= WIFI_SSID; + free(ssid); + break; + } + case WIFI_PASSWIRD: { + ESP_LOGD(TAG, "WIFI_PASSWIRD\n"); + uint8_t length = data[data_ptr]; + data_ptr += 1; + if ( length > 20) { + ESP_LOGE(TAG, "password length error"); + break; + } + char *password = malloc(length + 1); + if (password == NULL) { + ESP_LOGE(TAG, "%s malloc fail\n", __func__); + return ; + } + memset(password, '0', sizeof(length + 1)); + for (int i = length - 1 ; i >= 0 ; i--) { + password[i] = data[data_ptr + i] + '0'; + } + password[length] = '\n'; + coex_set_test_env("ap_password", password, length); + coex_print_test_env(); + (*recv_param_bit) |= WIFI_PASSWIRD; + free(password); + break; + } + default: + break; + } + } + +} + +void sync_cmd_recv(uint8_t *raw_data, uint32_t raw_data_len) +{ + if (raw_data_len < MSG_MIN_LEN) { + ESP_LOGD(TAG, "msg length is low"); + } + sync_msg_head msg_head = {0}; + memcpy(&msg_head, raw_data, sizeof(sync_msg_head)); + + if (msg_head.type != MSG_TYPE || msg_head.head != MSG_HEAD) { + ESP_LOGD(TAG, "msg is unknown"); + return; + } + ESP_LOGD(TAG, "msg_id: %x\n", msg_head.msg_id); + // ESP_LOG_BUFFER_HEX("sync recv:", raw_data, raw_data_len); + switch (sync_obj.state) { +#if defined(CONFIG_EXAMPLE_WIFI_ROLE) || defined(CONFIG_EXAMPLE_BT_ROLE) + case WAIT_CASE: { + ESP_LOGD(TAG, "WAIT_CASE\n"); + if (msg_head.msg_id == MSG_ID_ASSIGN_CASE) { + analys_param(msg_head.param_bit, raw_data + MSG_DATA_BASE, &sync_obj.recv_param_bit ); +#if defined(CONFIG_EXAMPLE_WIFI_ROLE) + if (sync_obj.own_wifi_case != NOT_CASE) { + if ((sync_obj.recv_param_bit & auto_tb[sync_obj.own_wifi_case].excpet_param_bit) == auto_tb[sync_obj.own_wifi_case].excpet_param_bit) { + excute_case(sync_obj.own_wifi_case); + sync_obj.state = WAIT_START; + esp_timer_start_periodic(sync_obj.sync_timer, SYNC_TIMEOUT ); + } + } +#endif +#if defined(CONFIG_EXAMPLE_BT_ROLE) + if (sync_obj.own_ble_case != NOT_CASE) { + if ((sync_obj.recv_param_bit & auto_tb[sync_obj.own_ble_case].excpet_param_bit) == auto_tb[sync_obj.own_ble_case].excpet_param_bit) { + sync_obj.state = WAIT_START; + esp_timer_start_periodic(sync_obj.sync_timer, SYNC_TIMEOUT ); + } + } +#endif + } + break; + } + case WAIT_START: + ESP_LOGD(TAG, "WAIT_START\n"); + ESP_LOGD(TAG, "WAIT_START %x\n", msg_head.msg_id); + if (msg_head.msg_id == MSG_ID_START_CASE) { + analys_param(msg_head.param_bit, raw_data + MSG_DATA_BASE, &sync_obj.recv_param_bit ); + sync_obj.state = START_CASE; + ble_gap_util_stop(); +#if defined(CONFIG_EXAMPLE_WIFI_ROLE) + bt_test_deinit(); +#endif + esp_timer_stop(sync_obj.sync_timer); + esp_timer_start_once(sync_obj.sync_timer, sync_obj.start_time * 1000000); + } + break; +#endif +#if defined(CONFIG_EXAMPLE_COEX_ROLE) + case ASSIGN_CASE: + ESP_LOGD(TAG, "ASSIGN_CASE\n"); + switch (msg_head.msg_id) { + case MSG_ID_WIFI_DEV_INIT_FINISH: + if (msg_head.param_bit != 0x0) { + analys_param(msg_head.param_bit, raw_data + MSG_DATA_BASE, &sync_obj.recv_param_bit ); + } + sync_obj.except_recv_wifi_id = true; + break; + case MSG_ID_BT_DEV_INIT_FINISH: + sync_obj.except_recv_bt_id = true; + break; + default: + break; + } + send_start_countdown(); + break; +#endif + default: + ESP_LOGD(TAG, "state is unknown %s", __func__); + break; + } +} + +static void handle_sync_timeout(void *arg) +{ + static bool run_first = true; + if (run_first == true) { + xSemaphoreTake((SemaphoreHandle_t)arg, (portTickType)portMAX_DELAY); + esp_timer_start_periodic( (SemaphoreHandle_t)arg, 1000000); + run_first = false; + } + switch (sync_obj.state) { +#if defined(CONFIG_EXAMPLE_COEX_ROLE) + case ASSIGN_CASE: + ESP_LOGD(TAG, "ASSIGN_CASE\n"); + assign_test_case(); + esp_timer_start_periodic(sync_obj.sync_timer, SYNC_TIMEOUT); + break; +#endif + +#if defined(CONFIG_EXAMPLE_WIFI_ROLE) || defined(CONFIG_EXAMPLE_BT_ROLE) + case WAIT_START: { + ESP_LOGD(TAG, "WAIT_START\n"); +#if defined(CONFIG_EXAMPLE_WIFI_ROLE) + if ( WIFI_TCP_RX_CASE == sync_obj.own_wifi_case ) { + send_tcp_rx_inited_msg(); + } else { + send_case_inited_msg(MSG_ID_WIFI_DEV_INIT_FINISH); + } +#elif defined(CONFIG_EXAMPLE_BT_ROLE) + send_case_inited_msg(MSG_ID_BT_DEV_INIT_FINISH); +#endif + esp_timer_start_periodic(sync_obj.sync_timer, SYNC_TIMEOUT); + break; + } +#endif + + + case START_CASE: { + ESP_LOGD(TAG, "START_CASE\n"); +#if defined(CONFIG_EXAMPLE_BT_ROLE) + excute_case(sync_obj.own_ble_case); + +#elif defined(CONFIG_EXAMPLE_WIFI_ROLE) + ESP_LOGD(TAG, "START_CASE\n"); + if (arg != NULL) { + xSemaphoreGive((SemaphoreHandle_t)arg); + run_first = true; + esp_timer_stop(sync_obj.sync_timer); + + } +#else + static uint8_t send_start_count = 10; + if (send_start_count == 0) { + excute_case(sync_obj.own_ble_case); + xSemaphoreGive((SemaphoreHandle_t)arg); + run_first = true; + esp_timer_stop(sync_obj.sync_timer); + break; + } + + send_start_msg(send_start_count); + send_start_count -= 1; + esp_timer_start_once(sync_obj.sync_timer, 1000000); +#endif + break; + } + default: + ESP_LOGD(TAG, "state is unknown%s", __func__); + break; + } +} + +esp_err_t create_sync_timer(esp_timer_handle_t *timer_hdl) +{ + esp_err_t ret; + esp_timer_create_args_t tca = { + .callback = (esp_timer_cb_t)handle_sync_timeout, + .dispatch_method = ESP_TIMER_TASK, + .name = "SYNC_TIMER", + }; + tca.arg = client_mutex; + + ret = esp_timer_create(&tca, timer_hdl); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "timer create failed %d %x\n", __LINE__, ret); + return ret; + } + esp_timer_start_once( *timer_hdl, 10); + + return ret; +} + + +void sync_init(void) +{ + esp_err_t ret; + sync_obj.cmd_recv = &sync_cmd_recv; + client_mutex = xSemaphoreCreateMutex(); + if (!client_mutex) { + ESP_LOGE(TAG, "client_mutex Create failed "); + return; + } + coex_set_test_env("mutex", NULL, 0); + + bt_test_init(); + init_ble_gap_test_util(); + ret = esp_ble_gap_start_scanning(BLE_TC_SCAN_REPORT_PERIOD); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_start_scanning error, %d", ret); + return ; + } + ret = create_sync_timer(&sync_obj.sync_timer); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "sync timer create failed"); + return ; + } + +#if defined(CONFIG_EXAMPLE_COEX_ROLE) + excute_case(sync_obj.own_wifi_case); + vTaskDelay(3000 / portTICK_PERIOD_MS); +#endif + +} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/sync.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/sync.h new file mode 100644 index 000000000..ad9df667d --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/sync.h @@ -0,0 +1,122 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __SYNC_H__ +#define __SYNC_H__ + +#include +#include +#include +#include +#include "esp_log.h" +#include "esp_timer.h" +#include "ble_unit.h" +#include "test_env.h" + +#include "esp_bt.h" +#include "esp_bt_main.h" +#include "esp_bt_device.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/task.h" +#include "freertos/queue.h" + +#include "mesh_util.h" +#define PARAM_MAX 7 + +#define SYNC_TIMEOUT 500000 //500ms +#define PARAMTER(value) (((uint32_t)value) << 7) + +#define WIFI_TCP_TX_CASE 0x0 +#define WIFI_TCP_RX_CASE 0x1 +#define BLE_ADV_CASE 0x2 +#define BLE_SCAN_CASE 0x3 +#define NOT_CASE 0xff + +#define MSG_HEAD 0xcbb3 +#define MSG_TYPE 0xff +#define MSG_CONTINUE 0x0 +#define MSG_END 0x1 +#define MSG_DATA_BASE 0x8 +#define MSG_ID_ASSIGN_CASE 0x1 +#define MSG_ID_WIFI_DEV_INIT_FINISH 0x2 +#define MSG_ID_BT_DEV_INIT_FINISH 0x3 +#define MSG_ID_START_CASE 0x4 + +#define BLE_CASE_ID 0b100000 << PARAM_MAX +#define WIFI_CASE_ID 0b010000 << PARAM_MAX +#define SERVER_IP 0b001000 << PARAM_MAX +#define START_TIME 0b000100 << PARAM_MAX +#define WIFI_SSID 0b000010 << PARAM_MAX +#define WIFI_PASSWIRD 0b000001 << PARAM_MAX + + +#define GET_PARAM(value,bit) (((value) & (bit)) ? bit:0x0) + +#define MSG_MIN_LEN 8 + +typedef void (*sync_recv)(uint8_t *raw_data, uint32_t raw_data_len); + +typedef struct { + uint8_t length; + uint8_t type; + uint16_t head; + uint8_t msg_id; + uint16_t ctl: 3, + param_bit: 13; +} __attribute__((packed)) sync_msg_head; + +typedef struct { + uint8_t length; + uint8_t type; + uint16_t head; + uint8_t msg_id; + uint16_t ctl: 3, + param_bit: 13; + uint8_t reserve; //reserved for extend param_bit + uint8_t data[23]; +} __attribute__((packed)) sync_msg; + +typedef struct { + uint8_t case_id; + const uint16_t excpet_param_bit; +} auto_tc; +auto_tc auto_tb[6]; + + +typedef enum { +#if defined(CONFIG_EXAMPLE_COEX_ROLE) + ASSIGN_CASE, +#else + WAIT_CASE, + WAIT_START, +#endif + START_CASE, +} sync_state; + +struct sync_t { + sync_state state; + uint8_t own_wifi_case; + uint8_t own_ble_case; + uint8_t start_time; + + uint16_t recv_param_bit; + + bool except_recv_wifi_id; + bool except_recv_bt_id; + + esp_timer_handle_t sync_timer; + sync_recv cmd_recv; +}; +struct sync_t sync_obj; + +extern SemaphoreHandle_t client_mutex; +void sync_init(void); + +#endif \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/test_env.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/test_env.c new file mode 100644 index 000000000..c843598fd --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/test_env.c @@ -0,0 +1,128 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include + +#include "esp_err.h" +#include "esp_log.h" +#include "test_env.h" +#include "sync.h" + +#define TAG "ENV" + +coex_test_env_t test_env = { +#if defined(CONFIG_EXAMPLE_MANAUL) + .ap_ssid = CONFIG_EXAMPLE_WIFI_SSID, + .ap_password = CONFIG_EXAMPLE_WIFI_PASSWORD, +#endif +#if defined(CONFIG_EXAMPLE_COEX_ROLE) + .ap_ssid = CONFIG_EXAMPLE_WIFI_SSID, + .ap_password = CONFIG_EXAMPLE_WIFI_PASSWORD, +#endif + .test_port = "8080", + .server_ip = "192.168.3.32", + .duration = "120000", + .is_start = false, +}; + +esp_err_t coex_set_test_env(const char *keyword, const char *value, uint8_t length) +{ + esp_err_t ret = ESP_OK; + if (!strcmp(keyword, "ap_ssid")) { + memset(test_env.ap_ssid, '\0', sizeof(test_env.ap_ssid)); + strncpy(test_env.ap_ssid, value, length); + } else if (!strcmp(keyword, "ap_password")) { + memset(test_env.ap_password, '\0', sizeof(test_env.ap_password)); + strncpy(test_env.ap_password, value, length); + } else if (!strcmp( keyword, "test_port")) { + memset(test_env.test_port, '\0', sizeof(test_env.test_port)); + strncpy(test_env.test_port, value, length); + } else if (!strcmp(keyword, "server_ip")) { + memset(test_env.server_ip, '\0', sizeof(test_env.server_ip)); + strncpy(test_env.server_ip, value, length); + } else if (!strcmp(keyword, "duration")) { + strncpy(test_env.duration, value, length); + } else if (!strcmp(keyword, "mutex")) { + test_env.run_mutex = client_mutex; + + } else { + ret = ESP_ERR_NOT_SUPPORTED; + } + return ret; +} + +const char *coex_get_test_env(const char *keyword) +{ + const char *ret = NULL; + if (!strcmp(keyword, "ap_ssid")) { + ret = test_env.ap_ssid; + } else if (!strcmp(keyword, "ap_password")) { + ret = test_env.ap_password; + } else if (!strcmp(keyword, "test_port")) { + ret = test_env.test_port; + } else if (!strcmp(keyword, "server_ip")) { + ret = test_env.server_ip; + } else if (!strcmp(keyword, "duration")) { + ret = test_env.duration; + } + return ret; +} + +void coex_print_test_env(void) +{ + ESP_LOGI(TAG, "current test env:"); + ESP_LOGI(TAG, "\tap_ssid: %s", test_env.ap_ssid); + ESP_LOGI(TAG, "\tap_password: %s", test_env.ap_password); + ESP_LOGI(TAG, "\ttest_port: %s", test_env.test_port); + ESP_LOGI(TAG, "\tserver_ip: %s", test_env.server_ip); + ESP_LOGI(TAG, "\tduration: %s", test_env.duration); +} + +bool coex_env_str_to_mac(uint8_t *str, uint8_t *dest) +{ + uint8_t loop = 0; + uint8_t tmp = 0; + uint8_t *src_p = str; + + if (strlen((char *)src_p) != 17) { // must be like 12:34:56:78:90:AB + ESP_LOGE(TAG, "wrong format"); + return false; + } + + for (loop = 0; loop < 17 ; loop++) { + if (loop % 3 == 2) { + if (src_p[loop] != ':') { + ESP_LOGE(TAG, "wrong format"); + return false; + } + + continue; + } + + if ((src_p[loop] >= '0') && (src_p[loop] <= '9')) { + tmp = tmp * 16 + src_p[loop] - '0'; + } else if ((src_p[loop] >= 'A') && (src_p[loop] <= 'F')) { + tmp = tmp * 16 + src_p[loop] - 'A' + 10; + } else if ((src_p[loop] >= 'a') && (src_p[loop] <= 'f')) { + tmp = tmp * 16 + src_p[loop] - 'a' + 10; + } else { + ESP_LOGE(TAG, "wrong format"); + return false; + } + + if (loop % 3 == 1) { + *dest++ = tmp; + tmp = 0; + } + } + + return true; +} + diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/test_env.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/test_env.h new file mode 100644 index 000000000..aa419b934 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/test_env.h @@ -0,0 +1,43 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __TEST_ENV_H__ +#define __TEST_ENV_H__ + +#include +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +#define MAX_SSID_LEN 32 +#define MAX_PASSWORD_LEN 64 +#define MAX_IP_STR_LEN 15 +#define MAX_PORT_STR_LEN 5 +#define MAX_MAC_ADDR_LEN 17 +#define INVALID_REMOTE_BT_MAC "ff:ff:ff:ff:ff:ff" +#define DURATION_MAX_LEN 10 + +typedef struct { + char ap_ssid[MAX_SSID_LEN + 1]; + char ap_password[MAX_PASSWORD_LEN + 1]; + char test_port[MAX_PORT_STR_LEN + 1]; + char server_ip[MAX_IP_STR_LEN + 1]; + char duration[DURATION_MAX_LEN + 1]; + bool is_start; + SemaphoreHandle_t run_mutex; +} coex_test_env_t; + +extern coex_test_env_t test_env; + +esp_err_t coex_set_test_env(const char *keyword, const char *value, uint8_t length); +const char *coex_get_test_env(const char *keyword); +void coex_print_test_env(void); +bool coex_env_str_to_mac(uint8_t *str, uint8_t *dest); + +#endif /* __TEST_ENV_H__ */ diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_connect.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_connect.c new file mode 100644 index 000000000..720a532f6 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_connect.c @@ -0,0 +1,158 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include + +#include "esp_err.h" +#include "esp_log.h" + +#include "wifi_connect.h" + + +#include +#include "sdkconfig.h" +#include "esp_event.h" +#include "esp_wifi.h" +#include "esp_wifi_default.h" + +#include "esp_log.h" +#include "esp_netif.h" +#include "driver/gpio.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "lwip/err.h" +#include "lwip/sys.h" + +#define GOT_IPV4_BIT BIT(0) + +#define CONNECTED_BITS (GOT_IPV4_BIT) + + +static EventGroupHandle_t s_connect_event_group; +static esp_ip4_addr_t s_ip_addr; +static const char *s_connection_name; +static esp_netif_t *s_example_esp_netif = NULL; + + + +static const char *TAG = "example_connect"; + +/* set up connection, Wi-Fi or Ethernet */ +static void start(const char *ssid, const char *passwd); + +/* tear down connection, release resources */ +static void stop(void); + +static void on_got_ip(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + ESP_LOGI(TAG, "Got IP event!"); + ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; + memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr)); + xEventGroupSetBits(s_connect_event_group, GOT_IPV4_BIT); +} + +esp_err_t example_connect(const char *ssid, const char *passwd) +{ + if (s_connect_event_group != NULL) { + return ESP_ERR_INVALID_STATE; + } + s_connect_event_group = xEventGroupCreate(); + start(ssid, passwd); + ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop)); + ESP_LOGI(TAG, "Waiting for IP"); + xEventGroupWaitBits(s_connect_event_group, CONNECTED_BITS, true, true, portMAX_DELAY); + ESP_LOGI(TAG, "Connected to %s", s_connection_name); + ESP_LOGI(TAG, "IPv4 address: " IPSTR, IP2STR(&s_ip_addr)); + return ESP_OK; +} + +esp_err_t example_disconnect(void) +{ + if (s_connect_event_group == NULL) { + return ESP_ERR_INVALID_STATE; + } + vEventGroupDelete(s_connect_event_group); + s_connect_event_group = NULL; + stop(); + ESP_LOGI(TAG, "Disconnected from %s", s_connection_name); + s_connection_name = NULL; + return ESP_OK; +} + + +static void on_wifi_disconnect(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + ESP_LOGI(TAG, "Wi-Fi disconnected, trying to reconnect..."); + esp_err_t err = esp_wifi_connect(); + if (err == ESP_ERR_WIFI_NOT_STARTED) { + return; + } + ESP_ERROR_CHECK(err); +} + +static void start(const char *ssid, const char *passwd) +{ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_WIFI_STA(); + + esp_netif_t *netif = esp_netif_new(&netif_config); + + assert(netif); + + esp_netif_attach_wifi_station(netif); + esp_wifi_set_default_wifi_sta_handlers(); + + s_example_esp_netif = netif; + + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + + wifi_config_t wifi_config; + memset(&wifi_config, 0, sizeof(wifi_config)); + if (ssid) { + strncpy((char *)wifi_config.sta.ssid, ssid, strlen(ssid)); + } + if (passwd) { + strncpy((char *)wifi_config.sta.password, passwd, strlen(passwd)); + } + + ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + ESP_ERROR_CHECK(esp_wifi_connect()); + s_connection_name = ssid; +} + +static void stop(void) +{ + ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect)); + ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip)); + esp_err_t err = esp_wifi_stop(); + if (err == ESP_ERR_WIFI_NOT_INIT) { + return; + } + ESP_ERROR_CHECK(err); + ESP_ERROR_CHECK(esp_wifi_deinit()); + ESP_ERROR_CHECK(esp_wifi_clear_default_wifi_driver_and_handlers(s_example_esp_netif)); + esp_netif_destroy(s_example_esp_netif); + s_example_esp_netif = NULL; +} + +esp_netif_t *get_example_netif(void) +{ + return s_example_esp_netif; +} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_connect.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_connect.h new file mode 100644 index 000000000..57c2a4d86 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_connect.h @@ -0,0 +1,22 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __WIFI_CONNECT_H__ +#define __WIFI_CONNECT_H__ + +#include "esp_err.h" +#include "esp_netif.h" +#include "esp_event.h" + +esp_err_t example_connect(const char *ssid, const char *passwd); +esp_err_t example_disconnect(void); +esp_err_t example_configure_stdin_stdout(void); +esp_netif_t *get_example_netif(void); + +#endif /* __WIFI_CONNECT_H__ */ diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_unit.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_unit.c new file mode 100644 index 000000000..41f998600 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_unit.c @@ -0,0 +1,187 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include + +#include "wifi_unit.h" +#include "wifi_connect.h" +#define TAG "WIFI_UINT" + +uint32_t utils_get_system_ts(void) +{ + return esp_log_timestamp(); +} + +esp_err_t wifi_unit_client_establish(int *sock, const char *ip, const char *port) +{ + esp_err_t ret = 0; + uint32_t start_ts; + uint32_t timeout = 10000; + struct sockaddr_in sock_addr; + int s; + + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = ipaddr_addr(ip); + sock_addr.sin_port = htons(atoi(port)); + + start_ts = utils_get_system_ts(); + do { + s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (s < 0) { + ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); + } + ret = connect(s, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); + if (ret == 0) { + *sock = s; + break; + } else if (s > 0) { + close(s); + } + } while (utils_get_system_ts() - start_ts < timeout); + return ret; +} + +esp_err_t wifi_unit_server_establish(int *socket_id, const char *port) +{ + esp_err_t ret = -1; + struct sockaddr_in local_addr; + uint32_t local_ip; + + static int ls_sock = -1; + + local_ip = wifi_util_get_ip(); + + if (ls_sock < 0) { + ls_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (ls_sock < 0) { + ESP_LOGE(TAG, "create socket failed"); + return ls_sock; + } + + local_addr.sin_family = AF_INET; + local_addr.sin_port = htons(atoi(port)); + local_addr.sin_addr.s_addr = local_ip; + ret = bind(ls_sock, (struct sockaddr *)&local_addr, sizeof(local_addr)); + if (ret != 0) { + ESP_LOGE(TAG, "socket bind failed"); + return ret; + } + + ret = listen(ls_sock, 1); + if (ret < 0) { + ESP_LOGE(TAG, "socket listen failed"); + return ret; + } + } + + struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6 + socklen_t addrLen = sizeof(sourceAddr); + *socket_id = accept(ls_sock, (struct sockaddr *)&sourceAddr, &addrLen); + if (*socket_id < 0) { + ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno); + return -1; + } + ESP_LOGI(TAG, "Socket accepted"); + return ret; +} + +esp_err_t wifi_unit_tcp_recv(int socket_id, const char *duration, uint32_t user_date[]) +{ + esp_err_t ret = -1; + uint32_t start_ts; + uint8_t *buffer; + struct timeval tv_t; + uint32_t *recv_len = &user_date[1]; + tv_t.tv_sec = 1; + tv_t.tv_usec = 0; + ret = setsockopt(socket_id, SOL_SOCKET, SO_RCVTIMEO, &tv_t, sizeof(tv_t)); + + buffer = malloc(2920); + + if (buffer == NULL) { + ESP_LOGE(TAG, "%s malloc fail\n", __func__); + return ESP_ERR_NO_MEM; + } + + start_ts = utils_get_system_ts(); + + while (utils_get_system_ts() - start_ts < atoi(duration)) { + ret = recv(socket_id, buffer, 2920, 0); + if (ret > 0) { + *recv_len = *recv_len + ret; + } else if (ret == 0) { + break; + } + } + free(buffer); + if (ret > 0 ) { + ret = ESP_OK; + } + return ret; +} + +esp_err_t wifi_util_tcp_send(int socket_id, uint32_t len, uint32_t delay, uint32_t *sent_len, uint32_t timeout) +{ + esp_err_t ret = ESP_OK; + uint32_t start_ts; + uint8_t *buffer; + + if ( len == 0) { + return ESP_ERR_INVALID_ARG; + } + buffer = malloc(len); + if (buffer == NULL) { + ESP_LOGE(TAG, "%s malloc fail\n", __func__); + return ESP_ERR_NO_MEM; + } + + start_ts = utils_get_system_ts(); + + while (utils_get_system_ts() - start_ts < timeout) { + ret = send(socket_id, buffer, len, 0); + if (ret < 0) { + ESP_LOGE(TAG, "recv failed: errno %d", errno); + break; + } + *sent_len = *sent_len + ret; + + if (delay) { + vTaskDelay(delay / portTICK_PERIOD_MS); + } + } + if (ret == len) { + ret = ESP_OK; + } else { + ESP_LOGE(TAG, "tcp send error, %d", ret); + ret = -2; + } + + free(buffer); + + return ret; +} + +uint32_t wifi_util_get_ip(void) +{ + esp_netif_ip_info_t ip_info; + esp_netif_t *netif = get_example_netif(); + esp_netif_get_ip_info(netif, &ip_info); + return ip_info.ip.addr; +} + +void wifi_util_init(void) +{ + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); +} \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_unit.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_unit.h new file mode 100644 index 000000000..d0b664c70 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/components/case/wifi_unit.h @@ -0,0 +1,38 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef _WIFI_UNIT_H +#define _WIFI_UNIT_H + +#include "esp_wifi_types.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "esp_timer.h" +#include "nvs_flash.h" + +#include "esp_netif.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "lwip/netdb.h" +#include "lwip/dns.h" + +uint32_t utils_get_system_ts(void); + +void wifi_util_init(void); + +uint32_t wifi_util_get_ip(void); +esp_err_t wifi_unit_client_establish(int *sock, const char *ip, const char *port); +esp_err_t wifi_unit_server_establish(int *socket_id, const char *port); + +esp_err_t wifi_unit_tcp_recv(int socket_id, const char *duration, uint32_t user_date[]); +esp_err_t wifi_util_tcp_send(int socket_id, uint32_t len, uint32_t delay, uint32_t *sent_len, uint32_t timeout); +#endif /* _WIFI_UNIT_H */ \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/CMakeLists.txt b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/CMakeLists.txt new file mode 100644 index 000000000..44548e75f --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCS "main.c" + "coex_cmd.c") + +set(COMPONENT_ADD_INCLUDEDIRS ".") +set(SUPPORTED_TARGETS esp32) +register_component() diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/Kconfig.projbuild b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/Kconfig.projbuild new file mode 100644 index 000000000..ac52aa2a7 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/Kconfig.projbuild @@ -0,0 +1,70 @@ +menu "Example Configuration" + + choice EXAMPLE_RUN_MODE + prompt "select run mode" + help + select run mode + + config EXAMPLE_AUTO + bool "auto" + help + In automatic mode, the program coordinates three development board work + through a synchronization mechanism. + + config EXAMPLE_MANAUL + bool "manual" + help + In manual mode, you will work with three development boards via commands. + endchoice + + config EXAMPLE_WIFI_SSID + depends on EXAMPLE_MANAUL + string "WiFi SSID" + help + SSID (network name) for the example to connect to. The length cannot exceed 20 bytes. + config EXAMPLE_WIFI_PASSWORD + depends on EXAMPLE_MANAUL + string "WiFi Password" + help + WiFi password (WPA or WPA2) for the example to use. + Can be left blank if the network has no security set. + The length cannot exceed 20 bytes. + + choice EXAMPLE_SELECT_ROLE + prompt "select role" + depends on EXAMPLE_AUTO + config EXAMPLE_COEX_ROLE + bool "run device as coex role" + config EXAMPLE_WIFI_ROLE + bool "run device as wifi role" + config EXAMPLE_BT_ROLE + bool "run device as bluetooth role" + endchoice + + choice EXAMPLE_SELECT_CASE + prompt "select case" + depends on EXAMPLE_COEX_ROLE + config EXAMPLE_COEX_TX_ADV + bool "TCP TX and BLE ADV" + config EXAMPLE_COEX_RX_ADV + bool "TCP RX and BLE ADV" + config EXAMPLE_COEX_TX_SCAN + bool "TCP TX and BLE SCAN" + config EXAMPLE_COEX_RX_SCAN + bool "TCP RX and BLE SCAN" + endchoice + + config EXAMPLE_WIFI_SSID + depends on EXAMPLE_COEX_ROLE + string "WiFi SSID" + help + SSID (network name) for the example to connect to. The length cannot exceed 20 bytes. + config EXAMPLE_WIFI_PASSWORD + depends on EXAMPLE_COEX_ROLE + string "WiFi Password" + help + WiFi password (WPA or WPA2) for the example to use. + Can be left blank if the network has no security set. + The length cannot exceed 20 bytes. + +endmenu #"Example Configuration End" \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/coex_cmd.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/coex_cmd.c new file mode 100644 index 000000000..5df2616da --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/coex_cmd.c @@ -0,0 +1,168 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include "esp_log.h" +#include "esp_console.h" +#include "argtable3/argtable3.h" + +#include "esp_bt.h" +#include "esp_bt_main.h" +#include "esp_bt_device.h" + +#include "run_tc.h" +#include "test_env.h" + + +#define TAG_CNSL "CNSL" + +typedef struct { + struct arg_str *wifi_tc_idx; + struct arg_str *bt_tc_idx; + struct arg_end *end; +} tc_run_args_t; + +typedef struct { + struct arg_lit *set; + struct arg_lit *get; + struct arg_str *key; + struct arg_str *value; + struct arg_end *end; +} env_param_cmd_args_t; + +static tc_run_args_t tc_run_args; +static env_param_cmd_args_t env_param_cmd_args; + +static int process_env_parameter_cmd(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &env_param_cmd_args); + int ret; + const char *env_value = ""; + + if (nerrors != 0) { + arg_print_errors(stderr, env_param_cmd_args.end, argv[0]); + return 1; + } + if (env_param_cmd_args.set->count == 1) { + if (env_param_cmd_args.key->count == 1) { + if (env_param_cmd_args.value->count == 1) { + env_value = env_param_cmd_args.value->sval[0]; + } + ret = coex_set_test_env(env_param_cmd_args.key->sval[0], env_value, strlen(env_param_cmd_args.value->sval[0])); + if (ret == ESP_ERR_NOT_SUPPORTED) { + ESP_LOGE(TAG_CNSL, "Not supported env key"); + } else if (ret == ESP_ERR_INVALID_ARG) { + ESP_LOGE(TAG_CNSL, "Invalid value"); + } + ESP_LOGI(TAG_CNSL, "env set done"); + } else { + ESP_LOGE(TAG_CNSL, "env key not set correctly"); + } + } else if (env_param_cmd_args.get->count == 1) { + coex_print_test_env(); + } + return 0; +} + +static int process_restart_cmd(int argc, char **argv) +{ + ESP_LOGI(TAG_CNSL, "restarting..."); + esp_restart(); + return 0; +} + + +static int process_run_tc_cmd(int argc, char **argv) +{ + run_task_msg_t msg; + int nerrors = arg_parse(argc, argv, (void **) &tc_run_args); + if (nerrors != 0) { + arg_print_errors(stderr, tc_run_args.end, argv[0]); + return 1; + } + + if (tc_run_args.wifi_tc_idx->count == 1) { + msg.case_id = atoi(tc_run_args.wifi_tc_idx->sval[0]); + if (xQueueSend(xTaskQueue, &msg, portMAX_DELAY) != pdTRUE) { + ESP_LOGE(TAG_CNSL, "xTaskQueue Post failed\n"); + } + } + + if (tc_run_args.bt_tc_idx->count == 1) { + msg.case_id = atoi(tc_run_args.bt_tc_idx->sval[0]); + if (xQueueSend(xTaskQueue, &msg, portMAX_DELAY) != pdTRUE) { + ESP_LOGE(TAG_CNSL, "xTaskQueue Post failed\n"); + } + } + + return 0; +} + +static int process_get_mac_addr_cmd(int argc, char **argv) +{ + const uint8_t *mac = esp_bt_dev_get_address(); + + if (mac != NULL) { + ESP_LOGI(TAG_CNSL, "+BTMAC:"MACSTR"\n", MAC2STR(mac)); + } + return 0; +} +void register_coex_cmd(void) +{ + const esp_console_cmd_t restart_cmd = { + .command = "restart", + .help = "restart cmd", + .hint = NULL, + .func = &process_restart_cmd, + .argtable = NULL + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&restart_cmd) ); + + const esp_console_cmd_t get_mac_cmd = { + .command = "mac", + .help = "Get DUT mac address", + .hint = NULL, + .func = &process_get_mac_addr_cmd, + .argtable = NULL + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&get_mac_cmd) ); + + tc_run_args.wifi_tc_idx = arg_str0("w", "wifi", "", "0 : wifi_tcp_tx_throught 1 : wifi_tcp_rx_throught\n"); + tc_run_args.bt_tc_idx = arg_str0("b", "bluetooth", "", "2 :ble_adv 3 : ble_scan\n"); + tc_run_args.end = arg_end(2); + + const esp_console_cmd_t run_tc_cmd = { + .command = "run_tc", + .help = "run wifi bt test case command", + .hint = NULL, + .func = &process_run_tc_cmd, + .argtable = &tc_run_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&run_tc_cmd) ); + + env_param_cmd_args.set = arg_lit0("s", "set", "set env parameter"); + env_param_cmd_args.get = arg_lit0("g", "get", "get env parameter"); + env_param_cmd_args.key = arg_str0("k", "key", "", "env parameter key"); + env_param_cmd_args.value = arg_str0("v", "value", "", "env parameter value (only used with set)"); + env_param_cmd_args.end = arg_end(4); + + const esp_console_cmd_t env_cmd = { + .command = "env", + .help = "Set or get test environment parameters", + .hint = NULL, + .func = &process_env_parameter_cmd, + .argtable = &env_param_cmd_args, + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&env_cmd) ); +} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/coex_cmd.h b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/coex_cmd.h new file mode 100644 index 000000000..397c1b057 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/coex_cmd.h @@ -0,0 +1,16 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef MAIN_COEX_CMD_H_ +#define MAIN_COEX_CMD_H_ + +#define CNSL_CMD_OUTPUT_PREFIX "COEX_CNSL_OUTPUT" +void register_coex_cmd(void); + +#endif /* MAIN_COEX_CMD_H_ */ diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/component.mk b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/component.mk new file mode 100644 index 000000000..d68c5375e --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) +# \ No newline at end of file diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/main.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/main.c new file mode 100644 index 000000000..ff2c62b2e --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/main/main.c @@ -0,0 +1,145 @@ +/* ESP BLE Mesh Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include "esp_system.h" +#include "esp_log.h" +#include "esp_console.h" +#include "esp_vfs_dev.h" +#include "driver/uart.h" +#include "linenoise/linenoise.h" +#include "argtable3/argtable3.h" +#include "esp_vfs_fat.h" +#include "nvs.h" +#include "nvs_flash.h" + +#include "esp_coexist.h" +#include "coex_cmd.h" +#include "run_tc.h" +#include "sync.h" + +static void initialize_nvs(void) +{ + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK( nvs_flash_erase() ); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK(err); +} + +static void initialize_console(void) +{ + /* Disable buffering on stdin and stdout */ + setvbuf(stdin, NULL, _IONBF, 0); + + /* Minicom, screen, idf_monitor send CR when ENTER key is pressed */ + esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + + /* Configure UART. Note that REF_TICK is used so that the baud rate remains + * correct while APB frequency is changing in light sleep mode. + */ + const uart_config_t uart_config = { + .baud_rate = CONFIG_CONSOLE_UART_BAUDRATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .use_ref_tick = true + }; + ESP_ERROR_CHECK( uart_param_config(CONFIG_ESP_CONSOLE_UART_NUM, &uart_config) ); + + /* Install UART driver for interrupt-driven reads and writes */ + ESP_ERROR_CHECK( uart_driver_install(CONFIG_ESP_CONSOLE_UART_NUM, + 256, 0, 0, NULL, 0) ); + + /* Tell VFS to use UART driver */ + esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); + + /* Initialize the console */ + esp_console_config_t console_config = { + .max_cmdline_args = 8, + .max_cmdline_length = 256, +#if CONFIG_LOG_COLORS + .hint_color = atoi(LOG_COLOR_CYAN) +#endif + }; + ESP_ERROR_CHECK( esp_console_init(&console_config) ); + + /* Configure linenoise line completion library */ + /* Enable multiline editing. If not set, long commands will scroll within + * single line. + */ + linenoiseSetMultiLine(1); + + /* Tell linenoise where to get command completions and hints */ + linenoiseSetCompletionCallback(&esp_console_get_completion); + linenoiseSetHintsCallback((linenoiseHintsCallback *) &esp_console_get_hint); + + /* Set command history size */ + linenoiseHistorySetMaxLen(100); + +} + + + +void app_main(void) +{ + initialize_nvs(); + + initialize_console(); + run_tc_init(); + + /* Register commands */ + esp_console_register_help_command(); + register_coex_cmd(); + +#if defined(CONFIG_EXAMPLE_AUTO) + sync_init(); +#endif + + /* Prompt to be printed before each line. + * This can be customized, made dynamic, etc. + */ + printf("esp-idf version: %s\n\n", esp_get_idf_version()); + printf("coexist version: %s\n\n", esp_coex_version_get()); + const char *prompt = "esp32> "; + linenoiseSetDumbMode(1); + + + /* Main loop */ + while (true) { + /* Get a line using linenoise. + * The line is returned when ENTER is pressed. + */ + char *line = linenoise(prompt); + if (line == NULL) { /* Ignore empty lines */ + continue; + } + /* Add the command to the history */ + linenoiseHistoryAdd(line); + + /* Try to run the command */ + int ret; + esp_err_t err = esp_console_run(line, &ret); + if (err == ESP_ERR_NOT_FOUND) { + printf("Unrecognized command\n"); + } else if (err == ESP_ERR_INVALID_ARG) { + // command was empty + } else if (err == ESP_OK && ret != ESP_OK) { + printf("Command returned non-zero error code: 0x%x (%s)\n", ret, esp_err_to_name(err)); + } else if (err != ESP_OK) { + printf("Internal error: %s\n", esp_err_to_name(err)); + } + /* linenoise allocates line buffer on the heap, so need to free it */ + linenoiseFree(line); + } +} diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/partitions.csv b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/partitions.csv new file mode 100644 index 000000000..612494574 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/partitions.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 0x1F0000, diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/sdkconfig.defaults b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/sdkconfig.defaults new file mode 100644 index 000000000..ab9187792 --- /dev/null +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/sdkconfig.defaults @@ -0,0 +1,110 @@ +# +# Automatically generated file; DO NOT EDIT. +# Espressif IoT Development Framework Configuration +# + +# +# SDK tool configuration +# +CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES=y +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_APP_OFFSET=0x10000 + + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_BAUD_921600B=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y + +# +# Component config +# +# +# Bluetooth +# +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_PINNED_TO_CORE=1 +CONFIG_BTDM_MODEM_SLEEP=n +CONFIG_BTDM_BLE_SCAN_DUPL=y +CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE=y +CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN=y +CONFIG_BT_BLUEDROID_ENABLED=y +CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1=y +CONFIG_BT_BTU_TASK_STACK_SIZE=4512 +CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y +CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=y +CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY=y +CONFIG_BT_SMP_ENABLE=y +CONFIG_BT_RESERVE_DRAM=0x10000 + +# +# ESP32-specific +# +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_MEMMAP_SMP=y +CONFIG_ESP32_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096 +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=6 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_SPIRAM_IGNORE_NOTFOUND=y + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y +CONFIG_ESP32_WIFI_SW_COEXIST_PREFERENCE_BALANCE=y +CONFIG_ESP32_WIFI_SW_COEXIST_PREFERENCE_VALUE=2 +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=16 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=16 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=6 + +# +# FreeRTOS +# +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=1536 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=5 +CONFIG_FREERTOS_HZ=1000 + +# +# LWIP +# +CONFIG_LWIP_IP_FRAG=y +CONFIG_LWIP_IP_REASSEMBLY=y +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65534 +CONFIG_LWIP_TCP_WND_DEFAULT=65534 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=64 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=64 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0=y +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x0 + +# +# ble mesh +# +CONFIG_BLE_MESH=y +CONFIG_BLE_MESH_NODE=y +CONFIG_BLE_MESH_PB_GATT=y +CONFIG_BLE_MESH_TX_SEG_MSG_COUNT=10 +CONFIG_BLE_MESH_RX_SEG_MSG_COUNT=10 +CONFIG_BLE_MESH_GENERIC_ONOFF_CLI=y