[GH-ISSUE #773] WifiManager disconnects from Wifi and Won't Reconnect #648

Closed
opened 2026-02-28 01:26:23 +03:00 by kerem · 1 comment
Owner

Originally created by @mrlightsman on GitHub (Nov 26, 2018).
Original GitHub issue: https://github.com/tzapu/WiFiManager/issues/773

Basic Infos

Hardware

WiFimanager Branch/Release:

  • [X ] Master
  • Development

Esp8266/Esp32:

  • [X ] ESP8266
  • ESP32

Hardware: ESP-12e, esp01, esp25

  • [X ] ESP01
  • ESP12 E/F/S (nodemcu, wemos, feather)
  • Other

ESP Core Version: 2.4.0, staging

  • 2.3.0
  • [X ] 2.4.1
  • staging (master/dev)

Description

I have several ESP01 that I use as light switches in my house. They are all configured with WiFi Manager with parameters. They are set to DHCP, but have an address reservation in my router (Archer C7) via MAC address.

The code is mostly based on Kakopappa Sinric switch and udp examples. The wifiManager portion is from the master branch example code and expanded with additional parameters.

Problem description

Frequently, they seem to lose connection with the router and go back into ap mode and no longer function until I re-enter the WiFi credentials. They retain their other parameters.

Is there a command to have the ESP request a new IP address via DHCP? I'm thinking this might help renew the connection with the router... assuming the router is at fault.

Or, is there a better solution out there? I am a relative noob so all suggestions are appreciated.

At one time I tried using the development branch, but it broke other parts of my code for some reason. I decided to stick with the master just to be safe...

Settings in IDE

  • Board - Generic ESP8266
  • Flash Mode - DIO
  • Flash Size - 1M (512K SPIFFS)
  • Debug Port - Disabled
  • Debug Level - None
  • lwIP Variant - V2 prebuilt (MSS=536)
  • Reset Method - ck
  • Crystal Frequency - 26M
  • Flash Frequency - 40MHz
  • CPU Frequency - 80MHz
  • Upload Speed - 115200
  • Port - TBD by your setup
  • Programmer - Arduino as ISP

Module:
Generic ESP8266 Module

Additional libraries:
<FS.h>
<arduino.h>
<WebSocketsClient.h>
<ArduinoJson.h>
<WiFiManager.h>
<WiFiUDP.h>
<avdweb_Switch.h>

Sketch

#include <FS.h>
#include <arduino.h>
#include <WebSocketsClient.h>   // get it from https://github.com/Links2004/arduinoWebSockets/releases 
#include <ArduinoJson.h>        // get it from https://arduinojson.org/ or install via Arduino library manager
#include <WiFiManager.h>        // get it from https://github.com/the-real-orca/WiFiManager
#include <WiFiUDP.h>  //get it from https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WiFi/src
#include <avdweb_Switch.h>  //https://github.com/avandalen/avdweb_Switch

/* This version of the sinric switch uses the multi wifi manager to input wifi, API, and two device ids.
 * It is designed to work with an ESP8266-01 with the following pin use:
 * GPIO_2 = device 1. LOW is ON.  HIGH is OFF.  Intended to sink to an optoisolator with pin 1 connected to Vcc and pin 2 to GPIO_2.
 * GPIO_0 = device 2. LOW is ON.  HIGH is OFF.  Intended to sink to an optoisolator with pin 1 connected to Vcc and pin 2 to GPIO-0.
 * RX (pin 3)Connect a momentary N/O switch to GROUND and RX with a 220 ohm pullup resistor to Vcc.
 * TX (pin 1)Connect a momentary N/O switch to GROUND and RX with a 220 ohm pullup resistor to Vcc.
 * RX press = toggle device 1
 * RX doubleClick = toggle device 3
 * RX doubleClick = Invoke WiFi Manager
 * TX press = toggle device 2
 * TX doubleClick = toggle remote device 4
 * TX doubleClick = Invoke WiFi Manager with SPIFFS Format
 * 
 * All other ESP pins are connected per usual ESP set up.
 * 
 */

 
 /*ESP8266-01 Flash settings:
  * Board - Generic ESP8266
  * Flash Mode - DIO
  * Flash Size - 1M (512K SPIFFS)
  * Debug Port - Disabled
  * Debug Level - None
  * lwIP Variant - V2 prebuilt (MSS=536)
  * Reset Method - ck
  * Crystal Frequency - 26M
  * Flash Frequency - 40MHz
  * CPU Frequency - 80MHz
  * Upload Speed - 115200
  * Port - TBD by your setup
  * Programmer - Arduino as ISP
  */
 
WebSocketsClient webSocket;
WiFiClient client;
WiFiUDP Udp;

#define API_ENDPOINT "http://sinric.com"
#define HEARTBEAT_INTERVAL 300000 // 5 Minutes

//Switch Contols variables
const byte GPIO_2 = 2; //To control local Device 1
const byte GPIO_0 = 0; //To control local Device 2
const byte RX = 3;  //To manually toggle devices 1&3
const byte TX = 1;  //To manually toggle devices 2&4
int GPIO_2State; //State of local device 1
int GPIO_0State; //State of local device 2

//Define UDP server variables
char udp_port[6]; //used to store in json the udp port from user input on WiFi Manager page
unsigned int udpPort;  // used by udp.begin()command (it is udpPort converted for use)
char pktBuf[25]; //buffer for UDP packets

 //Define the local IP variables
char ap_SSID[15] = "New Box"; //SSID for ESP when in AP mode
char static_ip[16]; // ip address for ESP when in client mode
//char static_gw[16]; // gateway address for ESP when in client mode
//char static_sn[16]; // subnet address for ESP when in client mode

//Set up UDP variables for WiFIManager
char A_Click_IP[16]; // UDP target IP 3
char B_Click_IP[16]; // UDP target IP 3
char A_doubleClick_IP[16]; // UDP target IP 3
char B_doubleClick_IP[16]; // UDP target IP 4
char targetIP[16];

//Define the Alexa variables
char api_key[37]; //Sinric API Key
char Local_Device_One[25]; // local device 1
char Local_Device_Two[25]; // local device 2
char A_Click_Device[25]; //alexa device 1
char B_Click_Device[25]; //alexa device 2
char A_doubleClick_Device[25]; // alexa device 3
char B_doubleClick_Device[25]; // alexa device 4

//set up button debounce with Switch
Switch RXState = Switch(RX); //button to ground
Switch TXState = Switch(TX); //button to ground

//Define Auto-off Timer variables for local devices
char offTime1[7]; // auto-off time in minutes
char offTime2[7]; // auto-off time in minutes
unsigned int autoff1;
unsigned int autoff2;
unsigned long startTime1; // timer for local device 1
unsigned long startTime2; // timer for local device 2
unsigned long currentTime;
unsigned long period1;
unsigned long period2;

//Define the heartbeat timer variables
uint64_t heartbeatTimestamp = 0; //heartbeat timer reset
bool isConnected = false;

//flag for saving data
bool shouldSaveConfig = false;

//callback notifying us of the need to save config
void saveConfigCallback () {
//  Serial.println("Should save config");
  shouldSaveConfig = true;
}

void process(String target_Id, IPAddress targetIP) {
 if (target_Id == (Local_Device_One)) {
    String device_Id = (Local_Device_One);
    toggle(device_Id);
 } else if (target_Id == (Local_Device_Two)) {
    String device_Id = (Local_Device_Two);
    toggle(device_Id);  
  } else {
    char send_Id[25];
    target_Id.toCharArray(send_Id, 25);
    Udp.beginPacket(targetIP, udpPort);
    Udp.write(send_Id);
    Udp.endPacket();
  }
}


  //if a udp command or button push is detected, toggle the appropriate device
void toggle(String device_Id) {
  if (device_Id == (Local_Device_One)) {
    GPIO_2State = digitalRead(GPIO_2);
    GPIO_2State = !GPIO_2State;
    digitalWrite(GPIO_2, GPIO_2State);
    startTime1 = millis();
//       Serial.println("Device 1");
//       Serial.println("Status:");
//       Serial.println(GPIO_2State);
//       Serial.println("Waiting");

  } else if (device_Id == (Local_Device_Two)) {
    GPIO_0State = digitalRead(GPIO_0);
    GPIO_0State = !GPIO_0State;
    digitalWrite(GPIO_0, GPIO_0State);
    startTime2 = millis();
//       Serial.println("Device 2:");
//       Serial.println("Status:");
//       Serial.println(GPIO_0State);
//       Serial.println("Waiting");
  }
  device_Id = "";  
}

  //Alexa "ON" response
void turnOn(String deviceId) {
  if (deviceId == (Local_Device_One)) {  // Device ID of first device  
//    Serial.print("Turn on 1st-device id: ");
//    Serial.println(deviceId);
        digitalWrite(GPIO_2, LOW);
        startTime1 = millis();
  } else if (deviceId == (Local_Device_Two)) {  // Device ID of second device 
//    Serial.print("Turn on 2nd-device id: ");
//    Serial.println(deviceId);
        digitalWrite(GPIO_0, LOW);
        startTime2 = millis();
  } else { 
//    Serial.print("Turn on for unknown device id: ");
//    Serial.println(deviceId);
  }     
}

  //Alexa "OFF" response
void turnOff(String deviceId) {
   if (deviceId == (Local_Device_One)) {  // Device ID of first device  
//     Serial.print("Turn off 1st-Device ID: ");
//     Serial.println(deviceId);
        digitalWrite(GPIO_2, HIGH);
        startTime1 = millis();
   } else if (deviceId == (Local_Device_Two)) { // Device ID of second device
//     Serial.print("Turn off 2nd-Device ID: ");
//     Serial.println(deviceId);
        digitalWrite(GPIO_0, HIGH);
        startTime2 = millis();
  } else {
//     Serial.print("Turn off for unknown device id: ");
//     Serial.println(deviceId);
  }
}


  //Receive and process an Alexa command
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
  switch(type) {
    case WStype_DISCONNECTED:{
      isConnected = false;    
//      Serial.printf("[WSc] Webservice disconnected from sinric.com!\n");
      break;
    case WStype_CONNECTED: {
      isConnected = true;
//      Serial.printf("[WSc] Service connected to sinric.com at url: %s\n", payload);
//      Serial.printf("Waiting for commands from sinric.com ...\n");        
      }
      break;
    case WStype_TEXT: {
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject((char*)payload); 
        String deviceId = json ["deviceId"];     
        String action = json ["action"];

        if(action == "setPowerState") { // Switch or Light
            String value = json ["value"];
            if(value == "ON") {
                turnOn(deviceId);
            } else {
                turnOff(deviceId);
            }
//        } else if(action == "setBrightness") {
          
//        } else if(action == "AdjustBrightness") {
          
//        } else if (action == "test") {
//            Serial.println("[WSc] received test command from sinric.com");
        }
      }
      break;
    case WStype_BIN:
//      Serial.printf("[WSc] get binary length: %u\n", length);
      break;
    }
  }
}

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

  // Setup pins to off position
  pinMode(GPIO_2, OUTPUT);
  digitalWrite(GPIO_2, HIGH);
  pinMode(GPIO_0, OUTPUT);
  digitalWrite(GPIO_0, HIGH);
  pinMode(RX, INPUT_PULLUP);
  pinMode(TX, INPUT_PULLUP);

