• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Определение факта пропадания соединения с роутером и переключение в режим АР

Ildarmustafin86

Active member
Раньше я делал так:
C++:
void WiFiEvent(WiFiEvent_t event) {
  wifi.working = event;
}

void wifi_connect(byte e) {
  switch (e) {
    case 0: // WIFI_EVENT_STAMODE_CONNECTED
      DEBUG_PRINT("WIFI_EVENT_STAMODE_CONNECTED\n");
      break;
    case 1: // WIFI_EVENT_STAMODE_DISCONNECTED
      WiFi.reconnect();
      if (--wifi.countDS) {
        DEBUG_PRINT("CONNECTING...TRY:%i\n", wifi.countDS);
      } else {
        wifi.working = 7;
        WiFi_initAP();
        wifi.countDS = recTime;
      }
      break;
    case 3: // WIFI_EVENT_STAMODE_GOT_IP
      DEBUG_PRINT("WIFI_EVENT_STAMODE_GOT_IP\n");
      break;
    case 5: // WIFI_EVENT_SOFTAPMODE_STACONNECTED
      DEBUG_PRINT("USER CONNECTED\n");
      break;
    case 6: // WIFI_EVENT_SOFTAPMODE_STADISCONNECTED
      DEBUG_PRINT("USER DISCONNECTED\n");
      break;
    case 7: // WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED
      DEBUG_PRINT("WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED\n");
      WiFi.scanNetworksAsync(printScanResult);
      break;
  }
}

//Где-то в коде===================
  wifi_connect(wifi.working);
//================================
 

Melandr

Member
Спасибо за ответ. А хотел уточнить пару моментов.
В основном цикле Вы вызываете функцию wifi_connect(wifi.working);
Ее нужно вызывать с какой-то периодичностью, или просто в loop() ?
Что делает функция WiFiEvent? просто в параметр wifi.working помещает событие WiFi? Когда ее нужно вызывать?
И в примере Вашего кода вижу, что при пропадании WiFi от роутера создается точка доступа. Но не могу понять, как следует правильно сделать, чтобы при восстановлении связи переподключиться обратно
 

Melandr

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

Melandr

Member
Вот нашел пример
Получается необходимо объявить переменные типа WiFiEventHandler и определить обработчики, результат которых помещается в эти переменные. И далее все уже делает API ESP? Но непонятно, как вернуться к старому подключению, при его восстановлении. Я так понимаю необходимо сканировать с определённой периодичностью доступные WiFi сети, делать перебор по именам и при наличии нужной осуществлять подключении. Или есть более простой способ, используя API класса ESP8266WiFi
 

Ildarmustafin86

Active member
У меня wifi_connect делает проверку каждую секунду
Где-то попадался код, в котором проверялось наличие точки доступа с определенным именем, и если она находилась, происходило подключение. В обработчике событий WiFi такое можно сделать?
В обработчике событий же есть WiFi.scanNetworksAsync(printScanResult);. Эта функция и выполняет подключение при появлении сети
C++:
void printScanResult(int networksFound) {
  //DEBUG_PRINT("\nSEARCHING \n");
  for (int i = 0; i < networksFound; i++) {
    if (WiFi.SSID(i) == wifi.ssid) {
      DEBUG_PRINT("\nFOUND \"%s\"\nCONNECTING...PLEASE WAIT...\n", wifi.ssid);
      WiFi_initSTA();
    }
  }
}
 

Melandr

Member
У меня wifi_connect делает проверку каждую секунду
То есть Вы вызов этой функции завязали на таймер или millis()? А как много времени забирает вызов wifi_connect ?
Также если не сложно, подскажите. Начал разбираться с событиями WiFi в новой нотации, с WiFiEventHandler. Там тоже есть обработчик WiFiEventHandler onSoftAPModeProbeRequestReceived, который я так понял возвращает TRUE, когда ESP находится в режиме SoftAP, но не понятен момент. Как часто будет возвращаться данное событие? Так как все обработчики описываются в секции setup(), и в loop() ничего не вызывается, как происходит обработка этого события?
По примеру
#include <ESP8266WiFi.h>

const char* ssid = "SamsungS9+";
const char* password = "qwert789";

WiFiEventHandler gotIpEventHandler, disconnectedEventHandler;

bool ledState;

void setup()
{
Serial.begin(115200);
Serial.println();

pinMode(LED_BUILTIN, OUTPUT);

gotIpEventHandler = WiFi.onStationModeGotIP([](const WiFiEventStationModeGotIP& event)
{
Serial.print("Station connected, IP: ");
Serial.println(WiFi.localIP());
});

disconnectedEventHandler = WiFi.onStationModeDisconnected([](const WiFiEventStationModeDisconnected& event)
{
Serial.println("Station disconnected");
});

Serial.printf("Connecting to %s ...\n", ssid);
// "Подключение к %s ... "
WiFi.begin(ssid, password);
}

