Verlässliche WFi reconnect Routine für ESP8266

Hi,

da es immer wieder Probleme mit meinem ESP8266 und einem verlässlichen Reconnect gab, habe ich jetzt mal was zusammen geschustert.

So blockiert das WiFi Reconnect nicht mehr und das unzuverlässige "WiFi.status() != WL_CONNECTED" habe ich auch ersetzt.

Aber irgendwie kommt mir das recht "gross" vor.

Kann man das vielleicht irgendwie zusammenfassen?

Danke & Gruß

Peff



//=======Libraries

#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoOTA.h>                 
#include <TelnetPrint.h>

//=======SETTINGS


//Timer für Heartbeat 1 sec.
unsigned long HeartbeatMillis = 0;        // will store last time Heartbeat was running
const long Heartbeatinterval = 1000;           // interval at which to send (milliseconds)

//Timer für WiFi reconnect 300 sec.
unsigned long WiFiMillis = 0;        // will store last time WiFi Reconnect was running
const long WiFiinterval = 60000;           // interval at which to send (milliseconds)

bool WiFiconnecting = false;         // Schalter für Wifi reconnect
int WiFiconnecting_count = 0;      // Counter für WiFi connection
bool Wifiactive = false;            // Schalter für Wifi verbunden
bool WifiOff = false;               // Schalter für Wifi OFF
int WifiOff_count = 0;             //Counter wie lange WiFi Off bleiben soll

WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;



//============SETUP

void setup() {
  byte i = 0;
  Serial.begin(9600);
  wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
  wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
  Connect();
  Serial.print(F("Connecting WiFi."));
  while  (WiFi.localIP() == IPAddress(0, 0, 0, 0)) {
    delay (500);
    ++i;
    Serial.print(F("."));
    if (i > 20) {
      ESP.restart();
    }
  }
  ideOTASetup();
  ArduinoOTA.begin();
}

//============LOOP

void loop() {

  time_t now;
  time(&now);

  if (Wifiactive == true) {
    server.handleClient();                        // Listen for HTTP requests from clients
    delay(2);                                     //allow the cpu to switch to other tasks
    ArduinoOTA.handle();                          // IDE OTA Upload via ArduinoIDE
  }

  unsigned long currentMillis = millis();

  if (currentMillis - HeartbeatMillis >= Heartbeatinterval) {
    HeartbeatMillis = currentMillis;
    Serial.print(F("Wifiactive: "));
    Serial.println(Wifiactive);
    Serial.println(WiFi.localIP());
    Serial.println(WiFi.status());
    Serial.print(F("Wifi-OFF: "));
    Serial.println(WifiOff);
    Serial.print(F("Wifi-OFF_count: "));
    Serial.println(WifiOff_count);
    Serial.print(F("WiFi-Connecting: "));
    Serial.println(WiFiconnecting);
    Serial.print(F("WiFi-Connecting_count: "));
    Serial.println(WiFiconnecting_count);
    Serial.print(F("Unix-Time: "));
    Serial.println(now);

    if (Wifiactive == false && WifiOff == false && WiFiconnecting_count == 0) {
      Serial.println(F("Switching WiFi Off, no Wifi available"));
      WiFi.mode(WIFI_OFF);
      WifiOff = true;
      WifiOff_count = 60;
    }
    if (WifiOff == true) {
      --WifiOff_count;
    }
    if (WifiOff == true && WifiOff_count == 0) {
      WiFiconnecting = true;
    }
    if (Wifiactive == false && WiFiconnecting == true)  {
      Serial.println("Try to reconnect");
      WiFiconnecting = false;
      Connect();
      WiFiconnecting_count = 20;
    }
    if (Wifiactive == true && WiFiconnecting_count > 0)  {
      WiFiconnecting_count = 0;
    }
    if (Wifiactive == false && WiFiconnecting_count > 0)  {
      --WiFiconnecting_count;
    }
    
    if (Wifiactive == true) {
      TelnetPrint.print(F("."));
    }
    Serial.println(F("___________________________"));
  }
  }
}



void onWifiConnect(const WiFiEventStationModeGotIP& event) {
  Wifiactive = true;
  TelnetPrint.begin();
  Serial.println(F("Connected to Wi-Fi."));
}