//  SPIFFS.format();  //clean FS, for testing

  //read configuration from FS json
//  Serial.println("mounting FS...");

  if (SPIFFS.begin()) {
//    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
//      Serial.println("reading config file");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
//        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
//          Serial.println("\nparsed json");

          strcpy(ap_SSID, json["ap_SSID"]);
          strcpy(udp_port, json["udp_port"]);
          strcpy(api_key, json["api_key"]);
          strcpy(Local_Device_One, json["Local_Device_One"]);
          strcpy(offTime1, json["offTime1"]);
          strcpy(Local_Device_Two, json["Local_Device_Two"]);
          strcpy(offTime2, json["offTime2"]);
          strcpy(A_Click_Device, json["A_Click_Device"]);
          strcpy(A_Click_IP, json["A_Click_IP"]);
          strcpy(A_doubleClick_Device, json["A_doubleClick_Device"]);
          strcpy(A_doubleClick_IP, json["A_doubleClick_IP"]);
          strcpy(B_Click_Device, json["B_Click_Device"]);
          strcpy(B_Click_IP, json["B_Click_IP"]);
          strcpy(B_doubleClick_Device, json["B_doubleClick_Device"]);
          strcpy(B_doubleClick_IP, json["B_doubleClick_IP"]);

          if(json["ip"]) {
//            Serial.println("setting custom ip from config");
            //static_ip = json["ip"];
            strcpy(static_ip, json["ip"]);
//            strcpy(static_gw, json["gateway"]);
//            strcpy(static_sn, json["subnet"]);
//            Serial.println(static_ip);
          } else { 
//            Serial.println("no custom ip in config");
          }
        } else {
//          Serial.println("failed to load json config");
        }
      }
    }
  } else {
//    Serial.println("failed to mount FS");
  }
  //end read
