Merge branch 'feature/ftm_support_stage2_v4.3' into 'release/v4.3'

wifi/ftm: Additional FTM features implementation (Backport v4.3)

See merge request espressif/esp-idf!14157
This commit is contained in:
Jiang Jiang Jian
2021-06-30 15:20:01 +00:00
4 changed files with 146 additions and 89 deletions

View File

@ -1177,6 +1177,31 @@ esp_err_t esp_wifi_set_rssi_threshold(int32_t rssi);
*/ */
esp_err_t esp_wifi_ftm_initiate_session(wifi_ftm_initiator_cfg_t *cfg); esp_err_t esp_wifi_ftm_initiate_session(wifi_ftm_initiator_cfg_t *cfg);
/**
* @brief End the ongoing FTM Initiator session
*
* @attention This API works only on FTM Initiator
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_ftm_end_session(void);
/**
* @brief Set offset in cm for FTM Responder. An equivalent offset is calculated in picoseconds
* and added in TOD of FTM Measurement frame (T1).
*
* @attention Use this API only in AP mode before performing FTM as responder
*
* @param offset_cm T1 Offset to be added in centimeters
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_ftm_resp_set_offset(int16_t offset_cm);
/** /**
* @brief Enable or disable 11b rate of specified interface * @brief Enable or disable 11b rate of specified interface
* *

View File

@ -32,18 +32,17 @@ Build and flash the example on a supported device to see below output -
========================================================== ==========================================================
| Steps to test FTM | | Steps to test FTM |
| | | |
| 1. Use 'help' to gain overview of commands | | 1. Use 'help' for detailed information on parameters |
| 2. Use 'scan' command to search for external AP's | | 2. Start SoftAP with command 'ap <SSID> <password>' |
| OR | | OR |
| 2. Start SoftAP on another device using 'ap' command | | 2. Use 'scan' command to search for external AP's |
| 3. Start FTM with command 'ftm -I -s <SSID>' | | 3. On second device initiate FTM with an AP using |
| | | command 'ftm -I -s <SSID>' |
========================================================== ==========================================================
ftm> ftm>
``` ```
Use `help` to get a list of available commands and options. Use `scan` command to scan for AP's that support FTM Responder mode. Use `help` to get a list of available commands and options. Use `scan` command to scan for AP's that support FTM Responder mode. Before initiating FTM with an external AP, make sure that `FTM Responder` tag is visible in the respective scan result entry. Alternatively, start SoftAP on another device using `ap` command, it supports FTM Responder by default. If external FTM Initiators get a large error in distance readings with the SoftAP, note down the reading at zero distance in centimeters, say `cm0`. This distance can be offset using command `ftm -R -o <cm0>` to give accurate readings with the Initiator.
Before initiating FTM with an external AP, make sure that `FTM Responder` is visible in the respective scan result entry.
```bash ```bash
ftm> scan ftm> scan
@ -65,17 +64,17 @@ ftm>
``` ```
Issue `ftm -I` to initiate a session with default configuration of 32 FTM frames. For more configurations below options are available - Issue `ftm -I` to initiate a session with default configuration of 32 FTM frames. For more configurations below options are available -
`ftm [-I] [-c <0/16/24/32/64>] [-p <2-255 (x 100 mSec)>] [-s SSID]` `ftm [-I] [-c <0/8/16/24/32/64>] [-p <2-255 (x 100 mSec)>] [-s SSID]`
Where - Where -
* `-I` OR `--ftm_initiator`: FTM Initiator mode * `-I` OR `--ftm_initiator`: FTM Initiator mode
* `-c` OR `--frm_count`: FTM frames to be exchanged (Valid values: 0=No preference, 16, 24, 32, 64, default: 32) * `-c` OR `--frm_count`: FTM frames to be exchanged (Valid values: 0=No preference, 8, 16, 24, 32, 64, default: 32)
* `-p` OR `--burst_period`: Periodicity of FTM bursts in 100's of miliseconds (0: No preference, default: 2) * `-p` OR `--burst_period`: Periodicity of FTM bursts in 100's of miliseconds (0: No preference, default: 2)
* `-s` OR `--ssid=SSID`: SSID of AP that supports FTM Responder mode * `-s` OR `--ssid=SSID`: SSID of AP that supports FTM Responder mode
Currently FTM is only supported in below configuration - Currently FTM is only supported in below configuration -
1. Station as Initiator and SoftAP as Responder on supported ESP devices 1. Station as Initiator and SoftAP as Responder on supported ESP devices
2. Station as Initiator and an external AP that supports FTM in Responder mode 2. Station as Initiator and an external AP that supports FTM in Responder mode
The first option should be preferred since ESP devices are self calibrated for high resolution measurement. FTM Responder support for external Stations and ASAP mode will follow in future updates. The first option should be preferred since ESP devices are self calibrated for high resolution measurement.
## Example Output ## Example Output
Example output of an FTM Procedure - Example output of an FTM Procedure -

View File

@ -34,10 +34,16 @@ typedef struct {
} wifi_scan_arg_t; } wifi_scan_arg_t;
typedef struct { typedef struct {
struct arg_lit *mode; /* FTM Initiator */
struct arg_lit *initiator;
struct arg_int *frm_count; struct arg_int *frm_count;
struct arg_int *burst_period; struct arg_int *burst_period;
struct arg_str *ssid; struct arg_str *ssid;
/* FTM Responder */
struct arg_lit *responder;
struct arg_lit *enable;
struct arg_lit *disable;
struct arg_int *offset;
struct arg_end *end; struct arg_end *end;
} wifi_ftm_args_t; } wifi_ftm_args_t;
@ -46,6 +52,12 @@ static wifi_args_t ap_args;
static wifi_scan_arg_t scan_args; static wifi_scan_arg_t scan_args;
static wifi_ftm_args_t ftm_args; static wifi_ftm_args_t ftm_args;
wifi_config_t g_ap_config = {
.ap.max_connection = 4,
.ap.authmode = WIFI_AUTH_WPA2_PSK,
.ap.ftm_responder = true
};
static bool s_reconnect = true; static bool s_reconnect = true;
static const char *TAG_STA = "ftm_station"; static const char *TAG_STA = "ftm_station";
static const char *TAG_AP = "ftm_ap"; static const char *TAG_AP = "ftm_ap";
@ -60,6 +72,7 @@ const int FTM_FAILURE_BIT = BIT1;
wifi_ftm_report_entry_t *g_ftm_report; wifi_ftm_report_entry_t *g_ftm_report;
uint8_t g_ftm_report_num_entries; uint8_t g_ftm_report_num_entries;
static uint32_t g_rtt_est, g_dist_est; static uint32_t g_rtt_est, g_dist_est;
bool g_ap_started;
const int g_report_lvl = const int g_report_lvl =
#ifdef CONFIG_ESP_FTM_REPORT_SHOW_DIAG #ifdef CONFIG_ESP_FTM_REPORT_SHOW_DIAG
@ -79,46 +92,44 @@ const int g_report_lvl =
uint16_t g_scan_ap_num; uint16_t g_scan_ap_num;
wifi_ap_record_t *g_ap_list_buffer; wifi_ap_record_t *g_ap_list_buffer;
static void wifi_connected_handler(void *arg, esp_event_base_t event_base, static void event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data) int32_t event_id, void *event_data)
{ {
wifi_event_sta_connected_t *event = (wifi_event_sta_connected_t *)event_data; if (event_id == WIFI_EVENT_STA_CONNECTED) {
wifi_event_sta_connected_t *event = (wifi_event_sta_connected_t *)event_data;
ESP_LOGI(TAG_STA, "Connected to %s (BSSID: "MACSTR", Channel: %d)", event->ssid, ESP_LOGI(TAG_STA, "Connected to %s (BSSID: "MACSTR", Channel: %d)", event->ssid,
MAC2STR(event->bssid), event->channel); MAC2STR(event->bssid), event->channel);
xEventGroupClearBits(wifi_event_group, DISCONNECTED_BIT); xEventGroupClearBits(wifi_event_group, DISCONNECTED_BIT);
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
} } else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
if (s_reconnect) {
ESP_LOGI(TAG_STA, "sta disconnect, s_reconnect...");
esp_wifi_connect();
} else {
ESP_LOGI(TAG_STA, "sta disconnect");
}
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
xEventGroupSetBits(wifi_event_group, DISCONNECTED_BIT);
} else if (event_id == WIFI_EVENT_FTM_REPORT) {
wifi_event_ftm_report_t *event = (wifi_event_ftm_report_t *) event_data;
static void disconnect_handler(void *arg, esp_event_base_t event_base, if (event->status == FTM_STATUS_SUCCESS) {
int32_t event_id, void *event_data) g_rtt_est = event->rtt_est;
{ g_dist_est = event->dist_est;
if (s_reconnect) { g_ftm_report = event->ftm_report_data;
ESP_LOGI(TAG_STA, "sta disconnect, s_reconnect..."); g_ftm_report_num_entries = event->ftm_report_num_entries;
esp_wifi_connect(); xEventGroupSetBits(ftm_event_group, FTM_REPORT_BIT);
} else { } else {
ESP_LOGI(TAG_STA, "sta disconnect"); ESP_LOGI(TAG_STA, "FTM procedure with Peer("MACSTR") failed! (Status - %d)",
} MAC2STR(event->peer_mac), event->status);
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); xEventGroupSetBits(ftm_event_group, FTM_FAILURE_BIT);
xEventGroupSetBits(wifi_event_group, DISCONNECTED_BIT); }
} } else if (event_id == WIFI_EVENT_AP_START) {
g_ap_started = true;
static void ftm_report_handler(void *arg, esp_event_base_t event_base, } else if (event_id == WIFI_EVENT_AP_STOP) {
int32_t event_id, void *event_data) g_ap_started = false;
{
wifi_event_ftm_report_t *event = (wifi_event_ftm_report_t *) event_data;
if (event->status == FTM_STATUS_SUCCESS) {
g_rtt_est = event->rtt_est;
g_dist_est = event->dist_est;
g_ftm_report = event->ftm_report_data;
g_ftm_report_num_entries = event->ftm_report_num_entries;
xEventGroupSetBits(ftm_event_group, FTM_REPORT_BIT);
} else {
ESP_LOGI(TAG_STA, "FTM procedure with Peer("MACSTR") failed! (Status - %d)",
MAC2STR(event->peer_mac), event->status);
xEventGroupSetBits(ftm_event_group, FTM_FAILURE_BIT);
} }
} }
@ -178,21 +189,14 @@ void initialise_wifi(void)
ESP_ERROR_CHECK( esp_event_loop_create_default() ); ESP_ERROR_CHECK( esp_event_loop_create_default() );
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_event_handler_instance_t instance_any_id;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
WIFI_EVENT_STA_CONNECTED, ESP_EVENT_ANY_ID,
&wifi_connected_handler, &event_handler,
NULL, NULL,
NULL)); &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
WIFI_EVENT_STA_DISCONNECTED,
&disconnect_handler,
NULL,
NULL));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
WIFI_EVENT_FTM_REPORT,
&ftm_report_handler,
NULL,
NULL));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) ); ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) );
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL) ); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL) );
ESP_ERROR_CHECK(esp_wifi_start() ); ESP_ERROR_CHECK(esp_wifi_start() );
@ -299,34 +303,23 @@ static int wifi_cmd_scan(int argc, char **argv)
static bool wifi_cmd_ap_set(const char* ssid, const char* pass) static bool wifi_cmd_ap_set(const char* ssid, const char* pass)
{ {
wifi_config_t wifi_config = {
.ap = {
.ssid = "",
.ssid_len = 0,
.max_connection = 4,
.password = "",
.authmode = WIFI_AUTH_WPA2_PSK,
.ftm_responder = true
},
};
s_reconnect = false; s_reconnect = false;
strlcpy((char*) wifi_config.ap.ssid, ssid, sizeof(wifi_config.ap.ssid)); strlcpy((char*) g_ap_config.ap.ssid, ssid, MAX_SSID_LEN);
if (pass) { if (pass) {
if (strlen(pass) != 0 && strlen(pass) < 8) { if (strlen(pass) != 0 && strlen(pass) < 8) {
s_reconnect = true; s_reconnect = true;
ESP_LOGE(TAG_AP, "password less than 8"); ESP_LOGE(TAG_AP, "password less than 8");
return false; return false;
} }
strlcpy((char*) wifi_config.ap.password, pass, sizeof(wifi_config.ap.password)); strlcpy((char*) g_ap_config.ap.password, pass, MAX_PASSPHRASE_LEN);
} }
if (strlen(pass) == 0) { if (strlen(pass) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN; g_ap_config.ap.authmode = WIFI_AUTH_OPEN;
} }
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &g_ap_config));
return true; return true;
} }
@ -419,10 +412,14 @@ static int wifi_cmd_ftm(int argc, char **argv)
return 0; return 0;
} }
if (ftm_args.mode->count == 0) { if (ftm_args.initiator->count != 0 && ftm_args.responder->count != 0) {
goto ftm_start; ESP_LOGE(TAG_STA, "Invalid FTM cmd argument");
return 0;
} }
if (ftm_args.responder->count != 0)
goto ftm_responder;
if (ftm_args.ssid->count == 1) { if (ftm_args.ssid->count == 1) {
ap_record = find_ftm_responder_ap(ftm_args.ssid->sval[0]); ap_record = find_ftm_responder_ap(ftm_args.ssid->sval[0]);
if (ap_record) { if (ap_record) {
@ -435,9 +432,9 @@ static int wifi_cmd_ftm(int argc, char **argv)
if (ftm_args.frm_count->count != 0) { if (ftm_args.frm_count->count != 0) {
uint8_t count = ftm_args.frm_count->ival[0]; uint8_t count = ftm_args.frm_count->ival[0];
if (count != 0 && count != 16 && if (count != 0 && count != 8 && count != 16 &&
count != 24 && count != 32 && count != 64) { count != 24 && count != 32 && count != 64) {
ESP_LOGE(TAG_STA, "Invalid Frame Count! Valid options are 0/16/24/32/64"); ESP_LOGE(TAG_STA, "Invalid Frame Count! Valid options are 0/8/16/24/32/64");
return 0; return 0;
} }
ftmi_cfg.frm_count = count; ftmi_cfg.frm_count = count;
@ -453,7 +450,6 @@ static int wifi_cmd_ftm(int argc, char **argv)
} }
} }
ftm_start:
ESP_LOGI(TAG_STA, "Requesting FTM session with Frm Count - %d, Burst Period - %dmSec (0: No Preference)", ESP_LOGI(TAG_STA, "Requesting FTM session with Frm Count - %d, Burst Period - %dmSec (0: No Preference)",
ftmi_cfg.frm_count, ftmi_cfg.burst_period*100); ftmi_cfg.frm_count, ftmi_cfg.burst_period*100);
@ -477,6 +473,37 @@ ftm_start:
/* Failure case */ /* Failure case */
} }
return 0;
ftm_responder:
if (ftm_args.offset->count != 0) {
int16_t offset_cm = ftm_args.offset->ival[0];
esp_wifi_ftm_resp_set_offset(offset_cm);
}
if (ftm_args.enable->count != 0) {
if (!g_ap_started) {
ESP_LOGE(TAG_AP, "Start the SoftAP first with 'ap' command");
return 0;
}
g_ap_config.ap.ftm_responder = true;
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &g_ap_config));
ESP_LOGI(TAG_AP, "Re-starting SoftAP with FTM Responder enabled");
return 0;
}
if (ftm_args.disable->count != 0) {
if (!g_ap_started) {
ESP_LOGE(TAG_AP, "Start the SoftAP first with 'ap' command");
return 0;
}
g_ap_config.ap.ftm_responder = false;
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &g_ap_config));
ESP_LOGI(TAG_AP, "Re-starting SoftAP with FTM Responder disabled");
}
return 0; return 0;
} }
@ -531,10 +558,16 @@ void register_wifi(void)
}; };
ESP_ERROR_CHECK( esp_console_cmd_register(&query_cmd) ); ESP_ERROR_CHECK( esp_console_cmd_register(&query_cmd) );
ftm_args.mode = arg_lit1("I", "ftm_initiator", "FTM Initiator mode"); /* FTM Initiator commands */
ftm_args.initiator = arg_lit0("I", "ftm_initiator", "FTM Initiator mode");
ftm_args.ssid = arg_str0("s", "ssid", "SSID", "SSID of AP"); ftm_args.ssid = arg_str0("s", "ssid", "SSID", "SSID of AP");
ftm_args.frm_count = arg_int0("c", "frm_count", "<0/16/24/32/64>", "FTM frames to be exchanged (0: No preference)"); ftm_args.frm_count = arg_int0("c", "frm_count", "<0/8/16/24/32/64>", "FTM frames to be exchanged (0: No preference)");
ftm_args.burst_period = arg_int0("p", "burst_period", "<2-255 (x 100 mSec)>", "Periodicity of FTM bursts in 100's of miliseconds (0: No preference)"); ftm_args.burst_period = arg_int0("p", "burst_period", "<2-255 (x 100 mSec)>", "Periodicity of FTM bursts in 100's of miliseconds (0: No preference)");
/* FTM Responder commands */
ftm_args.responder = arg_lit0("R", "ftm_responder", "FTM Responder mode");
ftm_args.enable = arg_lit0("e", "enable", "Restart SoftAP with FTM enabled");
ftm_args.disable = arg_lit0("d", "disable", "Restart SoftAP with FTM disabled");
ftm_args.offset = arg_int0("o", "offset", "Offset in cm", "T1 offset in cm for FTM Responder");
ftm_args.end = arg_end(1); ftm_args.end = arg_end(1);
const esp_console_cmd_t ftm_cmd = { const esp_console_cmd_t ftm_cmd = {
@ -572,12 +605,12 @@ void app_main(void)
printf("\n ==========================================================\n"); printf("\n ==========================================================\n");
printf(" | Steps to test FTM |\n"); printf(" | Steps to test FTM |\n");
printf(" | |\n"); printf(" | |\n");
printf(" | 1. Use 'help' to gain overview of commands |\n"); printf(" | 1. Use 'help' for detailed information on parameters |\n");
printf(" | 2. Use 'scan' command to search for external AP's |\n"); printf(" | 2. Start SoftAP with command 'ap <SSID> <password>' |\n");
printf(" | OR |\n"); printf(" | OR |\n");
printf(" | 2. Start SoftAP on another device using 'ap' command |\n"); printf(" | 2. Use 'scan' command to search for external AP's |\n");
printf(" | 3. Start FTM with command 'ftm -I -s <SSID>' |\n"); printf(" | 3. On second device initiate FTM with an AP using |\n");
printf(" | |\n"); printf(" | command 'ftm -I -s <SSID>' |\n");
printf(" ==========================================================\n\n"); printf(" ==========================================================\n\n");
// start console REPL // start console REPL