- ESP8266: Scanning WiFi Networks
- The code
- Arduino.ru
- ESP8266: сканировать вайфай сети и подключиться, если есть известная (нужная)
- Простое и асинхронное сканирование WiFi-сетей [1]
- Простое сканирование
- Отключение
- Сканирование сетей
- Пример целиком
- Пример в действии
- Асинхронное сканирование
- Без delay()
- Исходные настройки
- Когда начать
- Проверяем, выполнено ли сканирование
- Пример целиком
- Пример в действии
- Итого
- См.также
- Внешние ссылки
- Решено получить список доступных сетей
- CodeNameHawk
- Алексей.
- Chatlanin
ESP8266: Scanning WiFi Networks
The objective of this post is to explain how to scan the surrounding WiFi networks with the ESP8266.
The code
The code for this tutorial will be very simple and since we only want to scan and get some information about the surrounding WiFi networks, we will do all the coding on the setup function. So, we will leave the main loop empty.
First of all, we include the ESP8266WiFi library, which will make available the functionality needed for the ESP8266 to interact with the WiFi networks. We can remember from previous posts that this is also the library needed for us to connect to a WiFi network.
In the setup function, we start by opening a serial connection, so we can send the data to the Arduino IDE serial console.
Next, to scan the networks, we call the scanNetworks method on the WiFi object of the library we included. This method will return the number of networks discovered [1].
Note that this method can be called with two additional arguments, one that indicates the scanning should be done asynchronously, and another to show networks with hidden SSID [1]. More details about these functionalities can be found here.
int numberOfNetworks = WiFi.scanNetworks();
Now, to get each network SSID, we just need to call the SSID method, which receives as argument the index of one of the previously discovered networks. In the example bellow, we are getting this parameter for the first network of the list. Naturally, you should check first if any network was discovered
We can also get the RSSI (Received Signal Strength Indicator) of each network by calling the RSSI method on the WiFi object, again passing as input the index of the network.
The complete code is shown bellow, which includes the iteration over the discovered networks and printing of these indicators to the serial port.
#include "ESP8266WiFi.h" void setup() < Serial.begin(115200); int numberOfNetworks = WiFi.scanNetworks(); for(int i =0; i> void loop() <>
To test the code just upload it to the ESP8266 and open the serial console. You should get something similar to figure 1.
Figure 1 – Output of the program.
Note that there are more functionalities associated with the scanning of surrounding WiFi networks, which can be seen here.
Arduino.ru
ESP8266: сканировать вайфай сети и подключиться, если есть известная (нужная)
Доброго времени суток. Приходится часто переезжать и разбираться с ардуино (ESP) то в одном месте, то в другом. Руками постоянно перебивать пару ссид/пароль уже надоело. Решил написать функцию сканирования доступных сетей и подключаться, если есть ссид из моего списка. Вроде все сканирует, но не подключается, ну или по крайней мере не выводит полученный айпишник.
#include // Библиотека для создания Wi-Fi подключения (клиент или точка доступа) #include char* array_ssid[] = ; // Массив необходимых ссидов char* array_pass[] = ; // Массив необходимых паролей к этим ссидам int count_ssid = sizeof(array_ssid) / sizeof(array_ssid[0]); // Размер массива ссидов // Функция скарирования и подключения к найденной известной сети из нашего списка, другие будут игнорится void conekt_to_wifi(int networksFound) < // for (int i = 0; i < networksFound; i++) < for (int j = 0; j < count_ssid; j++) < if (WiFi.SSID(i)==array_ssid[j]) < Serial.println("One of ouer ssid was found = " +WiFi.SSID(i)); WiFi.begin(array_ssid[j], array_pass[j]); // Инициализируем подключение к указанной вайфай сети WiFi.setHostname("Host_MDNS"); // Устанавливаем новое имя нашего клиента Serial.println(WiFi.hostname()); // Распечатываем имя клиента while (WiFi.status() != WL_CONNECTED) < // Зупускаем ожидание поднятия вайфай сервера Serial.println("waiting. "); delay(1000); Serial.println(WiFi.localIP()); // Выводим в монитор порта айпишник нашей платы >> > > > void setup() < Serial.begin(9600); while (!Serial) < // ждём, пока не откроется монитор последовательного порта // для того, чтобы отследить все события в программе >WiFi.mode(WIFI_OFF); // Останавливаем вайфай delay(1000); WiFi.mode(WIFI_STA); // Запускаем вайфай Serial.println("Ouer mac else" тут не приводил, смысла нет, потому что зацикливается на подключении и выдает что-то типа этого:(IP unset) waiting. --------------- CUT HERE FOR EXCEPTION DECODER --------------- Soft WDT reset >>>stack>>> ctx: sys sp: 3fffec40 end: 3fffffb0 offset: 01a0 3fffede0: 00000000 00000002 3ffe8889 4020299a 3fffedf0: 00000000 00000002 3ffe8889 40204557 3fffee00: 3ffe888a 00000001 00000020 3ffee638 3fffee10: 3fffee70 3ffe85d8 3ffee638 3ffee638 3fffee20: 40201cac 3ffe8888 3ffee638 40201cb8 3fffee30: 40201cac 3ffe8888 3ffee638 40201fecПростое и асинхронное сканирование WiFi-сетей [1]
Чтобы подключить мобильный телефон к точке доступа, вы, как правило, открываете меню WiFi, находите список доступных точек и затем выбираете ту, что вам нужна. Данная статья рассказывает, как проделать то же самое при помощи ESP8266.
Простое сканирование
Этот пример показывает минимум кода, необходимый для поиска доступных сетей.
Отключение
Чтобы начать, переключите модуль в режим станции и отключитесь от точки доступа.
WiFi.mode(WIFI_STA); WiFi.disconnect();Функция disconnect() разорвет соединение с точкой доступа, которое модуль автоматически установил, используя данные, сохраненные в прошлый раз.
Сканирование сетей
Сделав небольшую задержку, чтобы модуль успел отключиться, начинаем сканирование ближайших сетей:
Теперь просто проверяем значение в переменной n. Если оно больше нуля, выводим список доступных сетей:
for (int i = 0; i n; i++) Serial.println(WiFi.SSID(i)); >Пример целиком
В верхней части этого скетча обязательно должна быть строчка
Целиком это выглядит следующим образом:
#include "ESP8266WiFi.h" void setup() Serial.begin(115200); Serial.println(); WiFi.mode(WIFI_STA); WiFi.disconnect(); delay(100); > void loop() Serial.print("Scan start . "); // "Запускаем сканирование . " int n = WiFi.scanNetworks(); Serial.print(n); Serial.println(" network(s) found"); // " сетей найдено" for (int i = 0; i n; i++) Serial.println(WiFi.SSID(i)); > Serial.println(); delay(5000); >Пример в действии
Загрузите этот скетч на ESP8266 и откройте монитор порта. Если вокруг ESP8266 есть какие-то точки доступа, в мониторе порта начнет появляться повторяющаяся запись вроде этой:
Scan start . 5 network(s) found Tech_D005107 HP-Print-A2-Photosmart 7520 ESP_0B09E3 Hack-4-fun-net UPC Wi-FreeВы наверняка заметите, что между появлением в мониторе порта фраз «Scan start . » и «X network(s) found» пройдет очень много времени. Дело в том, что выполнение функции WiFi.scanNetworks() отнимает время – скетч ждет, пока она завершится, и лишь затем переходит к следующей строчке кода. Но что, если в это время ESP8266 будет выполнять задачу, нарушать действие которой никак нельзя (например, анимацию)?
Но решение есть. Можно воспользоваться асинхронным режимом сканирования, о котором рассказывается в разделе ниже. В нем также рассказывается, как печатать не только SSID, но и другие параметры доступных сетей.
Асинхронное сканирование
В этом скетче мы запустим процесс сканирования, а затем вернемся к выполнению кода в блоке loop(). Когда сканирование завершится, мы выверим время и проверим, удалось ли найти какие-нибудь WiFi-сети. «Критически важный процесс» будет симулирован миганием светодиода 4 раза в секунду. Необходимо, чтобы процесс сканирования не нарушал паттерн мигания светодиода.
Без delay()
Чтобы реализовать такой функционал, мы должны отказаться от функции delay() внутри блока loop(). Вместо этого мы зададим период, запускающий определенное действие. Затем внутри блока loop() поставим функцию millis(), при помощи которой будет проверяться, истек ли заданный период, и если истек, то запустим нужное действие. Аналогичную технику можно применить для периодического сканирования WiFi-сетей.
Исходные настройки
Во-первых, нам нужно задать период сканирования и внутреннюю переменную lastScanMillis, в которой будет храниться время последнего сканирования.
#define SCAN_PERIOD 5000 long lastScanMillis;Когда начать
Внутри блока loop() проверяем, истек ли период SCAN_PERIOD, чтобы знать, нужно ли запустить следующее сканирование:
if (currentMillis - lastScanMillis > SCAN_PERIOD) WiFi.scanNetworks(true); Serial.print("\nScan start . "); // "Запуск сканирования . " lastScanMillis = currentMillis; >Обратите внимание, что функция WiFi.scanNetworks(true) имеет дополнительный параметр true, которого не было в примере выше. Этот параметр активирует сканирование в асинхронном режиме, т.е. запускает процесс сканирования, не дожидаясь результата (обработка будет выполняться в фоновом режиме) и сразу переходя к следующей строчке кода. Асинхронный режим необходим, иначе 250-миллисекундный паттерн будет нарушен, т.к. сканирование занимает больше 250 мс.
Проверяем, выполнено ли сканирование
Наконец, нам нужно периодически проверять, завершился ли процесс сканирования, чтобы знать, пора ли печатать результаты. Для этого нам понадобится функция WiFi.scanComplete(), которая после завершения сканирования возвращает количество найденных сетей. Если сканирование по-прежнему в процессе, она вернет «-1», а если сканирование еще даже не было запущено, то «-2».
int n = WiFi.scanComplete(); if(n >= 0) Serial.printf("%d network(s) found\n", n); // " сетей найдено" for (int i = 0; i n; i++) Serial.printf("%d: %s, Ch:%d (%ddBm) %s\n", i+1, WiFi.SSID(i).c_str(), WiFi.channel(i), WiFi.RSSI(i), WiFi.encryptionType(i) == ENC_TYPE_NONE ? "open" : ""); > WiFi.scanDelete(); >Обратите внимание, что функция WiFi.scanDelete() удаляет результаты сканирования из памяти, поэтому результаты не будут печататься в мониторе порта с каждым проходом через цикл loop().
Пример целиком
Ниже – полая версия скетча. Код внутри блока setup() описан в предыдущем примере, за исключением дополнительной функции pinMode(), которая настраивает контакт светодиода на вывод данных.
#include "ESP8266WiFi.h" #define BLINK_PERIOD 250 long lastBlinkMillis; boolean ledState; #define SCAN_PERIOD 5000 long lastScanMillis; void setup() Serial.begin(115200); Serial.println(); pinMode(LED_BUILTIN, OUTPUT); WiFi.mode(WIFI_STA); WiFi.disconnect(); delay(100); > void loop() long currentMillis = millis(); // мигаем светодиодом: if (currentMillis - lastBlinkMillis > BLINK_PERIOD) digitalWrite(LED_BUILTIN, ledState); ledState = !ledState; lastBlinkMillis = currentMillis; > // запускаем сканирование WiFi-сетей: if (currentMillis - lastScanMillis > SCAN_PERIOD) WiFi.scanNetworks(true); Serial.print("\nScan start . "); // "Запуск сканирования . " lastScanMillis = currentMillis; > // после завершения сканирования печатаем результаты: int n = WiFi.scanComplete(); if(n >= 0) Serial.printf("%d network(s) found\n", n); // " сетей найдено" for (int i = 0; i n; i++) Serial.printf("%d: %s, Ch:%d (%ddBm) %s\n", i+1, WiFi.SSID(i).c_str(), WiFi.channel(i), WiFi.RSSI(i), WiFi.encryptionType(i) == ENC_TYPE_NONE ? "open" : ""); > WiFi.scanDelete(); > >Пример в действии
Загрузите этот скетч на ESP8266 и откройте монитор порта. В мониторе порта должна появиться примерно такая запись:
Scan start . 5 network(s) found 1: Tech_D005107, Ch:6 (-72dBm) 2: HP-Print-A2-Photosmart 7520, Ch:6 (-79dBm) 3: ESP_0B09E3, Ch:9 (-89dBm) open 4: Hack-4-fun-net, Ch:9 (-91dBm) 5: UPC Wi-Free, Ch:11 (-79dBm)Проверяем светодиод. Он должен, не прерываясь, мигать с частотой четыре раза в секунду.
Итого
Функции класса сканирования дают массу возможностей для сканирования в синхронном и асинхронном режимах. Благодаря им мы можем запустить фоновое сканирование, которое не будет мешать другим процессам, запущенным модулем ESP8266.
О функциях для сканирования WiFi-сетей модулем ESP8266 читайте в [ссылка этой статье].
См.также
Внешние ссылки
Решено получить список доступных сетей
здравствуйте!
нужно получить список доступных Wi-Fi сетей, чтобы отсортировать их и подключиться к открытой AP с самым сильным сигналом.в исходниках для ESP нашел функцию поиска КОЛИЧЕСТВА доступных сетей
int8_t WiFiClass::scanNetworks()
что бляха муха ровным счетом ничего не дает
как решить данную проблему?
CodeNameHawk
Moderator
Алексей.
Active member
Chatlanin
New member
if (scan) < int n = WiFi.scanNetworks(); DEBUG_WM(F("Scan done")); if (n == 0) < DEBUG_WM(F("No networks found")); >else < //sort networks int indices[n]; for (int i = 0; i < n; i++) < indices[i] = i; >// RSSI SORT // old sort for (int i = 0; i < n; i++) < for (int j = i + 1; j < n; j++) < if (WiFi.RSSI(indices[j]) >WiFi.RSSI(indices[i])) < std::swap(indices[i], indices[j]); >> > /*std::sort(indices, indices + n, [](const int & a, const int & b) -> bool < return WiFi.RSSI(a) >WiFi.RSSI(b); >);*/ // remove duplicates ( must be RSSI sorted ) if (_removeDuplicateAPs) < String cssid; for (int i = 0; i < n; i++) < if (indices[i] == -1) continue; cssid = WiFi.SSID(indices[i]); for (int j = i + 1; j < n; j++) < if (cssid == WiFi.SSID(indices[j])) < DEBUG_WM("DUP AP: " + WiFi.SSID(indices[j])); indices[j] = -1; // set dup aps to index -1 >> > > //display networks in page for (int i = 0; i < n; i++) < if (indices[i] == -1) continue; // skip dups DEBUG_WM(WiFi.SSID(indices[i])); DEBUG_WM(WiFi.RSSI(indices[i])); int quality = getRSSIasQuality(WiFi.RSSI(indices[i])); if (_minimumQuality == -1 || _minimumQuality < quality) < String item = FPSTR(HTTP_ITEM); String rssiQ; rssiQ += quality; item.replace("", WiFi.SSID(indices[i])); item.replace("", rssiQ); if (WiFi.encryptionType(indices[i]) != ENC_TYPE_NONE) < item.replace("", "l"); > else < item.replace("", ""); > //DEBUG_WM(item); page += item; delay(0); > else < DEBUG_WM(F("Skipping due to quality")); >> page += "
"; > >