//  Serial.println(static_ip);
//  Serial.println(udp_port);
//  Serial.println(api_key);
//  Serial.println(A_Click_Device);
//  Serial.println(B_Click_Device);


  // The extra parameters to be configured (can be either global or just in the setup)
  // After connecting, parameter.getValue() will get you the configured value
  // id/name placeholder/prompt default length
  WiFiManagerParameter custom_ap_SSID("ap_SSID", "Box name and SSID", ap_SSID, 25);
  WiFiManagerParameter custom_udp_port("udp_port", "Interconnect Port", udp_port, 6);
  WiFiManagerParameter custom_api_key("api key", "api key", api_key, 37);
  WiFiManagerParameter custom_Local_Device_One("Local_Device_One", "1st Local deviceId", Local_Device_One, 25);
  WiFiManagerParameter custom_offTime1("offTime1", "Auto Off Timer 1st Local Device", offTime1, 7);
  WiFiManagerParameter custom_Local_Device_Two("Local_Device_Two", "2nd Local deviceId", Local_Device_Two, 25);
  WiFiManagerParameter custom_offTime2("offTime2", "Auto Off Timer 2nd Local Device", offTime2, 7);
  WiFiManagerParameter custom_A_Click_Device("A_Click_Device", "Button A Click deviceId", A_Click_Device, 25);
  WiFiManagerParameter custom_A_Click_IP("A_Click_IP", "Button A Click IP", A_Click_IP, 16);
  WiFiManagerParameter custom_A_doubleClick_Device("A_doubleClick_Device", "Button A doubleClick deviceId", A_doubleClick_Device, 25);
  WiFiManagerParameter custom_A_doubleClick_IP("A_doubleClick_IP", "Button A doubleClick IP", A_doubleClick_IP, 16);
  WiFiManagerParameter custom_B_Click_Device("B_Click_Device", "Button B Click deviceId", B_Click_Device, 25);
  WiFiManagerParameter custom_B_Click_IP("B_Click_IP", "Button B Click IP", B_Click_IP, 16);
  WiFiManagerParameter custom_B_doubleClick_Device("B_doubleClick_Device", "Button B doubleClick deviceId", B_doubleClick_Device, 25);
  WiFiManagerParameter custom_B_doubleClick_IP("B_doubleClick_IP", "Button B doubleClick IP", B_doubleClick_IP, 16);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;

  //set config save notify callback
  wifiManager.setSaveConfigCallback(saveConfigCallback);

  //set static ip
  IPAddress _ip,_gw,_sn;
  _ip.fromString(static_ip);
//  _gw.fromString(static_gw);
//  _sn.fromString(static_sn);

  wifiManager.setSTAStaticIPConfig(_ip, _gw, _sn);
  
  //add all your parameters here
  wifiManager.addParameter(&custom_ap_SSID);
  wifiManager.addParameter(&custom_udp_port);
  wifiManager.addParameter(&custom_api_key);
  wifiManager.addParameter(&custom_Local_Device_One);
  wifiManager.addParameter(&custom_offTime1);
  wifiManager.addParameter(&custom_Local_Device_Two);
  wifiManager.addParameter(&custom_offTime2);
  wifiManager.addParameter(&custom_A_Click_Device);
  wifiManager.addParameter(&custom_A_Click_IP);
  wifiManager.addParameter(&custom_A_doubleClick_Device);
  wifiManager.addParameter(&custom_A_doubleClick_IP);
  wifiManager.addParameter(&custom_B_Click_Device);
  wifiManager.addParameter(&custom_B_Click_IP);
  wifiManager.addParameter(&custom_B_doubleClick_Device);
  wifiManager.addParameter(&custom_B_doubleClick_IP);

  //reset settings - for testing
  //wifiManager.resetSettings();

  //set minimu quality of signal so it ignores AP's under that quality
  //defaults to 8%
  wifiManager.setMinimumSignalQuality();
  
  //sets timeout until configuration portal gets turned off
  //useful to make it all retry or go to sleep
  //in seconds
  //wifiManager.ConfigPortalTimeout(120); //new

  //fetches ssid and pass and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  if (!wifiManager.autoConnect(ap_SSID)) {
//    Serial.println("failed to connect and hit timeout");
    delay(3000);
    //reset and try again, or maybe put it to deep sleep
    ESP.restart();
    delay(3000);
  }

  //if you get here you have connected to the WiFi