void loop()
{
digitalWrite(LED_BUILTIN, ledState);
ledState = !ledState;
delay(250);
}
Все работает.
Для отслеживания событий WiFi мне нужно описать действия, которые необходимо произвести, при наступлении какого-либо события WiFi. С onStationModeDisconnected,все более менее ясно, при возникновении этого события пробуем переподключить несколько раз, если не получилось, то переводим ESP в режим AP. А вот, и в принципе при восстановлении без перевода в режим AP ESP подключается к роутеру. Но если ее перевести в режим AP,как вернуть в режим STA при восстановлении связи.
ЗЫ: По Вашему примеру понятно, но хочется разобраться с новым кодом. Спасибо за помощь.
 

Ildarmustafin86

Active member
Внимательней посмотрите в коде есть WIFI_initSTA() и WIFI_iniAP();
Сами функции

C++:
void WiFi_initAP() {
  WiFi.mode(WIFI_OFF);
  WiFi.mode(WIFI_AP);
  IPAddress apIP(192, 168, 4, 1);
  WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
  WiFi.softAP(wifi.ssidAP, wifi.passwordAP);
}
void WiFi_initSTA() {
  WiFi.mode(WIFI_OFF);
  WiFi.mode(WIFI_STA);
  if (strcmp(wifi.ip_str, "") && strcmp(wifi.ip_gw_str, "")) {
    bitSet(aux_bf, 7);
    IPAddress ip_subnet(255, 255, 255, 0);
    WiFi.config(wifi.ip, wifi.ip_gw, ip_subnet, wifi.ip_gw);
  } else {
    bitClear(aux_bf, 7);
  }
  if (strcmp(wifi.ssid, "") && strcmp(wifi.password, "")) {
    WiFi.begin(wifi.ssid, wifi.password);
  } else {
    WiFi_initAP();
  }
}
 

Melandr

Member
А вот есть еще объект
wifi (маленькие буквы, в отличие от WiFi)
и его свойства
countDS
working
и другие.
Где этот объект создается? В Вашем примере не увидел.
ЗЫ: 'wifi' was not declared in this scope
 

Melandr

Member
Спасибо, интересно посмотреть. С wifi уже понятней, это объект типа wifi_t , в котором хранятся текущие параметры wifi.
Это Вы делали контроллер для аквариума?
Посмотрел на Ваш код, подкупает конечно ESP8266 своими возможностями, но я тут в другой теме пытаюсь реализовать диммер переменного напряжения, то конечно в приложениях, критичных к выполнению кода, ESP проигрывает AVR.
 

Melandr

Member
Ildarmustafin86, доброй ночи!
Наваял по Вашему исходнику небольшой пример, используя WiFiEventHandler, но не могу понять, почему функция WiFi.getMode(); возвращает 1 независимо от режима.
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <stdio.h>

extern "C" {
#include "user_interface.h"
}

#define recTime 5
byte countDS = recTime;

const char* ssid = "LORD";
const char* ssidPass = "4182H{v7";
const char* ssidAP = "ESP8266";
const char* ssidApPass = "";

IPAddress apIP(192, 168, 4, 1);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);

IPAddress stIP(192, 168, 1, 120);
IPAddress gateIP(192, 168, 1, 1);
IPAddress subnetIP(255, 255, 255, 0);

WiFiEventHandler gotIpEventHandler;
WiFiEventHandler disconnectedEventHandler;
WiFiEventHandler clientConnectedEventHandler;
WiFiEventHandler clientDisconnectedEventHandler;

bool ledState;
bool modeWiFi; //0 - WIFI_AP, 1 - WIFI_STA, 2 - WIFI_AP_STA, 3 - WIFI_OFF

void WiFi_initAP() {
// WiFi.disconnect(true);
// WiFi.mode(WIFI_OFF);
// delay(1000);
WiFi.mode(WIFI_AP);
modeWiFi = WiFi.getMode();
WiFi.softAPConfig(apIP, gateway, subnet);
WiFi.softAP(ssidAP, ssidApPass);

Serial.print("SoftAP, IP: ");
Serial.println(WiFi.softAPIP());
}

void WiFi_initSTA() {
// WiFi.softAPdisconnect(true);
// WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
WiFi.mode(WIFI_STA);
WiFi.config(stIP, gateIP, subnetIP);
WiFi.begin(ssid, ssidPass);
}

void printScanResult(int networksFound) {
//DEBUG_PRINT("\nSEARCHING \n");
for (int i = 0; i < networksFound; i++) {
if (WiFi.SSID(i) == ssid) {
Serial.printf("\nFOUND \"%s\"\nCONNECTING...PLEASE WAIT...\n", ssid);
WiFi_initSTA();
}
}
}