void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
  Wifiactive = false;
  TelnetPrint.stop();
  Serial.println(F("Disconnected from Wi-Fi."));
}


void Connect() {
  WiFi.setAutoReconnect(false);
  WiFi.mode(WIFI_STA);
  WiFi.hostname("ESP8266-TEST");
  WiFi.begin(ssid, password);
  WifiOff = false;
}

void  ideOTASetup()
{
  ArduinoOTA.setHostname("ESP8266-TEST");     
  ArduinoOTA.onStart([]() {
    TelnetPrint.println("[otaide] OTA started");
  });
}

Hallo,
ich habe für das login eine eigene function WIFI_login() erstellt. Die rufe ich im Setup auf. Im Loop gibts dann eine Abfrage

 if (WiFi.status() != WL_CONNECTED) {
    WIFI_login();

Das klappt zuverlässig, blockt aber leider etwas. Für den Fall das das Ding auch ohne WiFi was machen muss ist die Variante mit dem EventHandler natürlich besser geeignet weil das im Hintergrund läuft. Das hab ich aber bisher noch nicht eingesetzt.

Für den Fall das Du das nicht kennst.
https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/generic-examples.html

Heinz

Hi,

also bei mir lief die Abfrage (WiFi.status() != WL_CONNECTED) nicht immer zuverlässig im DHCP Betrieb. Hatte auch schon wo anders von ähnlichen Problemen gelesen.

Und ja, das Ding muss auch was tun ohne WiFi.

Hast Du Dir das Skript angeschaut?
Ich nutze doch die EventHandler :wink:

Peff

Hallo,
ja das habe ich. das Beispiel aus dem Link sieht allerdings etwas einfacher aus, ok das ist bei Beispielen immer so. :wink: Aber wie gesagt probiert habe ich das nicht. Du hast allerdings noch ein paar Diagnose Infos und Zähler mit eingebaut, das bläst es auch etwas auf.

Nachtrag
Warum lässt Du denn eigentlich nicht zu das der reconnect im Hintergrund automatisch läuft , das ist doch eigendlich der Sinn von dem Event.
Heinz

der Reconnect im Hintergrund schlägt irgendwann (nach einigen Tagen) fehl, oder hängt oder was weiß ich. Zumindest kommt das Device nicht mehr online.
Dort wo es eingesetzt wird ist nur sporadisch WLAN aktiv. Ich vermute irgendwann verschluckt sich die WiFi autoreconnect Funktion, daher habe ich da so gebaut.
Das was WiFi oft über Stunden nicht aktiv ist, habe ich den Zähler eingebaut der das Wifi alle Ewigkeit mal wieder einschaltet und checkt ob Wifi da ist.

Ich fand es halt nur ne ganze Menge an IF Abfragen und habe mich gefragt, ob man das nicht irgendwie geschickt hinbekommt.

Peff

Hallo,

WiFi.status() liefert WL_CONNECTED sobald eine Verbindung zum AP hergestellt ist.
Da hat der ESP8266 aber vom DHCP nicht zwingend schon eine IP bekommen, gerade bei instabilen Verbindungen oder lahmen AP kann das passieren.
Die Steuerung über Event WiFi.onStationModeGotIP() ist da schon der richtige Ansatz.
Ich packe hier mal einen Sketch von mir rein, da war speziell das Problem, daß der MQTT-connect beim WiFi reconnect komplett auf die Nase fiel.

Eigentlich wollte ich die .ino per Upload anhängen, gibt aber nur eine Fehlermeldung...

Gruß aus Berlin
Michael

type or paste code here

/*--------------------------------------------------
v1.0 MSoft 14.05.2016
D1 mini OTA
--------------------------------------------------*/

#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>
#include <Ticker.h>
#include <AsyncMqttClient.h>

//#define DEBUG

#define HOSTNAME "OTA-IN9"

// IN9 -Daten setzen
#define analogPin 3
#define IN9_MIN 165
#define IN9_MAX 820
#define TEMP_MIN 150                        // 1/10 Grad
#define TEMP_MAX 350                        // 1/10 Grad

#define WIFI_SSID "xxxxxxxxxxxx"
#define WIFI_PASSWORD "xxxxxxxxxx"

#define MQTT_HOST IPAddress(192, 168, 0, 99)
#define MQTT_PORT 1883

// WiFi
WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;
Ticker wifiReconnectTimer;

void connectToWifi(void);
void onWifiConnect(const WiFiEventStationModeGotIP& event);
void onWifiDisconnect(const WiFiEventStationModeDisconnected& event);

// MQTT
AsyncMqttClient mqttClient;
Ticker mqttReconnectTimer;

void connectToMqtt(void);
void onMqttConnect(bool sessionPresent);
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason);
void onMqttSubscribe(uint16_t packetId, uint8_t qos);
void onMqttUnsubscribe(uint16_t packetId);
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total);
void onMqttPublish(uint16_t packetId);
//void onMqttPublish(const char* topic, const char* payload, uint8_t qos, size_t len, size_t index, size_t total);