//  Serial.println("connected to WiFi...");

  //read updated parameters
  strcpy(ap_SSID, custom_ap_SSID.getValue());
  strcpy(udp_port, custom_udp_port.getValue());
  strcpy(api_key, custom_api_key.getValue());
  strcpy(Local_Device_One, custom_Local_Device_One.getValue());
  strcpy(offTime1, custom_offTime1.getValue());
  strcpy(Local_Device_Two, custom_Local_Device_Two.getValue());
  strcpy(offTime2, custom_offTime2.getValue());
  strcpy(A_Click_Device, custom_A_Click_Device.getValue());
  strcpy(A_Click_IP, custom_A_Click_IP.getValue());
  strcpy(A_doubleClick_Device, custom_A_doubleClick_Device.getValue());
  strcpy(A_doubleClick_IP, custom_A_doubleClick_IP.getValue());
  strcpy(B_Click_Device, custom_B_Click_Device.getValue());
  strcpy(B_Click_IP, custom_B_Click_IP.getValue());
  strcpy(B_doubleClick_Device, custom_B_doubleClick_Device.getValue());
  strcpy(B_doubleClick_IP, custom_B_doubleClick_IP.getValue());

  //save the custom parameters to FS
  if (shouldSaveConfig) {
//    Serial.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["ap_SSID"] = ap_SSID;
    json["udp_port"] = udp_port;
    json["api_key"] = api_key;
    json["Local_Device_One"] = Local_Device_One;
    json["offTime1"] = offTime1;
    json["Local_Device_Two"] = Local_Device_Two;
    json["offTime2"] = offTime2;
    json["A_Click_Device"] = A_Click_Device;
    json["A_Click_IP"] = A_Click_IP;
    json["A_doubleClick_Device"] = A_doubleClick_Device;
    json["A_doubleClick_IP"] = A_doubleClick_IP;
    json["B_Click_Device"] = B_Click_Device;
    json["B_Click_IP"] = B_Click_IP;
    json["B_doubleClick_Device"] = B_doubleClick_Device;
    json["B_doubleClick_IP"] = B_doubleClick_IP;

    json["ip"] = WiFi.localIP().toString();
//    json["gateway"] = WiFi.gatewayIP().toString();
//    json["subnet"] = WiFi.subnetMask().toString();

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
//      Serial.println("failed to open config file for writing");
    }

    json.prettyPrintTo(Serial);
    json.printTo(configFile);
    configFile.close();
    //end save
  }

//  Serial.println("local ip");
//  Serial.println(WiFi.localIP());
//  Serial.println(WiFi.gatewayIP());
//  Serial.println(WiFi.subnetMask());
    delay(500);

  // Alexa server address, port and URL
  webSocket.begin("iot.sinric.com", 80, "/");


  // Alexa event handler
  webSocket.onEvent(webSocketEvent);
  webSocket.setAuthorization("apikey", api_key);
  // try again every 5000ms if connection has failed
  webSocket.setReconnectInterval(5000);   // If you see 'class WebSocketsClient' has no member named 'setReconnectInterval' error update arduinoWebSockets


  //Start UDP server
  udpPort = atoi(udp_port);
  Udp.begin(udpPort);
//  Serial.println("UDP Target IP");
//  Serial.println(WiFi.localIP());
//  Serial.println("UDP port");
//  Serial.println(udpPort);


    //Set up Auto-off Timers
  startTime1 = millis(); //save the start time for device 1
  startTime2 = millis(); //save the start time for device 2
  autoff1 = atoi(offTime1);
  autoff2 = atoi(offTime2);
  
  period1 = (autoff1 * 60000);
  period2 = (autoff2 * 60000);

  if(period1 == 0) {
    period1 = 86400000;
  }

  if (period2 == 0) {
    period2 = 86400000;
  }
  
} //end void setup()


void loop() {
  RXState.poll();
  TXState.poll();
  
  //Receive incoming Udp packet and parse information
  int pktSize = Udp.parsePacket();
  if (pktSize) {
//    Serial.print(Udp.remoteIP());
//    Serial.print(":");
//    Serial.println(Udp.remotePort());
    Udp.read(pktBuf, pktSize);
   }

  String packetbuffer (pktBuf);

  //What to do with Udp packet
  if (packetbuffer.startsWith(Local_Device_One)) {  //Toggle A_Click_Device
      String device_Id = (Local_Device_One);
      toggle(device_Id);
      String packetbuffer = "";
      for (int i = 0; i<25; i++){
        pktBuf[i] = (char) 0;
        }
      Udp.flush();
  }
        
  if (packetbuffer.startsWith(Local_Device_Two)) {  //Toggle B_Click_Device
      String device_Id = (Local_Device_Two);
      toggle(device_Id);
      String packetbuffer = "";
      for (int i = 0; i<25; i++){
        pktBuf[i] = (char) 0;
        }
      Udp.flush();  
    }
    
    if (packetbuffer.startsWith("format")) { // invoke AP reset with UDP
      WiFiManager wifiManager;
      SPIFFS.format();
      delay(1000);
      wifiManager.resetSettings();
      delay(1000);
      ESP.reset();  //reset and try again, or maybe put it to deep sleep
      delay(3000);
    }
    
    if (packetbuffer.startsWith("reset")) { // invoke AP reset with UDP
       WiFiManager wifiManager;
       delay(1000);
       wifiManager.resetSettings();
       delay(1000);
       ESP.reset();  //reset and try again, or maybe put it to deep sleep
       delay(3000);   
    }
    
    if (packetbuffer.startsWith("survey")) { // send status update to controller
        Udp.beginPacket(Udp.remoteIP(), udpPort);
        Udp.write(ap_SSID);
        Udp.endPacket();
        for (int i = 0; i<25; i++){
          pktBuf[i] = (char) 0;
          }
        Udp.flush();
    }

  //What to do with button presses
  if (RXState.singleClick()){ 
      String target_Id = (A_Click_Device);
      IPAddress targetIP;
      targetIP.fromString(A_Click_IP);
      process(target_Id, targetIP); 
  }

  if (RXState.doubleClick()){
      String target_Id = (A_doubleClick_Device);
      IPAddress targetIP;
      targetIP.fromString(A_doubleClick_IP);
      process(target_Id, targetIP);
  }
   
  if (RXState.longPress()) {
     WiFiManager wifiManager;
     wifiManager.resetSettings();
     delay(1000);
     ESP.reset();  //reset and try again, or maybe put it to deep sleep
     delay(3000);
  }
       
  if (TXState.singleClick()){
      String target_Id = (B_Click_Device);
      IPAddress targetIP;
      targetIP.fromString(B_Click_IP);
      process(target_Id, targetIP);
  }

  if (TXState.doubleClick()){
      String target_Id = (B_doubleClick_Device);
      IPAddress targetIP;
      targetIP.fromString(B_doubleClick_IP);
      process(target_Id, targetIP);  
  }
  
  if (TXState.longPress()) {
      WiFiManager wifiManager;
      SPIFFS.format();
      delay(1000);
      wifiManager.resetSettings();
      delay(1000);
      ESP.reset();  //reset and try again, or maybe put it to deep sleep
      delay(3000);       
  }
  

  //Set timer
  currentTime = millis();

  //Auto-off timer device 1
  if (currentTime - startTime1 >= period1) {
    digitalWrite(GPIO_2, HIGH);
    startTime1 = millis();
  }

  //Auto-off timer device 2
  if (currentTime - startTime2 >= period2) {
    digitalWrite(GPIO_0, HIGH);
    startTime2 = millis();
  }

  webSocket.loop();
  
  if(isConnected) {
    uint64_t now = millis();
      
    // Send heartbeat in order to avoid disconnections during ISP resetting IPs over night.
    if((now - heartbeatTimestamp) > HEARTBEAT_INTERVAL) {
      heartbeatTimestamp = now;
      webSocket.sendTXT("H");          
    }
  }   
}

