This commit is contained in:
2026-05-22 21:52:50 +03:00
commit be7c60e4dd
1854 changed files with 583428 additions and 0 deletions
@@ -0,0 +1,91 @@
/* Wi-Fi FTM Initiator Arduino 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 "WiFi.h"
/*
THIS FEATURE IS SUPPORTED ONLY BY ESP32-S2 AND ESP32-C3
*/
// Change the SSID and PASSWORD here if needed
const char *WIFI_FTM_SSID = "WiFi_FTM_Responder"; // SSID of AP that has FTM Enabled
const char *WIFI_FTM_PASS = "ftm_responder"; // STA Password
// FTM settings
// Number of FTM frames requested in terms of 4 or 8 bursts (allowed values - 0 (No pref), 16, 24, 32, 64)
const uint8_t FTM_FRAME_COUNT = 16;
// Requested time period between consecutive FTM bursts in 100s of milliseconds (allowed values - 0 (No pref) or 2-255)
const uint16_t FTM_BURST_PERIOD = 2;
// Semaphore to signal when FTM Report has been received
SemaphoreHandle_t ftmSemaphore;
// Status of the received FTM Report
bool ftmSuccess = true;
// FTM report handler with the calculated data from the round trip
// WARNING: This function is called from a separate FreeRTOS task (thread)!
void onFtmReport(arduino_event_t *event) {
const char *status_str[5] = {"SUCCESS", "UNSUPPORTED", "CONF_REJECTED", "NO_RESPONSE", "FAIL"};
wifi_event_ftm_report_t *report = &event->event_info.wifi_ftm_report;
// Set the global report status
ftmSuccess = report->status == FTM_STATUS_SUCCESS;
if (ftmSuccess) {
// The estimated distance in meters may vary depending on some factors (see README file)
Serial.printf("FTM Estimate: Distance: %.2f m, Return Time: %lu ns\n", (float)report->dist_est / 100.0, report->rtt_est);
// Pointer to FTM Report with multiple entries, should be freed after use
free(report->ftm_report_data);
} else {
Serial.print("FTM Error: ");
Serial.println(status_str[report->status]);
}
// Signal that report is received
xSemaphoreGive(ftmSemaphore);
}
// Initiate FTM Session and wait for FTM Report
bool getFtmReport() {
if (!WiFi.initiateFTM(FTM_FRAME_COUNT, FTM_BURST_PERIOD)) {
Serial.println("FTM Error: Initiate Session Failed");
return false;
}
// Wait for signal that report is received and return true if status was success
return xSemaphoreTake(ftmSemaphore, portMAX_DELAY) == pdPASS && ftmSuccess;
}
void setup() {
Serial.begin(115200);
// Create binary semaphore (initialized taken and can be taken/given from any thread/ISR)
ftmSemaphore = xSemaphoreCreateBinary();
// Will call onFtmReport() from another thread with FTM Report events.
WiFi.onEvent(onFtmReport, ARDUINO_EVENT_WIFI_FTM_REPORT);
// Connect to AP that has FTM Enabled
Serial.println("Connecting to FTM Responder");
WiFi.begin(WIFI_FTM_SSID, WIFI_FTM_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi Connected");
Serial.print("Initiating FTM session with Frame Count ");
Serial.print(FTM_FRAME_COUNT);
Serial.print(" and Burst Period ");
Serial.print(FTM_BURST_PERIOD * 100);
Serial.println(" ms");
// Request FTM reports until one fails
while (getFtmReport());
}
void loop() {
delay(1000);
}
@@ -0,0 +1,106 @@
# Wi-Fi FTM Initiator Arduino Example
This example demonstrates how to use the Fine Timing Measurement (FTM) to calculate the distance 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.
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.
Some usages for this feature includes:
* Indoor positioning systems.
* Navigation.
* Device Location.
* Smart Devices.
* Alarms.
# Supported Targets
Currently, this example supports the following targets:
| Supported Targets | ESP32-S2 | ESP32-C3 |
| ----------------- | -------- | -------- |
## How to Use Example
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.
See the **Responder** example to prepare the environment.
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
### Configure the Project
To configure this project, you can change the following configuration related to FTM feature:
```c
// Change the SSID and PASSWORD here if needed
const char * WIFI_FTM_SSID = "WiFi_FTM_Responder"; // SSID of AP that has FTM Enabled
const char * WIFI_FTM_PASS = "ftm_responder"; // STA Password
// FTM settings
// Number of FTM frames requested in terms of 4 or 8 bursts (allowed values - 0 (No pref), 16, 24, 32, 64)
const uint8_t FTM_FRAME_COUNT = 16;
// Requested time period between consecutive FTM bursts in 100s of milliseconds (allowed values - 0 (No pref) or 2-255)
const uint16_t FTM_BURST_PERIOD = 2;
```
* Change the Wi-Fi `SSID` and `PASSWORD` as the same as the Responder/Router.
* Change `FTM_FRAME_COUNT` with the number of frames requested to the Responder.
* Change `FTM_BURST_PERIOD` with the time between each FTM burst.
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).
#### Using Arduino IDE
To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits).
* Before Compile/Verify, select the correct board: `Tools -> Board`.
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
## Log Output
Expected log output:
```
ESP-ROM:esp32s2-rc4-20191025
Build:Oct 25 2019
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3ffe6100,len:0x4b0
load:0x4004c000,len:0xa6c
load:0x40050000,len:0x25c4
entry 0x4004c198
Connecting to FTM Responder
.....
WiFi Connected
Initiating FTM session with Frame Count 16 and Burst Period 200 ms
FTM Estimate: Distance: 0.13 m, Return Time: 0 ns
FTM Estimate: Distance: 0.13 m, Return Time: 0 ns
FTM Estimate: Distance: 0.13 m, Return Time: 0 ns
FTM Estimate: Distance: 0.00 m, Return Time: 0 ns
...
```
## Troubleshooting
***Important: Make sure you are using a good quality USB cable and that you have a reliable power source.***
* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed.
* **COM port not detected:** Check the USB cable and the USB to Serial driver installation.
If the error persist, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
## Contribute
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
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!
Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else.
## Resources
* Official ESP32 Forum: [Link](https://esp32.com)
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,23 @@
/* Wi-Fi FTM Responder Arduino 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 "WiFi.h"
// Change the SSID and PASSWORD here if needed
const char *WIFI_FTM_SSID = "WiFi_FTM_Responder";
const char *WIFI_FTM_PASS = "ftm_responder";
void setup() {
Serial.begin(115200);
Serial.println("Starting SoftAP with FTM Responder support");
// Enable AP with FTM support (last argument is 'true')
WiFi.softAP(WIFI_FTM_SSID, WIFI_FTM_PASS, 1, 0, 4, true);
}
void loop() {
delay(1000);
}
@@ -0,0 +1,90 @@
# Wi-Fi FTM Responder Arduino Example
This example demonstrates how to use the Fine Timing Measurement (FTM) to calculate the distance 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.
This example will simulate the Router with FTM capability.
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.
Some usages for this feature includes:
* Indoor positioning systems.
* Navigation.
* Device Location.
* Smart Devices.
* Alarms.
# Supported Targets
Currently, this example supports the following targets:
| Supported Targets | ESP32-S2 | ESP32-C3 |
| ----------------- | -------- | -------- |
## How to Use Example
See the **Initiator** example to prepare the environment.
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
### Configure the Project
To configure this project, you can change the following configuration related to STA:
```c
// Change the SSID and PASSWORD here if needed
const char * WIFI_FTM_SSID = "WiFi_FTM_Responder";
const char * WIFI_FTM_PASS = "ftm_responder";
```
* Change the Wi-Fi `SSID` and `PASSWORD` as the same as the Initiator.
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).
#### Using Arduino IDE
To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits).
* Before Compile/Verify, select the correct board: `Tools -> Board`.
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
## Log Output
Expected log output:
```
Build:Oct 25 2019
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3ffe6100,len:0x4b0
load:0x4004c000,len:0xa6c
load:0x40050000,len:0x25c4
entry 0x4004c198
Starting SoftAP with FTM Responder support
```
## Troubleshooting
***Important: Make sure you are using a good quality USB cable and that you have a reliable power source.***
* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed.
* **COM port not detected:** Check the USB cable and the USB to Serial driver installation.
If the error persist, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
## Contribute
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
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!
Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else.
## Resources
* Official ESP32 Forum: [Link](https://esp32.com)
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,112 @@
/*
WiFi Web Server LED Blink
A simple web server that lets you blink an LED via the web.
This sketch will print the IP address of your WiFi Shield (once connected)
to the Serial monitor. From there, you can open that address in a web browser
to turn on and off the LED on pin 5.
If the IP address of your shield is yourAddress:
http://yourAddress/H turns the LED on
http://yourAddress/L turns it off
This example is written for a network using WPA2 encryption. For insecure
WEP or WPA, change the Wifi.begin() call and use Wifi.setMinSecurity() accordingly.
Circuit:
* WiFi shield attached
* LED attached to pin 5
created for arduino 25 Nov 2012
by Tom Igoe
ported for sparkfun esp32
31.01.2017 by Jan Hendrik Berlin
*/
#include <WiFi.h>
const char *ssid = "yourssid";
const char *password = "yourpasswd";
NetworkServer server(80);
void setup() {
Serial.begin(115200);
pinMode(5, OUTPUT); // set the LED pin mode
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
void loop() {
NetworkClient client = server.accept(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("New Client."); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("Click <a href=\"/H\">here</a> to turn the LED on pin 5 on.<br>");
client.print("Click <a href=\"/L\">here</a> to turn the LED on pin 5 off.<br>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
digitalWrite(5, HIGH); // GET /H turns the LED on
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(5, LOW); // GET /L turns the LED off
}
}
}
// close the connection:
client.stop();
Serial.println("Client Disconnected.");
}
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
+104
View File
@@ -0,0 +1,104 @@
Example Serial Logs For Various Cases
======================================
For WPS Push Button method,after the ESP32 boots up and prints that WPS has started, press the button that looks something like [this](https://www.verizon.com/supportresources/images/fqgrouter-frontview-wps-button.png) on your router. In case you dont find anything similar, check your router specs if it does really support WPS Push functionality.
As for WPS Pin Mode, it will output a 8 digit Pin on the Serial Monitor that will change every 2 minutes if it hasn't connected. You need to log in to your router (generally reaching 192.168.0.1) and enter the pin shown in Serial Monitor in the WPS Settings of your router.
#### WPS Push Button Failure
```
ets Jun 8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0010,len:4
load:0x3fff0014,len:732
load:0x40078000,len:0
load:0x40078000,len:11572
entry 0x40078a14
Starting WPS
Station Mode Started
WPS Timedout, retrying
WPS Timedout, retrying
```
#### WPS Push Button Successful
```
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
ets Jun 8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0010,len:4
load:0x3fff0014,len:732
load:0x40078000,len:0
load:0x40078000,len:11572
entry 0x40078a14
Starting WPS
Station Mode Started
WPS Successful, stopping WPS and connecting to: < Your Router SSID >
Disconnected from station, attempting reconnection
Connected to : < Your Router SSID >
Got IP: 192.168.1.100
```
#### WPS PIN Failure
```
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
ets Jun 8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0010,len:4
load:0x3fff0014,len:732
load:0x40078000,len:0
load:0x40078000,len:11572
entry 0x40078a14
Starting WPS
Station Mode Started
WPS_PIN = 94842104
WPS Timedout, retrying
WPS_PIN = 55814171
WPS Timedout, retrying
WPS_PIN = 71321622
```
#### WPS PIN Successful
```
ets Jun 8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0010,len:4
load:0x3fff0014,len:732
load:0x40078000,len:0
load:0x40078000,len:11572
entry 0x40078a14
Starting WPS
Station Mode Started
WPS_PIN = 36807581
WPS Successful, stopping WPS and connecting to: <Your Router SSID>
Disconnected from station, attempting reconnection
Connected to :<Your Router SSID>
Got IP: 192.168.1.100
```
+116
View File
@@ -0,0 +1,116 @@
/*
Example Code To Get ESP32 To Connect To A Router Using WPS
===========================================================
This example code provides both Push Button method and Pin
based WPS entry to get your ESP connected to your WiFi router.
Hardware Requirements
========================
ESP32 and a Router having WPS functionality
This code is under Public Domain License.
Author:
Pranav Cherukupalli <cherukupallip@gmail.com>
*/
#include "sdkconfig.h"
#if CONFIG_ESP_WIFI_REMOTE_ENABLED
#error "WPS is only supported in SoCs with native Wi-Fi support"
#endif
#include "WiFi.h"
#include "esp_wps.h"
/*
Change the definition of the WPS mode
from WPS_TYPE_PBC to WPS_TYPE_PIN in
the case that you are using pin type
WPS (pin is 00000000)
*/
#define ESP_WPS_MODE WPS_TYPE_PBC
void wpsStart() {
esp_wps_config_t config;
memset(&config, 0, sizeof(esp_wps_config_t));
//Same as config = WPS_CONFIG_INIT_DEFAULT(ESP_WPS_MODE);
config.wps_type = ESP_WPS_MODE;
strcpy(config.factory_info.manufacturer, "ESPRESSIF");
strcpy(config.factory_info.model_number, CONFIG_IDF_TARGET);
strcpy(config.factory_info.model_name, "ESPRESSIF IOT");
strcpy(config.factory_info.device_name, "ESP DEVICE");
strcpy(config.pin, "00000000");
esp_err_t err = esp_wifi_wps_enable(&config);
if (err != ESP_OK) {
Serial.printf("WPS Enable Failed: 0x%x: %s\n", err, esp_err_to_name(err));
return;
}
err = esp_wifi_wps_start(0);
if (err != ESP_OK) {
Serial.printf("WPS Start Failed: 0x%x: %s\n", err, esp_err_to_name(err));
}
}
void wpsStop() {
esp_err_t err = esp_wifi_wps_disable();
if (err != ESP_OK) {
Serial.printf("WPS Disable Failed: 0x%x: %s\n", err, esp_err_to_name(err));
}
}
String wpspin2string(uint8_t a[]) {
char wps_pin[9];
for (int i = 0; i < 8; i++) {
wps_pin[i] = a[i];
}
wps_pin[8] = '\0';
return (String)wps_pin;
}
// WARNING: WiFiEvent is called from a separate FreeRTOS task (thread)!
void WiFiEvent(WiFiEvent_t event, arduino_event_info_t info) {
switch (event) {
case ARDUINO_EVENT_WIFI_STA_START: Serial.println("Station Mode Started"); break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.println("Connected to :" + String(WiFi.SSID()));
Serial.print("Got IP: ");
Serial.println(WiFi.localIP());
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
Serial.println("Disconnected from station, attempting reconnection");
WiFi.reconnect();
break;
case ARDUINO_EVENT_WPS_ER_SUCCESS:
Serial.println("WPS Successful, stopping WPS and connecting to: " + String(WiFi.SSID()));
wpsStop();
delay(10);
WiFi.begin();
break;
case ARDUINO_EVENT_WPS_ER_FAILED:
Serial.println("WPS Failed, retrying");
wpsStop();
wpsStart();
break;
case ARDUINO_EVENT_WPS_ER_TIMEOUT:
Serial.println("WPS Timedout, retrying");
wpsStop();
wpsStart();
break;
case ARDUINO_EVENT_WPS_ER_PIN: Serial.println("WPS_PIN = " + wpspin2string(info.wps_er_pin.pin_code)); break;
default: break;
}
}
void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread.
WiFi.mode(WIFI_MODE_STA);
Serial.println("Starting WPS");
wpsStart();
}
void loop() {
//nothing to do here
}
+2
View File
@@ -0,0 +1,2 @@
requires:
- CONFIG_SOC_WIFI_SUPPORTED=y
@@ -0,0 +1,98 @@
/*
WiFiAccessPoint.ino creates a WiFi access point and provides a web server on it.
Steps:
1. Connect to the access point "yourAp"
2. Point your web browser to http://192.168.4.1/H to turn the LED on or http://192.168.4.1/L to turn it off
OR
Run raw TCP "GET /H" and "GET /L" on PuTTY terminal with 192.168.4.1 as IP address and 80 as port
Created for arduino-esp32 on 04 July, 2018
by Elochukwu Ifediora (fedy0)
*/
#include <WiFi.h>
#include <NetworkClient.h>
#include <WiFiAP.h>
#ifndef LED_BUILTIN
#define LED_BUILTIN 2 // Set the GPIO pin where you connected your test LED or comment this line out if your dev board has a built-in LED
#endif
// Set these to your desired credentials.
const char *ssid = "yourAP";
const char *password = "yourPassword";
NetworkServer server(80);
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
Serial.println();
Serial.println("Configuring access point...");
// You can remove the password parameter if you want the AP to be open.
// a valid password must have more than 7 characters
if (!WiFi.softAP(ssid, password)) {
log_e("Soft AP creation failed.");
while (1);
}
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.begin();
Serial.println("Server started");
}
void loop() {
NetworkClient client = server.accept(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("New Client."); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("Click <a href=\"/H\">here</a> to turn ON the LED.<br>");
client.print("Click <a href=\"/L\">here</a> to turn OFF the LED.<br>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
digitalWrite(LED_BUILTIN, HIGH); // GET /H turns the LED on
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(LED_BUILTIN, LOW); // GET /L turns the LED off
}
}
}
// close the connection:
client.stop();
Serial.println("Client Disconnected.");
}
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,133 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Sketch shows how to switch between WiFi and BlueTooth or use both
// Button is attached between GPIO 0 and GND and modes are switched with each press
#include "soc/soc_caps.h"
#if !CONFIG_SOC_BT_SUPPORTED
#error "This example requires native Bluetooth support"
#endif
#include "WiFi.h"
#define STA_SSID "your-ssid"
#define STA_PASS "your-pass"
#define AP_SSID "esp32"
enum {
STEP_BTON,
STEP_BTOFF,
STEP_STA,
STEP_AP,
STEP_AP_STA,
STEP_OFF,
STEP_BT_STA,
STEP_END
};
void onButton() {
static uint32_t step = STEP_BTON;
switch (step) {
case STEP_BTON: //BT Only
Serial.println("** Starting BT");
btStart();
break;
case STEP_BTOFF: //All Off
Serial.println("** Stopping BT");
btStop();
break;
case STEP_STA: //STA Only
Serial.println("** Starting STA");
WiFi.begin(STA_SSID, STA_PASS);
break;
case STEP_AP: //AP Only
Serial.println("** Stopping STA");
WiFi.mode(WIFI_AP);
Serial.println("** Starting AP");
WiFi.softAP(AP_SSID);
break;
case STEP_AP_STA: //AP+STA
Serial.println("** Starting STA");
WiFi.begin(STA_SSID, STA_PASS);
break;
case STEP_OFF: //All Off
Serial.println("** Stopping WiFi");
WiFi.mode(WIFI_OFF);
break;
case STEP_BT_STA: //BT+STA
Serial.println("** Starting STA+BT");
WiFi.begin(STA_SSID, STA_PASS);
btStart();
break;
case STEP_END: //All Off
Serial.println("** Stopping WiFi+BT");
WiFi.mode(WIFI_OFF);
btStop();
break;
default: break;
}
if (step == STEP_END) {
step = STEP_BTON;
} else {
step++;
}
//little debounce
delay(100);
}
// WARNING: WiFiEvent is called from a separate FreeRTOS task (thread)!
void WiFiEvent(WiFiEvent_t event) {
switch (event) {
case ARDUINO_EVENT_WIFI_AP_START:
Serial.println("AP Started");
WiFi.softAPsetHostname(AP_SSID);
break;
case ARDUINO_EVENT_WIFI_AP_STOP: Serial.println("AP Stopped"); break;
case ARDUINO_EVENT_WIFI_STA_START:
Serial.println("STA Started");
WiFi.setHostname(AP_SSID);
break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("STA Connected"); break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
Serial.print("STA IPv6: ");
Serial.println(WiFi.linkLocalIPv6());
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.print("STA IPv4: ");
Serial.println(WiFi.localIP());
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: Serial.println("STA Disconnected"); break;
case ARDUINO_EVENT_WIFI_STA_STOP: Serial.println("STA Stopped"); break;
default: break;
}
}
void setup() {
Serial.begin(115200);
pinMode(0, INPUT_PULLUP);
WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread.
WiFi.enableIPv6();
Serial.print("ESP32 SDK: ");
Serial.println(ESP.getSdkVersion());
Serial.println("Press the button to select the next mode");
}
void loop() {
static uint8_t lastPinState = 1;
uint8_t pinState = digitalRead(0);
if (!pinState && lastPinState) {
onButton();
}
lastPinState = pinState;
}
@@ -0,0 +1,6 @@
requires:
- CONFIG_SOC_BT_SUPPORTED=y
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,161 @@
# NetworkClient
This example demonstrates reading and writing data from and to a web service which can be used for logging data, creating insights and taking actions based on those data.
# Supported Targets
Currently, this example supports all SoC with Wi-Fi.
| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 |
## How to Use Example
Flash this example and observe the serial output. You can also take a look at the values at [https://thingspeak.com/channels/2005329](https://thingspeak.com/channels/2005329)
Please note that this public channel can be accessed by anyone and it is possible that more people will write their values.
### Configure the Project
Change `SSID` and `password` to connect to your Wi-Fi.
Default values will allow you to use this example without any changes. If you want to use your own channel and you don't have one already follow these steps:
* Create an account on [thingspeak.com](https://www.thingspeak.com).
* After logging in, click on the "New Channel" button to create a new channel for your data. This is where your data will be stored and displayed.
* Fill in the Name, Description, and other fields for your channel as desired, then click the "Save Channel" button.
* Take note of the "Write API Key" located in the "API keys" tab, this is the key you will use to send data to your channel.
* Replace the channelID from tab "Channel Settings" and privateKey with "Read API Keys" from "API Keys" tab.
* Replace the host variable with the thingspeak server hostname "api.thingspeak.com"
* Upload the sketch to your ESP32 board and make sure that the board is connected to the internet. The ESP32 should now send data to your Thingspeak channel at the intervals specified by the loop function.
* Go to the channel view page on thingspeak and check the "Field1" for the new incoming data.
* You can use the data visualization and analysis tools provided by Thingspeak to display and process your data in various ways.
* Please note, that Thingspeak accepts only integer values.
#### Config example:
You can find the data to be changed at the top of the file:
```cpp
const char* ssid = "your-ssid"; // Change this to your WiFi SSID
const char* password = "your-password"; // Change this to your WiFi password
const char* host = "api.thingspeak.com"; // This should not be changed
const int httpPort = 80; // This should not be changed
const String channelID = "2005329"; // Change this to your channel ID
const String writeApiKey = "V6YOTILH9I7D51F9"; // Change this to your Write API key
const String readApiKey = "34W6LGLIFXD56MPM"; // Change this to your Read API key
// The default example accepts one data filed named "field1"
// For your own server you can ofcourse create more of them.
int field1 = 0;
int numberOfResults = 3; // Number of results to be read
int fieldNumber = 1; // Field number which will be read out
```
#### Using Arduino IDE
To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits).
* Before Compile/Verify, select the correct board: `Tools -> Board`.
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
## Example Log Output
The initial output which is common for all examples can be ignored:
```
SP-ROM:esp32c3-api1-20210207
Build:Feb 7 2021
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5810,len:0x438
load:0x403cc710,len:0x918
load:0x403ce710,len:0x24e4
entry 0x403cc710
```
Follows the setup output where connection to your Wi-Fi happens:
```
******************************************************
Connecting to your-ssid
.
WiFi connected
IP address:
192.168.1.2
```
Then you can see the write log:
```
HTTP/1.1 200 OK
Date: Fri, 13 Jan 2023 13:12:31 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 1
Connection: close
Status: 200 OK
Cache-Control: max-age=0, private, must-revalidate
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 1800
X-Request-Id: 188e3464-f155-44b0-96f6-0f3614170bb0
Access-Control-Allow-Headers: origin, content-type, X-Requested-With
Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS, DELETE, PATCH
ETag: W/"5feceb66ffc86f38d952786c6d696c79"
X-Frame-Options: SAMEORIGIN
0
Closing connection
```
Last portion is the read log:
```
HTTP/1.1 200 OK
Date: Fri, 13 Jan 2023 13:12:32 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: close
Status: 200 OK
Cache-Control: max-age=7, private
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 1800
X-Request-Id: 91b97016-7625-44f6-9797-1b2973aa57b7
Access-Control-Allow-Headers: origin, content-type, X-Requested-With
Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS, DELETE, PATCH
ETag: W/"8e9c308fe2c50309f991586be1aff28d"
X-Frame-Options: SAMEORIGIN
1e3
{"channel":{"id":2005329,"name":"WiFiCLient example","description":"Default setup for Arduino ESP32 NetworkClient example","latitude":"0.0","longitude":"0.0","field1":"data0","created_at":"2023-01-11T15:56:08Z","updated_at":"2023-01-13T08:13:58Z","last_entry_id":2871},"feeds":[{"created_at":"2023-01-13T13:11:30Z","entry_id":2869,"field1":"359"},{"created_at":"2023-01-13T13:11:57Z","entry_id":2870,"field1":"361"},{"created_at":"2023-01-13T13:12:23Z","entry_id":2871,"field1":"363"}]}
0
Closing connection
```
After this the write+read log repeat every 10 seconds.
## Troubleshooting
***Important: Make sure you are using a good quality USB cable and that you have a reliable power source***
* **Wi-Fi not connected:** Check the SSID and password and also that the signal has sufficient strength.
* **400 Bad Request:** Check the writeApiKey.
* **404 Not Found:** Check the channel ID.
* **No data on chart / reading NULL:** Data must be sent as an integer, without commas.
If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
## Contribute
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
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!
Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else.
## Resources
* Official ESP32 Forum: [Link](https://esp32.com)
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf)
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
@@ -0,0 +1,105 @@
/*
Go to thingspeak.com and create an account if you don't have one already.
After logging in, click on the "New Channel" button to create a new channel for your data. This is where your data will be stored and displayed.
Fill in the Name, Description, and other fields for your channel as desired, then click the "Save Channel" button.
Take note of the "Write API Key" located in the "API keys" tab, this is the key you will use to send data to your channel.
Replace the channelID from tab "Channel Settings" and privateKey with "Read API Keys" from "API Keys" tab.
Replace the host variable with the thingspeak server hostname "api.thingspeak.com"
Upload the sketch to your ESP32 board and make sure that the board is connected to the internet. The ESP32 should now send data to your Thingspeak channel at the intervals specified by the loop function.
Go to the channel view page on thingspeak and check the "Field1" for the new incoming data.
You can use the data visualization and analysis tools provided by Thingspeak to display and process your data in various ways.
Please note, that Thingspeak accepts only integer values.
You can later check the values at https://thingspeak.com/channels/2005329
Please note that this public channel can be accessed by anyone and it is possible that more people will write their values.
*/
#include <WiFi.h>
const char *ssid = "your-ssid"; // Change this to your WiFi SSID
const char *password = "your-password"; // Change this to your WiFi password
const char *host = "api.thingspeak.com"; // This should not be changed
const int httpPort = 80; // This should not be changed
const String channelID = "2005329"; // Change this to your channel ID
const String writeApiKey = "V6YOTILH9I7D51F9"; // Change this to your Write API key
const String readApiKey = "34W6LGLIFXD56MPM"; // Change this to your Read API key
// The default example accepts one data filed named "field1"
// For your own server you can ofcourse create more of them.
int field1 = 0;
int numberOfResults = 3; // Number of results to be read
int fieldNumber = 1; // Field number which will be read out
void setup() {
Serial.begin(115200);
// We start by connecting to a WiFi network
Serial.println();
Serial.println("******************************************************");
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void readResponse(NetworkClient *client) {
unsigned long timeout = millis();
while (client->available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client->stop();
return;
}
}
// Read all the lines of the reply from server and print them to Serial
while (client->available()) {
String line = client->readStringUntil('\r');
Serial.print(line);
}
Serial.printf("\nClosing connection\n\n");
}
void loop() {
NetworkClient client;
String footer = String(" HTTP/1.1\r\n") + "Host: " + String(host) + "\r\n" + "Connection: close\r\n\r\n";
// WRITE --------------------------------------------------------------------------------------------
if (!client.connect(host, httpPort)) {
return;
}
client.print("GET /update?api_key=" + writeApiKey + "&field1=" + field1 + footer);
readResponse(&client);
// READ --------------------------------------------------------------------------------------------
String readRequest = "GET /channels/" + channelID + "/fields/" + fieldNumber + ".json?results=" + numberOfResults + " HTTP/1.1\r\n" + "Host: " + host + "\r\n"
+ "Connection: close\r\n\r\n";
if (!client.connect(host, httpPort)) {
return;
}
client.print(readRequest);
readResponse(&client);
// -------------------------------------------------------------------------------------------------
++field1;
delay(10000);
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,80 @@
/*
* This sketch sends a message to a TCP server
*
*/
#include <WiFi.h>
#include <WiFiMulti.h>
WiFiMulti WiFiMulti;
void setup() {
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
WiFiMulti.addAP("SSID", "passpasspass");
Serial.println();
Serial.println();
Serial.print("Waiting for WiFi... ");
while (WiFiMulti.run() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
delay(500);
}
void loop() {
// const uint16_t port = 80;
// const char * host = "192.168.1.1"; // ip or dns
const uint16_t port = 1337;
const char *host = "192.168.1.10"; // ip or dns
Serial.print("Connecting to ");
Serial.println(host);
// Use NetworkClient class to create TCP connections
NetworkClient client;
if (!client.connect(host, port)) {
Serial.println("Connection failed.");
Serial.println("Waiting 5 seconds before retrying...");
delay(5000);
return;
}
// This will send a request to the server
//uncomment this line to send an arbitrary string to the server
//client.print("Send this data to the server");
//uncomment this line to send a basic document request to the server
client.print("GET /index.html HTTP/1.1\n\n");
int maxloops = 0;
//wait for the server's reply to become available
while (!client.available() && maxloops < 1000) {
maxloops++;
delay(1); //delay 1 msec
}
if (client.available() > 0) {
//read back one line from the server
String line = client.readStringUntil('\r');
Serial.println(line);
} else {
Serial.println("client.available() timed out ");
}
Serial.println("Closing connection.");
client.stop();
Serial.println("Waiting 5 seconds before restarting...");
delay(5000);
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,71 @@
# NetworkClientConnect Example
This example demonstrates how to connect to the Wi-Fi and manage the status and disconnection from STA.
# Supported Targets
Currently, this example supports the following targets.
| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 |
| ----------------- | ----- | -------- | -------- |
## How to Use Example
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
#### Using Arduino IDE
* Before Compile/Verify, select the correct board: `Tools -> Board`.
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
## Example/Log Output
```
[WiFi] Connecting to MyWiFiNetwork
[ 66][D][WiFiGeneric.cpp:929] _eventCallback(): Arduino Event: 0 - WIFI_READY
[ 150][V][WiFiGeneric.cpp:338] _arduino_event_cb(): STA Started
[ 151][V][WiFiGeneric.cpp:97] set_esp_interface_ip(): Configuring Station static IP: 0.0.0.0, MASK: 0.0.0.0, GW: 0.0.0.0
[ 151][D][WiFiGeneric.cpp:929] _eventCallback(): Arduino Event: 2 - STA_START
[WiFi] WiFi is disconnected
[ 234][V][WiFiGeneric.cpp:353] _arduino_event_cb(): STA Connected: SSID: MyWiFiNetwork, BSSID: xx:xx:xx:xx:xx:xx, Channel: 8, Auth: WPA2_PSK
[ 235][D][WiFiGeneric.cpp:929] _eventCallback(): Arduino Event: 4 - STA_CONNECTED
[ 560][V][WiFiGeneric.cpp:367] _arduino_event_cb(): STA Got New IP:192.168.68.114
[ 561][D][WiFiGeneric.cpp:929] _eventCallback(): Arduino Event: 7 - STA_GOT_IP
[ 564][D][WiFiGeneric.cpp:1004] _eventCallback(): STA IP: 192.168.68.114, MASK: 255.255.255.0, GW: 192.168.68.1
[WiFi] WiFi is connected!
[WiFi] IP address: 192.168.68.114
[WiFi] Disconnecting from WiFi!
[ 2633][V][WiFiGeneric.cpp:360] _arduino_event_cb(): STA Disconnected: SSID: MyWiFiNetwork, BSSID: xx:xx:xx:xx:xx:xx, Reason: 8
[ 2634][D][WiFiGeneric.cpp:929] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[ 2635][V][WiFiGeneric.cpp:341] _arduino_event_cb(): STA Stopped
[ 2641][W][WiFiGeneric.cpp:953] _eventCallback(): Reason: 8 - ASSOC_LEAVE
[ 2654][D][WiFiGeneric.cpp:975] _eventCallback(): WiFi the station is disconnected
[ 2661][D][WiFiGeneric.cpp:929] _eventCallback(): Arduino Event: 3 - STA_STOP
[WiFi] Disconnected from WiFi!
...
```
## Troubleshooting
***Important: Be sure you're using a good quality USB cable that has enough power for your project.***
* **Programming Fail:** If the programming/flash procedure fails, try to reduce the serial connection speed.
* **COM port not detected:** Check the USB cable connection and the USB to Serial driver installation.
If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
## Contribute
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
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!
Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else.
## Resources
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
@@ -0,0 +1,90 @@
/* Wi-Fi STA Connect and Disconnect 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 <WiFi.h>
const char *ssid = "your-ssid";
const char *password = "your-password";
int btnGPIO = 0;
int btnState = false;
void setup() {
Serial.begin(115200);
delay(10);
// Set GPIO0 Boot button as input
pinMode(btnGPIO, INPUT);
// We start by connecting to a WiFi network
// To debug, please enable Core Debug Level to Verbose
Serial.println();
Serial.print("[WiFi] Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// Auto reconnect is set true as default
// To set auto connect off, use the following function
// WiFi.setAutoReconnect(false);
// Will try for about 10 seconds (20x 500ms)
int tryDelay = 500;
int numberOfTries = 20;
// Wait for the WiFi event
while (true) {
switch (WiFi.status()) {
case WL_NO_SSID_AVAIL: Serial.println("[WiFi] SSID not found"); break;
case WL_CONNECT_FAILED:
Serial.print("[WiFi] Failed - WiFi not connected! Reason: ");
return;
break;
case WL_CONNECTION_LOST: Serial.println("[WiFi] Connection was lost"); break;
case WL_SCAN_COMPLETED: Serial.println("[WiFi] Scan is completed"); break;
case WL_DISCONNECTED: Serial.println("[WiFi] WiFi is disconnected"); break;
case WL_CONNECTED:
Serial.println("[WiFi] WiFi is connected!");
Serial.print("[WiFi] IP address: ");
Serial.println(WiFi.localIP());
return;
break;
default:
Serial.print("[WiFi] WiFi Status: ");
Serial.println(WiFi.status());
break;
}
delay(tryDelay);
if (numberOfTries <= 0) {
Serial.print("[WiFi] Failed to connect to WiFi!");
// Use disconnect function to force stop trying to connect
WiFi.disconnect();
return;
} else {
numberOfTries--;
}
}
}
void loop() {
// Read the button state
btnState = digitalRead(btnGPIO);
if (btnState == LOW) {
// Disconnect from WiFi
Serial.println("[WiFi] Disconnecting from WiFi!");
// This function will disconnect and turn off the WiFi (NVS WiFi data is kept)
if (WiFi.disconnect(true, false)) {
Serial.println("[WiFi] Disconnected from WiFi!");
}
delay(1000);
}
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,45 @@
# ESP32-Eduroam
* Eduroam Wi-Fi connection with university login identity
* Working under Eduroam networks worldwide
* Methods: PEAP + MsCHAPv2
# Format
* IDENTITY = youridentity --> if connecting from different university, use youridentity@youruniversity.domain format
* PASSWORD = yourpassword
# Usage
* Change IDENTITY
* Change password
* Upload sketch and enjoy!
* After successful assign of IP address, board will connect to HTTP page on internet to verify your authentication
* Board will auto reconnect to Eduroam if it lost connection
# Tested locations
<!-- vale off -->
|University|Board|Method|Result|
|-------------|-------------| -----|------|
|Technical University in Košice (Slovakia)|ESP32 Devkit v1|PEAP + MsCHAPv2|Working|
|Technical University in Košice (Slovakia)|ESP32 Devmodule v4|PEAP + MsCHAPv2|Working on 6th attempt in loop|
|Slovak Technical University in Bratislava (Slovakia)|ESP32 Devkit v1|PEAP + MsCHAPv2|Working|
|University of Antwerp (Belgium)|Lolin32|PEAP + MsCHAPv2|Working|
|UPV Universitat Politècnica de València (Spain)|ESP32 Devmodule v4|PEAP + MsCHAPv2|Working|
|Local Zeroshell powered network|ESP32 Devkit v1|PEAP + MsCHAPv2|*Not working*|
|Hasselt University (Belgium)|xxx|PEAP + MsCHAPv2|Working with fix sketch|
|Universidad de Granada (Spain)|Lolin D32 Pro|PEAP + MsCHAPv2|Working|
|Universidad de Granada (Spain)|Lolin D32|PEAP + MsCHAPv2|Working|
|Universidade Federal de Santa Catarina (Brazil)|xxx|EAP-TTLS + MsCHAPv2|Working|
|University of Central Florida (Orlando, Florida)|ESP32 Built-in OLED Heltec WiFi Kit 32|PEAP + MsCHAPv2|Working|
|Université de Montpellier (France)|NodeMCU-32S|PEAP + MsCHAPv2|Working|
<!-- vale on -->
# Common errors - Switch to Debug mode for Serial monitor prints
|Error|Appearance|Solution|
|-------------|-------------|-------------|
|Wi-Fi: Set status to INIT|Frequent|Hold EN button for few seconds|
|HANDSHAKE_TIMEOUT|Rare|Bug was found under Zeroshell RADIUS authentization - Unsuccessful connection|
|AUTH_EXPIRE|Common|In the case of weak Wi-Fi network signal, this error is quite common, bring your device closer to AP|
|ASSOC_EXPIRE|Rare|-|
# Successful connection example
![alt text](https://i.nahraj.to/f/24Kc.png)
# Unsuccessful connection example
![alt text](https://camo.githubusercontent.com/87e47d1b27f4e8ace87423e40e8edbce7983bafa/68747470733a2f2f692e6e616872616a2e746f2f662f323435572e504e47)
@@ -0,0 +1,89 @@
#include "sdkconfig.h"
#if CONFIG_ESP_WIFI_REMOTE_ENABLED
#error "WPA-Enterprise is only supported in SoCs with native Wi-Fi support"
#endif
#include <WiFi.h> //Wifi library
#define EAP_IDENTITY "login" //if connecting from another corporation, use identity@organization.domain in Eduroam
#define EAP_USERNAME "login" //oftentimes just a repeat of the identity
#define EAP_PASSWORD "password" //your Eduroam password
const char *ssid = "eduroam"; // Eduroam SSID
const char *host = "arduino.php5.sk"; //external server domain for HTTP connection after authentication
int counter = 0;
// NOTE: For some systems, various certification keys are required to connect to the wifi system.
// Usually you are provided these by the IT department of your organization when certs are required
// and you can't connect with just an identity and password.
// Most eduroam setups we have seen do not require this level of authentication, but you should contact
// your IT department to verify.
// You should uncomment these and populate with the contents of the files if this is required for your scenario (See Example 2 and Example 3 below).
//const char *ca_pem = "insert your CA cert from your .pem file here";
//const char *client_cert = "insert your client cert from your .crt file here";
//const char *client_key = "insert your client key from your .key file here";
void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
Serial.print("Connecting to network: ");
Serial.println(ssid);
WiFi.disconnect(true); //disconnect form wifi to set new wifi connection
WiFi.mode(WIFI_STA); //init wifi mode
// Example1 (most common): a cert-file-free eduroam with PEAP (or TTLS)
WiFi.begin(ssid, WPA2_AUTH_PEAP, EAP_IDENTITY, EAP_USERNAME, EAP_PASSWORD);
// Example 2: a cert-file WPA2 Enterprise with PEAP
//WiFi.begin(ssid, WPA2_AUTH_PEAP, EAP_IDENTITY, EAP_USERNAME, EAP_PASSWORD, ca_pem, client_cert, client_key);
// Example 3: TLS with cert-files and no password
//WiFi.begin(ssid, WPA2_AUTH_TLS, EAP_IDENTITY, NULL, NULL, ca_pem, client_cert, client_key);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
counter++;
if (counter >= 60) { //after 30 seconds timeout - reset board
ESP.restart();
}
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address set: ");
Serial.println(WiFi.localIP()); //print LAN IP
}
void loop() {
if (WiFi.status() == WL_CONNECTED) { //if we are connected to Eduroam network
counter = 0; //reset counter
Serial.println("Wifi is still connected with IP: ");
Serial.println(WiFi.localIP()); //inform user about his IP address
} else if (WiFi.status() != WL_CONNECTED) { //if we lost connection, retry
WiFi.begin(ssid);
}
while (WiFi.status() != WL_CONNECTED) { //during lost connection, print dots
delay(500);
Serial.print(".");
counter++;
if (counter >= 60) { //30 seconds timeout - reset board
ESP.restart();
}
}
Serial.print("Connecting to website: ");
Serial.println(host);
NetworkClient client;
if (client.connect(host, 80)) {
String url = "/rele/rele1.txt";
client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: ESP32\r\n" + "Connection: close\r\n\r\n");
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") {
break;
}
}
String line = client.readStringUntil('\n');
Serial.println(line);
} else {
Serial.println("Connection unsuccessful");
}
}
@@ -0,0 +1,2 @@
requires:
- CONFIG_SOC_WIFI_SUPPORTED=y
@@ -0,0 +1,124 @@
/*
* This sketch shows the WiFi event usage
*
*/
/*
* WiFi Events
0 ARDUINO_EVENT_WIFI_READY < ESP32 WiFi ready
1 ARDUINO_EVENT_WIFI_SCAN_DONE < ESP32 finish scanning AP
2 ARDUINO_EVENT_WIFI_STA_START < ESP32 station start
3 ARDUINO_EVENT_WIFI_STA_STOP < ESP32 station stop
4 ARDUINO_EVENT_WIFI_STA_CONNECTED < ESP32 station connected to AP
5 ARDUINO_EVENT_WIFI_STA_DISCONNECTED < ESP32 station disconnected from AP
6 ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE < the auth mode of AP connected by ESP32 station changed
7 ARDUINO_EVENT_WIFI_STA_GOT_IP < ESP32 station got IP from connected AP
8 ARDUINO_EVENT_WIFI_STA_LOST_IP < ESP32 station lost IP and the IP is reset to 0
9 ARDUINO_EVENT_WPS_ER_SUCCESS < ESP32 station wps succeeds in enrollee mode
10 ARDUINO_EVENT_WPS_ER_FAILED < ESP32 station wps fails in enrollee mode
11 ARDUINO_EVENT_WPS_ER_TIMEOUT < ESP32 station wps timeout in enrollee mode
12 ARDUINO_EVENT_WPS_ER_PIN < ESP32 station wps pin code in enrollee mode
13 ARDUINO_EVENT_WIFI_AP_START < ESP32 soft-AP start
14 ARDUINO_EVENT_WIFI_AP_STOP < ESP32 soft-AP stop
15 ARDUINO_EVENT_WIFI_AP_STACONNECTED < a station connected to ESP32 soft-AP
16 ARDUINO_EVENT_WIFI_AP_STADISCONNECTED < a station disconnected from ESP32 soft-AP
17 ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED < ESP32 soft-AP assign an IP to a connected station
18 ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED < Receive probe request packet in soft-AP interface
19 ARDUINO_EVENT_WIFI_AP_GOT_IP6 < ESP32 ap interface v6IP addr is preferred
19 ARDUINO_EVENT_WIFI_STA_GOT_IP6 < ESP32 station interface v6IP addr is preferred
20 ARDUINO_EVENT_ETH_START < ESP32 ethernet start
21 ARDUINO_EVENT_ETH_STOP < ESP32 ethernet stop
22 ARDUINO_EVENT_ETH_CONNECTED < ESP32 ethernet phy link up
23 ARDUINO_EVENT_ETH_DISCONNECTED < ESP32 ethernet phy link down
24 ARDUINO_EVENT_ETH_GOT_IP < ESP32 ethernet got IP from connected AP
19 ARDUINO_EVENT_ETH_GOT_IP6 < ESP32 ethernet interface v6IP addr is preferred
25 ARDUINO_EVENT_MAX
*/
#include <WiFi.h>
const char *ssid = "your-ssid";
const char *password = "your-password";
// WARNING: This function is called from a separate FreeRTOS task (thread)!
void WiFiEvent(WiFiEvent_t event) {
Serial.printf("[WiFi-event] event: %d\n", event);
switch (event) {
case ARDUINO_EVENT_WIFI_READY: Serial.println("WiFi interface ready"); break;
case ARDUINO_EVENT_WIFI_SCAN_DONE: Serial.println("Completed scan for access points"); break;
case ARDUINO_EVENT_WIFI_STA_START: Serial.println("WiFi client started"); break;
case ARDUINO_EVENT_WIFI_STA_STOP: Serial.println("WiFi clients stopped"); break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("Connected to access point"); break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: Serial.println("Disconnected from WiFi access point"); break;
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: Serial.println("Authentication mode of access point has changed"); break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.print("Obtained IP address: ");
Serial.println(WiFi.localIP());
break;
case ARDUINO_EVENT_WIFI_STA_LOST_IP: Serial.println("Lost IP address and IP address is reset to 0"); break;
case ARDUINO_EVENT_WPS_ER_SUCCESS: Serial.println("WiFi Protected Setup (WPS): succeeded in enrollee mode"); break;
case ARDUINO_EVENT_WPS_ER_FAILED: Serial.println("WiFi Protected Setup (WPS): failed in enrollee mode"); break;
case ARDUINO_EVENT_WPS_ER_TIMEOUT: Serial.println("WiFi Protected Setup (WPS): timeout in enrollee mode"); break;
case ARDUINO_EVENT_WPS_ER_PIN: Serial.println("WiFi Protected Setup (WPS): pin code in enrollee mode"); break;
case ARDUINO_EVENT_WIFI_AP_START: Serial.println("WiFi access point started"); break;
case ARDUINO_EVENT_WIFI_AP_STOP: Serial.println("WiFi access point stopped"); break;
case ARDUINO_EVENT_WIFI_AP_STACONNECTED: Serial.println("Client connected"); break;
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: Serial.println("Client disconnected"); break;
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: Serial.println("Assigned IP address to client"); break;
case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: Serial.println("Received probe request"); break;
case ARDUINO_EVENT_WIFI_AP_GOT_IP6: Serial.println("AP IPv6 is preferred"); break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP6: Serial.println("STA IPv6 is preferred"); break;
case ARDUINO_EVENT_ETH_GOT_IP6: Serial.println("Ethernet IPv6 is preferred"); break;
case ARDUINO_EVENT_ETH_START: Serial.println("Ethernet started"); break;
case ARDUINO_EVENT_ETH_STOP: Serial.println("Ethernet stopped"); break;
case ARDUINO_EVENT_ETH_CONNECTED: Serial.println("Ethernet connected"); break;
case ARDUINO_EVENT_ETH_DISCONNECTED: Serial.println("Ethernet disconnected"); break;
case ARDUINO_EVENT_ETH_GOT_IP: Serial.println("Obtained IP address"); break;
default: break;
}
}
// WARNING: This function is called from a separate FreeRTOS task (thread)!
void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
}
void setup() {
Serial.begin(115200);
// delete old config
WiFi.disconnect(true);
delay(1000);
// Examples of different ways to register wifi events;
// these handlers will be called from another thread.
WiFi.onEvent(WiFiEvent);
WiFi.onEvent(WiFiGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
WiFiEventId_t eventID = WiFi.onEvent(
[](WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.print("WiFi lost connection. Reason: ");
Serial.println(info.wifi_sta_disconnected.reason);
},
WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED
);
// Remove WiFi event
Serial.print("WiFi Event ID: ");
Serial.println(eventID);
// WiFi.removeEvent(eventID);
WiFi.begin(ssid, password);
Serial.println();
Serial.println();
Serial.println("Wait for WiFi... ");
}
void loop() {
delay(1000);
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,87 @@
/*
Example of connection using Static IP
by Evandro Luis Copercini
Public domain - 2017
*/
#include <WiFi.h>
const char *ssid = "your_network_name";
const char *password = "your_network_password";
const char *host = "example.com";
const char *url = "/index.html";
IPAddress local_IP(192, 168, 31, 115);
IPAddress gateway(192, 168, 31, 1);
IPAddress subnet(255, 255, 0, 0);
IPAddress primaryDNS(8, 8, 8, 8); //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional
void setup() {
Serial.begin(115200);
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure");
}
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("ESP Mac Address: ");
Serial.println(WiFi.macAddress());
Serial.print("Subnet Mask: ");
Serial.println(WiFi.subnetMask());
Serial.print("Gateway IP: ");
Serial.println(WiFi.gatewayIP());
Serial.print("DNS: ");
Serial.println(WiFi.dnsIP());
}
void loop() {
delay(5000);
Serial.print("connecting to ");
Serial.println(host);
// Use NetworkClient class to create TCP connections
NetworkClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
Serial.print("Requesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
// Read all the lines of the reply from server and print them to Serial
while (client.available()) {
String line = client.readStringUntil('\r');
Serial.print(line);
}
Serial.println();
Serial.println("closing connection");
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,68 @@
#include <WiFi.h>
#define STA_SSID "YOUR-SSID"
#define STA_PASS "YOUR-PASS"
#define AP_SSID "ESP32-WIFI-EXTENDER"
#define AP_PASS "password"
IPAddress ap_ip(192, 168, 4, 1);
IPAddress ap_mask(255, 255, 255, 0);
IPAddress ap_leaseStart(192, 168, 4, 2);
IPAddress ap_dns(8, 8, 4, 4);
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Network.onEvent(onEvent);
WiFi.AP.begin();
WiFi.AP.config(ap_ip, ap_ip, ap_mask, ap_leaseStart, ap_dns);
WiFi.AP.create(AP_SSID, AP_PASS);
if (!WiFi.AP.waitStatusBits(ESP_NETIF_STARTED_BIT, 1000)) {
Serial.println("Failed to start AP!");
return;
}
WiFi.begin(STA_SSID, STA_PASS);
}
void loop() {
delay(20000);
}
void onEvent(arduino_event_id_t event, arduino_event_info_t info) {
switch (event) {
case ARDUINO_EVENT_WIFI_STA_START: Serial.println("STA Started"); break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED: Serial.println("STA Connected"); break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.println("STA Got IP");
Serial.println(WiFi.STA);
WiFi.AP.enableNAPT(true);
break;
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
Serial.println("STA Lost IP");
WiFi.AP.enableNAPT(false);
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
Serial.println("STA Disconnected");
WiFi.AP.enableNAPT(false);
break;
case ARDUINO_EVENT_WIFI_STA_STOP: Serial.println("STA Stopped"); break;
case ARDUINO_EVENT_WIFI_AP_START:
Serial.println("AP Started");
Serial.println(WiFi.AP);
break;
case ARDUINO_EVENT_WIFI_AP_STACONNECTED: Serial.println("AP STA Connected"); break;
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: Serial.println("AP STA Disconnected"); break;
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:
Serial.print("AP STA IP Assigned: ");
Serial.println(IPAddress(info.wifi_ap_staipassigned.ip.addr));
break;
case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: Serial.println("AP Probe Request Received"); break;
case ARDUINO_EVENT_WIFI_AP_STOP: Serial.println("AP Stopped"); break;
default: break;
}
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,120 @@
#include "WiFi.h"
#define STA_SSID "**********"
#define STA_PASS "**********"
#define AP_SSID "esp32-v6"
static volatile bool wifi_connected = false;
NetworkUDP ntpClient;
void wifiOnConnect() {
Serial.println("STA Connected");
Serial.print("STA IPv4: ");
Serial.println(WiFi.localIP());
ntpClient.begin(2390);
}
void wifiOnDisconnect() {
Serial.println("STA Disconnected");
delay(1000);
WiFi.begin(STA_SSID, STA_PASS);
}
void wifiConnectedLoop() {
//lets check the time
const int NTP_PACKET_SIZE = 48;
byte ntpPacketBuffer[NTP_PACKET_SIZE];
IPAddress address;
WiFi.hostByName("time.nist.gov", address);
memset(ntpPacketBuffer, 0, NTP_PACKET_SIZE);
ntpPacketBuffer[0] = 0b11100011; // LI, Version, Mode
ntpPacketBuffer[1] = 0; // Stratum, or type of clock
ntpPacketBuffer[2] = 6; // Polling Interval
ntpPacketBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
ntpPacketBuffer[12] = 49;
ntpPacketBuffer[13] = 0x4E;
ntpPacketBuffer[14] = 49;
ntpPacketBuffer[15] = 52;
ntpClient.beginPacket(address, 123); //NTP requests are to port 123
ntpClient.write(ntpPacketBuffer, NTP_PACKET_SIZE);
ntpClient.endPacket();
delay(1000);
int packetLength = ntpClient.parsePacket();
if (packetLength) {
if (packetLength >= NTP_PACKET_SIZE) {
ntpClient.read(ntpPacketBuffer, NTP_PACKET_SIZE);
}
ntpClient.clear();
uint32_t secsSince1900 =
(uint32_t)ntpPacketBuffer[40] << 24 | (uint32_t)ntpPacketBuffer[41] << 16 | (uint32_t)ntpPacketBuffer[42] << 8 | ntpPacketBuffer[43];
//Serial.printf("Seconds since Jan 1 1900: %u\n", secsSince1900);
uint32_t epoch = secsSince1900 - 2208988800UL;
//Serial.printf("EPOCH: %u\n", epoch);
uint8_t h = (epoch % 86400L) / 3600;
uint8_t m = (epoch % 3600) / 60;
uint8_t s = (epoch % 60);
Serial.printf("UTC: %02u:%02u:%02u (GMT)\n", h, m, s);
}
delay(9000);
}
// WARNING: WiFiEvent is called from a separate FreeRTOS task (thread)!
void WiFiEvent(WiFiEvent_t event) {
switch (event) {
case ARDUINO_EVENT_WIFI_AP_START:
//can set ap hostname here
WiFi.softAPsetHostname(AP_SSID);
break;
case ARDUINO_EVENT_WIFI_STA_START:
//set sta hostname here
WiFi.setHostname(AP_SSID);
break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED: break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
Serial.print("STA IPv6: ");
Serial.println(WiFi.linkLocalIPv6());
break;
case ARDUINO_EVENT_WIFI_AP_GOT_IP6:
Serial.print("AP IPv6: ");
Serial.println(WiFi.softAPlinkLocalIPv6());
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
wifiOnConnect();
wifi_connected = true;
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
wifi_connected = false;
wifiOnDisconnect();
break;
default: break;
}
}
void setup() {
Serial.begin(115200);
WiFi.disconnect(true);
WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread.
WiFi.mode(WIFI_MODE_APSTA);
//enable ap ipv6 here
WiFi.softAPenableIPv6();
WiFi.softAP(AP_SSID);
//enable sta ipv6 here
WiFi.enableIPv6();
WiFi.begin(STA_SSID, STA_PASS);
}
void loop() {
if (wifi_connected) {
wifiConnectedLoop();
}
while (Serial.available()) {
Serial.write(Serial.read());
}
}
+3
View File
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,33 @@
/*
* This sketch tries to Connect to the best AP based on a given list
*
*/
#include <WiFi.h>
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
void setup() {
Serial.begin(115200);
delay(10);
wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1");
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");
Serial.println("Connecting Wifi...");
if (wifiMulti.run() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
}
void loop() {
if (wifiMulti.run() != WL_CONNECTED) {
Serial.println("WiFi not connected!");
delay(1000);
}
}
+3
View File
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,64 @@
/*
* This sketch tries to connect to the best AP available
* and tests for captive portals on open networks
*
*/
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
WiFiMulti wifiMulti;
// callback used to check Internet connectivity
bool testConnection() {
HTTPClient http;
http.begin("http://www.espressif.com");
int httpCode = http.GET();
// we expect to get a 301 because it will ask to use HTTPS instead of HTTP
if (httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
return true;
}
return false;
}
void setup() {
Serial.begin(115200);
delay(10);
wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1");
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");
// These options can help when you need ANY kind of wifi connection to get a config file, report errors, etc.
wifiMulti.setStrictMode(false); // Default is true. Library will disconnect and forget currently connected AP if it's not in the AP list.
wifiMulti.setAllowOpenAP(true); // Default is false. True adds open APs to the AP list.
wifiMulti.setConnectionTestCallbackFunc(testConnection); // Attempts to connect to a remote webserver in case of captive portals.
Serial.println("Connecting Wifi...");
if (wifiMulti.run() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
}
void loop() {
static bool isConnected = false;
uint8_t WiFiStatus = wifiMulti.run();
if (WiFiStatus == WL_CONNECTED) {
if (!isConnected) {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
isConnected = true;
} else {
Serial.println("WiFi not connected!");
isConnected = false;
delay(5000);
}
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,61 @@
# WiFiScan Example
This example demonstrates how to use the Wi-Fi library to scan available Wi-Fi networks and print the results.
## Supported Targets
Currently, this example supports the following targets.
| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C6 |
| ----------------- | ----- | -------- | -------- | -------- | -------- |
## How to Use Example
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
#### Using Arduino IDE
* Before Compile/Verify, select the correct board: `Tools -> Board`.
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
## Example/Log Output
```
Setup done
Scan start
Scan done
17 networks found
Nr | SSID | RSSI | CH | Encryption
1 | IoTNetwork | -62 | 1 | WPA2
2 | WiFiSSID | -62 | 1 | WPA2-EAP
3 | B3A7992 | -63 | 6 | WPA+WPA2
4 | WiFi | -63 | 6 | WPA3
5 | IoTNetwork2 | -64 | 11 | WPA2+WPA3
...
```
## Troubleshooting
***Important: Be sure you're using a good quality USB cable and you have enough power source for your project.***
* **Programming Fail:** If the programming/flash procedure fails, try to reduce the serial connection speed.
* **COM port not detected:** Check the USB cable connection and the USB to Serial driver installation.
If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
## Contribute
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
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!
Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else.
## Resources
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf)
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
@@ -0,0 +1,83 @@
/*
* This sketch demonstrates how to scan WiFi networks. For chips that support 5GHz band, separate scans are done for all bands.
* The API is based on the Arduino WiFi Shield library, but has significant changes as newer WiFi functions are supported.
* E.g. the return value of `encryptionType()` different because more modern encryption is supported.
*/
#include "WiFi.h"
void setup() {
Serial.begin(115200);
// Enable Station Interface
WiFi.STA.begin();
Serial.println("Setup done");
}
void ScanWiFi() {
Serial.println("Scan start");
// WiFi.scanNetworks will return the number of networks found.
int n = WiFi.scanNetworks();
Serial.println("Scan done");
if (n == 0) {
Serial.println("no networks found");
} else {
Serial.print(n);
Serial.println(" networks found");
Serial.println("Nr | SSID | RSSI | CH | Encryption");
for (int i = 0; i < n; ++i) {
// Print SSID and RSSI for each network found
Serial.printf("%2d", i + 1);
Serial.print(" | ");
Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
Serial.print(" | ");
Serial.printf("%4ld", WiFi.RSSI(i));
Serial.print(" | ");
Serial.printf("%2ld", WiFi.channel(i));
Serial.print(" | ");
switch (WiFi.encryptionType(i)) {
case WIFI_AUTH_OPEN: Serial.print("open"); break;
case WIFI_AUTH_WEP: Serial.print("WEP"); break;
case WIFI_AUTH_WPA_PSK: Serial.print("WPA"); break;
case WIFI_AUTH_WPA2_PSK: Serial.print("WPA2"); break;
case WIFI_AUTH_WPA_WPA2_PSK: Serial.print("WPA+WPA2"); break;
case WIFI_AUTH_WPA2_ENTERPRISE: Serial.print("WPA2-EAP"); break;
case WIFI_AUTH_WPA3_PSK: Serial.print("WPA3"); break;
case WIFI_AUTH_WPA2_WPA3_PSK: Serial.print("WPA2+WPA3"); break;
case WIFI_AUTH_WAPI_PSK: Serial.print("WAPI"); break;
default: Serial.print("unknown");
}
Serial.println();
delay(10);
}
}
// Delete the scan result to free memory for code below.
WiFi.scanDelete();
Serial.println("-------------------------------------");
}
void loop() {
Serial.println("-------------------------------------");
Serial.println("Default wifi band mode scan:");
Serial.println("-------------------------------------");
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
WiFi.setBandMode(WIFI_BAND_MODE_AUTO);
#endif
ScanWiFi();
#if CONFIG_SOC_WIFI_SUPPORT_5G
// Wait a bit before scanning again.
delay(1000);
Serial.println("-------------------------------------");
Serial.println("2.4 Ghz wifi band mode scan:");
Serial.println("-------------------------------------");
WiFi.setBandMode(WIFI_BAND_MODE_2G_ONLY);
ScanWiFi();
// Wait a bit before scanning again.
delay(1000);
Serial.println("-------------------------------------");
Serial.println("5 Ghz wifi band mode scan:");
Serial.println("-------------------------------------");
WiFi.setBandMode(WIFI_BAND_MODE_5G_ONLY);
ScanWiFi();
#endif
// Wait a bit before scanning again.
delay(10000);
}
+3
View File
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,71 @@
# WiFiScanAsync Example
This example demonstrates how to use the Wi-Fi library to scan available Wi-Fi networks in asynchronous mode and print the results.
## Supported Targets
Currently, this example supports the following targets.
| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C6 |
| ----------------- | ----- | -------- | -------- | -------- | -------- |
## How to Use Example
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
#### Using Arduino IDE
* Before Compile/Verify, select the correct board: `Tools -> Board`.
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
## Example/Log Output
```
Setup done
Scan start
Loop running...
Loop running...
Loop running...
Loop running...
Loop running...
Loop running...
Loop running...
Loop running...
Loop running...
Scan done
17 networks found
Nr | SSID | RSSI | CH | Encryption
1 | IoTNetwork | -62 | 1 | WPA2
2 | WiFiSSID | -62 | 1 | WPA2-EAP
3 | B3A7992 | -63 | 6 | WPA+WPA2
4 | WiFi | -63 | 6 | WPA3
5 | IoTNetwork2 | -64 | 11 | WPA2+WPA3
...
```
## Troubleshooting
***Important: Be sure you're using a good quality USB cable and you have enough power source for your project.***
* **Programming Fail:** If the programming/flash procedure fails, try to reduce the serial connection speed.
* **COM port not detected:** Check the USB cable connection and the USB to Serial driver installation.
If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
## Contribute
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
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!
Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else.
## Resources
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf)
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
@@ -0,0 +1,82 @@
/*
This sketch demonstrates how to scan WiFi networks in Async Mode.
The API is based on the Arduino WiFi Shield library, but has significant changes as newer WiFi functions are supported.
E.g. the return value of `encryptionType()` different because more modern encryption is supported.
*/
#include "WiFi.h"
void startWiFiScan() {
Serial.println("Scan start");
// WiFi.scanNetworks will return immediately in Async Mode.
WiFi.scanNetworks(true); // 'true' turns Async Mode ON
}
void printScannedNetworks(uint16_t networksFound) {
if (networksFound == 0) {
Serial.println("no networks found");
} else {
Serial.println("\nScan done");
Serial.print(networksFound);
Serial.println(" networks found");
Serial.println("Nr | SSID | RSSI | CH | Encryption");
for (int i = 0; i < networksFound; ++i) {
// Print SSID and RSSI for each network found
Serial.printf("%2d", i + 1);
Serial.print(" | ");
Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
Serial.print(" | ");
Serial.printf("%4ld", WiFi.RSSI(i));
Serial.print(" | ");
Serial.printf("%2ld", WiFi.channel(i));
Serial.print(" | ");
switch (WiFi.encryptionType(i)) {
case WIFI_AUTH_OPEN: Serial.print("open"); break;
case WIFI_AUTH_WEP: Serial.print("WEP"); break;
case WIFI_AUTH_WPA_PSK: Serial.print("WPA"); break;
case WIFI_AUTH_WPA2_PSK: Serial.print("WPA2"); break;
case WIFI_AUTH_WPA_WPA2_PSK: Serial.print("WPA+WPA2"); break;
case WIFI_AUTH_WPA2_ENTERPRISE: Serial.print("WPA2-EAP"); break;
case WIFI_AUTH_WPA3_PSK: Serial.print("WPA3"); break;
case WIFI_AUTH_WPA2_WPA3_PSK: Serial.print("WPA2+WPA3"); break;
case WIFI_AUTH_WAPI_PSK: Serial.print("WAPI"); break;
default: Serial.print("unknown");
}
Serial.println();
delay(10);
}
Serial.println("");
// Delete the scan result to free memory for code below.
WiFi.scanDelete();
}
}
void setup() {
Serial.begin(115200);
// Set WiFi to station mode and disconnect from an AP if it was previously connected.
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.println("Setup done");
startWiFiScan();
}
void loop() {
// check WiFi Scan Async process
int16_t WiFiScanStatus = WiFi.scanComplete();
if (WiFiScanStatus < 0) { // it is busy scanning or got an error
if (WiFiScanStatus == WIFI_SCAN_FAILED) {
Serial.println("WiFi Scan has failed. Starting again.");
startWiFiScan();
}
// other option is status WIFI_SCAN_RUNNING - just wait.
} else { // Found Zero or more Wireless Networks
printScannedNetworks(WiFiScanStatus);
startWiFiScan(); // start over...
}
// Loop can do something else...
delay(250);
Serial.println("Loop running...");
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,66 @@
# WiFiScan Example
This example demonstrates how to use the Wi-Fi library to scan available Wi-Fi networks and print the results.
This example shows the basic functionality of the dual antenna capability.
# Supported Targets
This example is compatible with the ESP32-WROOM-DA.
## How to Use Example
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
#### Using Arduino IDE
* Before Compile/Verify, select the correct board: `Tools -> Board`.
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
## Example/Log Output
```
ets Jul 29 2019 12:21:46
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1412
load:0x40078000,len:13400
load:0x40080400,len:3672
entry 0x400805f8
Setup done
scan start
scan done
17 networks found
1: IoTNetwork (-62)*
2: WiFiSSID (-62)*
3: B3A7992 (-63)*
4: WiFi (-63)
5: IoTNetwork2 (-64)*
...
```
## Troubleshooting
***Important: Be sure you're using a good quality USB cable and you have enough power source for your project.***
* **Programming Fail:** If the programming/flash procedure fails, try to reduce the serial connection speed.
* **COM port not detected:** Check the USB cable connection and the USB to Serial driver installation.
If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
## Contribute
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
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!
Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else.
## Resources
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)
* ESP32-WROOM-DA Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-wroom-da_datasheet_en.pdf)
@@ -0,0 +1,77 @@
/*
* This sketch demonstrates how to scan WiFi networks.
* The API is almost the same as with the WiFi Shield library,
* the most obvious difference being the different file you need to include:
*/
#include "WiFi.h"
/* These are the GPIOs connected to the antenna switch on the ESP32-WROOM-DA.
* Both GPIOs are not exposed to the module pins and cannot be used except to
* control the antnnas switch.
*
* For more details, see the datashhet at:
* https://www.espressif.com/sites/default/files/documentation/esp32-wroom-da_datasheet_en.pdf
*/
#define GPIO_ANT1 2 // GPIO for antenna 1
#define GPIO_ANT2 25 // GPIO for antenna 2 (default)
void setup() {
bool err = false;
Serial.begin(115200);
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
/* Attention: This is the manual procedure for the dual antenna configuration.
* If you choose the ESP32-WROOM-DA module from the Tools -> Board, this configuration
* is not necessary!
*
* Set WiFi dual antenna configuration by passing the GPIO and antenna mode for RX ant TX
*/
err = WiFi.setDualAntennaConfig(GPIO_ANT1, GPIO_ANT2, WIFI_RX_ANT_AUTO, WIFI_TX_ANT_AUTO);
/* For more details on how to use this feature, see our docs:
* https://docs.espressif.com/projects/arduino-esp32/en/latest/api/wifi.html
*/
if (err == false) {
Serial.println("Dual Antenna configuration failed!");
} else {
Serial.println("Dual Antenna configuration successfully done!");
}
WiFi.disconnect();
delay(100);
Serial.println("Setup done");
}
void loop() {
Serial.println("scan start");
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n == 0) {
Serial.println("no networks found");
} else {
Serial.print(n);
Serial.println(" networks found");
for (int i = 0; i < n; ++i) {
// Print SSID and RSSI for each network found
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
delay(10);
}
}
Serial.println("");
// Wait a bit before scanning again
delay(5000);
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,61 @@
# WiFiScanTime Example
This example demonstrates how to use the Wi-Fi library to scan available Wi-Fi networks with custom scan timing and print the results.
## Supported Targets
Currently, this example supports the following targets.
| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C6 |
| ----------------- | ----- | -------- | -------- | -------- | -------- |
## How to Use Example
* How to install the Arduino IDE: [Install Arduino IDE](https://github.com/espressif/arduino-esp32/tree/master/docs/arduino-ide).
#### Using Arduino IDE
* Before Compile/Verify, select the correct board: `Tools -> Board`.
* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port.
## Example/Log Output
```
Setup done
Scan start
Scan done, elapsed time: 4960 ms
17 networks found
Nr | SSID | RSSI | CH | Encryption
1 | IoTNetwork | -62 | 1 | WPA2
2 | WiFiSSID | -62 | 1 | WPA2-EAP
3 | B3A7992 | -63 | 6 | WPA+WPA2
4 | WiFi | -63 | 6 | WPA3
5 | IoTNetwork2 | -64 | 11 | WPA2+WPA3
...
```
## Troubleshooting
***Important: Be sure you're using a good quality USB cable and you have enough power source for your project.***
* **Programming Fail:** If the programming/flash procedure fails, try to reduce the serial connection speed.
* **COM port not detected:** Check the USB cable connection and the USB to Serial driver installation.
If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute).
## Contribute
To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst)
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!
Before creating a new issue, be sure to try the Troubleshooting and to check if the same issue was already created by someone else.
## Resources
* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf)
* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf)
* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf)
* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf)
* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com)
@@ -0,0 +1,92 @@
/*
* This sketch demonstrates how to scan WiFi networks with custom scanning time.
* The API is based on the Arduino WiFi Shield library, but has significant changes as newer WiFi functions are supported.
* E.g. the return value of `encryptionType()` different because more modern encryption is supported.
*/
/*
* WiFi scan timing parameters explained:
*
* min=0, max=0: scan dwells on each channel for 120 ms.
* min>0, max=0: scan dwells on each channel for 120 ms.
* min=0, max>0: scan dwells on each channel for max ms.
* min>0, max>0: the minimum time the scan dwells on each channel is min ms. If no AP is found during this time frame, the scan switches to the next channel. Otherwise, the scan dwells on the channel for max ms.
*/
#include "WiFi.h"
void wifiScan(uint16_t min_time, uint16_t max_time) {
Serial.println("Scan start");
// Set the minimum time per channel for active scanning.
WiFi.setScanActiveMinTime(min_time);
// Capture the start time of the scan.
uint32_t start = millis();
// WiFi.scanNetworks will return the number of networks found.
// Scan networks with those options: Synchrone mode, show hidden networks, active scan, max scan time per channel.
int n = WiFi.scanNetworks(false, true, false, max_time);
Serial.printf("Scan done, elapsed time: %lu ms\n", millis() - start);
if (n == 0) {
Serial.println("no networks found");
} else {
Serial.print(n);
Serial.println(" networks found");
Serial.println("Nr | SSID | RSSI | CH | Encryption");
for (int i = 0; i < n; ++i) {
// Print SSID and RSSI for each network found
Serial.printf("%2d", i + 1);
Serial.print(" | ");
Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
Serial.print(" | ");
Serial.printf("%4ld", WiFi.RSSI(i));
Serial.print(" | ");
Serial.printf("%2ld", WiFi.channel(i));
Serial.print(" | ");
switch (WiFi.encryptionType(i)) {
case WIFI_AUTH_OPEN: Serial.print("open"); break;
case WIFI_AUTH_WEP: Serial.print("WEP"); break;
case WIFI_AUTH_WPA_PSK: Serial.print("WPA"); break;
case WIFI_AUTH_WPA2_PSK: Serial.print("WPA2"); break;
case WIFI_AUTH_WPA_WPA2_PSK: Serial.print("WPA+WPA2"); break;
case WIFI_AUTH_WPA2_ENTERPRISE: Serial.print("WPA2-EAP"); break;
case WIFI_AUTH_WPA3_PSK: Serial.print("WPA3"); break;
case WIFI_AUTH_WPA2_WPA3_PSK: Serial.print("WPA2+WPA3"); break;
case WIFI_AUTH_WAPI_PSK: Serial.print("WAPI"); break;
default: Serial.print("unknown");
}
Serial.println();
delay(10);
}
}
Serial.println("");
// Delete the scan result to free memory for code below.
WiFi.scanDelete();
// Wait a bit before scanning again
delay(2000);
}
void setup() {
Serial.begin(115200);
// Set WiFi to station mode and disconnect from an AP if it was previously connected.
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
// Scan WiFi networks with a minimum time of 100 ms per channel and a maximum time of 300 ms per channel (default values).
wifiScan(100, 300);
// Scan WiFi networks with a minimum time of 100 ms per channel and a maximum time of 1500 ms per channel.
wifiScan(100, 1500);
// Scan WiFi networks with a minimum time of 0 ms per channel and a maximum time of 1500 ms per channel.
wifiScan(0, 1500);
}
void loop() {
// Nothing to do here
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,40 @@
#include "sdkconfig.h"
#if CONFIG_ESP_WIFI_REMOTE_ENABLED
#error "SmartConfig is only supported in SoCs with native Wi-Fi support"
#endif
#include "WiFi.h"
void setup() {
Serial.begin(115200);
//Init WiFi as Station, start SmartConfig
WiFi.mode(WIFI_AP_STA);
WiFi.beginSmartConfig();
//Wait for SmartConfig packet from mobile
Serial.println("Waiting for SmartConfig.");
while (!WiFi.smartConfigDone()) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("SmartConfig received.");
//Wait for WiFi to connect to AP
Serial.println("Waiting for WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi Connected.");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
void loop() {
// put your main code here, to run repeatedly:
}
@@ -0,0 +1,2 @@
requires:
- CONFIG_SOC_WIFI_SUPPORTED=y
@@ -0,0 +1,135 @@
/*
WiFiTelnetToSerial - Example Transparent UART to Telnet Server for ESP32
Copyright (c) 2017 Hristo Gochkov. All rights reserved.
This file is part of the ESP32 WiFi library for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <WiFi.h>
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
//how many clients should be able to telnet to this ESP32
#define MAX_SRV_CLIENTS 1
const char *ssid = "**********";
const char *password = "**********";
NetworkServer server(23);
NetworkClient serverClients[MAX_SRV_CLIENTS];
void setup() {
Serial.begin(115200);
Serial.println("\nConnecting");
wifiMulti.addAP(ssid, password);
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");
Serial.println("Connecting Wifi ");
for (int loops = 10; loops > 0; loops--) {
if (wifiMulti.run() == WL_CONNECTED) {
Serial.println("");
Serial.print("WiFi connected ");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
break;
} else {
Serial.println(loops);
delay(1000);
}
}
if (wifiMulti.run() != WL_CONNECTED) {
Serial.println("WiFi connect failed");
delay(1000);
ESP.restart();
}
//start UART and the server
Serial1.begin(9600);
server.begin();
server.setNoDelay(true);
Serial.print("Ready! Use 'telnet ");
Serial.print(WiFi.localIP());
Serial.println(" 23' to connect");
}
void loop() {
uint8_t i;
if (wifiMulti.run() == WL_CONNECTED) {
//check if there are any new clients
if (server.hasClient()) {
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
//find free/disconnected spot
if (!serverClients[i] || !serverClients[i].connected()) {
if (serverClients[i]) {
serverClients[i].stop();
}
serverClients[i] = server.accept();
if (!serverClients[i]) {
Serial.println("available broken");
}
Serial.print("New client: ");
Serial.print(i);
Serial.print(' ');
Serial.println(serverClients[i].remoteIP());
break;
}
}
if (i >= MAX_SRV_CLIENTS) {
//no free/disconnected spot so reject
server.accept().stop();
}
}
//check clients for data
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i] && serverClients[i].connected()) {
if (serverClients[i].available()) {
//get data from the telnet client and push it to the UART
while (serverClients[i].available()) {
Serial1.write(serverClients[i].read());
}
}
} else {
if (serverClients[i]) {
serverClients[i].stop();
}
}
}
//check UART for data
if (Serial1.available()) {
size_t len = Serial1.available();
uint8_t sbuf[len];
Serial1.readBytes(sbuf, len);
//push UART data to all connected telnet clients
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i] && serverClients[i].connected()) {
serverClients[i].write(sbuf, len);
delay(1);
}
}
}
} else {
Serial.println("WiFi not connected!");
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i]) {
serverClients[i].stop();
}
}
delay(1000);
}
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,76 @@
/*
* This sketch sends random data over UDP on a ESP32 device
*
*/
#include <WiFi.h>
#include <NetworkUdp.h>
// WiFi network name and password:
const char *networkName = "your-ssid";
const char *networkPswd = "your-password";
//IP address to send UDP data to:
// either use the ip address of the server or
// a network broadcast address
const char *udpAddress = "192.168.0.255";
const int udpPort = 3333;
//Are we currently connected?
boolean connected = false;
//The udp library class
NetworkUDP udp;
void setup() {
// Initialize hardware serial:
Serial.begin(115200);
//Connect to the WiFi network
connectToWiFi(networkName, networkPswd);
}
void loop() {
//only send data when connected
if (connected) {
//Send a packet
udp.beginPacket(udpAddress, udpPort);
udp.printf("Seconds since boot: %lu", millis() / 1000);
udp.endPacket();
}
//Wait for 1 second
delay(1000);
}
void connectToWiFi(const char *ssid, const char *pwd) {
Serial.println("Connecting to WiFi network: " + String(ssid));
// delete old config
WiFi.disconnect(true);
//register event handler
WiFi.onEvent(WiFiEvent); // Will call WiFiEvent() from another thread.
//Initiate connection
WiFi.begin(ssid, pwd);
Serial.println("Waiting for WIFI connection...");
}
// WARNING: WiFiEvent is called from a separate FreeRTOS task (thread)!
void WiFiEvent(WiFiEvent_t event) {
switch (event) {
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
//When connected set
Serial.print("WiFi connected! IP address: ");
Serial.println(WiFi.localIP());
//initializes the UDP state
//This initializes the transfer buffer
udp.begin(WiFi.localIP(), udpPort);
connected = true;
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
Serial.println("WiFi lost connection");
connected = false;
break;
default: break;
}
}
@@ -0,0 +1,3 @@
requires_any:
- CONFIG_SOC_WIFI_SUPPORTED=y
- CONFIG_ESP_WIFI_REMOTE_ENABLED=y
@@ -0,0 +1,124 @@
# This python script listens on UDP port 3333
# for messages from the ESP32 board and prints them
import socket
import sys
import subprocess
import platform
def get_interface_ips():
"""Get all available interface IP addresses"""
interface_ips = []
# Try using system commands to get interface IPs
system = platform.system().lower()
try:
if system == "darwin" or system == "linux":
# Use 'ifconfig' on macOS/Linux
result = subprocess.run(["ifconfig"], capture_output=True, text=True, timeout=5)
if result.returncode == 0:
lines = result.stdout.split("\n")
for line in lines:
if "inet " in line and "127.0.0.1" not in line:
# Extract IP address from ifconfig output
parts = line.strip().split()
for i, part in enumerate(parts):
if part == "inet":
if i + 1 < len(parts):
ip = parts[i + 1]
if ip not in interface_ips and ip != "127.0.0.1":
interface_ips.append(ip)
break
elif system == "windows":
# Use 'ipconfig' on Windows
result = subprocess.run(["ipconfig"], capture_output=True, text=True, timeout=5)
if result.returncode == 0:
lines = result.stdout.split("\n")
for line in lines:
if "IPv4 Address" in line and "127.0.0.1" not in line:
# Extract IP address from ipconfig output
if ":" in line:
ip = line.split(":")[1].strip()
if ip not in interface_ips and ip != "127.0.0.1":
interface_ips.append(ip)
except (subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError):
print("Error: Failed to get interface IPs using system commands")
print("Trying fallback methods...")
# Fallback: try to get IPs using socket methods
if not interface_ips:
try:
# Get all IP addresses associated with the hostname
hostname = socket.gethostname()
ip_list = socket.gethostbyname_ex(hostname)[2]
for ip in ip_list:
if ip not in interface_ips and ip != "127.0.0.1":
interface_ips.append(ip)
except socket.gaierror:
print("Error: Failed to get interface IPs using sockets")
# Fail if no interfaces found
if not interface_ips:
print("Error: No network interfaces found. Please check your network configuration.")
sys.exit(1)
return interface_ips
def select_interface(interface_ips):
"""Ask user to select which interface to bind to"""
if len(interface_ips) == 1:
print(f"Using interface: {interface_ips[0]}")
return interface_ips[0]
print("Multiple network interfaces detected:")
for i, ip in enumerate(interface_ips, 1):
print(f" {i}. {ip}")
while True:
try:
choice = input(f"Select interface (1-{len(interface_ips)}): ").strip()
choice_idx = int(choice) - 1
if 0 <= choice_idx < len(interface_ips):
selected_ip = interface_ips[choice_idx]
print(f"Selected interface: {selected_ip}")
return selected_ip
else:
print(f"Please enter a number between 1 and {len(interface_ips)}")
except ValueError:
print("Please enter a valid number")
except KeyboardInterrupt:
print("\nExiting...")
sys.exit(1)
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
except socket.error as msg:
print("Failed to create socket. Error Code : " + str(msg[0]) + " Message " + msg[1])
sys.exit()
# Get available interfaces and let user choose
interface_ips = get_interface_ips()
selected_ip = select_interface(interface_ips)
try:
s.bind((selected_ip, 3333))
except socket.error as msg:
print("Bind failed. Error: " + str(msg[0]) + ": " + msg[1])
sys.exit()
print(f"Server listening on {selected_ip}:3333")
while 1:
d = s.recvfrom(1024)
data = d[0]
if not data:
break
print(data.strip())
s.close()
@@ -0,0 +1,16 @@
# This ruby script listens on UDP port 3333
# for messages from the ESP32 board and prints them
require 'socket'
include Socket::Constants
udp_socket = UDPSocket.new(AF_INET)
#bind
udp_socket.bind("", 3333)
puts 'Server listening'
while true do
message, sender = udp_socket.recvfrom(1024)
puts message
end
+68
View File
@@ -0,0 +1,68 @@
#######################################
# Syntax Coloring Map For WiFi
#######################################
#######################################
# Library (KEYWORD3)
#######################################
WiFi KEYWORD3
#######################################
# Datatypes (KEYWORD1)
#######################################
WiFi KEYWORD1
NetworkClient KEYWORD1
NetworkServer KEYWORD1
NetworkUDP KEYWORD1
NetworkClientSecure KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
status KEYWORD2
mode KEYWORD2
connect KEYWORD2
write KEYWORD2
available KEYWORD2
config KEYWORD2
setDNS KEYWORD2
read KEYWORD2
flush KEYWORD2
stop KEYWORD2
connected KEYWORD2
begin KEYWORD2
beginMulticast KEYWORD2
disconnect KEYWORD2
macAddress KEYWORD2
localIP KEYWORD2
subnetMask KEYWORD2
gatewayIP KEYWORD2
SSID KEYWORD2
psk KEYWORD2
BSSID KEYWORD2
RSSI KEYWORD2
encryptionType KEYWORD2
beginPacket KEYWORD2
beginPacketMulticast KEYWORD2
endPacket KEYWORD2
parsePacket KEYWORD2
destinationIP KEYWORD2
remoteIP KEYWORD2
remotePort KEYWORD2
softAP KEYWORD2
softAPIP KEYWORD2
softAPmacAddress KEYWORD2
softAPConfig KEYWORD2
printDiag KEYWORD2
hostByName KEYWORD2
scanNetworks KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
WIFI_AP LITERAL1
WIFI_STA LITERAL1
WIFI_AP_STA LITERAL1
+9
View File
@@ -0,0 +1,9 @@
name=WiFi
version=3.3.7
author=Hristo Gochkov
maintainer=Hristo Gochkov <hristo@espressif.com>
sentence=Enables network connection (local and Internet) using the ESP32 built-in WiFi.
paragraph=With this library you can instantiate Servers, Clients and send/receive UDP packets through WiFi. The shield can connect either to open or encrypted networks. The IP address can be assigned statically or through a DHCP. The library can also manage DNS.
category=Communication
url=
architectures=esp32
+418
View File
@@ -0,0 +1,418 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "WiFi.h"
#include "WiFiGeneric.h"
#include "WiFiAP.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <esp_err.h>
#include <esp_mac.h>
#include <esp_wifi.h>
#include <esp_event.h>
#include <lwip/ip_addr.h>
#include "dhcpserver/dhcpserver_options.h"
#include "esp_netif.h"
esp_netif_t *get_esp_interface_netif(esp_interface_t interface);
static size_t _wifi_strncpy(char *dst, const char *src, size_t dst_len) {
if (!dst || !src || !dst_len) {
return 0;
}
size_t src_len = strlen(src);
if (src_len >= dst_len) {
src_len = dst_len;
} else {
src_len += 1;
}
memcpy(dst, src, src_len);
return src_len;
}
/**
* compare two AP configurations
* @param lhs softap_config
* @param rhs softap_config
* @return equal
*/
static bool softap_config_equal(const wifi_config_t &lhs, const wifi_config_t &rhs) {
if (strncmp(reinterpret_cast<const char *>(lhs.ap.ssid), reinterpret_cast<const char *>(rhs.ap.ssid), 32) != 0) {
return false;
}
if (strncmp(reinterpret_cast<const char *>(lhs.ap.password), reinterpret_cast<const char *>(rhs.ap.password), 64) != 0) {
return false;
}
if (lhs.ap.channel != rhs.ap.channel) {
return false;
}
if (lhs.ap.authmode != rhs.ap.authmode) {
return false;
}
if (lhs.ap.ssid_hidden != rhs.ap.ssid_hidden) {
return false;
}
if (lhs.ap.max_connection != rhs.ap.max_connection) {
return false;
}
if (lhs.ap.pairwise_cipher != rhs.ap.pairwise_cipher) {
return false;
}
if (lhs.ap.ftm_responder != rhs.ap.ftm_responder) {
return false;
}
return true;
}
static APClass *_ap_network_if = NULL;
static esp_event_handler_instance_t _ap_ev_instance = NULL;
static void _ap_event_cb(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
if (event_base == WIFI_EVENT) {
((APClass *)arg)->_onApEvent(event_id, event_data);
}
}
static void _onApArduinoEvent(arduino_event_t *ev) {
if (_ap_network_if == NULL || ev->event_id < ARDUINO_EVENT_WIFI_AP_START || ev->event_id > ARDUINO_EVENT_WIFI_AP_GOT_IP6) {
return;
}
log_v("Arduino AP Event: %d - %s", ev->event_id, Network.eventName(ev->event_id));
if (ev->event_id == ARDUINO_EVENT_WIFI_AP_START) {
#if CONFIG_LWIP_IPV6
if (_ap_network_if->getStatusBits() & ESP_NETIF_WANT_IP6_BIT) {
esp_err_t err = esp_netif_create_ip6_linklocal(_ap_network_if->netif());
if (err != ESP_OK) {
log_e("Failed to enable IPv6 Link Local on AP: 0x%x: %s", err, esp_err_to_name(err));
} else {
log_v("Enabled IPv6 Link Local on %s", _ap_network_if->desc());
}
}
#endif
}
}
void APClass::_onApEvent(int32_t event_id, void *event_data) {
arduino_event_t arduino_event;
arduino_event.event_id = ARDUINO_EVENT_MAX;
if (event_id == WIFI_EVENT_AP_START) {
log_v("AP Started");
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_START;
setStatusBits(ESP_NETIF_STARTED_BIT);
} else if (event_id == WIFI_EVENT_AP_STOP) {
log_v("AP Stopped");
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_STOP;
clearStatusBits(ESP_NETIF_STARTED_BIT | ESP_NETIF_CONNECTED_BIT | ESP_NETIF_HAS_IP_BIT | ESP_NETIF_HAS_LOCAL_IP6_BIT | ESP_NETIF_HAS_GLOBAL_IP6_BIT);
} else if (event_id == WIFI_EVENT_AP_PROBEREQRECVED) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_ap_probe_req_rx_t *event = (wifi_event_ap_probe_req_rx_t *)event_data;
log_v("AP Probe Request: RSSI: %d, MAC: " MACSTR, event->rssi, MAC2STR(event->mac));
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED;
memcpy(&arduino_event.event_info.wifi_ap_probereqrecved, event_data, sizeof(wifi_event_ap_probe_req_rx_t));
} else if (event_id == WIFI_EVENT_AP_STACONNECTED) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_ap_staconnected_t *event = (wifi_event_ap_staconnected_t *)event_data;
log_v("AP Station Connected: MAC: " MACSTR ", AID: %d", MAC2STR(event->mac), event->aid);
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_STACONNECTED;
memcpy(&arduino_event.event_info.wifi_ap_staconnected, event_data, sizeof(wifi_event_ap_staconnected_t));
setStatusBits(ESP_NETIF_CONNECTED_BIT);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_ap_stadisconnected_t *event = (wifi_event_ap_stadisconnected_t *)event_data;
log_v("AP Station Disconnected: MAC: " MACSTR ", AID: %d", MAC2STR(event->mac), event->aid);
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_AP_STADISCONNECTED;
memcpy(&arduino_event.event_info.wifi_ap_stadisconnected, event_data, sizeof(wifi_event_ap_stadisconnected_t));
// If no more clients are left
wifi_sta_list_t clients;
if (esp_wifi_ap_get_sta_list(&clients) != ESP_OK || clients.num == 0) {
clearStatusBits(ESP_NETIF_CONNECTED_BIT);
}
} else {
return;
}
if (arduino_event.event_id < ARDUINO_EVENT_MAX) {
Network.postEvent(&arduino_event);
}
}
APClass::APClass() : _wifi_ap_event_handle(0) {
_ap_network_if = this;
}
APClass::~APClass() {
end();
_ap_network_if = NULL;
}
bool APClass::onEnable() {
if (_ap_ev_instance == NULL && esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &_ap_event_cb, this, &_ap_ev_instance)) {
log_e("event_handler_instance_register for WIFI_EVENT Failed!");
return false;
}
if (_esp_netif == NULL) {
_wifi_ap_event_handle = Network.onSysEvent(_onApArduinoEvent);
_esp_netif = get_esp_interface_netif(ESP_IF_WIFI_AP);
/* attach to receive events */
initNetif(ESP_NETIF_ID_AP);
}
return true;
}
bool APClass::onDisable() {
Network.removeEvent(_wifi_ap_event_handle);
_wifi_ap_event_handle = 0;
// we just set _esp_netif to NULL here, so destroyNetif() does not try to destroy it.
// That would be done by WiFi.enableAP(false) if STA is not enabled, or when it gets disabled
_esp_netif = NULL;
destroyNetif();
if (_ap_ev_instance != NULL) {
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &_ap_event_cb);
_ap_ev_instance = NULL;
}
return true;
}
bool APClass::begin() {
if (!WiFi.enableAP(true)) {
log_e("AP enable failed!");
return false;
}
if (!waitStatusBits(ESP_NETIF_STARTED_BIT, 1000)) {
log_e("Failed to start AP!");
return false;
}
return true;
}
bool APClass::end() {
if (!WiFi.enableAP(false)) {
log_e("AP disable failed!");
return false;
}
return true;
}
bool APClass::create(
const char *ssid, const char *passphrase, int channel, int ssid_hidden, int max_connection, bool ftm_responder, wifi_auth_mode_t auth_mode,
wifi_cipher_type_t cipher
) {
if (!ssid || *ssid == 0) {
log_e("SSID missing!");
return false;
}
if (passphrase && (strlen(passphrase) > 0 && strlen(passphrase) < 8)) {
log_e("passphrase too short!");
return false;
}
if (!begin()) {
return false;
}
wifi_config_t conf;
memset(&conf, 0, sizeof(wifi_config_t));
conf.ap.channel = channel;
conf.ap.max_connection = max_connection;
conf.ap.beacon_interval = 100;
conf.ap.ssid_hidden = ssid_hidden;
conf.ap.ftm_responder = ftm_responder;
if (ssid != NULL && ssid[0] != 0) {
_wifi_strncpy((char *)conf.ap.ssid, ssid, 32);
conf.ap.ssid_len = strlen(ssid);
if (passphrase != NULL && passphrase[0] != 0) {
conf.ap.authmode = auth_mode;
conf.ap.pairwise_cipher = cipher;
_wifi_strncpy((char *)conf.ap.password, passphrase, 64);
}
}
wifi_config_t conf_current;
esp_err_t err = esp_wifi_get_config(WIFI_IF_AP, &conf_current);
if (err) {
log_e("Get AP config failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
if (!softap_config_equal(conf, conf_current)) {
err = esp_wifi_set_config(WIFI_IF_AP, &conf);
if (err) {
log_e("Set AP config failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
}
return true;
}
bool APClass::clear() {
if (!begin()) {
return false;
}
wifi_config_t conf;
memset(&conf, 0, sizeof(wifi_config_t));
conf.ap.channel = 1;
conf.ap.max_connection = 4;
conf.ap.beacon_interval = 100;
esp_err_t err = esp_wifi_set_config(WIFI_IF_AP, &conf);
if (err) {
log_e("Set AP config failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
return true;
}
bool APClass::bandwidth(wifi_bandwidth_t bandwidth) {
if (!begin()) {
return false;
}
esp_err_t err = esp_wifi_set_bandwidth(WIFI_IF_AP, bandwidth);
if (err) {
log_e("Could not set AP bandwidth! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
return true;
}
bool APClass::enableNAPT(bool enable) {
if (!started()) {
log_e("AP must be first started to enable/disable NAPT");
return false;
}
esp_err_t err = ESP_OK;
if (enable) {
err = esp_netif_napt_enable(_esp_netif);
} else {
err = esp_netif_napt_disable(_esp_netif);
}
if (err) {
log_e("Could not set enable/disable NAPT! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
return true;
}
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
bool APClass::enableDhcpCaptivePortal() {
esp_err_t err = ESP_OK;
static char captiveportal_uri[32] = {
0,
};
if (!started()) {
log_e("AP must be first started to enable DHCP Captive Portal");
return false;
}
// Create Captive Portal URL: http://192.168.0.4
strcpy(captiveportal_uri, "http://");
strcat(captiveportal_uri, localIP().toString().c_str());
log_i("DHCP Captive Portal URL: %s", captiveportal_uri);
// Stop DHCPS
err = esp_netif_dhcps_stop(_esp_netif);
if (err && err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) {
log_e("DHCPS Stop Failed! 0x%04x: %s", err, esp_err_to_name(err));
return false;
}
// Enable DHCP Captive Portal
err = esp_netif_dhcps_option(_esp_netif, ESP_NETIF_OP_SET, ESP_NETIF_CAPTIVEPORTAL_URI, captiveportal_uri, strlen(captiveportal_uri));
if (err) {
log_e("Could not set enable DHCP Captive Portal! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
// Start DHCPS
err = esp_netif_dhcps_start(_esp_netif);
if (err) {
log_e("DHCPS Start Failed! 0x%04x: %s", err, esp_err_to_name(err));
return false;
}
return true;
}
#endif
String APClass::SSID(void) const {
if (!started()) {
return String();
}
wifi_config_t info;
if (!esp_wifi_get_config(WIFI_IF_AP, &info)) {
return String(reinterpret_cast<char *>(info.ap.ssid));
}
return String();
}
uint8_t APClass::stationCount() {
wifi_sta_list_t clients;
if (!started()) {
return 0;
}
if (esp_wifi_ap_get_sta_list(&clients) == ESP_OK) {
return clients.num;
}
return 0;
}
size_t APClass::printDriverInfo(Print &out) const {
size_t bytes = 0;
wifi_config_t info;
wifi_sta_list_t clients;
if (!started()) {
return bytes;
}
if (esp_wifi_get_config(WIFI_IF_AP, &info) != ESP_OK) {
return bytes;
}
bytes += out.print(",");
bytes += out.print((const char *)info.ap.ssid);
bytes += out.print(",CH:");
bytes += out.print(info.ap.channel);
if (info.ap.authmode == WIFI_AUTH_OPEN) {
bytes += out.print(",OPEN");
} else if (info.ap.authmode == WIFI_AUTH_WEP) {
bytes += out.print(",WEP");
} else if (info.ap.authmode == WIFI_AUTH_WPA_PSK) {
bytes += out.print(",WPA_PSK");
} else if (info.ap.authmode == WIFI_AUTH_WPA2_PSK) {
bytes += out.print(",WPA2_PSK");
} else if (info.ap.authmode == WIFI_AUTH_WPA_WPA2_PSK) {
bytes += out.print(",WPA_WPA2_PSK");
} else if (info.ap.authmode == WIFI_AUTH_ENTERPRISE) {
bytes += out.print(",WEAP");
} else if (info.ap.authmode == WIFI_AUTH_WPA3_PSK) {
bytes += out.print(",WPA3_PSK");
} else if (info.ap.authmode == WIFI_AUTH_WPA2_WPA3_PSK) {
bytes += out.print(",WPA2_WPA3_PSK");
} else if (info.ap.authmode == WIFI_AUTH_WAPI_PSK) {
bytes += out.print(",WAPI_PSK");
} else if (info.ap.authmode == WIFI_AUTH_OWE) {
bytes += out.print(",OWE");
} else if (info.ap.authmode == WIFI_AUTH_WPA3_ENT_192) {
bytes += out.print(",WPA3_ENT_SUITE_B_192_BIT");
}
if (esp_wifi_ap_get_sta_list(&clients) == ESP_OK) {
bytes += out.print(",STA:");
bytes += out.print(clients.num);
}
return bytes;
}
#endif /* SOC_WIFI_SUPPORTED */
+800
View File
@@ -0,0 +1,800 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "WiFi.h"
#include "WiFiGeneric.h"
#include "WiFiSTA.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <esp_err.h>
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp32-hal.h>
#include <lwip/ip_addr.h>
#include "lwip/err.h"
#include "lwip/dns.h"
#include <esp_smartconfig.h>
#include <esp_netif.h>
#include "esp_mac.h"
#if __has_include("esp_eap_client.h")
#include "esp_eap_client.h"
#else
#include "esp_wpa2.h"
#endif
esp_netif_t *get_esp_interface_netif(esp_interface_t interface);
static size_t _wifi_strncpy(char *dst, const char *src, size_t dst_len) {
if (!dst || !src || !dst_len) {
return 0;
}
size_t src_len = strlen(src);
if (src_len >= dst_len) {
src_len = dst_len;
} else {
src_len += 1;
}
memcpy(dst, src, src_len);
return src_len;
}
static STAClass *_sta_network_if = NULL;
static esp_event_handler_instance_t _sta_ev_instance = NULL;
static void _sta_event_cb(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
if (event_base == WIFI_EVENT) {
((STAClass *)arg)->_onStaEvent(event_id, event_data);
}
}
static bool _is_staReconnectableReason(uint8_t reason) {
switch (reason) {
case WIFI_REASON_UNSPECIFIED:
//Timeouts (retry)
case WIFI_REASON_AUTH_EXPIRE:
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT:
case WIFI_REASON_802_1X_AUTH_FAILED:
case WIFI_REASON_HANDSHAKE_TIMEOUT:
//Transient error (reconnect)
case WIFI_REASON_AUTH_LEAVE:
case WIFI_REASON_ASSOC_EXPIRE:
case WIFI_REASON_ASSOC_TOOMANY:
case WIFI_REASON_NOT_AUTHED:
case WIFI_REASON_NOT_ASSOCED:
case WIFI_REASON_ASSOC_NOT_AUTHED:
case WIFI_REASON_MIC_FAILURE:
case WIFI_REASON_IE_IN_4WAY_DIFFERS:
case WIFI_REASON_INVALID_PMKID:
case WIFI_REASON_BEACON_TIMEOUT:
case WIFI_REASON_NO_AP_FOUND:
case WIFI_REASON_ASSOC_FAIL:
case WIFI_REASON_CONNECTION_FAIL:
case WIFI_REASON_AP_TSF_RESET:
case WIFI_REASON_ROAMING: return true;
default: return false;
}
}
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
static const char *auth_mode_str(int authmode) {
switch (authmode) {
case WIFI_AUTH_OPEN: return ("OPEN"); break;
case WIFI_AUTH_WEP: return ("WEP"); break;
case WIFI_AUTH_WPA_PSK: return ("WPA_PSK"); break;
case WIFI_AUTH_WPA2_PSK: return ("WPA2_PSK"); break;
case WIFI_AUTH_WPA_WPA2_PSK: return ("WPA_WPA2_PSK"); break;
case WIFI_AUTH_WPA2_ENTERPRISE: return ("WPA2_ENTERPRISE"); break;
case WIFI_AUTH_WPA3_PSK: return ("WPA3_PSK"); break;
case WIFI_AUTH_WPA2_WPA3_PSK: return ("WPA2_WPA3_PSK"); break;
case WIFI_AUTH_WAPI_PSK: return ("WPAPI_PSK"); break;
default: break;
}
return ("UNKNOWN");
}
#endif
static void _onStaArduinoEvent(arduino_event_t *ev) {
if (_sta_network_if == NULL || ev->event_id < ARDUINO_EVENT_WIFI_STA_START || ev->event_id > ARDUINO_EVENT_WIFI_STA_LOST_IP) {
return;
}
static bool first_connect = true;
log_v("Arduino STA Event: %d - %s", ev->event_id, Network.eventName(ev->event_id));
if (ev->event_id == ARDUINO_EVENT_WIFI_STA_START) {
_sta_network_if->_setStatus(WL_DISCONNECTED);
if (esp_wifi_set_ps(WiFi.getSleep()) != ESP_OK) {
log_e("esp_wifi_set_ps failed");
}
} else if (ev->event_id == ARDUINO_EVENT_WIFI_STA_STOP) {
_sta_network_if->_setStatus(WL_STOPPED);
} else if (ev->event_id == ARDUINO_EVENT_WIFI_STA_CONNECTED) {
_sta_network_if->_setStatus(WL_IDLE_STATUS);
#if CONFIG_LWIP_IPV6
if (_sta_network_if->getStatusBits() & ESP_NETIF_WANT_IP6_BIT) {
esp_err_t err = esp_netif_create_ip6_linklocal(_sta_network_if->netif());
if (err != ESP_OK) {
log_e("Failed to enable IPv6 Link Local on STA: 0x%x: %s", err, esp_err_to_name(err));
} else {
log_v("Enabled IPv6 Link Local on %s", _sta_network_if->desc());
}
}
#endif
} else if (ev->event_id == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) {
uint8_t reason = ev->event_info.wifi_sta_disconnected.reason;
// Reason 0 causes crash, use reason 1 (UNSPECIFIED) instead
if (!reason) {
reason = WIFI_REASON_UNSPECIFIED;
}
log_w("Reason: %u - %s", reason, WiFi.STA.disconnectReasonName((wifi_err_reason_t)reason));
if (reason == WIFI_REASON_NO_AP_FOUND) {
_sta_network_if->_setStatus(WL_NO_SSID_AVAIL);
} else if ((reason == WIFI_REASON_AUTH_FAIL) && !first_connect) {
_sta_network_if->_setStatus(WL_CONNECT_FAILED);
} else if (reason == WIFI_REASON_BEACON_TIMEOUT || reason == WIFI_REASON_HANDSHAKE_TIMEOUT) {
_sta_network_if->_setStatus(WL_CONNECTION_LOST);
} else if (reason == WIFI_REASON_AUTH_EXPIRE) {
} else {
_sta_network_if->_setStatus(WL_DISCONNECTED);
}
bool DoReconnect = false;
if (reason == WIFI_REASON_ASSOC_LEAVE) { //Voluntarily disconnected. Don't reconnect!
} else if (first_connect) { //Retry once for all failure reasons
first_connect = false;
DoReconnect = true;
log_d("WiFi Reconnect Running");
} else if (_sta_network_if->getAutoReconnect() && _is_staReconnectableReason(reason)) {
DoReconnect = true;
log_d("WiFi AutoReconnect Running");
} else if (reason == WIFI_REASON_ASSOC_FAIL) {
_sta_network_if->_setStatus(WL_CONNECT_FAILED);
}
if (DoReconnect) {
_sta_network_if->disconnect();
_sta_network_if->connect();
}
} else if (ev->event_id == ARDUINO_EVENT_WIFI_STA_GOT_IP) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
uint8_t *ip = (uint8_t *)&(ev->event_info.got_ip.ip_info.ip.addr);
uint8_t *mask = (uint8_t *)&(ev->event_info.got_ip.ip_info.netmask.addr);
uint8_t *gw = (uint8_t *)&(ev->event_info.got_ip.ip_info.gw.addr);
log_v(
"STA IP: %u.%u.%u.%u, MASK: %u.%u.%u.%u, GW: %u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3], mask[0], mask[1], mask[2], mask[3], gw[0], gw[1], gw[2], gw[3]
);
#endif
_sta_network_if->_setStatus(WL_CONNECTED);
} else if (ev->event_id == ARDUINO_EVENT_WIFI_STA_LOST_IP) {
_sta_network_if->_setStatus(WL_IDLE_STATUS);
}
}
void STAClass::_onStaEvent(int32_t event_id, void *event_data) {
arduino_event_t arduino_event;
arduino_event.event_id = ARDUINO_EVENT_MAX;
if (event_id == WIFI_EVENT_STA_START) {
log_v("STA Started");
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_START;
setStatusBits(ESP_NETIF_STARTED_BIT);
} else if (event_id == WIFI_EVENT_STA_STOP) {
log_v("STA Stopped");
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_STOP;
clearStatusBits(
ESP_NETIF_STARTED_BIT | ESP_NETIF_CONNECTED_BIT | ESP_NETIF_HAS_IP_BIT | ESP_NETIF_HAS_LOCAL_IP6_BIT | ESP_NETIF_HAS_GLOBAL_IP6_BIT
| ESP_NETIF_HAS_STATIC_IP_BIT
);
} else if (event_id == WIFI_EVENT_STA_AUTHMODE_CHANGE) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_sta_authmode_change_t *event = (wifi_event_sta_authmode_change_t *)event_data;
log_v("STA Auth Mode Changed: From: %s, To: %s", auth_mode_str(event->old_mode), auth_mode_str(event->new_mode));
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE;
memcpy(&arduino_event.event_info.wifi_sta_authmode_change, event_data, sizeof(wifi_event_sta_authmode_change_t));
} else if (event_id == WIFI_EVENT_STA_CONNECTED) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_sta_connected_t *event = (wifi_event_sta_connected_t *)event_data;
log_v(
"STA Connected: SSID: %s, BSSID: " MACSTR ", Channel: %u, Auth: %s", event->ssid, MAC2STR(event->bssid), event->channel, auth_mode_str(event->authmode)
);
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_CONNECTED;
memcpy(&arduino_event.event_info.wifi_sta_connected, event_data, sizeof(wifi_event_sta_connected_t));
setStatusBits(ESP_NETIF_CONNECTED_BIT);
} else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
wifi_event_sta_disconnected_t *event = (wifi_event_sta_disconnected_t *)event_data;
log_v("STA Disconnected: SSID: %s, BSSID: " MACSTR ", Reason: %u", event->ssid, MAC2STR(event->bssid), event->reason);
#endif
arduino_event.event_id = ARDUINO_EVENT_WIFI_STA_DISCONNECTED;
memcpy(&arduino_event.event_info.wifi_sta_disconnected, event_data, sizeof(wifi_event_sta_disconnected_t));
clearStatusBits(ESP_NETIF_CONNECTED_BIT | ESP_NETIF_HAS_IP_BIT | ESP_NETIF_HAS_LOCAL_IP6_BIT | ESP_NETIF_HAS_GLOBAL_IP6_BIT);
} else {
return;
}
if (arduino_event.event_id < ARDUINO_EVENT_MAX) {
Network.postEvent(&arduino_event);
}
}
STAClass::STAClass()
: _minSecurity(WIFI_AUTH_WPA2_PSK), _scanMethod(WIFI_FAST_SCAN), _sortMethod(WIFI_CONNECT_AP_BY_SIGNAL), _autoReconnect(true), _status(WL_STOPPED),
_wifi_sta_event_handle(0) {
_sta_network_if = this;
}
STAClass::~STAClass() {
end();
_sta_network_if = NULL;
}
wl_status_t STAClass::status() {
return _status;
}
void STAClass::_setStatus(wl_status_t status) {
_status = status;
}
/**
* Sets the working bandwidth of the STA mode
* @param m wifi_bandwidth_t
*/
bool STAClass::bandwidth(wifi_bandwidth_t bandwidth) {
if (!begin()) {
return false;
}
esp_err_t err;
err = esp_wifi_set_bandwidth(WIFI_IF_STA, bandwidth);
if (err) {
log_e("Could not set STA bandwidth! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
return true;
}
bool STAClass::onEnable() {
if (_sta_ev_instance == NULL && esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &_sta_event_cb, this, &_sta_ev_instance)) {
log_e("event_handler_instance_register for WIFI_EVENT Failed!");
return false;
}
if (_esp_netif == NULL) {
_esp_netif = get_esp_interface_netif(ESP_IF_WIFI_STA);
if (_esp_netif == NULL) {
log_e("STA was enabled, but netif is NULL???");
return false;
}
/* attach to receive events */
_wifi_sta_event_handle = Network.onSysEvent(_onStaArduinoEvent);
initNetif(ESP_NETIF_ID_STA);
}
return true;
}
bool STAClass::onDisable() {
Network.removeEvent(_wifi_sta_event_handle);
_wifi_sta_event_handle = 0;
// we just set _esp_netif to NULL here, so destroyNetif() does not try to destroy it.
// That would be done by WiFi.enableSTA(false) if AP is not enabled, or when it gets disabled
_esp_netif = NULL;
destroyNetif();
if (_sta_ev_instance != NULL) {
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &_sta_event_cb);
_sta_ev_instance = NULL;
}
return true;
}
bool STAClass::begin(bool tryConnect) {
if (!WiFi.enableSTA(true)) {
log_e("STA enable failed!");
return false;
}
if (!waitStatusBits(ESP_NETIF_STARTED_BIT, 1000)) {
log_e("Failed to start STA!");
return false;
}
if (tryConnect) {
return connect();
}
return true;
}
bool STAClass::end() {
if (!WiFi.enableSTA(false)) {
log_e("STA disable failed!");
return false;
}
return true;
}
bool STAClass::connect() {
if (_esp_netif == NULL) {
log_e("STA not started! You must call begin() first.");
return false;
}
if (connected()) {
log_w("STA already connected.");
return true;
}
wifi_config_t current_conf;
if (esp_wifi_get_config(WIFI_IF_STA, &current_conf) != ESP_OK || esp_wifi_set_config(WIFI_IF_STA, &current_conf) != ESP_OK) {
log_e("STA config failed");
return false;
}
if ((getStatusBits() & ESP_NETIF_HAS_STATIC_IP_BIT) == 0 && !config()) {
log_e("STA failed to configure dynamic IP!");
return false;
}
esp_err_t err = esp_wifi_connect();
if (err) {
log_e("STA connect failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
return true;
}
/**
* Start Wifi connection
* if passphrase is set the most secure supported mode will be automatically selected
* @param ssid const char* Pointer to the SSID string.
* @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal).
* @param bssid uint8_t[6] Optional. BSSID / MAC of AP
* @param channel Optional. Channel of AP
* @param tryConnect Optional. call connect
* @return
*/
bool STAClass::connect(const char *ssid, const char *passphrase, int32_t channel, const uint8_t *bssid, bool tryConnect) {
if (_esp_netif == NULL) {
log_e("STA not started! You must call begin() first.");
return false;
}
if (connected()) {
log_w("STA currently connected. Disconnecting...");
if (!disconnect(true, 1000)) {
return false;
}
}
if (!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
log_e("SSID too long or missing!");
return false;
}
if (passphrase && strlen(passphrase) > 64) {
log_e("passphrase too long!");
return false;
}
wifi_config_t conf;
memset(&conf, 0, sizeof(wifi_config_t));
conf.sta.channel = channel;
conf.sta.scan_method = _scanMethod;
conf.sta.sort_method = _sortMethod;
conf.sta.threshold.rssi = -127;
conf.sta.pmf_cfg.capable = true;
if (ssid != NULL && ssid[0] != 0) {
_wifi_strncpy((char *)conf.sta.ssid, ssid, 32);
if (passphrase != NULL && passphrase[0] != 0) {
conf.sta.threshold.authmode = _minSecurity;
_wifi_strncpy((char *)conf.sta.password, passphrase, 64);
}
if (bssid != NULL) {
conf.sta.bssid_set = 1;
memcpy(conf.sta.bssid, bssid, 6);
}
}
esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &conf);
if (err != ESP_OK) {
log_e("STA clear config failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
if ((getStatusBits() & ESP_NETIF_HAS_STATIC_IP_BIT) == 0 && !config()) {
log_e("STA failed to configure dynamic IP!");
return false;
}
if (tryConnect) {
esp_err_t err = esp_wifi_connect();
if (err) {
log_e("STA connect failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
}
return true;
}
#if CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT
/**
* Start Wifi connection with a WPA2 Enterprise AP
* if passphrase is set the most secure supported mode will be automatically selected
* @param ssid const char* Pointer to the SSID string.
* @param method wpa2_method_t The authentication method of WPA2 (WPA2_AUTH_TLS, WPA2_AUTH_PEAP, WPA2_AUTH_TTLS)
* @param wpa2_identity const char* Pointer to the entity
* @param wpa2_username const char* Pointer to the username
* @param password const char * Pointer to the password.
* @param ca_pem const char* Pointer to a string with the contents of a .pem file with CA cert
* @param client_crt const char* Pointer to a string with the contents of a .crt file with client cert
* @param client_key const char* Pointer to a string with the contents of a .key file with client key
* @param bssid uint8_t[6] Optional. BSSID / MAC of AP
* @param channel Optional. Channel of AP
* @param tryConnect Optional. call connect
* @return
*/
bool STAClass::connect(
const char *wpa2_ssid, wpa2_auth_method_t method, const char *wpa2_identity, const char *wpa2_username, const char *wpa2_password, const char *ca_pem,
const char *client_crt, const char *client_key, int ttls_phase2_type, int32_t channel, const uint8_t *bssid, bool tryConnect
) {
if (_esp_netif == NULL) {
log_e("STA not started! You must call begin() first.");
return false;
}
if (connected()) {
log_w("STA currently connected. Disconnecting...");
if (!disconnect(true, 1000)) {
return false;
}
}
if (!wpa2_ssid || *wpa2_ssid == 0x00 || strlen(wpa2_ssid) > 32) {
log_e("SSID too long or missing!");
return false;
}
if (wpa2_identity && strlen(wpa2_identity) > 64) {
log_e("identity too long!");
return false;
}
if (wpa2_username && strlen(wpa2_username) > 64) {
log_e("username too long!");
return false;
}
if (wpa2_password && strlen(wpa2_password) > 64) {
log_e("password too long!");
return false;
}
if (ttls_phase2_type >= 0) {
#if __has_include("esp_eap_client.h")
esp_eap_client_set_ttls_phase2_method((esp_eap_ttls_phase2_types)ttls_phase2_type);
#else
esp_wifi_sta_wpa2_ent_set_ttls_phase2_method((esp_eap_ttls_phase2_types)ttls_phase2_type);
#endif
}
if (ca_pem) {
#if __has_include("esp_eap_client.h")
esp_eap_client_set_ca_cert((uint8_t *)ca_pem, strlen(ca_pem));
#else
esp_wifi_sta_wpa2_ent_set_ca_cert((uint8_t *)ca_pem, strlen(ca_pem));
#endif
}
if (client_crt) {
#if __has_include("esp_eap_client.h")
esp_eap_client_set_certificate_and_key((uint8_t *)client_crt, strlen(client_crt), (uint8_t *)client_key, strlen(client_key), NULL, 0);
#else
esp_wifi_sta_wpa2_ent_set_cert_key((uint8_t *)client_crt, strlen(client_crt), (uint8_t *)client_key, strlen(client_key), NULL, 0);
#endif
}
#if __has_include("esp_eap_client.h")
esp_eap_client_set_identity((uint8_t *)wpa2_identity, strlen(wpa2_identity));
#else
esp_wifi_sta_wpa2_ent_set_identity((uint8_t *)wpa2_identity, strlen(wpa2_identity));
#endif
if (method == WPA2_AUTH_PEAP || method == WPA2_AUTH_TTLS) {
#if __has_include("esp_eap_client.h")
esp_eap_client_set_username((uint8_t *)wpa2_username, strlen(wpa2_username));
esp_eap_client_set_password((uint8_t *)wpa2_password, strlen(wpa2_password));
#else
esp_wifi_sta_wpa2_ent_set_username((uint8_t *)wpa2_username, strlen(wpa2_username));
esp_wifi_sta_wpa2_ent_set_password((uint8_t *)wpa2_password, strlen(wpa2_password));
#endif
}
#if __has_include("esp_eap_client.h")
esp_wifi_sta_enterprise_enable(); //set config settings to enable function
#else
esp_wifi_sta_wpa2_ent_enable(); //set config settings to enable function
#endif
return connect(wpa2_ssid, NULL, channel, bssid, tryConnect); //connect to wifi
}
#endif /* CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT */
bool STAClass::disconnect(bool eraseap, unsigned long timeout) {
esp_err_t err = esp_wifi_disconnect();
if (err != ESP_OK) {
log_e("STA disconnect failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
if (timeout) {
const unsigned long start = millis();
while (connected() && ((millis() - start) < timeout)) {
delay(5);
}
if (connected()) {
return false;
}
}
if (eraseap) {
if (!started()) {
log_e("STA not started! You must call begin first.");
return false;
}
wifi_config_t conf;
memset(&conf, 0, sizeof(wifi_config_t));
esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &conf);
if (err != ESP_OK) {
log_e("STA clear config failed! 0x%x: %s", err, esp_err_to_name(err));
return false;
}
}
return true;
}
bool STAClass::reconnect() {
if (connected()) {
if (esp_wifi_disconnect() != ESP_OK) {
return false;
}
}
return esp_wifi_connect() == ESP_OK;
}
bool STAClass::erase() {
if (!started()) {
log_e("STA not started! You must call begin first.");
return false;
}
return esp_wifi_restore() == ESP_OK;
}
uint8_t STAClass::waitForConnectResult(unsigned long timeoutLength) {
//1 and 3 have STA enabled
if ((WiFiGenericClass::getMode() & WIFI_MODE_STA) == 0) {
return WL_DISCONNECTED;
}
unsigned long start = millis();
while ((!status() || status() >= WL_DISCONNECTED) && (millis() - start) < timeoutLength) {
delay(100);
}
return status();
}
bool STAClass::setAutoReconnect(bool autoReconnect) {
_autoReconnect = autoReconnect;
return true;
}
bool STAClass::getAutoReconnect() {
return _autoReconnect;
}
void STAClass::setMinSecurity(wifi_auth_mode_t minSecurity) {
_minSecurity = minSecurity;
}
void STAClass::setScanMethod(wifi_scan_method_t scanMethod) {
_scanMethod = scanMethod;
}
void STAClass::setSortMethod(wifi_sort_method_t sortMethod) {
_sortMethod = sortMethod;
}
String STAClass::SSID() const {
if (!started()) {
return String();
}
wifi_ap_record_t info;
if (!esp_wifi_sta_get_ap_info(&info)) {
return String(reinterpret_cast<char *>(info.ssid));
}
return String();
}
String STAClass::psk() const {
if (!started()) {
return String();
}
wifi_config_t conf;
esp_wifi_get_config((wifi_interface_t)ESP_IF_WIFI_STA, &conf);
return String(reinterpret_cast<char *>(conf.sta.password));
}
uint8_t *STAClass::BSSID(uint8_t *buff) {
static uint8_t bssid[6];
wifi_ap_record_t info;
if (!started()) {
return NULL;
}
esp_err_t err = esp_wifi_sta_get_ap_info(&info);
if (buff != NULL) {
if (err) {
memset(buff, 0, 6);
} else {
memcpy(buff, info.bssid, 6);
}
return buff;
}
if (!err) {
memcpy(bssid, info.bssid, 6);
return reinterpret_cast<uint8_t *>(bssid);
}
return NULL;
}
String STAClass::BSSIDstr() {
uint8_t *bssid = BSSID();
if (!bssid) {
return String();
}
char mac[18] = {0};
sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
return String(mac);
}
int8_t STAClass::RSSI() {
if (!started()) {
return 0;
}
wifi_ap_record_t info;
if (!esp_wifi_sta_get_ap_info(&info)) {
return info.rssi;
}
return 0;
}
size_t STAClass::printDriverInfo(Print &out) const {
size_t bytes = 0;
wifi_ap_record_t info;
if (!started()) {
return bytes;
}
if (esp_wifi_sta_get_ap_info(&info) != ESP_OK) {
return bytes;
}
bytes += out.print(",");
bytes += out.print((const char *)info.ssid);
bytes += out.print(",CH:");
bytes += out.print(info.primary);
bytes += out.print(",RSSI:");
bytes += out.print(info.rssi);
bytes += out.print(",");
if (info.phy_11ax) {
bytes += out.print("AX");
} else if (info.phy_11n) {
bytes += out.print("N");
} else if (info.phy_11g) {
bytes += out.print("G");
} else if (info.phy_11b) {
bytes += out.print("B");
}
if (info.phy_lr) {
bytes += out.print(",");
bytes += out.print("LR");
}
if (info.authmode == WIFI_AUTH_OPEN) {
bytes += out.print(",OPEN");
} else if (info.authmode == WIFI_AUTH_WEP) {
bytes += out.print(",WEP");
} else if (info.authmode == WIFI_AUTH_WPA_PSK) {
bytes += out.print(",WPA_PSK");
} else if (info.authmode == WIFI_AUTH_WPA2_PSK) {
bytes += out.print(",WPA2_PSK");
} else if (info.authmode == WIFI_AUTH_WPA_WPA2_PSK) {
bytes += out.print(",WPA_WPA2_PSK");
} else if (info.authmode == WIFI_AUTH_ENTERPRISE) {
bytes += out.print(",EAP");
} else if (info.authmode == WIFI_AUTH_WPA3_PSK) {
bytes += out.print(",WPA3_PSK");
} else if (info.authmode == WIFI_AUTH_WPA2_WPA3_PSK) {
bytes += out.print(",WPA2_WPA3_PSK");
} else if (info.authmode == WIFI_AUTH_WAPI_PSK) {
bytes += out.print(",WAPI_PSK");
} else if (info.authmode == WIFI_AUTH_OWE) {
bytes += out.print(",OWE");
} else if (info.authmode == WIFI_AUTH_WPA3_ENT_192) {
bytes += out.print(",WPA3_ENT_SUITE_B_192_BIT");
}
return bytes;
}
/**
* @brief Convert wifi_err_reason_t to a string.
* @param [in] reason The reason to be converted.
* @return A string representation of the error code.
* @note: wifi_err_reason_t values as of Mar 2023 (arduino-esp32 r2.0.7) are: (1-39, 46-51, 67-68, 200-208) and are defined in /tools/sdk/esp32/include/esp_wifi/include/esp_wifi_types.h.
*/
const char *STAClass::disconnectReasonName(wifi_err_reason_t reason) {
switch (reason) {
//ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2,0,7)
case WIFI_REASON_UNSPECIFIED: return "UNSPECIFIED";
case WIFI_REASON_AUTH_EXPIRE: return "AUTH_EXPIRE";
case WIFI_REASON_AUTH_LEAVE: return "AUTH_LEAVE";
case WIFI_REASON_ASSOC_EXPIRE: return "ASSOC_EXPIRE";
case WIFI_REASON_ASSOC_TOOMANY: return "ASSOC_TOOMANY";
case WIFI_REASON_NOT_AUTHED: return "NOT_AUTHED";
case WIFI_REASON_NOT_ASSOCED: return "NOT_ASSOCED";
case WIFI_REASON_ASSOC_LEAVE: return "ASSOC_LEAVE";
case WIFI_REASON_ASSOC_NOT_AUTHED: return "ASSOC_NOT_AUTHED";
case WIFI_REASON_DISASSOC_PWRCAP_BAD: return "DISASSOC_PWRCAP_BAD";
case WIFI_REASON_DISASSOC_SUPCHAN_BAD: return "DISASSOC_SUPCHAN_BAD";
case WIFI_REASON_BSS_TRANSITION_DISASSOC: return "BSS_TRANSITION_DISASSOC";
case WIFI_REASON_IE_INVALID: return "IE_INVALID";
case WIFI_REASON_MIC_FAILURE: return "MIC_FAILURE";
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: return "4WAY_HANDSHAKE_TIMEOUT";
case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT: return "GROUP_KEY_UPDATE_TIMEOUT";
case WIFI_REASON_IE_IN_4WAY_DIFFERS: return "IE_IN_4WAY_DIFFERS";
case WIFI_REASON_GROUP_CIPHER_INVALID: return "GROUP_CIPHER_INVALID";
case WIFI_REASON_PAIRWISE_CIPHER_INVALID: return "PAIRWISE_CIPHER_INVALID";
case WIFI_REASON_AKMP_INVALID: return "AKMP_INVALID";
case WIFI_REASON_UNSUPP_RSN_IE_VERSION: return "UNSUPP_RSN_IE_VERSION";
case WIFI_REASON_INVALID_RSN_IE_CAP: return "INVALID_RSN_IE_CAP";
case WIFI_REASON_802_1X_AUTH_FAILED: return "802_1X_AUTH_FAILED";
case WIFI_REASON_CIPHER_SUITE_REJECTED: return "CIPHER_SUITE_REJECTED";
case WIFI_REASON_TDLS_PEER_UNREACHABLE: return "TDLS_PEER_UNREACHABLE";
case WIFI_REASON_TDLS_UNSPECIFIED: return "TDLS_UNSPECIFIED";
case WIFI_REASON_SSP_REQUESTED_DISASSOC: return "SSP_REQUESTED_DISASSOC";
case WIFI_REASON_NO_SSP_ROAMING_AGREEMENT: return "NO_SSP_ROAMING_AGREEMENT";
case WIFI_REASON_BAD_CIPHER_OR_AKM: return "BAD_CIPHER_OR_AKM";
case WIFI_REASON_NOT_AUTHORIZED_THIS_LOCATION: return "NOT_AUTHORIZED_THIS_LOCATION";
case WIFI_REASON_SERVICE_CHANGE_PERCLUDES_TS: return "SERVICE_CHANGE_PERCLUDES_TS";
case WIFI_REASON_UNSPECIFIED_QOS: return "UNSPECIFIED_QOS";
case WIFI_REASON_NOT_ENOUGH_BANDWIDTH: return "NOT_ENOUGH_BANDWIDTH";
case WIFI_REASON_MISSING_ACKS: return "MISSING_ACKS";
case WIFI_REASON_EXCEEDED_TXOP: return "EXCEEDED_TXOP";
case WIFI_REASON_STA_LEAVING: return "STA_LEAVING";
case WIFI_REASON_END_BA: return "END_BA";
case WIFI_REASON_UNKNOWN_BA: return "UNKNOWN_BA";
case WIFI_REASON_TIMEOUT: return "TIMEOUT";
case WIFI_REASON_PEER_INITIATED: return "PEER_INITIATED";
case WIFI_REASON_AP_INITIATED: return "AP_INITIATED";
case WIFI_REASON_INVALID_FT_ACTION_FRAME_COUNT: return "INVALID_FT_ACTION_FRAME_COUNT";
case WIFI_REASON_INVALID_PMKID: return "INVALID_PMKID";
case WIFI_REASON_INVALID_MDE: return "INVALID_MDE";
case WIFI_REASON_INVALID_FTE: return "INVALID_FTE";
case WIFI_REASON_TRANSMISSION_LINK_ESTABLISH_FAILED: return "TRANSMISSION_LINK_ESTABLISH_FAILED";
case WIFI_REASON_ALTERATIVE_CHANNEL_OCCUPIED: return "ALTERATIVE_CHANNEL_OCCUPIED";
case WIFI_REASON_BEACON_TIMEOUT: return "BEACON_TIMEOUT";
case WIFI_REASON_NO_AP_FOUND: return "NO_AP_FOUND";
case WIFI_REASON_AUTH_FAIL: return "AUTH_FAIL";
case WIFI_REASON_ASSOC_FAIL: return "ASSOC_FAIL";
case WIFI_REASON_HANDSHAKE_TIMEOUT: return "HANDSHAKE_TIMEOUT";
case WIFI_REASON_CONNECTION_FAIL: return "CONNECTION_FAIL";
case WIFI_REASON_AP_TSF_RESET: return "AP_TSF_RESET";
case WIFI_REASON_ROAMING: return "ROAMING";
case WIFI_REASON_ASSOC_COMEBACK_TIME_TOO_LONG: return "ASSOC_COMEBACK_TIME_TOO_LONG";
default: return "";
}
}
#endif /* SOC_WIFI_SUPPORTED */
+99
View File
@@ -0,0 +1,99 @@
/*
ESP8266WiFi.cpp - WiFi library for esp8266
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Reworked on 28 Dec 2015 by Markus Sattler
*/
#include "WiFi.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
extern "C" {
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <esp_err.h>
#include <esp_wifi.h>
#include <esp_event.h>
}
// -----------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------- Debug ------------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------
/**
* Output WiFi settings to an object derived from Print interface (like Serial).
* @param p Print interface
*/
void WiFiClass::printDiag(Print &p) {
const char *modes[] = {"NULL", "STA", "AP", "STA+AP", "NAN"};
wifi_mode_t mode = WIFI_MODE_NULL;
esp_wifi_get_mode(&mode);
uint8_t primaryChan = 0;
wifi_second_chan_t secondChan = WIFI_SECOND_CHAN_NONE;
esp_wifi_get_channel(&primaryChan, &secondChan);
p.print("Mode: ");
p.println(modes[mode]);
p.print("Channel: ");
p.println(primaryChan);
/*
p.print("AP id: ");
p.println(wifi_station_get_current_ap_id());
p.print("Status: ");
p.println(wifi_station_get_connect_status());
*/
wifi_config_t conf = {0};
esp_wifi_get_config((wifi_interface_t)WIFI_IF_STA, &conf);
const char *ssid = reinterpret_cast<const char *>(conf.sta.ssid);
p.print("SSID (");
p.print(strlen(ssid));
p.print("): ");
p.println(ssid);
const char *passphrase = reinterpret_cast<const char *>(conf.sta.password);
p.print("Passphrase (");
p.print(strlen(passphrase));
p.print("): ");
p.println(passphrase);
p.print("BSSID set: ");
p.println(conf.sta.bssid_set);
}
void WiFiClass::enableProv(bool status) {
prov_enable = status;
}
bool WiFiClass::isProvEnabled() {
return prov_enable;
}
WiFiClass WiFi;
#endif /* SOC_WIFI_SUPPORTED */
+77
View File
@@ -0,0 +1,77 @@
/*
WiFi.h - esp32 Wifi support.
Based on WiFi.h from Arduino WiFi shield library.
Copyright (c) 2011-2014 Arduino. All right reserved.
Modified by Ivan Grokhotkov, December 2014
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include <stdint.h>
#include "Print.h"
#include "IPAddress.h"
#include "WiFiType.h"
#include "WiFiSTA.h"
#include "WiFiAP.h"
#include "WiFiScan.h"
#include "WiFiGeneric.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
#include "WiFiUdp.h"
class WiFiClass : public WiFiGenericClass, public WiFiSTAClass, public WiFiScanClass, public WiFiAPClass {
private:
bool prov_enable;
public:
WiFiClass() {
prov_enable = false;
}
using WiFiGenericClass::channel;
using WiFiSTAClass::BSSID;
using WiFiSTAClass::BSSIDstr;
using WiFiSTAClass::RSSI;
using WiFiSTAClass::SSID;
using WiFiScanClass::BSSID;
using WiFiScanClass::BSSIDstr;
using WiFiScanClass::channel;
using WiFiScanClass::encryptionType;
using WiFiScanClass::RSSI;
using WiFiScanClass::SSID;
public:
void printDiag(Print &dest);
friend class NetworkClient;
friend class NetworkServer;
friend class NetworkUDP;
void enableProv(bool status);
bool isProvEnabled();
};
extern WiFiClass WiFi;
#endif /* SOC_WIFI_SUPPORTED */
+198
View File
@@ -0,0 +1,198 @@
/*
ESP8266WiFiSTA.cpp - WiFi library for esp8266
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Reworked on 28 Dec 2015 by Markus Sattler
*/
#include "WiFi.h"
#include "WiFiGeneric.h"
#include "WiFiAP.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <esp_err.h>
#include <esp_wifi.h>
#include <esp_event.h>
#include <lwip/ip_addr.h>
#include "dhcpserver/dhcpserver_options.h"
/**
* Set up an access point
* @param ssid Pointer to the SSID (max 63 char).
* @param passphrase (for WPA2 min 8 char, for open use NULL)
* @param channel WiFi channel number, 1 - 13.
* @param ssid_hidden Network cloaking (0 = broadcast SSID, 1 = hide SSID)
* @param max_connection Max simultaneous connected clients, 1 - 4.
*/
bool WiFiAPClass::softAP(
const char *ssid, const char *passphrase, int channel, int ssid_hidden, int max_connection, bool ftm_responder, wifi_auth_mode_t auth_mode,
wifi_cipher_type_t cipher
) {
return AP.begin() && AP.create(ssid, passphrase, channel, ssid_hidden, max_connection, ftm_responder, auth_mode, cipher);
}
/**
* Return the current SSID associated with the network
* @return SSID
*/
String WiFiAPClass::softAPSSID() const {
return AP.SSID();
}
/**
* Configure access point
* @param local_ip access point IP
* @param gateway gateway IP
* @param subnet subnet mask
*/
bool WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dhcp_lease_start, IPAddress dns) {
return AP.begin() && AP.config(local_ip, gateway, subnet, dhcp_lease_start, dns);
}
/**
* Disconnect from the network (close AP)
* @param wifioff disable mode?
* @return one value of wl_status_t enum
*/
bool WiFiAPClass::softAPdisconnect(bool wifioff) {
if (!AP.clear()) {
return false;
}
if (wifioff) {
return AP.end();
}
return true;
}
/**
* Sets the working bandwidth of the AP mode
* @param m wifi_bandwidth_t
*/
bool WiFiAPClass::softAPbandwidth(wifi_bandwidth_t bandwidth) {
return AP.bandwidth(bandwidth);
}
/**
* Get the count of the Station / client that are connected to the softAP interface
* @return Stations count
*/
uint8_t WiFiAPClass::softAPgetStationNum() {
return AP.stationCount();
}
/**
* Get the softAP interface IP address.
* @return IPAddress softAP IP
*/
IPAddress WiFiAPClass::softAPIP() {
return AP.localIP();
}
/**
* Get the softAP broadcast IP address.
* @return IPAddress softAP broadcastIP
*/
IPAddress WiFiAPClass::softAPBroadcastIP() {
return AP.broadcastIP();
}
/**
* Get the softAP network ID.
* @return IPAddress softAP networkID
*/
IPAddress WiFiAPClass::softAPNetworkID() {
return AP.networkID();
}
/**
* Get the softAP subnet mask.
* @return IPAddress subnetMask
*/
IPAddress WiFiAPClass::softAPSubnetMask() {
return AP.subnetMask();
}
/**
* Get the softAP subnet CIDR.
* @return uint8_t softAP subnetCIDR
*/
uint8_t WiFiAPClass::softAPSubnetCIDR() {
return AP.subnetCIDR();
}
/**
* Get the softAP interface MAC address.
* @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
* @return pointer to uint8_t*
*/
uint8_t *WiFiAPClass::softAPmacAddress(uint8_t *mac) {
return AP.macAddress(mac);
}
/**
* Get the softAP interface MAC address.
* @return String mac
*/
String WiFiAPClass::softAPmacAddress(void) {
return AP.macAddress();
}
/**
* Get the softAP interface Host name.
* @return char array hostname
*/
const char *WiFiAPClass::softAPgetHostname() {
return AP.getHostname();
}
/**
* Set the softAP interface Host name.
* @param hostname pointer to const string
* @return true on success
*/
bool WiFiAPClass::softAPsetHostname(const char *hostname) {
return AP.setHostname(hostname);
}
#if CONFIG_LWIP_IPV6
/**
* Enable IPv6 on the softAP interface.
* @return true on success
*/
bool WiFiAPClass::softAPenableIPv6(bool enable) {
return AP.enableIPv6(enable);
}
/**
* Get the softAP interface IPv6 address.
* @return IPAddress softAP IPv6
*/
IPAddress WiFiAPClass::softAPlinkLocalIPv6() {
return AP.linkLocalIPv6();
}
#endif
#endif /* SOC_WIFI_SUPPORTED */
+131
View File
@@ -0,0 +1,131 @@
/*
ESP8266WiFiAP.h - esp8266 Wifi support.
Based on WiFi.h from Arduino WiFi shield library.
Copyright (c) 2011-2014 Arduino. All right reserved.
Modified by Ivan Grokhotkov, December 2014
Reworked by Markus Sattler, December 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include "esp_wifi_types.h"
#include "WiFiType.h"
#include "WiFiGeneric.h"
#define WIFI_AP_DEFAULT_AUTH_MODE WIFI_AUTH_WPA2_PSK
#define WIFI_AP_DEFAULT_CIPHER WIFI_CIPHER_TYPE_CCMP // Disable by default enabled insecure TKIP and use just CCMP.
// ----------------------------------------------------------------------------------------------
// ------------------------------------ NEW AP Implementation ----------------------------------
// ----------------------------------------------------------------------------------------------
class APClass : public NetworkInterface {
public:
APClass();
~APClass();
bool begin();
bool end();
bool create(
const char *ssid, const char *passphrase = NULL, int channel = 1, int ssid_hidden = 0, int max_connection = 4, bool ftm_responder = false,
wifi_auth_mode_t auth_mode = WIFI_AP_DEFAULT_AUTH_MODE, wifi_cipher_type_t cipher = WIFI_AP_DEFAULT_CIPHER
);
bool create(
const String &ssid, const String &passphrase = emptyString, int channel = 1, int ssid_hidden = 0, int max_connection = 4, bool ftm_responder = false,
wifi_auth_mode_t auth_mode = WIFI_AP_DEFAULT_AUTH_MODE, wifi_cipher_type_t cipher = WIFI_AP_DEFAULT_CIPHER
) {
return create(ssid.c_str(), passphrase.c_str(), channel, ssid_hidden, max_connection, ftm_responder, auth_mode, cipher);
}
bool clear();
bool bandwidth(wifi_bandwidth_t bandwidth);
bool enableNAPT(bool enable = true);
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
bool enableDhcpCaptivePortal();
#endif
String SSID(void) const;
uint8_t stationCount();
void _onApEvent(int32_t event_id, void *event_data);
protected:
network_event_handle_t _wifi_ap_event_handle;
size_t printDriverInfo(Print &out) const;
friend class WiFiGenericClass;
bool onEnable();
bool onDisable();
};
// ----------------------------------------------------------------------------------------------
// ------------------------------- OLD AP API (compatibility) ----------------------------------
// ----------------------------------------------------------------------------------------------
class WiFiAPClass {
public:
APClass AP;
bool softAP(
const char *ssid, const char *passphrase = NULL, int channel = 1, int ssid_hidden = 0, int max_connection = 4, bool ftm_responder = false,
wifi_auth_mode_t auth_mode = WIFI_AP_DEFAULT_AUTH_MODE, wifi_cipher_type_t cipher = WIFI_AP_DEFAULT_CIPHER
);
bool softAP(
const String &ssid, const String &passphrase = emptyString, int channel = 1, int ssid_hidden = 0, int max_connection = 4, bool ftm_responder = false,
wifi_auth_mode_t auth_mode = WIFI_AP_DEFAULT_AUTH_MODE, wifi_cipher_type_t cipher = WIFI_AP_DEFAULT_CIPHER
) {
return softAP(ssid.c_str(), passphrase.c_str(), channel, ssid_hidden, max_connection, ftm_responder, auth_mode, cipher);
}
bool softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dhcp_lease_start = (uint32_t)0, IPAddress dns = (uint32_t)0);
bool softAPdisconnect(bool wifioff = false);
bool softAPbandwidth(wifi_bandwidth_t bandwidth);
uint8_t softAPgetStationNum();
String softAPSSID(void) const;
IPAddress softAPIP();
IPAddress softAPBroadcastIP();
IPAddress softAPNetworkID();
IPAddress softAPSubnetMask();
uint8_t softAPSubnetCIDR();
#if CONFIG_LWIP_IPV6
bool softAPenableIPv6(bool enable = true);
IPAddress softAPlinkLocalIPv6();
#endif
const char *softAPgetHostname();
bool softAPsetHostname(const char *hostname);
uint8_t *softAPmacAddress(uint8_t *mac);
String softAPmacAddress(void);
protected:
};
#endif /* SOC_WIFI_SUPPORTED*/
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#include "NetworkClient.h"
typedef NetworkClient WiFiClient;
File diff suppressed because it is too large Load Diff
+164
View File
@@ -0,0 +1,164 @@
/*
ESP8266WiFiGeneric.h - esp8266 Wifi support.
Based on WiFi.h from Ardiono WiFi shield library.
Copyright (c) 2011-2014 Arduino. All right reserved.
Modified by Ivan Grokhotkov, December 2014
Reworked by Markus Sattler, December 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include "esp_err.h"
#include "esp_event.h"
#include <functional>
#include "WiFiType.h"
#include "IPAddress.h"
#include "esp_smartconfig.h"
#include "esp_netif_types.h"
#if CONFIG_ETH_ENABLED
#include "esp_eth_driver.h"
#endif
#if CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI
#include "network_provisioning/manager.h"
#endif
#include "lwip/ip_addr.h"
#include "Network.h"
#define WiFiEventCb NetworkEventCb
#define WiFiEventFuncCb NetworkEventFuncCb
#define WiFiEventSysCb NetworkEventSysCb
#define wifi_event_id_t network_event_handle_t
typedef enum {
WIFI_POWER_21dBm = 84, // 21dBm
WIFI_POWER_20_5dBm = 82, // 20.5dBm
WIFI_POWER_20dBm = 80, // 20dBm
WIFI_POWER_19_5dBm = 78, // 19.5dBm
WIFI_POWER_19dBm = 76, // 19dBm
WIFI_POWER_18_5dBm = 74, // 18.5dBm
WIFI_POWER_17dBm = 68, // 17dBm
WIFI_POWER_15dBm = 60, // 15dBm
WIFI_POWER_13dBm = 52, // 13dBm
WIFI_POWER_11dBm = 44, // 11dBm
WIFI_POWER_8_5dBm = 34, // 8.5dBm
WIFI_POWER_7dBm = 28, // 7dBm
WIFI_POWER_5dBm = 20, // 5dBm
WIFI_POWER_2dBm = 8, // 2dBm
WIFI_POWER_MINUS_1dBm = -4 // -1dBm
} wifi_power_t;
typedef enum {
WIFI_RX_ANT0 = 0,
WIFI_RX_ANT1,
WIFI_RX_ANT_AUTO
} wifi_rx_ant_t;
typedef enum {
WIFI_TX_ANT0 = 0,
WIFI_TX_ANT1,
WIFI_TX_ANT_AUTO
} wifi_tx_ant_t;
class WiFiGenericClass {
public:
WiFiGenericClass();
#if CONFIG_ESP_WIFI_REMOTE_ENABLED
// Set SDIO pins for connection to external ESP MCU
static bool setPins(int8_t clk, int8_t cmd, int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t rst);
#endif
wifi_event_id_t onEvent(WiFiEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
wifi_event_id_t onEvent(WiFiEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
wifi_event_id_t onEvent(WiFiEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
void removeEvent(WiFiEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
void removeEvent(WiFiEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
void removeEvent(wifi_event_id_t id);
static int getStatusBits();
static int waitStatusBits(int bits, uint32_t timeout_ms);
int32_t channel(void);
int setChannel(uint8_t primary, wifi_second_chan_t secondary = WIFI_SECOND_CHAN_NONE);
void persistent(bool persistent);
void enableLongRange(bool enable);
static bool mode(wifi_mode_t);
static wifi_mode_t getMode();
bool enableSTA(bool enable);
bool enableAP(bool enable);
bool setSleep(bool enabled);
bool setSleep(wifi_ps_type_t sleepType);
wifi_ps_type_t getSleep();
bool setTxPower(wifi_power_t power);
wifi_power_t getTxPower();
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
bool setBandMode(wifi_band_mode_t band_mode);
wifi_band_mode_t getBandMode();
#endif
wifi_band_t getBand();
bool initiateFTM(uint8_t frm_count = 16, uint16_t burst_period = 2, uint8_t channel = 1, const uint8_t *mac = NULL);
static bool setDualAntennaConfig(uint8_t gpio_ant1, uint8_t gpio_ant2, wifi_rx_ant_t rx_mode, wifi_tx_ant_t tx_mode);
static const char *getHostname();
static bool setHostname(const char *hostname);
static bool hostname(const String &aHostname) {
return setHostname(aHostname.c_str());
}
static void useStaticBuffers(bool bufferMode);
static bool useStaticBuffers();
static int hostByName(const char *aHostname, IPAddress &aResult);
static IPAddress calculateNetworkID(IPAddress ip, IPAddress subnet);
static IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet);
static uint8_t calculateSubnetCIDR(IPAddress subnetMask);
const char *disconnectReasonName(wifi_err_reason_t reason);
const char *eventName(arduino_event_id_t id);
static void _eventCallback(arduino_event_t *event);
protected:
static bool _persistent;
static bool _long_range;
static wifi_ps_type_t _sleepEnabled;
static bool _wifiUseStaticBuffers;
static int setStatusBits(int bits);
static int clearStatusBits(int bits);
friend class WiFiSTAClass;
friend class WiFiScanClass;
friend class WiFiAPClass;
friend class ETHClass;
};
#endif /* SOC_WIFI_SUPPORTED */
+353
View File
@@ -0,0 +1,353 @@
/**
*
* @file WiFiMulti.cpp
* @date 16.05.2015
* @author Markus Sattler
*
* Copyright (c) 2015 Markus Sattler. All rights reserved.
* This file is part of the esp8266 core for Arduino environment.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "WiFiMulti.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include <limits.h>
#include <string.h>
#include <esp32-hal.h>
WiFiMulti::WiFiMulti() {
ipv6_support = false;
}
void WiFiMulti::APlistClean(void) {
for (auto entry : APlist) {
if (entry.ssid) {
free(entry.ssid);
}
if (entry.passphrase) {
free(entry.passphrase);
}
}
APlist.clear();
}
WiFiMulti::~WiFiMulti() {
APlistClean();
}
bool WiFiMulti::addAP(const char *ssid, const char *passphrase) {
WifiAPlist_t newAP;
if (!ssid || *ssid == '\0' || strlen(ssid) > 31) {
// fail SSID too long or missing!
log_e("[WIFI][APlistAdd] no ssid or ssid too long");
return false;
}
if (passphrase && strlen(passphrase) > 63) {
// fail passphrase too long!
log_e("[WIFI][APlistAdd] passphrase too long");
return false;
}
newAP.ssid = strdup(ssid);
if (!newAP.ssid) {
log_e("[WIFI][APlistAdd] fail newAP.ssid == 0");
return false;
}
if (passphrase && *passphrase != '\0') {
newAP.passphrase = strdup(passphrase);
if (!newAP.passphrase) {
log_e("[WIFI][APlistAdd] fail newAP.passphrase == 0");
free(newAP.ssid);
return false;
}
} else {
newAP.passphrase = NULL;
}
newAP.hasFailed = false;
APlist.push_back(newAP);
log_i("[WIFI][APlistAdd] add SSID: %s", newAP.ssid);
return true;
}
uint8_t WiFiMulti::run(uint32_t connectTimeout, bool scanHidden) {
int8_t scanResult;
unsigned long startTime;
uint8_t status = WiFi.status();
if (status == WL_CONNECTED) {
if (!_bWFMInit && _connectionTestCBFunc != NULL) {
if (_connectionTestCBFunc() == true) {
_bWFMInit = true;
return status;
}
} else {
if (!_bStrict) {
return status;
} else {
for (auto ap : APlist) {
if (WiFi.SSID() == ap.ssid) {
return status;
}
}
}
}
WiFi.disconnect(false, false);
delay(10);
status = WiFi.status();
}
scanResult = WiFi.scanNetworks(false, scanHidden);
if (scanResult == WIFI_SCAN_RUNNING) {
// scan is running
return WL_NO_SSID_AVAIL;
} else if (scanResult >= 0) {
// scan done analyze
int32_t bestIndex = -1;
WifiAPlist_t bestNetwork{NULL, NULL, false};
int bestNetworkDb = INT_MIN;
int bestNetworkSec = WIFI_AUTH_MAX;
uint8_t bestBSSID[6];
int32_t bestChannel = 0;
log_i("[WIFI] scan done");
if (scanResult == 0) {
log_e("[WIFI] no networks found");
} else {
log_i("[WIFI] %d networks found", scanResult);
int8_t failCount = 0;
int8_t foundCount = 0;
for (int8_t i = 0; i < scanResult; ++i) {
String ssid_scan;
int32_t rssi_scan;
uint8_t sec_scan;
uint8_t *BSSID_scan;
int32_t chan_scan;
bool hidden_scan;
WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan);
hidden_scan = (ssid_scan.length() == 0) && scanHidden;
// add any Open WiFi AP to the list, if allowed with setAllowOpenAP(true)
if (_bAllowOpenAP && sec_scan == WIFI_AUTH_OPEN) {
bool found = false;
for (auto check : APlist) {
if (ssid_scan == check.ssid) {
found = true;
break;
}
}
// If we didn't find it, add this Open WiFi AP to the list
if (!found) {
log_i("[WIFI][APlistAdd] adding Open WiFi SSID: %s", ssid_scan.c_str());
addAP(ssid_scan.c_str());
}
}
if (hidden_scan) {
log_v("hidden ssid on channel %d found, trying to connect with known credentials...", chan_scan);
}
bool known = false;
for (uint32_t x = 0; x < APlist.size(); x++) {
WifiAPlist_t entry = APlist[x];
if (ssid_scan == entry.ssid || hidden_scan) { // SSID match or hidden network found
if (!hidden_scan) {
log_v("known ssid: %s, has failed: %s", entry.ssid, entry.hasFailed ? "yes" : "no");
foundCount++;
}
if (!entry.hasFailed) {
if (hidden_scan) {
WiFi.begin(entry.ssid, entry.passphrase, chan_scan, BSSID_scan);
// If the ssid returned from the scan is empty, it is a hidden SSID
// it appears that the WiFi.begin() function is asynchronous and takes
// additional time to connect to a hidden SSID. Therefore a delay of 1000ms
// is added for hidden SSIDs before calling WiFi.status()
delay(1000);
status = WiFi.status();
startTime = millis();
while (status != WL_CONNECTED && (millis() - startTime) <= connectTimeout) {
delay(10);
status = WiFi.status();
}
WiFi.disconnect();
delay(10);
if (status == WL_CONNECTED) {
log_v("hidden ssid %s found", entry.ssid);
ssid_scan = entry.ssid;
foundCount++;
} else {
continue;
}
}
known = true;
log_v("rssi_scan: %d, bestNetworkDb: %d", rssi_scan, bestNetworkDb);
if (rssi_scan > bestNetworkDb) { // best network
if (_bAllowOpenAP || (sec_scan == WIFI_AUTH_OPEN || entry.passphrase)) { // check for passphrase if not open wlan
log_v("best network is now: %s", ssid_scan);
bestIndex = x;
bestNetworkSec = sec_scan;
bestNetworkDb = rssi_scan;
bestChannel = chan_scan;
memcpy((void *)&bestNetwork, (void *)&entry, sizeof(bestNetwork));
memcpy((void *)&bestBSSID, (void *)BSSID_scan, sizeof(bestBSSID));
}
}
break;
} else {
failCount++;
}
}
}
if (known) {
log_d(
" ---> %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) (%c) (%s)", i, chan_scan, BSSID_scan[0], BSSID_scan[1], BSSID_scan[2], BSSID_scan[3],
BSSID_scan[4], BSSID_scan[5], ssid_scan.c_str(), rssi_scan, (sec_scan == WIFI_AUTH_OPEN) ? ' ' : '*', (hidden_scan) ? "hidden" : "visible"
);
} else {
log_d(
" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) (%c) (%s)", i, chan_scan, BSSID_scan[0], BSSID_scan[1], BSSID_scan[2], BSSID_scan[3],
BSSID_scan[4], BSSID_scan[5], ssid_scan.c_str(), rssi_scan, (sec_scan == WIFI_AUTH_OPEN) ? ' ' : '*', (hidden_scan) ? "hidden" : "visible"
);
}
}
log_v("foundCount = %d, failCount = %d", foundCount, failCount);
// if all the APs in the list have failed, reset the failure flags
if (foundCount == failCount) {
resetFails(); // keeps trying the APs in the list
}
}
// clean up ram
WiFi.scanDelete();
if (bestIndex >= 0) {
log_i(
"[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channel: %d (%d)", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3],
bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb
);
#if CONFIG_LWIP_IPV6
if (ipv6_support == true) {
WiFi.enableIPv6();
}
#endif
WiFi.disconnect();
delay(10);
WiFi.begin(bestNetwork.ssid, (_bAllowOpenAP && bestNetworkSec == WIFI_AUTH_OPEN) ? NULL : bestNetwork.passphrase, bestChannel, bestBSSID);
status = WiFi.status();
_bWFMInit = true;
startTime = millis();
// wait for connection, fail, or timeout
while (status != WL_CONNECTED && (millis() - startTime) <= connectTimeout) { // && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED
delay(10);
status = WiFi.status();
}
switch (status) {
case WL_CONNECTED:
log_i("[WIFI] Connecting done.");
log_d("[WIFI] SSID: %s", WiFi.SSID().c_str());
log_d("[WIFI] IP: %s", WiFi.localIP().toString().c_str());
log_d("[WIFI] MAC: %s", WiFi.BSSIDstr().c_str());
log_d("[WIFI] Channel: %d", WiFi.channel());
if (_connectionTestCBFunc != NULL) {
// We connected to an AP but if it's a captive portal we're not going anywhere. Test it.
if (_connectionTestCBFunc()) {
resetFails();
} else {
markAsFailed(bestIndex);
WiFi.disconnect();
delay(10);
status = WiFi.status();
}
} else {
resetFails();
}
break;
case WL_NO_SSID_AVAIL:
log_e("[WIFI] Connecting Failed AP not found.");
markAsFailed(bestIndex);
break;
case WL_CONNECT_FAILED:
log_e("[WIFI] Connecting Failed.");
markAsFailed(bestIndex);
break;
default:
log_e("[WIFI] Connecting Failed (%d).", status);
markAsFailed(bestIndex);
break;
}
} else {
log_e("[WIFI] no matching wifi found!");
}
} else {
// start scan
log_d("[WIFI] delete old wifi config...");
WiFi.disconnect();
log_d("[WIFI] start scan");
// scan wifi async mode
WiFi.scanNetworks(true);
}
return status;
}
#if CONFIG_LWIP_IPV6
void WiFiMulti::enableIPv6(bool state) {
ipv6_support = state;
}
#endif
void WiFiMulti::markAsFailed(int32_t i) {
APlist[i].hasFailed = true;
log_d("[WIFI] Marked SSID %s as failed", APlist[i].ssid);
}
void WiFiMulti::resetFails() {
for (uint32_t i = 0; i < APlist.size(); i++) {
APlist[i].hasFailed = false;
}
log_d("[WIFI] Resetting failure flags");
}
void WiFiMulti::setStrictMode(bool bStrict) {
_bStrict = bStrict;
}
void WiFiMulti::setAllowOpenAP(bool bAllowOpenAP) {
_bAllowOpenAP = bAllowOpenAP;
}
void WiFiMulti::setConnectionTestCallbackFunc(ConnectionTestCB_t cbFunc) {
_connectionTestCBFunc = cbFunc;
}
#endif /* SOC_WIFI_SUPPORTED */
+83
View File
@@ -0,0 +1,83 @@
/**
*
* @file ESP8266WiFiMulti.h
* @date 16.05.2015
* @author Markus Sattler
*
* Copyright (c) 2015 Markus Sattler. All rights reserved.
* This file is part of the esp8266 core for Arduino environment.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#pragma once
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include "WiFi.h"
#include <vector>
typedef struct {
char *ssid;
char *passphrase;
bool hasFailed;
} WifiAPlist_t;
typedef std::function<bool(void)> ConnectionTestCB_t;
class WiFiMulti {
public:
WiFiMulti();
~WiFiMulti();
bool addAP(const char *ssid, const char *passphrase = NULL);
uint8_t run(uint32_t connectTimeout = 5000, bool scanHidden = false);
#if CONFIG_LWIP_IPV6
void enableIPv6(bool state);
#endif
// Force (default: true) to only keep connected or to connect to an AP from the provided WiFiMulti list.
// When bStrict is false, it will keep the last/current connected AP even if not in the WiFiMulti List.
void setStrictMode(bool bStrict = true);
// allows (true) to connect to ANY open AP, even if not in the user list
// default false (do not connect to an open AP that has not been explicitaly added by the user to list)
void setAllowOpenAP(bool bAllowOpenAP = false);
// clears the current list of Multi APs and frees the memory
void APlistClean(void);
// allow the user to define a callback function that will validate the connection to the Internet.
// if the callback returns true, the connection is considered valid and the AP will added to the validated AP list.
// set the callback to NULL to disable the feature and validate any SSID that is in the list.
void setConnectionTestCallbackFunc(ConnectionTestCB_t cbFunc);
private:
std::vector<WifiAPlist_t> APlist;
bool ipv6_support;
bool _bStrict = true;
bool _bAllowOpenAP = false;
ConnectionTestCB_t _connectionTestCBFunc = NULL;
bool _bWFMInit = false;
void markAsFailed(int32_t i);
void resetFails();
};
#endif /* SOC_WIFI_SUPPORTED */
+486
View File
@@ -0,0 +1,486 @@
/*
WiFiSTA.cpp - WiFi library for esp32
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Reworked on 28 Dec 2015 by Markus Sattler
*/
#include "WiFi.h"
#include "WiFiGeneric.h"
#include "WiFiSTA.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <esp_err.h>
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp32-hal.h>
#include <lwip/ip_addr.h>
#include "lwip/err.h"
#include "lwip/dns.h"
#include <esp_smartconfig.h>
#include <esp_netif.h>
#include "esp_mac.h"
#if __has_include("esp_eap_client.h")
#include "esp_eap_client.h"
#else
#include "esp_wpa2.h"
#endif
// -----------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------- STA function -----------------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------
/**
* Return Connection status.
* @return one of the value defined in wl_status_t
*
*/
wl_status_t WiFiSTAClass::status() {
return STA.status();
}
#if CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT
wl_status_t WiFiSTAClass::begin(
const char *wpa2_ssid, wpa2_auth_method_t method, const char *wpa2_identity, const char *wpa2_username, const char *wpa2_password, const char *ca_pem,
const char *client_crt, const char *client_key, int ttls_phase2_type, int32_t channel, const uint8_t *bssid, bool tryConnect
) {
if (!STA.begin()) {
return WL_CONNECT_FAILED;
}
if (!STA.connect(
wpa2_ssid, method, wpa2_identity, wpa2_username, wpa2_password, ca_pem, client_crt, client_key, ttls_phase2_type, channel, bssid, tryConnect
)) {
return WL_CONNECT_FAILED;
}
return STA.status();
}
#endif /* CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT */
wl_status_t WiFiSTAClass::begin(const char *ssid, const char *passphrase, int32_t channel, const uint8_t *bssid, bool tryConnect) {
if (!STA.begin()) {
return WL_CONNECT_FAILED;
}
if (!STA.connect(ssid, passphrase, channel, bssid, tryConnect)) {
return WL_CONNECT_FAILED;
}
return STA.status();
}
/**
* Use to connect to SDK config.
* @return wl_status_t
*/
wl_status_t WiFiSTAClass::begin() {
if (!STA.begin(true)) {
return WL_CONNECT_FAILED;
}
return STA.status();
}
/**
* will force a disconnect and then start reconnecting to AP
* @return true when successful
*/
bool WiFiSTAClass::reconnect() {
return STA.reconnect();
}
/**
* Disconnect from the network.
* @param wifioff `true` to turn the Wi-Fi radio off.
* @param eraseap `true` to erase the AP configuration from the NVS memory.
* @return `true` when successful.
*/
bool WiFiSTAClass::disconnectAsync(bool wifioff, bool eraseap) {
return disconnect(wifioff, eraseap, 0);
}
/**
* Disconnect from the network.
* @param wifioff `true` to turn the Wi-Fi radio off.
* @param eraseap `true` to erase the AP configuration from the NVS memory.
* @param timeoutLength timeout to wait for status change
* @return `true` when successful.
*/
bool WiFiSTAClass::disconnect(bool wifioff, bool eraseap, unsigned long timeoutLength) {
if (!STA.disconnect(eraseap, timeoutLength)) {
return false;
}
if (wifioff) {
return STA.end();
}
return true;
}
/**
* @brief Reset WiFi settings in NVS to default values.
*
* This function will reset settings made using the following APIs:
* - esp_wifi_set_bandwidth,
* - esp_wifi_set_protocol,
* - esp_wifi_set_config related
* - esp_wifi_set_mode
*
* @return true if erase succeeded
* @note: Resets SSID, password, protocol, mode, etc.
* These settings are maintained by WiFi driver in IDF.
* WiFi driver must be initialized.
*/
bool WiFiSTAClass::eraseAP(void) {
return STA.erase();
}
/**
* Change IP configuration settings disabling the dhcp client
* @param local_ip Static ip configuration
* @param gateway Static gateway configuration
* @param subnet Static Subnet mask
* @param dns1 Static DNS server 1
* @param dns2 Static DNS server 2
*/
bool WiFiSTAClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) {
// handle Arduino ordering of parameters: ip, dns, gw, subnet
if (local_ip.type() == IPv4 && local_ip != INADDR_NONE && subnet[0] != 255) {
IPAddress tmp = dns1;
dns1 = gateway;
gateway = subnet;
subnet = (tmp != INADDR_NONE) ? tmp : IPAddress(255, 255, 255, 0);
}
return STA.begin() && STA.config(local_ip, gateway, subnet, dns1, dns2);
}
bool WiFiSTAClass::config(IPAddress local_ip, IPAddress dns) {
if (local_ip == INADDR_NONE) {
return config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
}
if (local_ip.type() != IPv4) {
return false;
}
IPAddress gw(local_ip);
gw[3] = 1;
if (dns == INADDR_NONE) {
dns = gw;
}
return config(local_ip, gw, IPAddress(255, 255, 255, 0), dns);
}
/**
* Change DNS server for static IP configuration
* @param dns1 Static DNS server 1
* @param dns2 Static DNS server 2 (optional)
*/
bool WiFiSTAClass::setDNS(IPAddress dns1, IPAddress dns2) {
return STA.begin() && STA.dnsIP(0, dns1) && STA.dnsIP(1, dns2);
}
/**
* Sets the working bandwidth of the STA mode
* @param m wifi_bandwidth_t
*/
bool WiFiSTAClass::bandwidth(wifi_bandwidth_t bandwidth) {
return STA.bandwidth(bandwidth);
}
/**
* is STA interface connected?
* @return true if STA is connected to an AP
*/
bool WiFiSTAClass::isConnected() {
return STA.connected() && STA.hasIP();
}
/**
* Set the minimum security for AP to be considered connectable.
* Must be called before WiFi.begin().
* @param minSecurity wifi_auth_mode_t
*/
void WiFiSTAClass::setMinSecurity(wifi_auth_mode_t minSecurity) {
return STA.setMinSecurity(minSecurity);
}
/**
* Set the way that AP is chosen.
* First SSID match[WIFI_FAST_SCAN] or Sorted[WIFI_ALL_CHANNEL_SCAN] (RSSI or Security)
* Must be called before WiFi.begin()
* @param scanMethod wifi_scan_method_t
*/
void WiFiSTAClass::setScanMethod(wifi_scan_method_t scanMethod) {
return STA.setScanMethod(scanMethod);
}
/**
* Set the way that AP is sorted. (requires scanMethod WIFI_ALL_CHANNEL_SCAN)
* By SSID[WIFI_CONNECT_AP_BY_SIGNAL] or Security[WIFI_CONNECT_AP_BY_SECURITY]
* Must be called before WiFi.begin()
* @param sortMethod wifi_sort_method_t
*/
void WiFiSTAClass::setSortMethod(wifi_sort_method_t sortMethod) {
return STA.setSortMethod(sortMethod);
}
/**
* Function used to set the automatic reconnection if the connection is lost.
* @param autoReconnect `true` to enable this option.
* @return true
*/
bool WiFiSTAClass::setAutoReconnect(bool autoReconnect) {
return STA.setAutoReconnect(autoReconnect);
}
/**
* Function used to get the automatic reconnection if the connection is lost.
* @return The function will return `true` if this setting is enabled.
*/
bool WiFiSTAClass::getAutoReconnect() {
return STA.getAutoReconnect();
}
/**
* Wait for WiFi connection to reach a result
* returns the status reached or disconnect if STA is off
* @return wl_status_t
*/
uint8_t WiFiSTAClass::waitForConnectResult(unsigned long timeoutLength) {
return STA.waitForConnectResult(timeoutLength);
}
/**
* Get the station interface IP address.
* @return IPAddress station IP
*/
IPAddress WiFiSTAClass::localIP() {
return STA.localIP();
}
/**
* Get the station interface MAC address.
* @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
* @return pointer to uint8_t *
*/
uint8_t *WiFiSTAClass::macAddress(uint8_t *mac) {
return STA.macAddress(mac);
}
/**
* Get the station interface MAC address.
* @return String mac
*/
String WiFiSTAClass::macAddress(void) {
return STA.macAddress();
}
/**
* Get the interface subnet mask address.
* @return IPAddress subnetMask
*/
IPAddress WiFiSTAClass::subnetMask() {
return STA.subnetMask();
}
/**
* Get the gateway ip address.
* @return IPAddress gatewayIP
*/
IPAddress WiFiSTAClass::gatewayIP() {
return STA.gatewayIP();
}
/**
* Get the DNS ip address.
* @param dns_no
* @return IPAddress DNS Server IP
*/
IPAddress WiFiSTAClass::dnsIP(uint8_t dns_no) {
return STA.dnsIP(dns_no);
}
/**
* Get the broadcast ip address.
* @return IPAddress broadcastIP
*/
IPAddress WiFiSTAClass::broadcastIP() {
return STA.broadcastIP();
}
/**
* Get the network id.
* @return IPAddress networkID
*/
IPAddress WiFiSTAClass::networkID() {
return STA.networkID();
}
/**
* Get the subnet CIDR.
* @return uint8_t subnetCIDR
*/
uint8_t WiFiSTAClass::subnetCIDR() {
return STA.subnetCIDR();
}
/**
* Return the current SSID associated with the network
* @return SSID
*/
String WiFiSTAClass::SSID() const {
return STA.SSID();
}
/**
* Return the current pre shared key associated with the network
* @return psk string
*/
String WiFiSTAClass::psk() const {
return STA.psk();
}
/**
* Return the current bssid / mac associated with the network if configured
* @return bssid uint8_t *
*/
uint8_t *WiFiSTAClass::BSSID(uint8_t *buff) {
return STA.BSSID(buff);
}
/**
* Return the current bssid / mac associated with the network if configured
* @return String bssid mac
*/
String WiFiSTAClass::BSSIDstr(void) {
return STA.BSSIDstr();
}
/**
* Return the current network RSSI.
* @return RSSI value
*/
int8_t WiFiSTAClass::RSSI(void) {
return STA.RSSI();
}
#if CONFIG_LWIP_IPV6
/**
* Enable IPv6 on the station interface.
* Should be called before WiFi.begin()
*
* @return true on success
*/
bool WiFiSTAClass::enableIPv6(bool en) {
return STA.enableIPv6(en);
}
/**
* Get the station interface link-local IPv6 address.
* @return IPAddress
*/
IPAddress WiFiSTAClass::linkLocalIPv6() {
return STA.linkLocalIPv6();
}
/**
* Get the station interface global IPv6 address.
* @return IPAddress
*/
IPAddress WiFiSTAClass::globalIPv6() {
return STA.globalIPv6();
}
#endif
bool WiFiSTAClass::_smartConfigStarted = false;
bool WiFiSTAClass::_smartConfigDone = false;
/**
* @brief
*
* @param type Select type of SmartConfig. Default type is SC_TYPE_ESPTOUCH
* @param crypt_key When using type SC_TYPE_ESPTOUTCH_V2 crypt key needed, else ignored. Length should be 16 chars.
* @return true if configuration is successful.
* @return false if configuration fails.
*/
bool WiFiSTAClass::beginSmartConfig(smartconfig_type_t type, char *crypt_key) {
esp_err_t err;
if (_smartConfigStarted) {
return false;
}
if (!WiFi.mode(WIFI_STA)) {
return false;
}
esp_wifi_disconnect();
smartconfig_start_config_t conf = SMARTCONFIG_START_CONFIG_DEFAULT();
if (type == SC_TYPE_ESPTOUCH_V2) {
conf.esp_touch_v2_enable_crypt = true;
conf.esp_touch_v2_key = crypt_key;
}
err = esp_smartconfig_set_type(type);
if (err != ESP_OK) {
log_e("SmartConfig Set Type Failed!");
return false;
}
err = esp_smartconfig_start(&conf);
if (err != ESP_OK) {
log_e("SmartConfig Start Failed!");
return false;
}
_smartConfigStarted = true;
_smartConfigDone = false;
return true;
}
bool WiFiSTAClass::stopSmartConfig() {
if (!_smartConfigStarted) {
return true;
}
if (esp_smartconfig_stop() == ESP_OK) {
_smartConfigStarted = false;
return true;
}
return false;
}
bool WiFiSTAClass::smartConfigDone() {
if (!_smartConfigStarted) {
return false;
}
return _smartConfigDone;
}
#endif /* SOC_WIFI_SUPPORTED */
+224
View File
@@ -0,0 +1,224 @@
/*
ESP8266WiFiSTA.h - esp8266 Wifi support.
Based on WiFi.h from Ardiono WiFi shield library.
Copyright (c) 2011-2014 Arduino. All right reserved.
Modified by Ivan Grokhotkov, December 2014
Reworked by Markus Sattler, December 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include "WiFiType.h"
#include "WiFiGeneric.h"
#ifdef ESP_IDF_VERSION_MAJOR
#include "esp_event.h"
#endif
typedef enum {
WPA2_AUTH_TLS = 0,
WPA2_AUTH_PEAP = 1,
WPA2_AUTH_TTLS = 2
} wpa2_auth_method_t;
// ----------------------------------------------------------------------------------------------
// ------------------------------------ NEW STA Implementation ----------------------------------
// ----------------------------------------------------------------------------------------------
class STAClass : public NetworkInterface {
public:
STAClass();
~STAClass();
bool begin(bool tryConnect = false);
bool end();
bool bandwidth(wifi_bandwidth_t bandwidth);
bool connect();
bool connect(const char *ssid, const char *passphrase = NULL, int32_t channel = 0, const uint8_t *bssid = NULL, bool tryConnect = true);
bool connect(const String &ssid, const String &passphrase = emptyString, int32_t channel = 0, const uint8_t *bssid = NULL, bool tryConnect = true) {
return connect(ssid.c_str(), passphrase.c_str(), channel, bssid, tryConnect);
}
#if CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT
bool connect(
const char *wpa2_ssid, wpa2_auth_method_t method, const char *wpa2_identity = NULL, const char *wpa2_username = NULL, const char *wpa2_password = NULL,
const char *ca_pem = NULL, const char *client_crt = NULL, const char *client_key = NULL, int ttls_phase2_type = -1, int32_t channel = 0,
const uint8_t *bssid = 0, bool tryConnect = true
);
bool connect(
const String &wpa2_ssid, wpa2_auth_method_t method, const String &wpa2_identity = emptyString, const String &wpa2_username = emptyString,
const String &wpa2_password = emptyString, const String &ca_pem = emptyString, const String &client_crt = emptyString,
const String &client_key = emptyString, int ttls_phase2_type = -1, int32_t channel = 0, const uint8_t *bssid = 0, bool tryConnect = true
) {
return connect(
wpa2_ssid.c_str(), method, wpa2_identity.c_str(), wpa2_username.c_str(), wpa2_password.c_str(), ca_pem.c_str(), client_crt.c_str(), client_key.c_str(),
ttls_phase2_type, channel, bssid, tryConnect
);
}
#endif /* CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT */
bool disconnect(bool eraseap = false, unsigned long timeout = 0);
bool reconnect();
bool erase();
uint8_t waitForConnectResult(unsigned long timeoutLength = 60000);
bool setAutoReconnect(bool autoReconnect);
bool getAutoReconnect();
// Next group functions must be called before WiFi.begin()
void setMinSecurity(wifi_auth_mode_t minSecurity); // Default is WIFI_AUTH_WPA2_PSK
void setScanMethod(wifi_scan_method_t scanMethod); // Default is WIFI_FAST_SCAN
void setSortMethod(wifi_sort_method_t sortMethod); // Default is WIFI_CONNECT_AP_BY_SIGNAL
wl_status_t status();
String SSID() const;
String psk() const;
uint8_t *BSSID(uint8_t *bssid = NULL);
String BSSIDstr();
int8_t RSSI();
const char *disconnectReasonName(wifi_err_reason_t reason);
// Private Use
void _setStatus(wl_status_t status);
void _onStaEvent(int32_t event_id, void *event_data);
protected:
wifi_auth_mode_t _minSecurity;
wifi_scan_method_t _scanMethod;
wifi_sort_method_t _sortMethod;
bool _autoReconnect;
wl_status_t _status;
network_event_handle_t _wifi_sta_event_handle;
size_t printDriverInfo(Print &out) const;
friend class WiFiGenericClass;
bool onEnable();
bool onDisable();
};
// ----------------------------------------------------------------------------------------------
// ------------------------------- OLD STA API (compatibility) ----------------------------------
// ----------------------------------------------------------------------------------------------
class WiFiSTAClass {
public:
STAClass STA;
#if CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT
wl_status_t begin(
const char *wpa2_ssid, wpa2_auth_method_t method, const char *wpa2_identity = NULL, const char *wpa2_username = NULL, const char *wpa2_password = NULL,
const char *ca_pem = NULL, const char *client_crt = NULL, const char *client_key = NULL, int ttls_phase2_type = -1, int32_t channel = 0,
const uint8_t *bssid = 0, bool tryConnect = true
);
wl_status_t begin(
const String &wpa2_ssid, wpa2_auth_method_t method, const String &wpa2_identity = (const char *)NULL, const String &wpa2_username = (const char *)NULL,
const String &wpa2_password = (const char *)NULL, const String &ca_pem = (const char *)NULL, const String &client_crt = (const char *)NULL,
const String &client_key = (const char *)NULL, int ttls_phase2_type = -1, int32_t channel = 0, const uint8_t *bssid = 0, bool tryConnect = true
) {
return begin(
wpa2_ssid.c_str(), method, wpa2_identity.c_str(), wpa2_username.c_str(), wpa2_password.c_str(), ca_pem.c_str(), client_crt.c_str(), client_key.c_str(),
ttls_phase2_type, channel, bssid, tryConnect
);
}
#endif /* CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT */
wl_status_t begin(const char *ssid, const char *passphrase = NULL, int32_t channel = 0, const uint8_t *bssid = NULL, bool tryConnect = true);
wl_status_t
begin(const String &ssid, const String &passphrase = (const char *)NULL, int32_t channel = 0, const uint8_t *bssid = NULL, bool tryConnect = true) {
return begin(ssid.c_str(), passphrase.c_str(), channel, bssid, tryConnect);
}
wl_status_t begin();
// also accepts Arduino ordering of parameters: ip, dns, gw, mask
bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000);
// two and one parameter version. 2nd parameter is DNS like in Arduino
bool config(IPAddress local_ip, IPAddress dns = (uint32_t)0x00000000);
bool setDNS(IPAddress dns1, IPAddress dns2 = (uint32_t)0x00000000); // sets DNS IP for all network interfaces
bool bandwidth(wifi_bandwidth_t bandwidth);
bool reconnect();
bool disconnectAsync(bool wifioff = false, bool eraseap = false);
bool disconnect(bool wifioff = false, bool eraseap = false, unsigned long timeoutLength = 100);
bool eraseAP(void);
bool isConnected();
bool setAutoReconnect(bool autoReconnect);
bool getAutoReconnect();
uint8_t waitForConnectResult(unsigned long timeoutLength = 60000);
// Next group functions must be called before WiFi.begin()
void setMinSecurity(wifi_auth_mode_t minSecurity); // Default is WIFI_AUTH_WPA2_PSK
void setScanMethod(wifi_scan_method_t scanMethod); // Default is WIFI_FAST_SCAN
void setSortMethod(wifi_sort_method_t sortMethod); // Default is WIFI_CONNECT_AP_BY_SIGNAL
// STA WiFi info
wl_status_t status();
String SSID() const;
String psk() const;
uint8_t *BSSID(uint8_t *bssid = NULL);
String BSSIDstr();
int8_t RSSI();
IPAddress localIP();
uint8_t *macAddress(uint8_t *mac);
String macAddress();
IPAddress subnetMask();
IPAddress gatewayIP();
IPAddress dnsIP(uint8_t dns_no = 0);
IPAddress broadcastIP();
IPAddress networkID();
uint8_t subnetCIDR();
#if CONFIG_LWIP_IPV6
bool enableIPv6(bool en = true);
IPAddress linkLocalIPv6();
IPAddress globalIPv6();
#endif
// ----------------------------------------------------------------------------------------------
// ---------------------------------------- Smart Config ----------------------------------------
// ----------------------------------------------------------------------------------------------
protected:
static bool _smartConfigStarted;
public:
bool beginSmartConfig(smartconfig_type_t type = SC_TYPE_ESPTOUCH, char *crypt_key = NULL);
bool stopSmartConfig();
bool smartConfigDone();
static bool _smartConfigDone;
};
#endif /* SOC_WIFI_SUPPORTED */
+294
View File
@@ -0,0 +1,294 @@
/*
ESP8266WiFiScan.cpp - WiFi library for esp8266
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Reworked on 28 Dec 2015 by Markus Sattler
*/
#include "WiFi.h"
#include "WiFiGeneric.h"
#include "WiFiScan.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
extern "C" {
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <esp_err.h>
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp32-hal.h>
#include <lwip/ip_addr.h>
#include "lwip/err.h"
}
bool WiFiScanClass::_scanAsync = false;
uint32_t WiFiScanClass::_scanStarted = 0;
uint32_t WiFiScanClass::_scanTimeout = 60000;
uint16_t WiFiScanClass::_scanCount = 0;
uint32_t WiFiScanClass::_scanActiveMinTime = 100;
void *WiFiScanClass::_scanResult = nullptr;
void WiFiScanClass::setScanTimeout(uint32_t ms) {
WiFiScanClass::_scanTimeout = ms;
}
void WiFiScanClass::setScanActiveMinTime(uint32_t ms) {
WiFiScanClass::_scanActiveMinTime = ms;
}
/**
* Start scan WiFi networks available
* @param async run in async mode
* @param show_hidden show hidden networks
* @return Number of discovered networks
*/
int16_t
WiFiScanClass::scanNetworks(bool async, bool show_hidden, bool passive, uint32_t max_ms_per_chan, uint8_t channel, const char *ssid, const uint8_t *bssid) {
if (WiFiGenericClass::getStatusBits() & WIFI_SCANNING_BIT) {
return WIFI_SCAN_RUNNING;
}
WiFiScanClass::_scanAsync = async;
WiFi.enableSTA(true);
scanDelete();
wifi_scan_config_t config;
memset(&config, 0, sizeof(wifi_scan_config_t));
config.ssid = (uint8_t *)ssid;
config.bssid = (uint8_t *)bssid;
config.channel = channel;
config.show_hidden = show_hidden;
if (passive) {
config.scan_type = WIFI_SCAN_TYPE_PASSIVE;
config.scan_time.passive = max_ms_per_chan;
} else {
config.scan_type = WIFI_SCAN_TYPE_ACTIVE;
config.scan_time.active.min = _scanActiveMinTime;
config.scan_time.active.max = max_ms_per_chan;
}
if (esp_wifi_scan_start(&config, false) == ESP_OK) {
_scanStarted = millis();
WiFiGenericClass::clearStatusBits(WIFI_SCAN_DONE_BIT);
WiFiGenericClass::setStatusBits(WIFI_SCANNING_BIT);
if (WiFiScanClass::_scanAsync) {
return WIFI_SCAN_RUNNING;
}
if (WiFiGenericClass::waitStatusBits(WIFI_SCAN_DONE_BIT, _scanTimeout)) {
return (int16_t)WiFiScanClass::_scanCount;
}
}
return WIFI_SCAN_FAILED;
}
/**
* private
* scan callback
* @param result void *arg
* @param status STATUS
*/
void WiFiScanClass::_scanDone() {
if (!(WiFiGenericClass::getStatusBits() & WIFI_SCANNING_BIT)) {
return; //Ignore if not scanning, scan was started by other
}
esp_wifi_scan_get_ap_num(&(WiFiScanClass::_scanCount));
if (WiFiScanClass::_scanResult) {
free(WiFiScanClass::_scanResult);
WiFiScanClass::_scanResult = NULL;
}
if (WiFiScanClass::_scanCount) {
WiFiScanClass::_scanResult = calloc(WiFiScanClass::_scanCount, sizeof(wifi_ap_record_t));
if (!WiFiScanClass::_scanResult) {
WiFiScanClass::_scanCount = 0;
} else if (esp_wifi_scan_get_ap_records(&(WiFiScanClass::_scanCount), (wifi_ap_record_t *)_scanResult) != ESP_OK) {
free(WiFiScanClass::_scanResult);
WiFiScanClass::_scanResult = NULL;
WiFiScanClass::_scanCount = 0;
}
}
WiFiGenericClass::setStatusBits(WIFI_SCAN_DONE_BIT);
WiFiGenericClass::clearStatusBits(WIFI_SCANNING_BIT);
}
/**
*
* @param i specify from which network item want to get the information
* @return bss_info *
*/
void *WiFiScanClass::_getScanInfoByIndex(int i) {
if (!WiFiScanClass::_scanResult || (size_t)i >= WiFiScanClass::_scanCount) {
return 0;
}
return reinterpret_cast<wifi_ap_record_t *>(WiFiScanClass::_scanResult) + i;
}
/**
* called to get the scan state in Async mode
* @return scan result or status
* -1 if scan not fin
* -2 if scan not triggered
*/
int16_t WiFiScanClass::scanComplete() {
if (WiFiGenericClass::getStatusBits() & WIFI_SCAN_DONE_BIT) {
return WiFiScanClass::_scanCount;
}
if (WiFiGenericClass::getStatusBits() & WIFI_SCANNING_BIT) {
// Check if the delay expired, return WIFI_SCAN_FAILED in this case
if ((millis() - WiFiScanClass::_scanStarted) > WiFiScanClass::_scanTimeout) {
WiFiGenericClass::clearStatusBits(WIFI_SCANNING_BIT);
return WIFI_SCAN_FAILED;
}
return WIFI_SCAN_RUNNING;
}
return WIFI_SCAN_FAILED;
}
/**
* delete last scan result from RAM
*/
void WiFiScanClass::scanDelete() {
WiFiGenericClass::clearStatusBits(WIFI_SCAN_DONE_BIT);
WiFiGenericClass::clearStatusBits(WIFI_SCANNING_BIT);
if (WiFiScanClass::_scanResult) {
free(WiFiScanClass::_scanResult);
WiFiScanClass::_scanResult = NULL;
}
WiFiScanClass::_scanCount = 0;
}
/**
* loads all infos from a scanned wifi in to the ptr parameters
* @param networkItem uint8_t
* @param ssid const char**
* @param encryptionType uint8_t *
* @param RSSI int32_t *
* @param BSSID uint8_t **
* @param channel int32_t *
* @return (true if ok)
*/
bool WiFiScanClass::getNetworkInfo(uint8_t i, String &ssid, uint8_t &encType, int32_t &rssi, uint8_t *&bssid, int32_t &channel) {
wifi_ap_record_t *it = reinterpret_cast<wifi_ap_record_t *>(_getScanInfoByIndex(i));
if (!it) {
return false;
}
ssid = (const char *)it->ssid;
encType = it->authmode;
rssi = it->rssi;
bssid = it->bssid;
channel = it->primary;
return true;
}
/**
* Return the SSID discovered during the network scan.
* @param i specify from which network item want to get the information
* @return ssid string of the specified item on the networks scanned list
*/
String WiFiScanClass::SSID(uint8_t i) {
wifi_ap_record_t *it = reinterpret_cast<wifi_ap_record_t *>(_getScanInfoByIndex(i));
if (!it) {
return String();
}
return String(reinterpret_cast<const char *>(it->ssid));
}
/**
* Return the encryption type of the networks discovered during the scanNetworks
* @param i specify from which network item want to get the information
* @return encryption type (enum wl_enc_type) of the specified item on the networks scanned list
*/
wifi_auth_mode_t WiFiScanClass::encryptionType(uint8_t i) {
wifi_ap_record_t *it = reinterpret_cast<wifi_ap_record_t *>(_getScanInfoByIndex(i));
if (!it) {
return WIFI_AUTH_OPEN;
}
return it->authmode;
}
/**
* Return the RSSI of the networks discovered during the scanNetworks
* @param i specify from which network item want to get the information
* @return signed value of RSSI of the specified item on the networks scanned list
*/
int32_t WiFiScanClass::RSSI(uint8_t i) {
wifi_ap_record_t *it = reinterpret_cast<wifi_ap_record_t *>(_getScanInfoByIndex(i));
if (!it) {
return 0;
}
return it->rssi;
}
/**
* return MAC / BSSID of scanned wifi
* @param i specify from which network item want to get the information
* @param buff optional buffer for the result uint8_t array with length 6
* @return uint8_t * MAC / BSSID of scanned wifi
*/
uint8_t *WiFiScanClass::BSSID(uint8_t i, uint8_t *buff) {
wifi_ap_record_t *it = reinterpret_cast<wifi_ap_record_t *>(_getScanInfoByIndex(i));
if (buff != NULL) {
if (!it) {
memset(buff, 0, 6);
} else {
memcpy(buff, it->bssid, 6);
}
return buff;
}
if (!it) {
return 0;
}
return it->bssid;
}
/**
* return MAC / BSSID of scanned wifi
* @param i specify from which network item want to get the information
* @return String MAC / BSSID of scanned wifi
*/
String WiFiScanClass::BSSIDstr(uint8_t i) {
char mac[18] = {0};
wifi_ap_record_t *it = reinterpret_cast<wifi_ap_record_t *>(_getScanInfoByIndex(i));
if (!it) {
return String();
}
sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", it->bssid[0], it->bssid[1], it->bssid[2], it->bssid[3], it->bssid[4], it->bssid[5]);
return String(mac);
}
int32_t WiFiScanClass::channel(uint8_t i) {
wifi_ap_record_t *it = reinterpret_cast<wifi_ap_record_t *>(_getScanInfoByIndex(i));
if (!it) {
return 0;
}
return it->primary;
}
#endif /* SOC_WIFI_SUPPORTED */
+74
View File
@@ -0,0 +1,74 @@
/*
ESP8266WiFiScan.h - esp8266 Wifi support.
Based on WiFi.h from Ardiono WiFi shield library.
Copyright (c) 2011-2014 Arduino. All right reserved.
Modified by Ivan Grokhotkov, December 2014
Reworked by Markus Sattler, December 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include "WiFiType.h"
#include "WiFiGeneric.h"
class WiFiScanClass {
public:
void setScanTimeout(uint32_t ms);
void setScanActiveMinTime(uint32_t ms);
int16_t scanNetworks(
bool async = false, bool show_hidden = false, bool passive = false, uint32_t max_ms_per_chan = 300, uint8_t channel = 0, const char *ssid = nullptr,
const uint8_t *bssid = nullptr
);
int16_t scanComplete();
void scanDelete();
// scan result
bool getNetworkInfo(uint8_t networkItem, String &ssid, uint8_t &encryptionType, int32_t &RSSI, uint8_t *&BSSID, int32_t &channel);
String SSID(uint8_t networkItem);
wifi_auth_mode_t encryptionType(uint8_t networkItem);
int32_t RSSI(uint8_t networkItem);
uint8_t *BSSID(uint8_t networkItem, uint8_t *bssid = NULL);
String BSSIDstr(uint8_t networkItem);
int32_t channel(uint8_t networkItem);
static void *getScanInfoByIndex(int i) {
return _getScanInfoByIndex(i);
};
static void _scanDone();
protected:
static bool _scanAsync;
static uint32_t _scanStarted;
static uint32_t _scanTimeout;
static uint16_t _scanCount;
static uint32_t _scanActiveMinTime;
static void *_scanResult;
static void *_getScanInfoByIndex(int i);
};
#endif /* SOC_WIFI_SUPPORTED */
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#include "NetworkServer.h"
typedef NetworkServer WiFiServer;
+55
View File
@@ -0,0 +1,55 @@
/*
ESP8266WiFiType.h - esp8266 Wifi support.
Copyright (c) 2011-2014 Arduino. All right reserved.
Modified by Ivan Grokhotkov, December 2014
Reworked by Markus Sattler, December 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED
#include "esp_wifi_types.h"
#define WIFI_SCAN_RUNNING (-1)
#define WIFI_SCAN_FAILED (-2)
#define WiFiMode_t wifi_mode_t
#define WIFI_OFF WIFI_MODE_NULL
#define WIFI_STA WIFI_MODE_STA
#define WIFI_AP WIFI_MODE_AP
#define WIFI_AP_STA WIFI_MODE_APSTA
#define WiFiEvent_t arduino_event_id_t
#define WiFiEventInfo_t arduino_event_info_t
#define WiFiEventId_t wifi_event_id_t
typedef enum {
WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
WL_STOPPED = 254,
WL_IDLE_STATUS = 0,
WL_NO_SSID_AVAIL = 1,
WL_SCAN_COMPLETED = 2,
WL_CONNECTED = 3,
WL_CONNECT_FAILED = 4,
WL_CONNECTION_LOST = 5,
WL_DISCONNECTED = 6
} wl_status_t;
#endif /* SOC_WIFI_SUPPORTED */
+3
View File
@@ -0,0 +1,3 @@
#pragma once
#include "NetworkUdp.h"
typedef NetworkUDP WiFiUDP;