void setup()
{
Serial.begin(115200);
Serial.println();

pinMode(LED_BUILTIN, OUTPUT);

gotIpEventHandler = WiFi.onStationModeGotIP([](const WiFiEventStationModeGotIP & event)
{
Serial.print("Station connected, IP: ");
Serial.println(WiFi.localIP());
});

disconnectedEventHandler = WiFi.onStationModeDisconnected([](const WiFiEventStationModeDisconnected & event)
{
Serial.println("Station disconnected");
modeWiFi = WiFi.getMode();
Serial.println(modeWiFi);
if (modeWiFi == WIFI_STA)
{
WiFi.reconnect();
if (--countDS) {
Serial.printf("CONNECTING...TRY:%i\n", countDS);
} else {
WiFi_initAP();
countDS = recTime;
}
}
if (modeWiFi == WIFI_AP)
{
WiFi.scanNetworksAsync(printScanResult);
}
});

clientConnectedEventHandler = WiFi.onSoftAPModeStationConnected([](const WiFiEventSoftAPModeStationConnected & event)
{
Serial.println("Client connected");
});

clientDisconnectedEventHandler = WiFi.onSoftAPModeStationDisconnected([](const WiFiEventSoftAPModeStationDisconnected & event)
{
Serial.println("Client disconnected");
});

Serial.printf("Connecting to %s ...\n", ssid);
// "Подключение к %s ... "
WiFi_initSTA();
}

void loop()
{
digitalWrite(LED_BUILTIN, ledState);
ledState = !ledState;
delay(250);

modeWiFi = WiFi.getMode();
Serial.println(modeWiFi);
}
А в новой нотации нет события, соответствующего WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED
 

Melandr

Member
А не подскажите еще , разобрался с WiFiMode_t modeWiFi; //WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3
но почему-то постоянно возвращает 3, если перевожу в режим WIFI_AP
#include <Arduino.h>
#include <ESP8266WiFi.h> // Standart ESP8266 2.7.3, NOT 2.7.4
#include <stdio.h>

extern "C" {
#include "user_interface.h"
}

#define recTime 5
byte countDS = recTime;

const char* ssid = "LORD";
const char* ssidPass = "4182H{v7";
const char* ssidAP = "ESP8266";
const char* ssidApPass = "";

IPAddress apIP(192, 168, 4, 1);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);

IPAddress stIP(192, 168, 1, 120);
IPAddress gateIP(192, 168, 1, 1);
IPAddress subnetIP(255, 255, 255, 0);

WiFiEventHandler gotIpEventHandler;
WiFiEventHandler disconnectedEventHandler;
WiFiEventHandler clientConnectedEventHandler;
WiFiEventHandler clientDisconnectedEventHandler;

bool ledState;
WiFiMode_t modeWiFi; //WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3

void WiFi_initAP() {
// WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
// delay(1000);
WiFi.mode(WIFI_AP);
modeWiFi = WiFi.getMode();
WiFi.softAPConfig(apIP, gateway, subnet);
WiFi.softAP(ssidAP, ssidApPass);

Serial.print("SoftAP, IP: ");
Serial.println(WiFi.softAPIP());
}

void WiFi_initSTA() {
// WiFi.softAPdisconnect(true);
// WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
WiFi.mode(WIFI_STA);
WiFi.config(stIP, gateIP, subnetIP);
WiFi.begin(ssid, ssidPass);
}

void printScanResult(int networksFound) {
//DEBUG_PRINT("\nSEARCHING \n");
for (int i = 0; i < networksFound; i++) {
if (WiFi.SSID(i) == ssid) {
Serial.printf("\nFOUND \"%s\"\nCONNECTING...PLEASE WAIT...\n", ssid);
WiFi_initSTA();
}
}
}

void setup()
{
Serial.begin(115200);
Serial.println();

WiFi.persistent(false);

pinMode(LED_BUILTIN, OUTPUT);

gotIpEventHandler = WiFi.onStationModeGotIP([](const WiFiEventStationModeGotIP & event)
{
Serial.print("Station connected, IP: ");
Serial.println(WiFi.localIP());
});

disconnectedEventHandler = WiFi.onStationModeDisconnected([](const WiFiEventStationModeDisconnected & event)
{
Serial.println("Station disconnected");
modeWiFi = WiFi.getMode();
Serial.println(modeWiFi);
if (modeWiFi == WIFI_STA)
{
WiFi.reconnect();
if (--countDS) {
Serial.printf("CONNECTING...TRY:%i\n", countDS);
} else {
WiFi_initAP();
countDS = recTime;
}
}
if (modeWiFi == WIFI_AP)
{
WiFi.scanNetworksAsync(printScanResult);
}
});

clientConnectedEventHandler = WiFi.onSoftAPModeStationConnected([](const WiFiEventSoftAPModeStationConnected & event)
{
Serial.println("Client connected");
});

clientDisconnectedEventHandler = WiFi.onSoftAPModeStationDisconnected([](const WiFiEventSoftAPModeStationDisconnected & event)
{
Serial.println("Client disconnected");
});

Serial.printf("Connecting to %s ...\n", ssid);
// "Подключение к %s ... "
WiFi_initSTA();
}

