Skip to content

Commit cf43d17

Browse files
authored
Add FTM support and examples (#5272)
Rework of #5266 by @pedrominatel
1 parent b1bcec0 commit cf43d17

File tree

8 files changed

+366
-6
lines changed

8 files changed

+366
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/* Wi-Fi FTM Initiator Arduino Example
2+
3+
This example code is in the Public Domain (or CC0 licensed, at your option.)
4+
5+
Unless required by applicable law or agreed to in writing, this
6+
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7+
CONDITIONS OF ANY KIND, either express or implied.
8+
*/
9+
#include "WiFi.h"
10+
11+
/*
12+
THIS FEATURE IS SUPPORTED ONLY BY ESP32-S2 AND ESP32-C3
13+
*/
14+
15+
// Change the SSID and PASSWORD here if needed
16+
const char * WIFI_FTM_SSID = "WiFi_FTM_Responder"; // SSID of AP that has FTM Enabled
17+
const char * WIFI_FTM_PASS = "ftm_responder"; // STA Password
18+
19+
// FTM settings
20+
// Number of FTM frames requested in terms of 4 or 8 bursts (allowed values - 0 (No pref), 16, 24, 32, 64)
21+
const uint8_t FTM_FRAME_COUNT = 16;
22+
// Requested time period between consecutive FTM bursts in 100’s of milliseconds (allowed values - 0 (No pref) or 2-255)
23+
const uint16_t FTM_BURST_PERIOD = 2;
24+
25+
// Semaphore to signal when FTM Report has been received
26+
xSemaphoreHandle ftmSemaphore;
27+
// Status of the received FTM Report
28+
bool ftmSuccess = true;
29+
30+
// FTM report handler with the calculated data from the round trip
31+
void onFtmReport(arduino_event_t *event) {
32+
const char * status_str[5] = {"SUCCESS", "UNSUPPORTED", "CONF_REJECTED", "NO_RESPONSE", "FAIL"};
33+
wifi_event_ftm_report_t * report = &event->event_info.wifi_ftm_report;
34+
// Set the global report status
35+
ftmSuccess = report->status == FTM_STATUS_SUCCESS;
36+
if (ftmSuccess) {
37+
// The estimated distance in meters may vary depending on some factors (see README file)
38+
Serial.printf("FTM Estimate: Distance: %.2f m, Return Time: %u ns\n", (float)report->dist_est / 100.0, report->rtt_est);
39+
// Pointer to FTM Report with multiple entries, should be freed after use
40+
free(report->ftm_report_data);
41+
} else {
42+
Serial.print("FTM Error: ");
43+
Serial.println(status_str[report->status]);
44+
}
45+
// Signal that report is received
46+
xSemaphoreGive(ftmSemaphore);
47+
}
48+
49+
// Initiate FTM Session and wait for FTM Report
50+
bool getFtmReport(){
51+
if(!WiFi.initiateFTM(FTM_FRAME_COUNT, FTM_BURST_PERIOD)){
52+
Serial.println("FTM Error: Initiate Session Failed");
53+
return false;
54+
}
55+
// Wait for signal that report is received and return true if status was success
56+
return xSemaphoreTake(ftmSemaphore, portMAX_DELAY) == pdPASS && ftmSuccess;
57+
}
58+
59+
void setup() {
60+
Serial.begin(115200);
61+
62+
// Create binary semaphore (initialized taken and can be taken/given from any thread/ISR)
63+
ftmSemaphore = xSemaphoreCreateBinary();
64+
65+
// Listen for FTM Report events
66+
WiFi.onEvent(onFtmReport, ARDUINO_EVENT_WIFI_FTM_REPORT);
67+
68+
// Connect to AP that has FTM Enabled
69+
Serial.println("Connecting to FTM Responder");
70+
WiFi.begin(WIFI_FTM_SSID, WIFI_FTM_PASS);
71+
while (WiFi.status() != WL_CONNECTED) {
72+
delay(500);
73+
Serial.print(".");
74+
}
75+
Serial.println("");
76+
Serial.println("WiFi Connected");
77+
78+
Serial.print("Initiating FTM session with Frame Count ");
79+
Serial.print(FTM_FRAME_COUNT);
80+
Serial.print(" and Burst Period ");
81+
Serial.print(FTM_BURST_PERIOD * 100);
82+
Serial.println(" ms");
83+
84+
// Request FTM reports until one fails
85+
while(getFtmReport());
86+
}
87+
88+
void loop() {
89+
delay(1000);
90+
}

Diff for: libraries/WiFi/examples/FTM/FTM_Initiator/README.md

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Wi-Fi FTM Initiator Arduino Example
2+
3+
This example demonstrates how to use the Fine Timing Measurement (FTM) to calculate the distace from the Access Point and the device. This is calculated by the Wi-Fi Round Trip Time (Wi-Fi RTT) introduced on the [IEEE Std 802.11-2016](https://en.wikipedia.org/wiki/IEEE_802.11mc) standard.
4+
5+
This example was based on the [ESP-IDF FTM](https://github.com/espressif/esp-idf/tree/master/examples/wifi/ftm). See the README file for more details about on how to use this feature.
6+
7+
Some usages for this feature includes:
8+
9+
* Indoor positioning systems.
10+
* Navigation.
11+
* Device Location.
12+
* Smart Devices.
13+
* Alarms.
14+
15+
# Supported Targets
16+
17+
Currently, this example supports the following targets:
18+
19+
| Supported Targets | ESP32-S2 | ESP32-C3 |
20+
| ----------------- | -------- | -------- |
21+
22+
## How to Use Example
23+
24+
In order to use the FTM, you will need a Responder or Wi-Fi router with FTM capabilities. If you don't own one, you can use a second ESP32-S2 or ESP32-C3 to simulate one.
25+
See the **Responder** example to prepare the environment.
26+
27+
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
28+
29+
### Configure the Project
30+
31+
To configure this project, you can change the following configuration related to FTM feature:
32+
33+
```c
34+
// Change the SSID and PASSWORD here if needed
35+
const char * WIFI_FTM_SSID = "WiFi_FTM_Responder"; // SSID of AP that has FTM Enabled
36+
const char * WIFI_FTM_PASS = "ftm_responder"; // STA Password
37+
38+
// FTM settings
39+
// Number of FTM frames requested in terms of 4 or 8 bursts (allowed values - 0 (No pref), 16, 24, 32, 64)
40+
const uint8_t FTM_FRAME_COUNT = 16;
41+
// Requested time period between consecutive FTM bursts in 100’s of milliseconds (allowed values - 0 (No pref) or 2-255)
42+
const uint16_t FTM_BURST_PERIOD = 2;
43+
```
44+
45+
* Change the Wi-Fi `SSID` and `PASSWORD` as the same as the Responder/Router.
46+
* Change `FTM_FRAME_COUNT` with the number of frames requested to the Responder.
47+
* Change `FTM_BURST_PERIOD` with the time between each FTM burst.
48+
49+
To see more details about FTM, please see the [ESP-IDF docs](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/network/esp_wifi.html).
50+
51+
#### Using Arduino IDE
52+
53+
To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits).
54+
55+
* Before Compile/Verify, select the correct board: `Tools -> Board`.
56+
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
57+
58+
#### Using Platform IO
59+
60+
* Select the COM port: `Devices` or setting the `upload_port` option on the `platformio.ini` file.
61+
62+
## Log Output
63+
64+
Expected log output:
65+
66+
```
67+
ESP-ROM:esp32s2-rc4-20191025
68+
Build:Oct 25 2019
69+
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
70+
SPIWP:0xee
71+
mode:DIO, clock div:1
72+
load:0x3ffe6100,len:0x4b0
73+
load:0x4004c000,len:0xa6c
74+
load:0x40050000,len:0x25c4
75+
entry 0x4004c198
76+
Connecting to FTM Responder
77+
.....
78+
WiFi Connected
79+
Initiating FTM session with Frame Count 16 and Burst Period 200 ms
80+
FTM Estimate: Distance: 0.13 m, Return Time: 0 ns
81+
FTM Estimate: Distance: 0.13 m, Return Time: 0 ns
82+
FTM Estimate: Distance: 0.13 m, Return Time: 0 ns
83+
FTM Estimate: Distance: 0.00 m, Return Time: 0 ns
84+
...
85+
```
86+
87+
## Troubleshooting
88+
89+
***Important: Make sure you are using a good quality USB cable and that you have a reliable power source.***
90+
91+
* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed.
92+
* **COM port not detected:** Check the USB cable and the USB to Serial driver installation.
93+
94+
If the error persist, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
95+
96+
## Contribute
97+
98+
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
99+
100+
If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome!
101+
102+
Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else.
103+
104+
## Resources
105+
106+
* Official ESP32 Forum: [Link](https://esp32.com)
107+
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
108+
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
109+
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
110+
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* Wi-Fi FTM Responder Arduino Example
2+
3+
This example code is in the Public Domain (or CC0 licensed, at your option.)
4+
5+
Unless required by applicable law or agreed to in writing, this
6+
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7+
CONDITIONS OF ANY KIND, either express or implied.
8+
*/
9+
#include "WiFi.h"
10+
// Change the SSID and PASSWORD here if needed
11+
const char * WIFI_FTM_SSID = "WiFi_FTM_Responder";
12+
const char * WIFI_FTM_PASS = "ftm_responder";
13+
14+
void setup() {
15+
Serial.begin(115200);
16+
Serial.println("Starting SoftAP with FTM Responder support");
17+
// Enable AP with FTM support (last argument is 'true')
18+
WiFi.softAP(WIFI_FTM_SSID, WIFI_FTM_PASS, 1, 0, 4, true);
19+
}
20+
21+
void loop() {
22+
delay(1000);
23+
}

Diff for: libraries/WiFi/examples/FTM/FTM_Responder/README.md

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Wi-Fi FTM Responder Arduino Example
2+
3+
This example demonstrates how to use the Fine Timing Measurement (FTM) to calculate the distace from the Access Point and the device. This is calculated by the Wi-Fi Round Trip Time (Wi-Fi RTT) introduced on the [IEEE Std 802.11-2016](https://en.wikipedia.org/wiki/IEEE_802.11mc) standard.
4+
5+
This example will simulate the Router with FTM capability.
6+
7+
This example was based on the [ESP-IDF FTM](https://github.com/espressif/esp-idf/tree/master/examples/wifi/ftm). See the README file for more details about on how to use this feature.
8+
9+
Some usages for this feature includes:
10+
11+
* Indoor positioning systems.
12+
* Navigation.
13+
* Device Location.
14+
* Smart Devices.
15+
* Alarms.
16+
17+
# Supported Targets
18+
19+
Currently, this example supports the following targets:
20+
21+
| Supported Targets | ESP32-S2 | ESP32-C3 |
22+
| ----------------- | -------- | -------- |
23+
24+
## How to Use Example
25+
26+
See the **Initiator** example to prepare the environment.
27+
28+
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
29+
30+
### Configure the Project
31+
32+
To configure this project, you can change the following configuration related to STA:
33+
34+
```c
35+
// Change the SSID and PASSWORD here if needed
36+
const char * WIFI_FTM_SSID = "WiFi_FTM_Responder";
37+
const char * WIFI_FTM_PASS = "ftm_responder";
38+
```
39+
40+
* Change the Wi-Fi `SSID` and `PASSWORD` as the same as the Initiator.
41+
42+
To see more details about FTM, please see the [ESP-IDF docs](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/network/esp_wifi.html).
43+
44+
#### Using Arduino IDE
45+
46+
To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits).
47+
48+
* Before Compile/Verify, select the correct board: `Tools -> Board`.
49+
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
50+
51+
#### Using Platform IO
52+
53+
* Select the COM port: `Devices` or setting the `upload_port` option on the `platformio.ini` file.
54+
55+
## Log Output
56+
57+
Expected log output:
58+
59+
```
60+
Build:Oct 25 2019
61+
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
62+
SPIWP:0xee
63+
mode:DIO, clock div:1
64+
load:0x3ffe6100,len:0x4b0
65+
load:0x4004c000,len:0xa6c
66+
load:0x40050000,len:0x25c4
67+
entry 0x4004c198
68+
Starting SoftAP with FTM Responder support
69+
```
70+
71+
## Troubleshooting
72+
73+
***Important: Make sure you are using a good quality USB cable and that you have a reliable power source.***
74+
75+
* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed.
76+
* **COM port not detected:** Check the USB cable and the USB to Serial driver installation.
77+
78+
If the error persist, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
79+
80+
## Contribute
81+
82+
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
83+
84+
If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome!
85+
86+
Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else.
87+
88+
## Resources
89+
90+
* Official ESP32 Forum: [Link](https://esp32.com)
91+
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
92+
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
93+
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
94+
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)

Diff for: libraries/WiFi/src/WiFiAP.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,22 @@ static bool softap_config_equal(const wifi_config_t& lhs, const wifi_config_t& r
8181
if(lhs.ap.pairwise_cipher != rhs.ap.pairwise_cipher) {
8282
return false;
8383
}
84+
if(lhs.ap.ftm_responder != rhs.ap.ftm_responder) {
85+
return false;
86+
}
8487
return true;
8588
}
8689

87-
void wifi_softap_config(wifi_config_t *wifi_config, const char * ssid=NULL, const char * password=NULL, uint8_t channel=6, wifi_auth_mode_t authmode=WIFI_AUTH_WPA2_PSK, uint8_t ssid_hidden=0, uint8_t max_connections=4, uint16_t beacon_interval=100){
88-
wifi_config->ap.channel = channel;
90+
void wifi_softap_config(wifi_config_t *wifi_config, const char * ssid=NULL, const char * password=NULL, uint8_t channel=6, wifi_auth_mode_t authmode=WIFI_AUTH_WPA2_PSK, uint8_t ssid_hidden=0, uint8_t max_connections=4, bool ftm_responder=false, uint16_t beacon_interval=100){
91+
wifi_config->ap.channel = channel;
8992
wifi_config->ap.max_connection = max_connections;
9093
wifi_config->ap.beacon_interval = beacon_interval;
9194
wifi_config->ap.ssid_hidden = ssid_hidden;
9295
wifi_config->ap.authmode = WIFI_AUTH_OPEN;
9396
wifi_config->ap.ssid_len = 0;
9497
wifi_config->ap.ssid[0] = 0;
9598
wifi_config->ap.password[0] = 0;
99+
wifi_config->ap.ftm_responder = ftm_responder;
96100
if(ssid != NULL && ssid[0] != 0){
97101
snprintf((char*)wifi_config->ap.ssid, 32, ssid);
98102
wifi_config->ap.ssid_len = strlen(ssid);
@@ -117,7 +121,7 @@ void wifi_softap_config(wifi_config_t *wifi_config, const char * ssid=NULL, cons
117121
* @param ssid_hidden Network cloaking (0 = broadcast SSID, 1 = hide SSID)
118122
* @param max_connection Max simultaneous connected clients, 1 - 4.
119123
*/
120-
bool WiFiAPClass::softAP(const char* ssid, const char* passphrase, int channel, int ssid_hidden, int max_connection)
124+
bool WiFiAPClass::softAP(const char* ssid, const char* passphrase, int channel, int ssid_hidden, int max_connection, bool ftm_responder)
121125
{
122126

123127
if(!WiFi.enableAP(true)) {
@@ -140,7 +144,7 @@ bool WiFiAPClass::softAP(const char* ssid, const char* passphrase, int channel,
140144

141145
wifi_config_t conf;
142146
wifi_config_t conf_current;
143-
wifi_softap_config(&conf, ssid, passphrase, channel, WIFI_AUTH_WPA2_PSK, ssid_hidden, max_connection);
147+
wifi_softap_config(&conf, ssid, passphrase, channel, WIFI_AUTH_WPA2_PSK, ssid_hidden, max_connection, ftm_responder);
144148
esp_err_t err = esp_wifi_get_config((wifi_interface_t)WIFI_IF_AP, &conf_current);
145149
if(err){
146150
log_e("get AP config failed");

Diff for: libraries/WiFi/src/WiFiAP.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class WiFiAPClass
3737

3838
public:
3939

40-
bool softAP(const char* ssid, const char* passphrase = NULL, int channel = 1, int ssid_hidden = 0, int max_connection = 4);
40+
bool softAP(const char* ssid, const char* passphrase = NULL, int channel = 1, int ssid_hidden = 0, int max_connection = 4, bool ftm_responder = false);
4141
bool softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet);
4242
bool softAPdisconnect(bool wifioff = false);
4343

0 commit comments

Comments
 (0)