ESP8266: сканировать вайфай сети и подключиться, если есть известная (нужная)

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

Доброго времени суток. Приходится часто переезжать и разбираться с ардуино (ESP) то в одном месте, то в другом. Руками постоянно перебивать пару ссид/пароль уже надоело. Решил написать функцию сканирования доступных сетей и подключаться, если есть ссид из моего списка. Вроде все сканирует, но не подключается, ну или по крайней мере не выводит полученный айпишник.

#include <ESP8266WiFi.h>                                                // Библиотека для создания Wi-Fi подключения (клиент или точка доступа)
#include <WiFiClient.h>

char* array_ssid[] = {"ssid1", "ssid2"};                        // Массив необходимых ссидов
char* array_pass[] = {"pass1", "pass2"};                    // Массив необходимых паролей к этим ссидам

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 = " +WiFi.macAddress());                     // Выводим мак адрес

  WiFi.scanNetworksAsync(conekt_to_wifi);                                // Сканируем вайфай сети и подклоючаемся, если есть из нашего списка
}

void loop() {}

Блок "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  

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

всё давно придумано до нас - wifimulti
Забиваешь все известные тебе точки и будет тебе счастье

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

ua6em пишет:

всё давно придумано до нас - wifimulti
Забиваешь все известные тебе точки и будет тебе счастье

Да уж... счастье получил... спасибо.

Но все же хотелось понять, почему мой код не работает. Понятно, что надо бы подправить массивы, сделать парными ссид-пароль, но не думаю, что в этом проблема. Ведь сеть сканируется. Нужная находится. Но вот почему не подключается?

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

И все же хотелось бы знать/понять, почему мой вариант не работает. Дело в том, что предложенный "стандартный", "давно придуманный до нас" способ имеет одну, на мой взгляд не очень хорошую штуку. Возможно я ошибаюсь, но мне не нравится, когда пары логин-пароль вбивают в самой функции. По идее такие списки должны корректироваться вне функции. А тут они в сетапе указаны.

У меня тоже способ не самый лучший с разбивкой на отдельные массивы ссидов и паролей. Но соединить их теоретически можно. Тут ведь работает многоуровневый массив. Значит можно и соединить.

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

Таки сделал один способ без использования доп библиотеки мультивайфай. И без метода стандартной билиотеки вайфай WiFi.scanNetworksAsync(), которую я использовал в первый раз. Получилось что-то типа такого:

#include <ESP8266WiFi.h>                                                // Библиотека для создания Wi-Fi подключения (клиент или точка доступа)
#include <WiFiClient.h>
#include <ESP8266WebServer.h>                                           // Библиотека для управления устройством по HTTP (например из браузера)
#include <FS.h>                                                         // Библиотека для работы с файловой системой
#include <ESP8266FtpServer.h>                                           // Библиотека для работы с SPIFFS по FTP
#include <ESP8266mDNS.h>                                                // Библиотека МДНС, позволяющая обращаться к плате по имени, а не по адресу

char* array_ssid[] = {"ssid1","ssid2","ssid3"};                   // Массив необходимых ссидов
char* array_pass[] = {"pas1","pas2","pas3"};         // Массив необходимых паролей к этим ссидам
int count_ssid = sizeof(array_ssid) / sizeof(array_ssid[0]);            // Размер массива ссидов


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);                                                   // Инициализируем вывод данных на серийный порт со скоростью 9600 бод
  while (!Serial) {
                                                                        // ждём, пока не откроется монитор последовательного порта
                                                                        // для того, чтобы отследить все события в программе
  }
  WiFi.mode(WIFI_OFF);                                                  // Останавливаем вайфай
  delay(1000);
  WiFi.mode(WIFI_STA); 
  WiFi.setHostname("Host_MDNS");                                        // Устанавливаем новое имя нашего клиента
  Serial.println(WiFi.hostname());                                      // Распечатываем имя клиента  
//  Serial.println(WiFi.status());
  while (WiFi.status() != WL_CONNECTED) {                               // Зупускаем ожидание поднятия вайфай сервера
    for (int i = 0; i < count_ssid; i++) {
      WiFi.begin(array_ssid[i], array_pass[i]);                         // Инициализируем подключение к указанной вайфай сети
      while (WiFi.status() != WL_CONNECTED) {                           // Зупускаем ожидание поднятия вайфай сервера
        for (int j = 0; j < 10; j++) {
        Serial.println("waiting...");  
        delay(1000);
        int ip = WiFi.localIP();
        Serial.println(WiFi.localIP());                                        // Выводим в монитор порта айпишник нашей платы
        if  (ip == true) {
          break;
        }
      }
      break;
      }  
    }
  }     
}

void loop() {
  // put your main code here, to run repeatedly:

}

В таком виде плата не отчитывается о других сетях, только пробует подключиться к существующему списку, перебирая его по кругу, пока не найдет сеть из списка.

По идее по такому же принципу можно переделать и мой первый вариант.

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Да потому шта... Выведи в терминал значение networksFound, после десятой строки. И сам все поймешь.

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

brokly пишет:

Да потому шта... Выведи в терминал значение networksFound, после десятой строки. И сам все поймешь.

Да, тут мой косяк. Сделал по инерции... Тут же показывает число найденных сетей и отсчет идет с единицы, а не с нуля. Но я переделал вот так:

for (int i = 1; i <= networksFound; i++)

И ничего не поменялось