void loop()
{
digitalWrite(LED_BUILTIN, ledState);
ledState = !ledState;
delay(250);

modeWiFi = WiFi.getMode();
Serial.println(modeWiFi);
}
 

Ildarmustafin86

Active member
C++:
#include <Arduino.h>
#include <ESP8266WiFi.h> // Standart ESP8266 2.7.3, NOT 2.7.4
#include <stdio.h>

extern "C" {
#include "user_interface.h"
}

#define recTime 5
byte countDS = recTime;

const char* ssid = "ччччччччччч";
const char* ssidPass = "пппппппппп";
const char* ssidAP = "ESP8266";
const char* ssidApPass = "";

IPAddress apIP(192, 168, 4, 1);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);

IPAddress stIP(192, 168, 1, 120);
IPAddress gateIP(192, 168, 1, 1);
IPAddress subnetIP(255, 255, 255, 0);

WiFiEventHandler gotIpEventHandler;
WiFiEventHandler disconnectedEventHandler;
WiFiEventHandler clientConnectedEventHandler;
WiFiEventHandler clientDisconnectedEventHandler;

bool ledState;
WiFiMode_t modeWiFi; //WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3

void WiFi_initAP() {
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  // delay(1000);
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(apIP, gateway, subnet);
  WiFi.softAP(ssidAP, ssidApPass);

  Serial.print("SoftAP, IP: ");
  Serial.println(WiFi.softAPIP());
}

void WiFi_initSTA() {
  // WiFi.softAPdisconnect(true);
  // WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  WiFi.mode(WIFI_STA);
  WiFi.config(stIP, gateIP, subnetIP);
  WiFi.begin(ssid, ssidPass);
}

void printScanResult(int networksFound) {
  //DEBUG_PRINT("\nSEARCHING \n");
  for (int i = 0; i < networksFound; i++) {
    if (WiFi.SSID(i) == ssid) {
      Serial.printf("\nFOUND \"%s\"\nCONNECTING...PLEASE WAIT...\n", ssid);
      WiFi_initSTA();
    }
  }
}

void setup()
{
  Serial.begin(115200);
  Serial.println();

  WiFi.persistent(false);

  pinMode(LED_BUILTIN, OUTPUT);

  gotIpEventHandler = WiFi.onStationModeGotIP([](const WiFiEventStationModeGotIP & event)
  {
    Serial.print("Station connected, IP: ");
    Serial.println(WiFi.localIP());
  });

  disconnectedEventHandler = WiFi.onStationModeDisconnected([](const WiFiEventStationModeDisconnected & event)
  {
    Serial.println("Station disconnected");
    if (modeWiFi == WIFI_STA)
    {
      WiFi.reconnect();
      if (--countDS) {
        Serial.printf("CONNECTING...TRY:%i\n", countDS);
      } else {
        WiFi_initAP();
        countDS = recTime;
      }
    }
    if (modeWiFi == WIFI_AP)
    {
      WiFi.scanNetworksAsync(printScanResult);
    }
  });

  clientConnectedEventHandler = WiFi.onSoftAPModeStationConnected([](const WiFiEventSoftAPModeStationConnected & event)
  {
    Serial.println("Client connected");
  });

  clientDisconnectedEventHandler = WiFi.onSoftAPModeStationDisconnected([](const WiFiEventSoftAPModeStationDisconnected & event)
  {
    Serial.println("Client disconnected");
  });

  Serial.printf("Connecting to %s ...\n", ssid);
  // "Подключение к %s ... "
  WiFi_initSTA();
}

void loop()
{
  digitalWrite(LED_BUILTIN, ledState);
  ledState = !ledState;
  delay(250);

  modeWiFi = WiFi.getMode();
  Serial.println(modeWiFi);
}
 

Ildarmustafin86

Active member
А не подскажите еще , разобрался с WiFiMode_t modeWiFi; //WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3
но почему-то постоянно возвращает 3, если перевожу в режим WIFI_AP
И если Вы говорите что разобрались с WiFiMode_t, но у Вас не получается. Это значит что Вы не разобрались
 

Melandr

Member
А зачем ты делаешь проверку события в событии?
Не могли бы пояснить?
Также не определяется событие:
onProbeRequestEventHandler = WiFi.onProbeRequestReceive([](const WiFiEventSoftAPModeProbeRequestReceived & event)
{
Serial.println("onProbeRequestReceive");
});


class ESP8266WiFiClass' has no member named 'onProbeRequestReceive
 
Сверху Снизу