Last active
May 22, 2023 01:08
-
-
Save toxicantidote/af13cfeb292dcbed0a0214208f5ca730 to your computer and use it in GitHub Desktop.
ESP32 Wi-Fi search and connect to saved
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <WiFi.h> | |
#include <Preferences.h> | |
#include <esp_task_wdt.h> | |
#define CMDPROMPT "ESP32> " | |
#define TIMEOUT 10000 | |
// cmd line vars | |
char cmdBuffer[32]; | |
int cmdBufferPosition = 0; | |
char cmdByte; | |
int cmdStatus = 0; | |
int echoInput = 1; | |
char command[32]; | |
char argument1[32]; | |
char argument2[32]; | |
int wifiCount = 0; | |
bool connected = false; | |
bool countdown = false; | |
Preferences preferences; | |
String ssid; | |
String password; | |
void wifiScan(void); | |
void setup() { | |
Serial.begin(9600); | |
preferences.begin("wifi", false); | |
Serial.println("Booting.."); | |
WiFi.mode(WIFI_STA); | |
WiFi.disconnect(); | |
delay(100); | |
ssid = preferences.getString("ssid", ""); | |
password = preferences.getString("password", ""); | |
if (ssid == "") { | |
Serial.println("No network saved"); | |
wifiScan(); | |
} else { | |
countdown = true; | |
Serial.print("Saved network SSID is "); | |
Serial.println(ssid); | |
Serial.print("Auto-connect in "); | |
unsigned int end = millis() + TIMEOUT; | |
int last_count = 0; | |
while (countdown == true) { | |
unsigned int remaining = end - millis(); | |
if ((remaining < 0) || (remaining > TIMEOUT)) { | |
break; | |
} else { | |
int count = (remaining / 1000); | |
if (count != last_count) { | |
last_count = count; | |
Serial.print(count); | |
Serial.print(".."); | |
if (Serial.available() > 1) { | |
countdown = false; | |
} | |
} | |
} | |
} | |
if (countdown == true) { | |
Serial.println("Connecting..."); | |
connect(ssid.c_str(), password.c_str()); | |
} else { | |
Serial.println("Connection aborted"); | |
wifiScan(); | |
} | |
} | |
esp_task_wdt_init(10, true); //enable panic so ESP32 restarts | |
esp_task_wdt_add(NULL); //add current thread to WDT watch | |
} | |
void loop() { | |
esp_task_wdt_reset(); | |
checkSerial(); | |
if ((WiFi.status() != WL_CONNECTED) && (connected == true)) { | |
Serial.println("Lost connection to Wi-Fi. Reconnecting..."); | |
WiFi.disconnect(); | |
connected = false; | |
delay(100); | |
connect(ssid.c_str(), password.c_str()); | |
} | |
} | |
void wifiScan() { | |
Serial.println("Searching for APs.."); | |
wifiCount = WiFi.scanNetworks(); | |
Serial.println("Networks found:"); | |
for (int i = 0; i < wifiCount; i++) { | |
Serial.print("\t["); | |
Serial.print(i); | |
Serial.print("]\t("); | |
Serial.print(WiFi.BSSIDstr(i)); | |
Serial.print(") "); | |
Serial.print(WiFi.SSID(i)); | |
Serial.print(" [Signal "); | |
Serial.print(WiFi.RSSI(i)); | |
Serial.println("dBm]"); | |
delay(10); | |
} | |
} | |
void checkSerial() { | |
// command stuff | |
for (int i = 0; i < Serial.available() && cmdStatus == 0; i++) { // if serial data is available to read | |
cmdStatus = 0; | |
cmdByte = Serial.read(); // read it | |
if (cmdByte == 0x0A || cmdByte == 0x0D) { // newline and carriage return | |
Serial.flush(); // clear the input buffer | |
if (cmdBufferPosition == 0) { // if command is blank | |
resetBuffers(); // reset buffers | |
} else { // if the command is not blank | |
cmdStatus = 1; // flag the command as 'ready for processing' | |
} | |
} else if (cmdByte == 0x7F) { // backspace | |
if (cmdBufferPosition != 0) { // don't backspace further than the prompt | |
cmdBufferPosition--; | |
if (echoInput == 1) { // if echo is enabled, backspace on the client | |
Serial.print('\b'); | |
} | |
} | |
} else { // other char, add to buffer | |
// restrict to printable characters | |
if (cmdByte >= 0x20 && cmdByte <= 0x7E) { | |
cmdBuffer[cmdBufferPosition] = cmdByte; // append to buffer | |
cmdBufferPosition++; // increment buffer position | |
if (echoInput == 1) { // if echo is enabled, echo the character back to the client | |
Serial.print(cmdByte); | |
} | |
} | |
} | |
} | |
if (cmdStatus == 1) { // cmd received, but not processed | |
// in case of backspace, truncate command buffer | |
for (int i = cmdBufferPosition; i <= strlen(cmdBuffer); i++) { | |
cmdBuffer[i] = NULL; | |
} | |
handleCommand(cmdBuffer); // process the command | |
resetBuffers(); // clear the command buffers | |
} | |
} | |
void connectIndex(int index, char *password) { | |
ssid = WiFi.SSID(index); | |
const char *ssid_chr = ssid.c_str(); | |
connect(ssid_chr, password); | |
} | |
void connect(const char *ssid, const char *password) { | |
Serial.println("Connecting to network..."); | |
unsigned long start = millis(); | |
unsigned long duration = 0; | |
WiFi.begin(ssid, password); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(500); | |
Serial.print("."); | |
duration = millis() - start; | |
if (duration > TIMEOUT) { | |
Serial.println("WiFi: Connection failed. Is the password correct?"); | |
break; | |
} | |
} | |
if (WiFi.status() == WL_CONNECTED) { | |
Serial.println("WiFi: Connected to network"); | |
preferences.putString("ssid", ssid); | |
preferences.putString("password", password); | |
Serial.print("IP address is "); | |
Serial.println(WiFi.localIP()); | |
connected = true; | |
} else { | |
connected = false; | |
} | |
} | |
// serial command interpreter | |
void handleCommand(char* cmdBuffer) { // handles commands | |
// init vars | |
char *command = NULL; | |
char *argument1 = NULL; | |
char *argument2 = NULL; | |
char *buf = cmdBuffer; | |
command = strtok(buf, " "); // first word (command, before space) | |
argument1 = strtok(NULL, " "); // second word (argument, after space) | |
argument2 = strtok(NULL, " "); // third word (argument, after space) | |
Serial.println(""); // newline | |
// process command | |
if (strcasecmp(command, "HELP") == 0) { | |
Serial.println("Command help:"); | |
Serial.println("\tSCAN - Scan for networks"); | |
Serial.println("\tCONNECT <#> <password> - Connect to a listed network (passwords cannot have spaces)"); | |
Serial.println("\tDISCONNECT - Disconnect from Wi-Fi"); | |
Serial.println("\tFORGET - Forget saved Wi-Fi"); | |
Serial.println("\tWSTATUS - Show current Wi-Fi status"); | |
} else if (strcasecmp(command, "SCAN") == 0) { | |
wifiScan(); | |
} else if (strcasecmp(command, "CONNECT") == 0) { | |
int index = atoi(argument1); | |
if (index <= wifiCount) { | |
connectIndex(index, argument2); | |
} else { | |
Serial.print("Invalid network. Select a number between 0 and "); | |
Serial.println(((int)wifiCount - 1)); | |
} | |
} else if (strcasecmp(command, "DISCONNECT") == 0) { | |
if (connected == true) { | |
Serial.println("Disconnecting.."); | |
connected = false; | |
WiFi.disconnect(); | |
Serial.println("Disconnected!"); | |
} else { | |
Serial.println("Not connected!"); | |
} | |
} else if (strcasecmp(command, "FORGET") == 0) { | |
preferences.putString("ssid", ""); | |
preferences.putString("password", ""); | |
Serial.println("Saved network cleared"); | |
} else if (strcasecmp(command, "WSTATUS") == 0) { | |
if (connected == false) { | |
Serial.println("Not connected to network"); | |
} else { | |
Serial.print("Connected to "); | |
Serial.println(ssid); | |
Serial.print("RSSI: "); | |
Serial.print(WiFi.RSSI()); | |
Serial.println("dBm"); | |
Serial.print("Our IP: "); | |
Serial.println(WiFi.localIP()); | |
Serial.print("Our MAC: "); | |
Serial.println(WiFi.macAddress()); | |
} | |
} else { | |
Serial.println("Unknown command. Enter HELP for help."); | |
} | |
} | |
// reset the serial command buffers | |
void resetBuffers() { // resets command buffers and command state | |
cmdStatus = 0; // reset the processing state | |
cmdBufferPosition = 0; // reset the buffer position | |
for (int x = 0; x < 32; x++) { // clear the buffer | |
cmdBuffer[x] = NULL; // command buffer | |
command[x] = NULL; // command | |
argument1[x] = NULL; // command arguments | |
argument2[x] = NULL; // command arguments | |
} | |
if (echoInput == 1) { // if echo is enabled, print a prompt | |
Serial.println(""); | |
Serial.print(CMDPROMPT); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment