ble_mesh: add ble mesh coex test example

This commit is contained in:
wangcheng 2019-10-16 10:25:00 +08:00
parent c65b67115a
commit 03d11913a2
25 changed files with 2564 additions and 0 deletions

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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()

View file

@ -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();
}

View file

@ -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 <stdio.h>
#include <string.h>
#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_ */

View file

@ -0,0 +1,7 @@
#
# Component Makefile
#
COMPONENT_SRCDIRS := .
COMPONENT_ADD_INCLUDEDIRS = .

View file

@ -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);
}

View file

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#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__ */

View file

@ -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
}

View file

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#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

View file

@ -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 <stdio.h>
#include <string.h>
#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;
}

View file

@ -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 <stdint.h>
#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__ */

View file

@ -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 <stdio.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "wifi_connect.h"
#include <string.h>
#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;
}

View file

@ -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__ */

View file

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#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());
}

View file

@ -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 */

View file

@ -0,0 +1,6 @@
set(COMPONENT_SRCS "main.c"
"coex_cmd.c")
set(COMPONENT_ADD_INCLUDEDIRS ".")
set(SUPPORTED_TARGETS esp32)
register_component()

View file

@ -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"

View file

@ -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 <stdio.h>
#include <string.h>
#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", "<str>", "0 : wifi_tcp_tx_throught 1 : wifi_tcp_rx_throught\n");
tc_run_args.bt_tc_idx = arg_str0("b", "bluetooth", "<str>", "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", "<str>", "env parameter key");
env_param_cmd_args.value = arg_str0("v", "value", "<str>", "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) );
}

View file

@ -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_ */

View file

@ -0,0 +1,5 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
#

View file

@ -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 <stdio.h>
#include <string.h>
#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);
}
}

View file

@ -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,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 0x1F0000,

View file

@ -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