точка доступа для выбора и подключения к wi-fi
- Войдите на сайт для отправки комментариев
Вс, 26/05/2019 - 22:05
привет, народ, есть у кого-то пример кода для ESP32 or ESP8266, который создает точку доступа для выбора и подключения к wifi, а затем, подключившись к wifi запоминает пароль и используя это подключение создает web server?
заранее спасибо!
в гугле примеров тыщщщи, забанили ?
буду благодарен хотябы за один...
при поиске по запросу "arduino точка доступа для выбора и подключения к wi-fi" нихрена путнего не находит
Я так понимаю, что вам нужно:
а) Создать на базе ESP точку доступа с вебмордой.
б) Подключиться к вебморде и в ней выбрать WiFi-сеть для подключения (ввести пароль и все прочие настройки).
в) Переподключить ESP в режим клиента, подключенного к выбранной сети и запустить вебсервер.
Все эти вещи есть в стандартных примерах ESP. Вам нужно только собрать это все в кучу. Готовую программу вы вряд ли найдете.
FoxJone, спасибо за совет.
точку доступа создал, в предложеном Вами алгоритме после перезагрузки надо будет опять искать сеть и вводить пароль, а затем переключаться или пароль бвудет сохранен?
Я вот использую эту. https://github.com/tzapu/WiFiManager
FoxJone, спасибо за совет.
точку доступа создал, в предложеном Вами алгоритме после перезагрузки надо будет опять искать сеть и вводить пароль, а затем переключаться или пароль бвудет сохранен?
После настройки клиента пишите настройки (сеть, пароль и флаг того, что клиент настроен) в постоянную память (например, в EEPROM, или к примеру на SD-карту, если такая есть в конструкции) и при загрузке читайте их оттуда.
void loadDataWiFiEEPROM() { byte i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_wifi_p1 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0; strcpy(ssid, eep_str); i = 0; while (((eep_str[i] = EEPROM.read(eep_pos_wifi_p2 + i)) > 0) && (i < eep_max_len_param)) ++i; eep_str[i] = 0; strcpy(password, eep_str); } void EEPROMinit() { EEPROM.begin(eep_max_len_param * eep_max_count_params); } // save String str_ppid = header.substring(p_id + 5, p_pp); str_ppid.toCharArray(eep_str, l_id + 1); eep_str[l_id] = 0; byte i = 0; while (eep_str[i] > 0) { EEPROM.write(eep_pos_wifi_p1 + i, eep_str[i]); ++i; } EEPROM.write(eep_pos_wifi_p1 + i, 0); str_ppid = header.substring(p_pp + 6, p_act); str_ppid.toCharArray(eep_str, l_pp + 1); eep_str[l_pp] = 0; i = 0; while (eep_str[i] > 0) { EEPROM.write(eep_pos_wifi_p2 + i, eep_str[i]); ++i; } EEPROM.write(eep_pos_wifi_p2 + i, 0); EEPROM.commit(); EEPROM.end(); EEPROMinit(); loadDataWiFiEEPROM(); // stop server and wifiМужики, спасибо за подсказки в каком направлении двигаться, к сожалению готовые решения не помогли - это часть огромного проэкта и попытка внедрить тот же вифи-менеджер приводила к неработоспособности кода сервера и телеграмм-бота, поэтому написал костыльный, но рабочий подход. В eeprom выделяется место 40 байт под хранение двух пар: ssid и пароль, при запуске ЕСПхи пробуются имеющиеся пароли - если не удается подключиться, то создается точка доступа с простой формой - только для вводи имени сети и пароля. дальше проблемка))) в терминале вижу строку с введенными ИД и паролем:
но не пойму как она выводится (в коде нет такго сериал-принтлайна), как это вывести в скетче, где это выводится в библеотеке тоже пока не нашел - поиск по слову в документе "Referer: " в папке с библитоеками ничего не находит, да и не придумал как разбить на аргументы, юзать регулярные выражения или есть более простой способ?.
в планах:
- добавить сканер доступных сетей, чтобы не вводить название, а выбирать.
- возможно отимизировать место в памяти, а не выделять по 10 символов на каждый пароль и ssid
#include <EEPROM.h> #include <WiFi.h> WiFiServer wifi_server(80); byte wifi_server_run = 0; #define last_byte_to_eeprom 106 String webpage; // Variable to store the HTTP request String header; // Replace with your network credentials const char* ssid = "KH-WiFi"; const char* password = "123456789"; void setup() { EEPROM.begin(last_byte_to_eeprom); Serial.begin(115200); connect_wifi (); } void loop() { while (true) { String command = Serial.readString(); // read a command if (command == "") break; // if no more commands, then exit else if (command.startsWith("psw2")) { // для тестирования записи ИД сети и пароля в EEPROM Serial.println("psw2"); write_wifi_password("Guest", "88888888"); } else if (command.startsWith("psw1")) { // для тестирования записи ИД сети и пароля в EEPROM Serial.println("psw1"); write_wifi_password("ASUS", "99999999"); } } if (wifi_server_run == 1) { // если не законектились к вайфаю начинаем слушать WiFiClient client = wifi_server.available(); // Listen for incoming clients if (client ) { // If a new client connects, Serial.println("New Client."); // print a message out in 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 header += c; 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("Connection: close"); client.println(); // turns the GPIOs on and off if (header.indexOf("wifisave") >= 0) { Serial.print("header ");Serial.println(header); } // Display the HTML web page client.println("<!DOCTYPE html> <html lang=\"en\"> <head> <meta charset=\"UTF-8\"> <title>Title</title> <style> .wrapper { margin: 0 auto; text-align: center; } </style> </head> <body> <div class=\"wrapper\"> <form method='get' action='wifisave'> <input id='s' name='SSID' length=32 placeholder='SSID'><br/> <input id='p' name='password' length=64 type='password' placeholder='password'><br/> <br/><button type='submit'>save</button> </form> </div> </body> </html>"); // 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 } } } header = ""; // Clear the header variable client.stop(); // Close the connection Serial.println("Client disconnected."); Serial.println(""); } } } /* - Password and SSID couldn't be more than 10 chars - when writing new password the oldest one will be cleared - the script keeps max two pair of SSID and password */ void connect_wifi () { for (int i = 0; i < 30; i += 20) // пробуем подключиться к сети по всем паролям которіе есть в памяти { // Serial.print("try: "); Serial.println(i); char ssid[EEPROM_String_read(i).length() + 1]; char password[EEPROM_String_read(i + 10).length() + 1] ; EEPROM_String_read(i).toCharArray(ssid, EEPROM_String_read(i).length() + 1); EEPROM_String_read(i + 10).toCharArray(password, EEPROM_String_read(i + 10).length() + 1); Serial.print("ssid: "); Serial.print(ssid); Serial.print("; password: "); Serial.println(password); int x = 0; WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (x < 10) { if (WiFi.status() == WL_CONNECTED) break; Serial.println(x); x++; delay(500); } if (WiFi.status() == WL_CONNECTED) { Serial.println(""); Serial.println(F("WiFi connected")); Serial.print(F("IP address: ")); Serial.println(WiFi.localIP()); break; } } if (WiFi.status() != WL_CONNECTED) { // если не подклбчились к сети - создаем точку доступа для ввода имени сети и пароля Serial.println("Cant connect to wifi"); // Connect to Wi-Fi network with SSID and password Serial.print("Setting AP (Access Point)…"); // Remove the password parameter, if you want the AP (Access Point) to be open WiFi.softAP(ssid, password); IPAddress IP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(IP); Serial.println("Start local Wi-Fi server"); wifi_server.begin(); wifi_server_run = 1; } } void write_wifi_password (String ssid, String pswrd) { Serial.print("ssid: "); Serial.print(ssid); Serial.print("; password: "); Serial.println(pswrd); EEPROM_String_write(0, EEPROM_String_read(20)); EEPROM_String_write(10, EEPROM_String_read(30)); EEPROM_String_write(20, ssid); EEPROM_String_write(30, pswrd); } void EEPROM_String_write(char add, String data) { int _size = data.length(); int i; for (i = 0; i < _size; i++) EEPROM.write(add + i, data[i]); EEPROM.write(add + _size, '\0'); //Add termination null character for String Data EEPROM.commit(); } String EEPROM_String_read(char add) { int i; char data[50]; //Max 100 Bytes int len = 0; unsigned char k; k = EEPROM.read(add); while (k != '\0' && len < 500) //Read until null character { k = EEPROM.read(add + len); data[len] = k; len++; } data[len] = '\0'; return String(data); }Пример сканера сетей есть уже с библиотеками к платам
Чем вам не нравиться выделять по 10 байт под Логин пароль? Там памяти дофига
Работа с get и post запросами в esp8266 и esp32s немного отличается и библиотеки разные, но общий смысл одинаков- берём входящую строку и парсим её на нужные куски и вытаскиваем данные из нее
С ESP32 не работал, ничего не могу сказать, а у ESP8266 море памяти и нормальная скорость, вполне себе может поддержать нормальный веб-интерфейс. Я на коленке собирал простенькую вебморду и успешно продал девайсину с ней клиенту - клиент очень был доволен тем, что управлять можно с любого устройства лишь бы был браузер. И это при том, что в html вообще играл чуть ли не первый раз в жизни. Не понимаю, зачем использовать GET-запросы м вообще все эти танцы с адресной строкой браузера.
С другой стороны, НАСТОЙЧИВО НЕ РЕКОМЕНДУЮ (сам обжегся очень) вешать на ESP8266 какие то другие задачи, кроме WiFi, web-сервера и вебинтерфейса. Ну максимум что то простенькое, типа кнопки или датчика температуры. Иначе, ой сколько вам открытий чудных готовит парадоксов друг....
добавил сканер, сделал парсинг строки, но после ее записи (строка write_wifi_password ( String(SSID_s), String(password_s)); // ТАК НЕ РАБОТАЕТ - ВИСНЕТ) и попытке обращения к этой ячейке - происходит перезагрузка еспэхи... чтобы вернуть есп к жизни приходится заплнять память нулями...
хел плиз...
if (header.indexOf("GET /wifisave?") >= 0) { Serial.print("!!!!!!!!!!header "); Serial.println(header);//String header = "GET /wifisave?SSID=ASUS&password=123456 HTTP/1.1"; header.replace("GET /wifisave?SSID=", ""); header.replace("password=", ""); header.replace(" HTTP/1.1", ""); char token1[header.length()]; header.toCharArray(token1, header.length() + 1); // header.toCharArray(token1, header.length() + 1); char *token = strtok(token1, "&"); String SSID_s = token; token = strtok (NULL, "&"); String password_s = token; Serial.print("Extracted "); Serial.print(SSID_s);Serial.print(" "); Serial.println(password_s); delay(100); write_wifi_password ( String(SSID_s), String(password_s)); // ТАК НЕ РАБОТАЕТ - ВИСНЕТ // write_wifi_password("ASUS", "88888888"); // С ЭТОЙ СТРОКОЙ РАБОТАЕТ НОРМАЛЬНО }полный код:
#include <EEPROM.h> #include <WiFi.h> WiFiServer wifi_server(80); byte wifi_server_run = 0; String wifi_ssid[20] = {}; int Networks_count = 0; #define last_byte_to_eeprom 106 String webpage; // Variable to store the HTTP request String header; // Replace with your network credentials const char* ssid = "KH-цшаш"; const char* password = "123456789"; void setup() { EEPROM.begin(last_byte_to_eeprom); Serial.begin(115200); connect_wifi(); } void loop() { while (true) { String command = Serial.readString(); // read a command if (command == "") break; // if no more commands, then exit else if (command.startsWith("psw2")) { Serial.println("psw2"); String s = "Guest", p = "88888888"; write_wifi_password(s, p); } else if (command.startsWith("psw1")) { Serial.println("psw1"); write_wifi_password("ASUS", "88888888"); } } if (wifi_server_run == 1) { WiFiClient client = wifi_server.available(); // Listen for incoming clients if (client ) { // If a new client connects, Serial.println("New Client."); // print a message out in 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 header += c; 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("Connection: close"); client.println(); if (header.indexOf("GET /wifisave?") >= 0) { Serial.print("!!!!!!!!!!header "); Serial.println(header);//String header = "GET /wifisave?SSID=ASUS&password=123456 HTTP/1.1"; header.replace("GET /wifisave?SSID=", ""); header.replace("password=", ""); header.replace(" HTTP/1.1", ""); char token1[header.length()]; header.toCharArray(token1, header.length() + 1); // header.toCharArray(token1, header.length() + 1); char *token = strtok(token1, "&"); String SSID_s = token; token = strtok (NULL, "&"); String password_s = token; Serial.print("Extracted "); Serial.print(SSID_s);Serial.print(" "); Serial.println(password_s); delay(100); write_wifi_password ( String(SSID_s), String(password_s)); // ТАК НЕ РАБОТАЕТ - ВИСНЕТ // write_wifi_password("ASUS", "88888888"); // С ЭТОЙ СТРОКОЙ РАБОТАЕТ НОРМАЛЬНО } String web = "<!DOCTYPE html> <html lang=\"en\"> <head> <meta charset=\"UTF-8\"> <title>Title</title> <style> .wrapper { margin: 0 auto; text-align: center; } </style> </head> <body> <div class=\"wrapper\"> <form method='get' action='wifisave'>"; web += "<select id=\"SSID\" name=\"SSID\">"; // Serial.print("Networks_count "); Serial.println(Networks_count); if (Networks_count > 0) { for (int i = 0; i < Networks_count; ++i) { web += "<option value=\"" + WiFi.SSID(i) + "\">" + WiFi.SSID(i) + "</option>"; delay(10); } } // Display the HTML web page web += "</select>"; // web += "<input id='s' name='SSID' length=32 placeholder='SSID'>"; web += "<br/> <input id='p' name='password' length=64 type='password' placeholder='password'><span></span><br/> <br/><button type='submit'>save</button> </form> </div> </body> </html>"; client.println(web); // 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 } } } // Clear the header variable header = ""; // Close the connection client.stop(); Serial.println("Client disconnected."); Serial.println(""); } } } /* - Password and SSID couldn't be more than 10 chars - when writing new password the oldest one will be cleared - the script keeps max two pair of SSID and password */ void connect_wifi () { for (int i = 0; i <30; i += 20) { if (EEPROM_String_read(i).length() > 2 && EEPROM_String_read(i + 10).length() > 2) { Serial.print("EEPROM_String_read(i).length(): "); Serial.println(EEPROM_String_read(i).length()); Serial.print("EEPROM_String_read(i+10).length(): "); Serial.println(EEPROM_String_read(i+10).length()); // Serial.print("try: "); Serial.println(i); char ssid[EEPROM_String_read(i).length() + 1]; char password[EEPROM_String_read(i + 10).length() + 1] ; EEPROM_String_read(i).toCharArray(ssid, EEPROM_String_read(i).length() + 1); EEPROM_String_read(i + 10).toCharArray(password, EEPROM_String_read(i + 10).length() + 1); Serial.print("ssid: "); Serial.print(ssid); Serial.print("; password: "); Serial.println(password); int x = 0; WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while ((WiFi.status() != WL_CONNECTED) && x < 10) { // (выполнять цикл, пока хотя бы одно из условий истинно) if (WiFi.status() == WL_CONNECTED) break; Serial.println(x); x++; delay(500); } if (WiFi.status() == WL_CONNECTED) { Serial.println(""); Serial.println(F("WiFi connected")); Serial.print(F("IP address: ")); Serial.println(WiFi.localIP()); break; } } } if (WiFi.status() != WL_CONNECTED) { Serial.println("Cant connect to wifi"); // Connect to Wi-Fi network with SSID and password WiFi.mode(WIFI_STA); WiFi.disconnect(); delay(100); Networks_count = WiFi.scanNetworks(); Serial.println("scan done"); if (Networks_count == 0) { Serial.println("no networks found"); } else { Serial.print(Networks_count); Serial.println(" networks found"); if (Networks_count > 20) Networks_count = 20; for (int i = 0; i < Networks_count; ++i) { // Print SSID and RSSI for each network found wifi_ssid[i] = WiFi.SSID(i); 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.print("Setting AP (Access Point)…"); // Remove the password parameter, if you want the AP (Access Point) to be open WiFi.softAP(ssid, password); // IPAddress IP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(IP); Serial.println("Start local Wi-Fi server"); wifi_server.begin(); wifi_server_run = 1; } } void write_wifi_password (String ssid, String pswrd) { Serial.print("ssid: "); Serial.print(ssid); Serial.print("; password: "); Serial.println(pswrd); EEPROM_String_write(0, EEPROM_String_read(20)); EEPROM_String_write(10, EEPROM_String_read(30)); EEPROM_String_write(20, ssid); EEPROM_String_write(30, pswrd); } void EEPROM_String_write(char add, String data) { int _size = data.length(); int i; for (i = 0; i < _size; i++) EEPROM.write(add + i, data[i]); EEPROM.write(add + _size, '\0'); //Add termination null character for String Data EEPROM.commit(); } String EEPROM_String_read(char add) { int i; char data[50]; //Max 100 Bytes int len = 0; unsigned char k; k = EEPROM.read(add); while (k != '\0' && len < 55) //Read until null character { k = EEPROM.read(add + len); data[len] = k; len++; } data[len] = '\0'; return String(data); }странно как то... зачем закомментирована // server.handleClient(); ? в ESP32, да она не нужна, а тут работать не будет, потом еще и цикл бесконечный - конечно будет зависать.
Посмотретие пример из поставки HTTP сервер, там все просто и прозрачно.
Куски из моего проекта:
WiFi.disconnect(); Serial.print("Configuring access point..."); WiFi.mode(WIFI_AP); WiFi.softAP(srvssid, srvpass); IPAddress myIP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(myIP); // прописываем какие страницы открывать на разные запросы server.on("/", handleRoot); server.on("/setup", HTTP_GET, handleSetupGet); server.on("/setup", HTTP_POST, handleSetupPost); server.onNotFound(handleNotFound); server.begin(); // запускаем сервер Serial.println("HTTP server started"); server.handleClient(); // обрабатываем запрос if (server.hasArg("action")) { if (((server.arg("action").indexOf("savewifi")) >= 0) && (server.hasArg("ssid")) && (server.hasArg("pass"))) { Serial.println("There are new WiFi data"); // save data to eeprom // записываем введенные данные в eeprom byte l = server.arg("ssid").length() + 1; server.arg("ssid").toCharArray(eep_str, l); eep_str[l] = 0; byte i = 0; while (eep_str[i] > 0) { EEPROM.write(eep_pos_wifi_p1 + i, eep_str[i]); ++i; } EEPROM.write(eep_pos_wifi_p1 + i, 0); l = server.arg("pass").length() + 1; server.arg("pass").toCharArray(eep_str, l); eep_str[l] = 0; i = 0; while (eep_str[i] > 0) { EEPROM.write(eep_pos_wifi_p2 + i, eep_str[i]); ++i; } EEPROM.write(eep_pos_wifi_p2 + i, 0); EEPROM.commit(); EEPROM.end(); EEPROMinit(); loadDataWiFiEEPROM(); server.stop(); WiFi.disconnect(); ++deviceMode; } } void handleNotFound() { String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET) ? "GET" : "POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } server.send(404, "text/plain", message); } void handleRoot() { server.send(200, "text/html", "<h1>You are connected</h1>"); } void handleSetupGet() { String message = "<html lang='ru'>\ <head>\ <meta charset='utf - 8'>\ <title>ESP Server</title>\ </head>\ <body>\ <h1>WiFi Acces Point data</h1>\ <form action='?' method='post'>\ <div>\ <label for='ssid'>WiFi SSID: <input type='text' name='ssid' id='ssid' value='"; message += ssid; message += "'></label>\ </div>\ <div>\ <label for='pass'>WiFi Password: <input type='password' name='pass' id='pass' value='"; message += password; message += "'></label>\ </div>\ <p></p>\ <input type='hidden' name='action' value='savewifi'>\ <input type='submit' value='Save'>\ </div>\ </form>\ <p></p>\ <a href='../'>Return to main page</a>\ </body>\ </html>"; server.send(200, "text/html", message); } void handleSetupPost() { server.send(200, "text/html", "<html lang='ru'>\ <head>\ <meta charset='utf - 8'>\ <title>ESP temperature Server</title>\ </head>\ <body>\ <h1>OK</h1>\ <p></p>\ <a href='../'>Return to main page</a>\ </body>\ </html>"); }- так у меня как раз ESP32, та строка не нужна
- потом еще и цикл бесконечный - конечно будет зависать. - там нет бесконечных циклов... оно не зависает, а перезагружается после записи в память распарсеной строки, до сохранения все отлично работает...
у Вас пример для ESP8266? потому что у меня библиотека #include <WiFi.h> не поддерживает .hasArg ...
пример для esp32s
WiFi.mode(WIFI_AP); WiFi.disconnect(); Serial.print("Configuring access point..."); WiFi.softAP(srvssid, srvpass); IPAddress myIP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(myIP); server.begin(); // запускаем сервер header = ""; // очистка строки запроса WiFiClient client = server.available(); // Listen for incoming clients if (client) { // If a new client connects, Serial.println("New Client."); // print a message out in 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 header += c; 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("Connection: close"); client.println(); if (header.indexOf("GET / HTTP/") >= 0) { handleSetupGet(client); } else if (header.indexOf("POST /? HTTP/") >= 0) { // read data POST while (client.available()) { char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor header += c; } // start page handleRoot(client); // processing header int p_act = header.indexOf("&action=savewifi"); if (p_act >= 0) { // and find login password WiFi int p_id = header.indexOf("ssid="); int p_pp = header.indexOf("&pass="); int l_id = p_pp - p_id - 5; int l_pp = p_act - p_pp - 6; if ((l_pp > 0) && (l_id > 0)) { // save String str_ppid = header.substring(p_id + 5, p_pp); str_ppid.toCharArray(eep_str, l_id + 1); eep_str[l_id] = 0; byte i = 0; while (eep_str[i] > 0) { EEPROM.write(eep_pos_wifi_p1 + i, eep_str[i]); ++i; } EEPROM.write(eep_pos_wifi_p1 + i, 0); str_ppid = header.substring(p_pp + 6, p_act); str_ppid.toCharArray(eep_str, l_pp + 1); eep_str[l_pp] = 0; i = 0; while (eep_str[i] > 0) { EEPROM.write(eep_pos_wifi_p2 + i, eep_str[i]); ++i; } EEPROM.write(eep_pos_wifi_p2 + i, 0); EEPROM.commit(); EEPROM.end(); EEPROMinit(); loadDataWiFiEEPROM(); // stop server and wifi header = ""; // Clear the header variable delay(500); client.stop(); // Close the connection Serial.println("Client disconnected."); server.stop(); delay(500); ++deviceMode; break; } } } else { handleRoot(client); } 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 } } } header = ""; // Clear the header variable delay(100); client.stop(); // Close the connection Serial.println("Client disconnected."); }сами странички
void handleSetupGet(WiFiClient clwf) { String message = "<html lang='ru'>\ <head>\ <meta charset='utf - 8'>\ <title>ESP Server</title>\ </head>\ <body>\ <h1>WiFi Acces Point data</h1>\ <form action='?' method='post'>\ <div>\ <label for='ssid'>WiFi SSID: <input type='text' name='ssid' id='ssid' value='"; message += ssid; message += "'></label>\ </div>\ <div>\ <label for='pass'>WiFi Password: <input type='password' name='pass' id='pass' value='"; message += password; message += "'></label>\ </div>\ <p></p>\ <input type='hidden' name='action' value='savewifi'>\ <input type='submit' value='Save'>\ </div>\ </form>\ <p></p>\ </body>\ </html>"; clwf.println(message); } void handleRoot(WiFiClient clwf) { clwf.println("<h1>You are connected</h1>"); }всем спасибо! все получилось :)
andycat, спасибо, добавил еще выпадающее меню с перечнем доступных сетей
#include <EEPROM.h> #include <WiFi.h> WiFiServer wifi_server(80); byte wifi_server_run = 0; String wifi_ssid[20] = {}; int Networks_count = 0; #define last_byte_to_eeprom 106 String webpage; int eep_pos_wifi_p1 = 0; int eep_pos_wifi_p2 = 10; // Variable to store the HTTP request String header; // Replace with your network credentials const char* ssid = "KH-wifi"; const char* password = "123456789"; void setup() { EEPROM.begin(last_byte_to_eeprom); Serial.begin(115200); connect_wifi(); } void loop() { while (true) { String command = Serial.readString(); // read a command if (command == "") break; // if no more commands, then exit else if (command.startsWith("psw2")) { Serial.println("psw2"); String s = "Guest", p = "88888888"; write_wifi_password(s, p); } else if (command.startsWith("psw1")) { Serial.println("psw1"); write_wifi_password("ASUS", "99999999"); } } if (wifi_server_run == 1) { WiFiClient client = wifi_server.available(); // Listen for incoming clients if (client) { // If a new client connects, Serial.println("New Client."); // print a message out in 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 header += c; 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("Connection: close"); client.println(); if (header.indexOf("GET / HTTP/") >= 0) { handleSetupGet(client); } else if (header.indexOf("POST /? HTTP/") >= 0) { // read data POST while (client.available()) { char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor header += c; } // start page handleRoot(client); // processing header int p_act = header.indexOf("&action=savewifi"); if (p_act >= 0) { // and find login password WiFi int p_id = header.indexOf("ssid="); int p_pp = header.indexOf("&pass="); int p_ws = header.indexOf("&action="); String str_ppid = header.substring(p_id + 5, p_pp); String str_pppass = header.substring(p_pp + 6, p_ws); if ((str_ppid.length() > 0) && (str_pppass.length() > 0)) { // save // Serial.println("");Serial.println("----------------------------------------------------------"); // Serial.print("str_ppid: "); Serial.print(str_ppid); Serial.print("; str_pppass: "); Serial.print(str_pppass); Serial.println(";"); // Serial.println("----------------------------------------------------------"); write_wifi_password(str_ppid, str_pppass); // stop server and wifi header = ""; // Clear the header variable delay(500); client.stop(); // Close the connection Serial.println("Client disconnected."); wifi_server.stop(); delay(500); break; } } } else { handleRoot(client); } 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 } } } header = ""; // Clear the header variable delay(100); client.stop(); // Close the connection Serial.println("Client disconnected."); } } } void handleSetupGet(WiFiClient clwf) { String message = "<html lang='ru'>\ <head>\ <meta charset='utf - 8'>\ <title>KH-wifi Server</title>\ </head>\ <body>\ <h1>WiFi Acces Point data</h1>\ <form action='?' method='post'>\ <div>\ <label for='ssid'>WiFi SSID: <select name='ssid' id='ssid'>"; if (Networks_count > 0) { for (int i = 0; i < Networks_count; ++i) { message += "<option value=\"" + WiFi.SSID(i) + "\">" + WiFi.SSID(i) + "</option>"; delay(10); } } message += "</select></div>\ <div>\ <label for='pass'>WiFi Password: <input type='password' name='pass' id='pass' value='"; //<label for='ssid'>WiFi SSID: <input type='text' name='ssid' id='ssid' value='"; message += ssid; message += "'></label> message += password; message += "'></label>\ </div>\ <p></p>\ <input type='hidden' name='action' value='savewifi'>\ <input type='submit' value='Save'>\ </div>\ </form>\ <p></p>\ </body>\ </html>"; clwf.println(message); } void handleRoot(WiFiClient clwf) { clwf.println("<h1>SSID and Password saved</h1><br><br><h1>reload your KH-wifi</h1>"); } /* - Password and SSID couldn't be more than 10 chars - when writing new password the oldest one will be cleared - the script keeps max two pair of SSID and password */ void connect_wifi () { for (int i = 0; i < 30; i += 20) { if (EEPROM_String_read(i).length() > 2 && EEPROM_String_read(i + 10).length() > 2) { // Serial.print("EEPROM_String_read(i).length(): "); Serial.println(EEPROM_String_read(i).length()); // Serial.print("EEPROM_String_read(i+10).length(): "); Serial.println(EEPROM_String_read(i + 10).length()); char ssid[EEPROM_String_read(i).length() + 1]; char password[EEPROM_String_read(i + 10).length() + 1] ; EEPROM_String_read(i).toCharArray(ssid, EEPROM_String_read(i).length() + 1); EEPROM_String_read(i + 10).toCharArray(password, EEPROM_String_read(i + 10).length() + 1); Serial.print("ssid: "); Serial.print(ssid); Serial.print("; password: "); Serial.println(password); int x = 0; WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while ((WiFi.status() != WL_CONNECTED) && x < 10) { // (выполнять цикл, пока хотя бы одно из условий истинно) if (WiFi.status() == WL_CONNECTED) break; Serial.println(x); x++; delay(500); } if ( WiFi.status() == WL_CONNECTED ) { Serial.println(""); Serial.println(F("WiFi connected")); Serial.print(F("IP address: ")); Serial.println(WiFi.localIP()); break; } } } if (WiFi.status() != WL_CONNECTED) { Serial.println("Cant connect to wifi"); // Connect to Wi-Fi network with SSID and password WiFi.mode(WIFI_STA); WiFi.disconnect(); delay(100); Networks_count = WiFi.scanNetworks(); Serial.println("scan done"); if (Networks_count == 0) { Serial.println("no networks found"); } else { Serial.print(Networks_count); Serial.println(" networks found"); if (Networks_count > 20) Networks_count = 20; for (int i = 0; i < Networks_count; ++i) { // Print SSID and RSSI for each network found wifi_ssid[i] = WiFi.SSID(i); 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); } } WiFi.mode(WIFI_AP); WiFi.disconnect(); Serial.print("Configuring access point..."); WiFi.softAP(ssid, password); IPAddress myIP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(myIP); header = ""; // очистка строки запроса wifi_server.begin(); // запускаем сервер wifi_server_run = 1; } } void write_wifi_password (String ssid, String pswrd) { Serial.print("ssid: "); Serial.print(ssid); Serial.print("; password: "); Serial.println(pswrd); EEPROM_String_write(20, EEPROM_String_read(0)); EEPROM_String_write(30, EEPROM_String_read(10)); EEPROM_String_write(0, ssid); EEPROM_String_write(10, pswrd); } void EEPROM_String_write(char add, String data) { int _size = data.length(); int i; for (i = 0; i < _size; i++) EEPROM.write(add + i, data[i]); EEPROM.write(add + _size, '\0'); //Add termination null character for String Data EEPROM.commit(); } String EEPROM_String_read(char add) { int i; char data[50]; //Max 100 Bytes int len = 0; unsigned char k; k = EEPROM.read(add); while (k != '\0' && len < 10) //Read until null character { k = EEPROM.read(add + len); data[len] = k; len++; } data[len] = '\0'; return String(data); }добавил еще выпадающее меню с перечнем доступных сетей
вот просто из любопытства: в наше время с почти халявным и качественным 4G интернетом еще кому то нужны незапароленные WiFi сети?
вот просто из любопытства: в наше время с почти халявным и качественным 4G интернетом еще кому то нужны незапароленные WiFi сети?
А как же. Надзорным органам очень нужны!
За предоставление анонимного доступа в интернет с любого юрика можно очень красиво штрафов сорвать.
Именно поэтому все общественные вайфаи требуют авторизацию через телефон. Либо пароль предоставляется конкретному лицу (к примеру, жильцу в гостинице).
Вы использовали ESP32? Все работает? Я просто ищу нечто похожее для своего проекта. Есть ли баги при использовании?
если длина ssid и пароля более 10 символов видимо багам быть
Да, так у меня и получилось. Придется писать свой код. А если заказать, то почем выйдет?
если точки подключения и пароли известны, то лучше делать по другому
Ну так дело в том что вначале должна точка доступа с предустановленным именем и паролем. А после человек должен сам выбрать свою сеть и подключиться к ней. Ограничение по длине имени и паролю - осуждаю )))
если длина ssid и пароля более 10 символов видимо багам быть
Не подскажете, где в этом коде я могу исправить сие недоразумение?
Помоему стандартные ограничения на длину имени точки доступа и пароля 128 символов. Сканинг сетей на тему имен точек доступа с ESP32 на стандартных ардуиновских библиотеках работает через раз. Нужно спускаться на более низкий уровень. На первый взгляд простое задание, по факту окажется больше того кода который вы уже имеете :) Раза в три :)))
Не подскажете, где в этом коде я могу исправить сие недоразумение?
Серьезно ?! Начните с 6 строки :)
Ну а отчего же не серьезно? )) Был бы профи, то стал бы я сидеть на форуме? Я только начинаю, и для меня пока что все в диковинку.
У Arduino-EPS-шек всё немного покороче, чем 128 chars
ESP32 core:
if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { log_e("SSID too long or missing!"); return WL_CONNECT_FAILED; } if(passphrase && strlen(passphrase) > 64) { log_e("passphrase too long!"); return WL_CONNECT_FAILED; }ESP8266 Core:
if(!ssid || *ssid == 0x00 || strlen(ssid) > 32) { // fail SSID too long or missing! return WL_CONNECT_FAILED; } int passphraseLen = passphrase == nullptr ? 0 : strlen(passphrase); if(passphraseLen > 64) { // fail passphrase too long! return WL_CONNECT_FAILED; }Ребят, помогите запустить код, пожалуйста. Ну хотя бы сделать возможность ввода пароля длиной 20-30 символов.
Я этими костылями не пользуюсь :) Если уж делать то по "ГОСТУ" :)
Ого, по ГОСТу это как?
Это я так стандарты назвал.
На самом деле ошибся я. Садман прав, респект. Длинна SSID максимум 32 символа, длинна пароля до 64 символов.
Это я так стандарты назвал.
На самом деле ошибся я. Садман прав, респект. Длинна SSID максимум 32 символа, длинна пароля до 64 символов.
Тогда тем более интересно, почему ТС счел целесообразным остановиться именно на такой длине пароля?
От балды, память пожалел. Не всем приходит в голову посмотреть стандарты. Но в шестой строке , на самом деле описана переменная которая сохраняет всего 20 имен сетей, причем их длина не ограничена.
потому, что 9 символов в пароле, это минимум, когда включается шифрование, иначе точка открыта
От балды, память пожалел. Не всем приходит в голову посмотреть стандарты. Но в шестой строке , на самом деле описана переменная которая сохраняет всего 20 имен сетей, причем их длина не ограничена.
Стало еще непонятней и одновременно непонятно. Значит длина имен сетей практически неограничена, на кой хрен нужно 20 имен сетей, хотя за глаза хватило бы и 6-7 по убыванию мощности. А вот на пароль длины пожалел (( крыса ...
потому, что 9 символов в пароле, это минимум, когда включается шифрование, иначе точка открыта
Запомнил )) Спасибо.
Ну почему же, у меня бывает что требуемая сеть находится где нибудь на 30м месте. Кроме того этот код не ранжирует сети по RSSI.Так что для того что бы вывести на экран десяток самых "громких" нужно отсортировать весь список.
Я не знаю какие косяки вылезают в этом коде, но самое главное не забывать, что из-за того, что ESP имеют единый радиоканал для точки доступа и клиента, на время сканирования эфира на тему других точек доступа, она сама перестает быть точкой доступа, а это влечет отсоединение остальных клиентов от сети.
Поэтому вы хотите иметь список доступных сетей на страничке сформированной ESPшкой как http-сервером и одновременно точкой доступа. То есть вы должны так написать веб интерфейс и организовать сканирование, что бы клиенты вашей ESP как точки доступа не сваливали во время отключения.
Ну почему же, у меня бывает что требуемая сеть находится где нибудь на 30м месте. Кроме того этот код не ранжирует сети по RSSI.Так что для того что бы вывести на экран десяток самых "громких" нужно отсортировать весь список.
Я не знаю какие косяки вылезают в этом коде, но самое главное не забывать, что из-за того, что ESP имеют единый радиоканал для точки доступа и клиента, на время сканирования эфира на тему других точек доступа, она сама перестает быть точкой доступа, а это влечет отсоединение остальных клиентов от сети.
Поэтому вы хотите иметь список доступных сетей на страничке сформированной ESPшкой как http-сервером и одновременно точкой доступа. То есть вы должны так написать веб интерфейс и организовать сканирование, что бы клиенты вашей ESP как точки доступа не сваливали во время отключения.
Умно, нужно поглядеть пример из Factory test там есть скан сетей, и помоему они ранжируются. Попозже выложу этот скетч.
Хорошая тема. Подпишусь. В этом году планирую вшить подобный функционал в свой зоопарк устройств. Пока работает только быстрое переключение сценариев: работа - дом/дача - мобильный. К неизвестным сетям не умеют подключаться
Ну почему же, у меня бывает что требуемая сеть находится где нибудь на 30м месте. Кроме того этот код не ранжирует сети по RSSI.Так что для того что бы вывести на экран десяток самых "громких" нужно отсортировать весь список.
Я не знаю какие косяки вылезают в этом коде, но самое главное не забывать, что из-за того, что ESP имеют единый радиоканал для точки доступа и клиента, на время сканирования эфира на тему других точек доступа, она сама перестает быть точкой доступа, а это влечет отсоединение остальных клиентов от сети.
Поэтому вы хотите иметь список доступных сетей на страничке сформированной ESPшкой как http-сервером и одновременно точкой доступа. То есть вы должны так написать веб интерфейс и организовать сканирование, что бы клиенты вашей ESP как точки доступа не сваливали во время отключения.
надо посмотреть, если проверяю подключенных клиентов к первичной AP, то таки да, а сканирование точек безобрывное вроде )))
Хочу поделиться опытом. Полчаса назад нашел библиотеку tzapu/WiFiManager https://github.com/tzapu/WiFiManager.git но обязательно билд Developer. С ее помощью помощью можно к примеру создать точку доступа при подключении к которой можно выбрать из списка сетей искомую и введя ее пароль подключиться к ней. При этом точка доступа отключается (по крайней мере ее не видно в телефоне) и при необходимости нажав на кнопку на модуле инициировать ее вновь чтобы выбрать другую вай фай сеть. Код короткий, работает стабильно )) Замучал я его уже ...
Какой же он короткий !? Вы в файл wifimanager.cpp заглядывали ? Там всего ТРИ ТЫСЯЧИ строк кода.
Какой же он короткий !? Вы в файл wifimanager.cpp заглядывали ? Там всего ТРИ ТЫСЯЧИ строк кода.
Это я про тот что в скетче ))
С таким подходом могу написать код из двух строк и восьми букв.