// ###############################################################

void setup()
{
#ifdef DEBUG
  Serial.begin(115200);
  Serial.println("\r\nRESET");
#endif
 
// Start WiFi
  wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
  wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
  connectToWifi();

// Start MQTT server.
  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  mqttClient.onMessage(onMqttMessage);
  mqttClient.setClientId("ESP-IN-9");
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  mqttClient.setWill("IN-9/Status",0,false,"offline");

// Start OTA server.
  ArduinoOTA.setHostname(HOSTNAME);
  ArduinoOTA.begin();

  analogWrite(analogPin, 150);          // IN 9 Start
}

// ----------------------------------------------------------------------

void loop()
{
  ArduinoOTA.handle();                      // Handle OTA server.
}

// ###############################################################
// ---------------------- WiFi-Tools ------------------------------
// ###############################################################

void connectToWifi()
{
#ifdef DEBUG
  Serial.println("Connecting to Wi-Fi...");
#endif

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

// ----------------------------------------------------------------------

void onWifiConnect(const WiFiEventStationModeGotIP& event)
{
#ifdef DEBUG
  Serial.println("Connected to Wi-Fi.");
  Serial.println(WiFi.localIP());
#endif

  connectToMqtt();
}

// ----------------------------------------------------------------------

void onWifiDisconnect(const WiFiEventStationModeDisconnected& event)
{
#ifdef DEBUG
  Serial.println("Disconnected from Wi-Fi.");
#endif

  mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
  wifiReconnectTimer.once(2, connectToWifi);
}

// ###############################################################
// ---------------------- MQTT-Tools ------------------------------
// ###############################################################

void connectToMqtt()
{
#ifdef DEBUG
  Serial.println("Connecting to MQTT...");
#endif

  mqttClient.connect();
}

// ----------------------------------------------------------------------

void onMqttConnect(bool sessionPresent)
{
  uint16_t packetIdSub = mqttClient.subscribe("IN-9/Temperatur", 0);

  String output = String(WiFi.RSSI(), DEC);

#ifdef DEBUG
    Serial.print("RSSI: ");
    Serial.println(output);
#endif

  mqttClient.publish("IN-9/RSSI",0,true,output.c_str());
  mqttClient.publish("IN-9/Status",0,true,"online");
}

// ------------------------------------------------------------------------

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason)
{

#ifdef DEBUG
  Serial.println("MQTT Disconnected: ");
  Serial.println("Reconnecting to MQTT...");
#endif

  if (WiFi.isConnected())
  {
    mqttReconnectTimer.once(2, connectToMqtt);
  }
}

void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total)
{ 
  String tempstring;
  for (int i=0; i<len; i++)
  {
    tempstring += (char)payload[i];
  }

#ifdef DEBUG
  Serial.print("Topic: ");
  Serial.println(topic);
  Serial.print("Payload: ");
  Serial.println(tempstring);
#endif

  int temp = tempstring.toInt();
  
  if (temp < TEMP_MIN)
  {
    temp = TEMP_MIN - 10;
  }
  else if (temp > TEMP_MAX)
  {
    temp = TEMP_MAX + 10;
  }
    temp = map(temp,TEMP_MIN - 10,TEMP_MAX + 10,IN9_MIN,IN9_MAX);
    analogWrite(analogPin,temp);
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.