### Debug Messages

Because I am using all available pins as GPIO, there is no way to get debug messages.


Originally created by @mrlightsman on GitHub (Nov 26, 2018). Original GitHub issue: https://github.com/tzapu/WiFiManager/issues/773 ### Basic Infos #### Hardware **WiFimanager Branch/Release:** - [X ] Master - [ ] Development **Esp8266/Esp32:** - [X ] ESP8266 - [ ] ESP32 **Hardware: ESP-12e, esp01, esp25** - [X ] ESP01 - [ ] ESP12 E/F/S (nodemcu, wemos, feather) - [ ] Other **ESP Core Version: 2.4.0, staging** - [ ] 2.3.0 - [X ] 2.4.1 - [ ] staging (master/dev) ### Description I have several ESP01 that I use as light switches in my house. They are all configured with WiFi Manager with parameters. They are set to DHCP, but have an address reservation in my router (Archer C7) via MAC address. The code is mostly based on Kakopappa Sinric switch and udp examples. The wifiManager portion is from the master branch example code and expanded with additional parameters. Problem description Frequently, they seem to lose connection with the router and go back into ap mode and no longer function until I re-enter the WiFi credentials. They retain their other parameters. Is there a command to have the ESP request a new IP address via DHCP? I'm thinking this might help renew the connection with the router... assuming the router is at fault. Or, is there a better solution out there? I am a relative noob so all suggestions are appreciated. At one time I tried using the development branch, but it broke other parts of my code for some reason. I decided to stick with the master just to be safe... ### Settings in IDE * Board - Generic ESP8266 * Flash Mode - DIO * Flash Size - 1M (512K SPIFFS) * Debug Port - Disabled * Debug Level - None * lwIP Variant - V2 prebuilt (MSS=536) * Reset Method - ck * Crystal Frequency - 26M * Flash Frequency - 40MHz * CPU Frequency - 80MHz * Upload Speed - 115200 * Port - TBD by your setup * Programmer - Arduino as ISP Module: Generic ESP8266 Module Additional libraries: <FS.h> <arduino.h> <WebSocketsClient.h> <ArduinoJson.h> <WiFiManager.h> <WiFiUDP.h> <avdweb_Switch.h> ### Sketch ``` #include <FS.h> #include <arduino.h> #include <WebSocketsClient.h> // get it from https://github.com/Links2004/arduinoWebSockets/releases #include <ArduinoJson.h> // get it from https://arduinojson.org/ or install via Arduino library manager #include <WiFiManager.h> // get it from https://github.com/the-real-orca/WiFiManager #include <WiFiUDP.h> //get it from https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WiFi/src #include <avdweb_Switch.h> //https://github.com/avandalen/avdweb_Switch /* This version of the sinric switch uses the multi wifi manager to input wifi, API, and two device ids. * It is designed to work with an ESP8266-01 with the following pin use: * GPIO_2 = device 1. LOW is ON. HIGH is OFF. Intended to sink to an optoisolator with pin 1 connected to Vcc and pin 2 to GPIO_2. * GPIO_0 = device 2. LOW is ON. HIGH is OFF. Intended to sink to an optoisolator with pin 1 connected to Vcc and pin 2 to GPIO-0. * RX (pin 3)Connect a momentary N/O switch to GROUND and RX with a 220 ohm pullup resistor to Vcc. * TX (pin 1)Connect a momentary N/O switch to GROUND and RX with a 220 ohm pullup resistor to Vcc. * RX press = toggle device 1 * RX doubleClick = toggle device 3 * RX doubleClick = Invoke WiFi Manager * TX press = toggle device 2 * TX doubleClick = toggle remote device 4 * TX doubleClick = Invoke WiFi Manager with SPIFFS Format * * All other ESP pins are connected per usual ESP set up. * */ /*ESP8266-01 Flash settings: * Board - Generic ESP8266 * Flash Mode - DIO * Flash Size - 1M (512K SPIFFS) * Debug Port - Disabled * Debug Level - None * lwIP Variant - V2 prebuilt (MSS=536) * Reset Method - ck * Crystal Frequency - 26M * Flash Frequency - 40MHz * CPU Frequency - 80MHz * Upload Speed - 115200 * Port - TBD by your setup * Programmer - Arduino as ISP */ WebSocketsClient webSocket; WiFiClient client; WiFiUDP Udp; #define API_ENDPOINT "http://sinric.com" #define HEARTBEAT_INTERVAL 300000 // 5 Minutes //Switch Contols variables const byte GPIO_2 = 2; //To control local Device 1 const byte GPIO_0 = 0; //To control local Device 2 const byte RX = 3; //To manually toggle devices 1&3 const byte TX = 1; //To manually toggle devices 2&4 int GPIO_2State; //State of local device 1 int GPIO_0State; //State of local device 2 //Define UDP server variables char udp_port[6]; //used to store in json the udp port from user input on WiFi Manager page unsigned int udpPort; // used by udp.begin()command (it is udpPort converted for use) char pktBuf[25]; //buffer for UDP packets //Define the local IP variables char ap_SSID[15] = "New Box"; //SSID for ESP when in AP mode char static_ip[16]; // ip address for ESP when in client mode //char static_gw[16]; // gateway address for ESP when in client mode //char static_sn[16]; // subnet address for ESP when in client mode //Set up UDP variables for WiFIManager char A_Click_IP[16]; // UDP target IP 3 char B_Click_IP[16]; // UDP target IP 3 char A_doubleClick_IP[16]; // UDP target IP 3 char B_doubleClick_IP[16]; // UDP target IP 4 char targetIP[16]; //Define the Alexa variables char api_key[37]; //Sinric API Key char Local_Device_One[25]; // local device 1 char Local_Device_Two[25]; // local device 2 char A_Click_Device[25]; //alexa device 1 char B_Click_Device[25]; //alexa device 2 char A_doubleClick_Device[25]; // alexa device 3 char B_doubleClick_Device[25]; // alexa device 4 //set up button debounce with Switch Switch RXState = Switch(RX); //button to ground Switch TXState = Switch(TX); //button to ground //Define Auto-off Timer variables for local devices char offTime1[7]; // auto-off time in minutes char offTime2[7]; // auto-off time in minutes unsigned int autoff1; unsigned int autoff2; unsigned long startTime1; // timer for local device 1 unsigned long startTime2; // timer for local device 2 unsigned long currentTime; unsigned long period1; unsigned long period2; //Define the heartbeat timer variables uint64_t heartbeatTimestamp = 0; //heartbeat timer reset bool isConnected = false; //flag for saving data bool shouldSaveConfig = false; //callback notifying us of the need to save config void saveConfigCallback () { // Serial.println("Should save config"); shouldSaveConfig = true; } void process(String target_Id, IPAddress targetIP) { if (target_Id == (Local_Device_One)) { String device_Id = (Local_Device_One); toggle(device_Id); } else if (target_Id == (Local_Device_Two)) { String device_Id = (Local_Device_Two); toggle(device_Id); } else { char send_Id[25]; target_Id.toCharArray(send_Id, 25); Udp.beginPacket(targetIP, udpPort); Udp.write(send_Id); Udp.endPacket(); } } //if a udp command or button push is detected, toggle the appropriate device void toggle(String device_Id) { if (device_Id == (Local_Device_One)) { GPIO_2State = digitalRead(GPIO_2); GPIO_2State = !GPIO_2State; digitalWrite(GPIO_2, GPIO_2State); startTime1 = millis(); // Serial.println("Device 1"); // Serial.println("Status:"); // Serial.println(GPIO_2State); // Serial.println("Waiting"); } else if (device_Id == (Local_Device_Two)) { GPIO_0State = digitalRead(GPIO_0); GPIO_0State = !GPIO_0State; digitalWrite(GPIO_0, GPIO_0State); startTime2 = millis(); // Serial.println("Device 2:"); // Serial.println("Status:"); // Serial.println(GPIO_0State); // Serial.println("Waiting"); } device_Id = ""; } //Alexa "ON" response void turnOn(String deviceId) { if (deviceId == (Local_Device_One)) { // Device ID of first device // Serial.print("Turn on 1st-device id: "); // Serial.println(deviceId); digitalWrite(GPIO_2, LOW); startTime1 = millis(); } else if (deviceId == (Local_Device_Two)) { // Device ID of second device // Serial.print("Turn on 2nd-device id: "); // Serial.println(deviceId); digitalWrite(GPIO_0, LOW); startTime2 = millis(); } else { // Serial.print("Turn on for unknown device id: "); // Serial.println(deviceId); } } //Alexa "OFF" response void turnOff(String deviceId) { if (deviceId == (Local_Device_One)) { // Device ID of first device // Serial.print("Turn off 1st-Device ID: "); // Serial.println(deviceId); digitalWrite(GPIO_2, HIGH); startTime1 = millis(); } else if (deviceId == (Local_Device_Two)) { // Device ID of second device // Serial.print("Turn off 2nd-Device ID: "); // Serial.println(deviceId); digitalWrite(GPIO_0, HIGH); startTime2 = millis(); } else { // Serial.print("Turn off for unknown device id: "); // Serial.println(deviceId); } } //Receive and process an Alexa command void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { switch(type) { case WStype_DISCONNECTED:{ isConnected = false; // Serial.printf("[WSc] Webservice disconnected from sinric.com!\n"); break; case WStype_CONNECTED: { isConnected = true; // Serial.printf("[WSc] Service connected to sinric.com at url: %s\n", payload); // Serial.printf("Waiting for commands from sinric.com ...\n"); } break; case WStype_TEXT: { DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.parseObject((char*)payload); String deviceId = json ["deviceId"]; String action = json ["action"]; if(action == "setPowerState") { // Switch or Light String value = json ["value"]; if(value == "ON") { turnOn(deviceId); } else { turnOff(deviceId); } // } else if(action == "setBrightness") { // } else if(action == "AdjustBrightness") { // } else if (action == "test") { // Serial.println("[WSc] received test command from sinric.com"); } } break; case WStype_BIN: // Serial.printf("[WSc] get binary length: %u\n", length); break; } } } void setup() { Serial.begin(115200); // Serial.println(); // Setup pins to off position pinMode(GPIO_2, OUTPUT); digitalWrite(GPIO_2, HIGH); pinMode(GPIO_0, OUTPUT); digitalWrite(GPIO_0, HIGH); pinMode(RX, INPUT_PULLUP); pinMode(TX, INPUT_PULLUP); // SPIFFS.format(); //clean FS, for testing //read configuration from FS json // Serial.println("mounting FS..."); if (SPIFFS.begin()) { // Serial.println("mounted file system"); if (SPIFFS.exists("/config.json")) { //file exists, reading and loading // Serial.println("reading config file"); File configFile = SPIFFS.open("/config.json", "r"); if (configFile) { // Serial.println("opened config file"); size_t size = configFile.size(); // Allocate a buffer to store contents of the file. std::unique_ptr<char[]> buf(new char[size]); configFile.readBytes(buf.get(), size); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.parseObject(buf.get()); json.printTo(Serial); if (json.success()) { // Serial.println("\nparsed json"); strcpy(ap_SSID, json["ap_SSID"]); strcpy(udp_port, json["udp_port"]); strcpy(api_key, json["api_key"]); strcpy(Local_Device_One, json["Local_Device_One"]); strcpy(offTime1, json["offTime1"]); strcpy(Local_Device_Two, json["Local_Device_Two"]); strcpy(offTime2, json["offTime2"]); strcpy(A_Click_Device, json["A_Click_Device"]); strcpy(A_Click_IP, json["A_Click_IP"]); strcpy(A_doubleClick_Device, json["A_doubleClick_Device"]); strcpy(A_doubleClick_IP, json["A_doubleClick_IP"]); strcpy(B_Click_Device, json["B_Click_Device"]); strcpy(B_Click_IP, json["B_Click_IP"]); strcpy(B_doubleClick_Device, json["B_doubleClick_Device"]); strcpy(B_doubleClick_IP, json["B_doubleClick_IP"]); if(json["ip"]) { // Serial.println("setting custom ip from config"); //static_ip = json["ip"]; strcpy(static_ip, json["ip"]); // strcpy(static_gw, json["gateway"]); // strcpy(static_sn, json["subnet"]); // Serial.println(static_ip); } else { // Serial.println("no custom ip in config"); } } else { // Serial.println("failed to load json config"); } } } } else { // Serial.println("failed to mount FS"); } //end read // Serial.println(static_ip); // Serial.println(udp_port); // Serial.println(api_key); // Serial.println(A_Click_Device); // Serial.println(B_Click_Device); // The extra parameters to be configured (can be either global or just in the setup) // After connecting, parameter.getValue() will get you the configured value // id/name placeholder/prompt default length WiFiManagerParameter custom_ap_SSID("ap_SSID", "Box name and SSID", ap_SSID, 25); WiFiManagerParameter custom_udp_port("udp_port", "Interconnect Port", udp_port, 6); WiFiManagerParameter custom_api_key("api key", "api key", api_key, 37); WiFiManagerParameter custom_Local_Device_One("Local_Device_One", "1st Local deviceId", Local_Device_One, 25); WiFiManagerParameter custom_offTime1("offTime1", "Auto Off Timer 1st Local Device", offTime1, 7); WiFiManagerParameter custom_Local_Device_Two("Local_Device_Two", "2nd Local deviceId", Local_Device_Two, 25); WiFiManagerParameter custom_offTime2("offTime2", "Auto Off Timer 2nd Local Device", offTime2, 7); WiFiManagerParameter custom_A_Click_Device("A_Click_Device", "Button A Click deviceId", A_Click_Device, 25); WiFiManagerParameter custom_A_Click_IP("A_Click_IP", "Button A Click IP", A_Click_IP, 16); WiFiManagerParameter custom_A_doubleClick_Device("A_doubleClick_Device", "Button A doubleClick deviceId", A_doubleClick_Device, 25); WiFiManagerParameter custom_A_doubleClick_IP("A_doubleClick_IP", "Button A doubleClick IP", A_doubleClick_IP, 16); WiFiManagerParameter custom_B_Click_Device("B_Click_Device", "Button B Click deviceId", B_Click_Device, 25); WiFiManagerParameter custom_B_Click_IP("B_Click_IP", "Button B Click IP", B_Click_IP, 16); WiFiManagerParameter custom_B_doubleClick_Device("B_doubleClick_Device", "Button B doubleClick deviceId", B_doubleClick_Device, 25); WiFiManagerParameter custom_B_doubleClick_IP("B_doubleClick_IP", "Button B doubleClick IP", B_doubleClick_IP, 16); //WiFiManager //Local intialization. Once its business is done, there is no need to keep it around WiFiManager wifiManager; //set config save notify callback wifiManager.setSaveConfigCallback(saveConfigCallback); //set static ip IPAddress _ip,_gw,_sn; _ip.fromString(static_ip); // _gw.fromString(static_gw); // _sn.fromString(static_sn); wifiManager.setSTAStaticIPConfig(_ip, _gw, _sn); //add all your parameters here wifiManager.addParameter(&custom_ap_SSID); wifiManager.addParameter(&custom_udp_port); wifiManager.addParameter(&custom_api_key); wifiManager.addParameter(&custom_Local_Device_One); wifiManager.addParameter(&custom_offTime1); wifiManager.addParameter(&custom_Local_Device_Two); wifiManager.addParameter(&custom_offTime2); wifiManager.addParameter(&custom_A_Click_Device); wifiManager.addParameter(&custom_A_Click_IP); wifiManager.addParameter(&custom_A_doubleClick_Device); wifiManager.addParameter(&custom_A_doubleClick_IP); wifiManager.addParameter(&custom_B_Click_Device); wifiManager.addParameter(&custom_B_Click_IP); wifiManager.addParameter(&custom_B_doubleClick_Device); wifiManager.addParameter(&custom_B_doubleClick_IP); //reset settings - for testing //wifiManager.resetSettings(); //set minimu quality of signal so it ignores AP's under that quality //defaults to 8% wifiManager.setMinimumSignalQuality(); //sets timeout until configuration portal gets turned off //useful to make it all retry or go to sleep //in seconds //wifiManager.ConfigPortalTimeout(120); //new //fetches ssid and pass and tries to connect //if it does not connect it starts an access point with the specified name //here "AutoConnectAP" //and goes into a blocking loop awaiting configuration if (!wifiManager.autoConnect(ap_SSID)) { // Serial.println("failed to connect and hit timeout"); delay(3000); //reset and try again, or maybe put it to deep sleep ESP.restart(); delay(3000); } //if you get here you have connected to the WiFi // Serial.println("connected to WiFi..."); //read updated parameters strcpy(ap_SSID, custom_ap_SSID.getValue()); strcpy(udp_port, custom_udp_port.getValue()); strcpy(api_key, custom_api_key.getValue()); strcpy(Local_Device_One, custom_Local_Device_One.getValue()); strcpy(offTime1, custom_offTime1.getValue()); strcpy(Local_Device_Two, custom_Local_Device_Two.getValue()); strcpy(offTime2, custom_offTime2.getValue()); strcpy(A_Click_Device, custom_A_Click_Device.getValue()); strcpy(A_Click_IP, custom_A_Click_IP.getValue()); strcpy(A_doubleClick_Device, custom_A_doubleClick_Device.getValue()); strcpy(A_doubleClick_IP, custom_A_doubleClick_IP.getValue()); strcpy(B_Click_Device, custom_B_Click_Device.getValue()); strcpy(B_Click_IP, custom_B_Click_IP.getValue()); strcpy(B_doubleClick_Device, custom_B_doubleClick_Device.getValue()); strcpy(B_doubleClick_IP, custom_B_doubleClick_IP.getValue()); //save the custom parameters to FS if (shouldSaveConfig) { // Serial.println("saving config"); DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.createObject(); json["ap_SSID"] = ap_SSID; json["udp_port"] = udp_port; json["api_key"] = api_key; json["Local_Device_One"] = Local_Device_One; json["offTime1"] = offTime1; json["Local_Device_Two"] = Local_Device_Two; json["offTime2"] = offTime2; json["A_Click_Device"] = A_Click_Device; json["A_Click_IP"] = A_Click_IP; json["A_doubleClick_Device"] = A_doubleClick_Device; json["A_doubleClick_IP"] = A_doubleClick_IP; json["B_Click_Device"] = B_Click_Device; json["B_Click_IP"] = B_Click_IP; json["B_doubleClick_Device"] = B_doubleClick_Device; json["B_doubleClick_IP"] = B_doubleClick_IP; json["ip"] = WiFi.localIP().toString(); // json["gateway"] = WiFi.gatewayIP().toString(); // json["subnet"] = WiFi.subnetMask().toString(); File configFile = SPIFFS.open("/config.json", "w"); if (!configFile) { // Serial.println("failed to open config file for writing"); } json.prettyPrintTo(Serial); json.printTo(configFile); configFile.close(); //end save } // Serial.println("local ip"); // Serial.println(WiFi.localIP()); // Serial.println(WiFi.gatewayIP()); // Serial.println(WiFi.subnetMask()); delay(500); // Alexa server address, port and URL webSocket.begin("iot.sinric.com", 80, "/"); // Alexa event handler webSocket.onEvent(webSocketEvent); webSocket.setAuthorization("apikey", api_key); // try again every 5000ms if connection has failed webSocket.setReconnectInterval(5000); // If you see 'class WebSocketsClient' has no member named 'setReconnectInterval' error update arduinoWebSockets //Start UDP server udpPort = atoi(udp_port); Udp.begin(udpPort); // Serial.println("UDP Target IP"); // Serial.println(WiFi.localIP()); // Serial.println("UDP port"); // Serial.println(udpPort); //Set up Auto-off Timers startTime1 = millis(); //save the start time for device 1 startTime2 = millis(); //save the start time for device 2 autoff1 = atoi(offTime1); autoff2 = atoi(offTime2); period1 = (autoff1 * 60000); period2 = (autoff2 * 60000); if(period1 == 0) { period1 = 86400000; } if (period2 == 0) { period2 = 86400000; } } //end void setup() void loop() { RXState.poll(); TXState.poll(); //Receive incoming Udp packet and parse information int pktSize = Udp.parsePacket(); if (pktSize) { // Serial.print(Udp.remoteIP()); // Serial.print(":"); // Serial.println(Udp.remotePort()); Udp.read(pktBuf, pktSize); } String packetbuffer (pktBuf); //What to do with Udp packet if (packetbuffer.startsWith(Local_Device_One)) { //Toggle A_Click_Device String device_Id = (Local_Device_One); toggle(device_Id); String packetbuffer = ""; for (int i = 0; i<25; i++){ pktBuf[i] = (char) 0; } Udp.flush(); } if (packetbuffer.startsWith(Local_Device_Two)) { //Toggle B_Click_Device String device_Id = (Local_Device_Two); toggle(device_Id); String packetbuffer = ""; for (int i = 0; i<25; i++){ pktBuf[i] = (char) 0; } Udp.flush(); } if (packetbuffer.startsWith("format")) { // invoke AP reset with UDP WiFiManager wifiManager; SPIFFS.format(); delay(1000); wifiManager.resetSettings(); delay(1000); ESP.reset(); //reset and try again, or maybe put it to deep sleep delay(3000); } if (packetbuffer.startsWith("reset")) { // invoke AP reset with UDP WiFiManager wifiManager; delay(1000); wifiManager.resetSettings(); delay(1000); ESP.reset(); //reset and try again, or maybe put it to deep sleep delay(3000); } if (packetbuffer.startsWith("survey")) { // send status update to controller Udp.beginPacket(Udp.remoteIP(), udpPort); Udp.write(ap_SSID); Udp.endPacket(); for (int i = 0; i<25; i++){ pktBuf[i] = (char) 0; } Udp.flush(); } //What to do with button presses if (RXState.singleClick()){ String target_Id = (A_Click_Device); IPAddress targetIP; targetIP.fromString(A_Click_IP); process(target_Id, targetIP); } if (RXState.doubleClick()){ String target_Id = (A_doubleClick_Device); IPAddress targetIP; targetIP.fromString(A_doubleClick_IP); process(target_Id, targetIP); } if (RXState.longPress()) { WiFiManager wifiManager; wifiManager.resetSettings(); delay(1000); ESP.reset(); //reset and try again, or maybe put it to deep sleep delay(3000); } if (TXState.singleClick()){ String target_Id = (B_Click_Device); IPAddress targetIP; targetIP.fromString(B_Click_IP); process(target_Id, targetIP); } if (TXState.doubleClick()){ String target_Id = (B_doubleClick_Device); IPAddress targetIP; targetIP.fromString(B_doubleClick_IP); process(target_Id, targetIP); } if (TXState.longPress()) { WiFiManager wifiManager; SPIFFS.format(); delay(1000); wifiManager.resetSettings(); delay(1000); ESP.reset(); //reset and try again, or maybe put it to deep sleep delay(3000); } //Set timer currentTime = millis(); //Auto-off timer device 1 if (currentTime - startTime1 >= period1) { digitalWrite(GPIO_2, HIGH); startTime1 = millis(); } //Auto-off timer device 2 if (currentTime - startTime2 >= period2) { digitalWrite(GPIO_0, HIGH); startTime2 = millis(); } webSocket.loop(); if(isConnected) { uint64_t now = millis(); // Send heartbeat in order to avoid disconnections during ISP resetting IPs over night. if((now - heartbeatTimestamp) > HEARTBEAT_INTERVAL) { heartbeatTimestamp = now; webSocket.sendTXT("H"); } } } ``` ``` ### Debug Messages ``` Because I am using all available pins as GPIO, there is no way to get debug messages. ```
kerem closed this issue 2026-02-28 01:26:23 +03:00
Author
Owner

@tablatronix commented on GitHub (Nov 26, 2018):

setConfigPortalTimeout();
let the cp timeout and restart if not connected, or add your own delays to allow time to reconnect.

<!-- gh-comment-id:441654348 --> @tablatronix commented on GitHub (Nov 26, 2018): setConfigPortalTimeout(); let the cp timeout and restart if not connected, or add your own delays to allow time to reconnect.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/WiFiManager#648
No description provided.