BLYNK
BLYNK.IO       📲 GETTING STARTED       📗 DOCS       👉 SKETCH BUILDER

Esp32 Restarting Automatically If Not Connected To Hotspot

I am making a home automation project which also contains manual switches which provide live feedback when connected to internet and can be used as normal switches when not connected to internet. EVerything is working properly. But the only problem I am facing is that the esp32 is restarting after automatically if it is not connected to the Hotspot and hence the relay is getting turned off. How can I stop the esp32 from restarting itself if not connected to Hotspot? But it should reconnect automatically again when the Hotspot is available.

Here is the code I am using:

Main Code:

// Fill-in information from your Blynk Template here
#define BLYNK_TEMPLATE_ID "XXXXXXXXXXX"
#define BLYNK_DEVICE_NAME "XXXXX LED"


#define BLYNK_FIRMWARE_VERSION        "0.1.0"

#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG

#define APP_DEBUG 

// Define Relay Pins
#define r1 16
#define r2 5
#define r3 4
#define r4 12

// Define Switch Pins
#define s1 2
#define s2 14
#define s3 13
#define s4 25

// Pins of Fan Regulator Knob
#define f1  27
#define f2  35
#define f3  34
#define f4  39

// Pins of Relay (Fan Speed Control)
#define Speed1 21
#define Speed2 19
#define Speed4 18

bool speed1_flag = 1;
bool speed2_flag = 1;
bool speed3_flag = 1;
bool speed4_flag = 1;
bool speed0_flag = 1;

// Switch Flags
bool SWITCH5_FLAG = 1;
bool SWITCH6_FLAG = 1;
bool SWITCH7_FLAG = 1;
bool SWITCH8_FLAG = 1;

// Default Relay State
bool relay1 = LOW;
bool relay2 = LOW;
bool relay3 = LOW;
bool relay4 = LOW;


// Uncomment your board, or configure a custom board in Settings.h
//#define USE_WROVER_BOARD

#include "BlynkEdgent.h"


BLYNK_WRITE(V0)
{
  int fan_speed = param.asInt(); // assigning incoming value from pin V0 to a variable
  Serial.print("FAN VALUE -");Serial.print(fan_speed);Serial.println("-");
  if (fan_speed == 0)
  {
    speed0();
  }
  if (fan_speed == 1)
  {
    speed1();
  }
  if (fan_speed == 2)
  {
    speed2();
  }
  if (fan_speed == 3)
  {
    speed3();
  }
  if (fan_speed == 4)
  {
    speed4();
  }
}

BLYNK_WRITE(V1)
{
  int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable
  relay1 = pinValue;
  digitalWrite(r1 , pinValue);
  // process received value
}

BLYNK_WRITE(V2)
{
  int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable
  relay2 = pinValue;
  Serial.print("Relay2 - ");Serial.println(pinValue);
  digitalWrite(r2 , pinValue);
  // process received value
}

BLYNK_WRITE(V3)
{
  int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable
  relay3 = pinValue;
  Serial.print("Relay3 - ");Serial.println(pinValue);
  digitalWrite(r3 , pinValue);
  // process received value
}

BLYNK_WRITE(V4)
{
  int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable
  relay4 = pinValue;
  digitalWrite(r4 , pinValue);
  // process received value
}


void setup()
{
  Serial.begin(115200);
  delay(100);

  pinMode(s1, INPUT_PULLUP);
  pinMode(s2, INPUT_PULLUP);
  pinMode(s3, INPUT_PULLUP);
  pinMode(s4, INPUT_PULLUP);

  pinMode(f1, INPUT_PULLUP);
  pinMode(f2, INPUT_PULLUP);
  pinMode(f3, INPUT_PULLUP);
  pinMode(f4, INPUT_PULLUP);

  pinMode(r1, OUTPUT);
  pinMode(r2, OUTPUT);
  pinMode(r3, OUTPUT);
  pinMode(r4, OUTPUT);

  pinMode(Speed1, OUTPUT);
  pinMode(Speed2, OUTPUT);
  pinMode(Speed4, OUTPUT);

  digitalWrite(r1, 0);
  digitalWrite(r2, 0);
  digitalWrite(r3, 0);
  digitalWrite(r4, 0);

  BlynkEdgent.begin();
}

void loop()
{
  BlynkEdgent.run();
  swfeedback();
}

BlynkEdgent.h:

extern "C" {
  void app_loop();
  void eraseMcuConfig();
  void restartMCU();
}

#include "Settings.h"
#include <BlynkSimpleEsp32_SSL.h>

#ifndef BLYNK_NEW_LIBRARY
#error "Old version of Blynk library is in use. Please replace it with the new one."
#endif

#define DEBUG_SW 0


// Function Definition

void speed0();
void speed1();
void speed2();
void speed3();
void speed4();


#if !defined(BLYNK_TEMPLATE_ID) || !defined(BLYNK_DEVICE_NAME)
#error "Please specify your BLYNK_TEMPLATE_ID and BLYNK_DEVICE_NAME"
#endif

#include "BlynkState.h"
#include "ConfigStore.h"
#include "ResetButton.h"
#include "ConfigMode.h"
#include "Indicator.h"
#include "OTA.h"
void irsense();
void swfeedback();
inline
void BlynkState::set(State m) {
  if (state != m && m < MODE_MAX_VALUE) {
    DEBUG_PRINT(String(StateStr[state]) + " => " + StateStr[m]);
    state = m;

    // You can put your state handling here,
    // i.e. implement custom indication
  }
}

void printDeviceBanner()
{
  Blynk.printBanner();
  DEBUG_PRINT("--------------------------");
  DEBUG_PRINT(String("Product:  ") + BLYNK_DEVICE_NAME);
  DEBUG_PRINT(String("Hardware: ") + BOARD_HARDWARE_VERSION);
  DEBUG_PRINT(String("Firmware: ") + BLYNK_FIRMWARE_VERSION " (build " __DATE__ " " __TIME__ ")");
  if (configStore.getFlag(CONFIG_FLAG_VALID)) {
    DEBUG_PRINT(String("Token:    ...") + (configStore.cloudToken + 28));
  }
  DEBUG_PRINT(String("Device:   ") + BLYNK_INFO_DEVICE + " @ " + ESP.getCpuFreqMHz() + "MHz");
  DEBUG_PRINT(String("MAC:      ") + WiFi.macAddress());
  DEBUG_PRINT(String("Flash:    ") + ESP.getFlashChipSize() / 1024 + "K");
  DEBUG_PRINT(String("ESP sdk:  ") + ESP.getSdkVersion());
  DEBUG_PRINT(String("Chip rev: ") + ESP.getChipRevision());
  DEBUG_PRINT(String("Free mem: ") + ESP.getFreeHeap());
  DEBUG_PRINT("--------------------------");
}

void runBlynkWithChecks() {
  Blynk.run();
  if (BlynkState::get() == MODE_RUNNING) {
    if (!Blynk.connected()) {
      if (WiFi.status() == WL_CONNECTED) {
        BlynkState::set(MODE_CONNECTING_CLOUD);
      } else {
        BlynkState::set(MODE_CONNECTING_NET);
      }
    }
  }
}

class Edgent {

  public:
    void begin()
    {
      indicator_init();
      button_init();
      config_init();

      WiFi.persistent(false);
      WiFi.enableSTA(true);   // Needed to get MAC

      printDeviceBanner();

      if (configStore.getFlag(CONFIG_FLAG_VALID)) {
        BlynkState::set(MODE_CONNECTING_NET);
      } else if (config_load_blnkopt()) {
        DEBUG_PRINT("Firmware is preprovisioned");
        BlynkState::set(MODE_CONNECTING_NET);
      } else {
        BlynkState::set(MODE_WAIT_CONFIG);
      }
    }

    void run() {
      app_loop();
      switch (BlynkState::get()) {
        case MODE_WAIT_CONFIG:
        case MODE_CONFIGURING:       enterConfigMode();    break;
        case MODE_CONNECTING_NET:    enterConnectNet();    break;
        case MODE_CONNECTING_CLOUD:  enterConnectCloud();  break;
        case MODE_RUNNING:           runBlynkWithChecks(); break;
        case MODE_OTA_UPGRADE:       enterOTA();           break;
        case MODE_SWITCH_TO_STA:     enterSwitchToSTA();   break;
        case MODE_RESET_CONFIG:      enterResetConfig();   break;
        default:                     enterError();         break;
      }
    }

};

Edgent BlynkEdgent;
BlynkTimer timer;

void app_loop() {
  timer.run();
  swfeedback();
}

void swfeedback()
{
  if (digitalRead(s1) == HIGH && SWITCH5_FLAG == 1) {
    digitalWrite(r1, LOW);
    Blynk.virtualWrite(V1, LOW);
    Serial.println("r1 on");
    relay1 = 0;
    SWITCH5_FLAG = 0;
  }
  if (digitalRead(s1) == LOW && SWITCH5_FLAG == 0) {
    digitalWrite(r1, HIGH);
    Blynk.virtualWrite(V1, HIGH);
    Serial.println("r1 off");
    relay1 = 1;
    SWITCH5_FLAG = 1;
  }
  if (digitalRead(s2) == HIGH && SWITCH6_FLAG == 1) {
    digitalWrite(r2, LOW);
    Blynk.virtualWrite(V2, LOW);
    Serial.println("r2 on");
    relay2 = 0;
    SWITCH6_FLAG = 0;
  }
  if (digitalRead(s2) == LOW && SWITCH6_FLAG == 0) {
    digitalWrite(r2, HIGH);
    Blynk.virtualWrite(V2, HIGH);
    Serial.println("r2 off");
    relay2 = 1;
    SWITCH6_FLAG = 1;
  }
  if (digitalRead(s3) == HIGH && SWITCH7_FLAG == 1) {
    digitalWrite(r3, LOW);
    Blynk.virtualWrite(V3, LOW);
    Serial.println("r3 on");
    relay3 = 0;
    SWITCH7_FLAG = 0;
  }
  if (digitalRead(s3) == LOW && SWITCH7_FLAG == 0) {
    digitalWrite(r3, HIGH);
    Blynk.virtualWrite(V3, HIGH);
    Serial.println("r3 off");
    relay3 = 1;
    SWITCH7_FLAG = 1;
  }
  if (digitalRead(s4) == HIGH && SWITCH8_FLAG == 1) {
    digitalWrite(r4, LOW);
    Blynk.virtualWrite(V4, LOW);
    Serial.println("r4 on");
    relay4 = 0;
    SWITCH8_FLAG = 0;
  }
  if (digitalRead(s4) == LOW && SWITCH8_FLAG == 0) {
    digitalWrite(r4, HIGH);
    Blynk.virtualWrite(V4, HIGH);
    Serial.println("r4 off");
    relay4 = 1;
    SWITCH8_FLAG = 1;
  }

  // FOR FAN
  if (digitalRead(f1) == LOW && speed1_flag == 1)
  {
    speed1();
    Blynk.virtualWrite(V0, 1);
    speed1_flag = 0;
    speed2_flag = 1;
    speed3_flag = 1;
    speed4_flag = 1;
    speed0_flag = 1;


  }
  if (digitalRead(f2) == LOW && digitalRead(f3) == HIGH && speed2_flag == 1)
  {
    speed2();
    Blynk.virtualWrite(V0, 2);
    speed1_flag = 1;
    speed2_flag = 0;
    speed3_flag = 1;
    speed4_flag = 1;
    speed0_flag = 1;

  }
  if (digitalRead(f2) == LOW && digitalRead(f3) == LOW && speed3_flag == 1)
  {
    speed3();
    Blynk.virtualWrite(V0, 3);
    speed1_flag = 1;
    speed2_flag = 1;
    speed3_flag = 0;
    speed4_flag = 1;
    speed0_flag = 1;
  }
  if (digitalRead(f4) == LOW  && speed4_flag == 1)
  {
    speed4();
    Blynk.virtualWrite(V0, 4);
    speed1_flag = 1;
    speed2_flag = 1;
    speed3_flag = 1;
    speed4_flag = 0;
    speed0_flag = 1;
  }
  if (digitalRead(f1) == HIGH && digitalRead(f2) == HIGH && digitalRead(f3) == HIGH && digitalRead(f4) == HIGH  && speed0_flag == 1)
  {
    speed0();
    Blynk.virtualWrite(V0, 0);
    speed1_flag = 1;
    speed2_flag = 1;
    speed3_flag = 1;
    speed4_flag = 1;
    speed0_flag = 0;
  }
}



// Fan Speed Control

void speed0()
{
  //All Relays Off - Fan at speed 0
  if (DEBUG_SW)Serial.println("SPEED 0");
  digitalWrite(Speed1, LOW);
  digitalWrite(Speed2, LOW);
  digitalWrite(Speed4, LOW);

}

void speed1()
{
  //Speed1 Relay On - Fan at speed 1
  if (DEBUG_SW)Serial.println("SPEED 1");
  digitalWrite(Speed1, LOW);
  digitalWrite(Speed2, LOW);
  digitalWrite(Speed4, LOW);
  delay(1000);
  digitalWrite(Speed1, HIGH);
}

void speed2()
{
  //Speed2 Relay On - Fan at speed 2
  if (DEBUG_SW)Serial.println("SPEED 2");
  digitalWrite(Speed1, LOW);
  digitalWrite(Speed2, LOW);
  digitalWrite(Speed4, LOW);
  delay(1000);
  digitalWrite(Speed2, HIGH);
}

void speed3()
{
  //Speed1 & Speed2 Relays On - Fan at speed 3
  if (DEBUG_SW)Serial.println("SPEED 3");
  digitalWrite(Speed1, LOW);
  digitalWrite(Speed2, LOW);
  digitalWrite(Speed4, LOW);
  delay(1000);
  digitalWrite(Speed1, HIGH);
  digitalWrite(Speed2, HIGH);

}

void speed4()
{
  //Speed4 Relay On - Fan at speed 4
  if (DEBUG_SW)Serial.println("SPEED 4");
  digitalWrite(Speed1, LOW);
  digitalWrite(Speed2, LOW);
  digitalWrite(Speed4, LOW);
  delay(1000);
  digitalWrite(Speed4, HIGH);
}

BlynkState.h

enum State {
  MODE_WAIT_CONFIG,
  MODE_CONFIGURING,
  MODE_CONNECTING_NET,
  MODE_CONNECTING_CLOUD,
  MODE_RUNNING,
  MODE_OTA_UPGRADE,
  MODE_SWITCH_TO_STA,
  MODE_RESET_CONFIG,
  MODE_ERROR,

  MODE_MAX_VALUE
};

#if defined(APP_DEBUG)
const char* StateStr[MODE_MAX_VALUE+1] = {
  "WAIT_CONFIG",
  "CONFIGURING",
  "CONNECTING_NET",
  "CONNECTING_CLOUD",
  "RUNNING",
  "OTA_UPGRADE",
  "SWITCH_TO_STA",
  "RESET_CONFIG",
  "ERROR",

  "INIT"
};
#endif

namespace BlynkState
{
  volatile State state = MODE_MAX_VALUE;

  State get()        { return state; }
  bool  is (State m) { return (state == m); }
  void  set(State m);
};

ConfigMode.h:

#include <WiFiClient.h>
#include <WebServer.h>
#include <DNSServer.h>
#include <Update.h>

#include <nvs.h>
#include <nvs_flash.h>

#ifdef BLYNK_USE_SPIFFS
  #include "SPIFFS.h"
#else
  const char* config_form = R"html(
<!DOCTYPE HTML>
<html>
<head>
  <title>WiFi setup</title>
  <style>
  body {
    background-color: #fcfcfc;
    box-sizing: border-box;
  }
  body, input {
    font-family: Roboto, sans-serif;
    font-weight: 400;
    font-size: 16px;
  }
  .centered {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);

    padding: 20px;
    background-color: #ccc;
    border-radius: 4px;
  }
  td { padding:0 0 0 5px; }
  label { white-space:nowrap; }
  input { width: 20em; }
  input[name="port"] { width: 5em; }
  input[type="submit"], img { margin: auto; display: block; width: 30%; }
  </style>
</head> 
<body>
<div class="centered">
  <form method="get" action="config">
    <table>
    <tr><td><label for="ssid">WiFi SSID:</label></td>  <td><input type="text" name="ssid" length=64 required="required"></td></tr>
    <tr><td><label for="pass">Password:</label></td>   <td><input type="text" name="pass" length=64></td></tr>
    <tr><td><label for="blynk">Auth token:</label></td><td><input type="text" name="blynk" placeholder="a0b1c2d..." pattern="[-_a-zA-Z0-9]{32}" maxlength="32" required="required"></td></tr>
    <tr><td><label for="host">Host:</label></td>       <td><input type="text" name="host" length=64></td></tr>
    <tr><td><label for="port_ssl">Port:</label></td>   <td><input type="number" name="port_ssl" value="443" min="1" max="65535"></td></tr>
    </table><br/>
    <input type="submit" value="Apply">
  </form>
</div>
</body>
</html>
)html";
#endif

WebServer server(WIFI_AP_CONFIG_PORT);
DNSServer dnsServer;
const byte DNS_PORT = 53;

static const char serverUpdateForm[] PROGMEM =
  R"(<html><body>
      <form method='POST' action='' enctype='multipart/form-data'>
        <input type='file' name='update'>
        <input type='submit' value='Update'>
      </form>
    </body></html>)";

void restartMCU() {
  ESP.restart();
  while(1) {};
}

void eraseMcuConfig() {
  // Erase ESP32 NVS
  int err;
  //err=nvs_flash_init();
  //BLYNK_LOG2("nvs_flash_init: ", err ? String(err) : "Success");
  err=nvs_flash_erase();
  BLYNK_LOG2("nvs_flash_erase: ", err ? String(err) : "Success");
}

void getWiFiName(char* buff, size_t len, bool withPrefix = true) {
  const uint64_t chipId = ESP.getEfuseMac();
  uint32_t unique = 0;
  for (int i=0; i<4; i++) {
    unique = BlynkCRC32(&chipId, sizeof(chipId), unique);
  }
  if (withPrefix) {
    snprintf(buff, len, "Blynk %s-%05X", BLYNK_DEVICE_NAME, unique & 0xFFFFF);
  } else {
    snprintf(buff, len, "%s-%05X", BLYNK_DEVICE_NAME, unique & 0xFFFFF);      
  }
}

void enterConfigMode()
{
  char ssidBuff[64];
  getWiFiName(ssidBuff, sizeof(ssidBuff));

  WiFi.mode(WIFI_OFF);
  delay(100);
  WiFi.mode(WIFI_AP);
  delay(2000);
  WiFi.softAPConfig(WIFI_AP_IP, WIFI_AP_IP, WIFI_AP_Subnet);
  WiFi.softAP(ssidBuff);
  delay(500);

  IPAddress myIP = WiFi.softAPIP();
  DEBUG_PRINT(String("AP SSID: ") + ssidBuff);
  DEBUG_PRINT(String("AP IP:   ") + myIP[0] + "." + myIP[1] + "." + myIP[2] + "." + myIP[3]);

  // Set up DNS Server
  dnsServer.setTTL(300); // Time-to-live 300s
  dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure); // Return code for non-accessible domains
#ifdef WIFI_CAPTIVE_PORTAL_ENABLE
  dnsServer.start(DNS_PORT, "*", WiFi.softAPIP()); // Point all to our IP
  server.onNotFound(handleRoot);
#else
  dnsServer.start(DNS_PORT, CONFIG_AP_URL, WiFi.softAPIP());
  DEBUG_PRINT(String("AP URL:  ") + CONFIG_AP_URL);
#endif

  server.on("/update", HTTP_GET, []() {
    server.sendHeader("Connection", "close");
    server.send(200, "text/html", serverUpdateForm);
  });
  server.on("/update", HTTP_POST, []() {
    server.sendHeader("Connection", "close");
    if (!Update.hasError()) {
      server.send(200, "text/plain", "OK");
    } else {
      server.send(500, "text/plain", "FAIL");
    }
    delay(1000);
    restartMCU();
  }, []() {
    HTTPUpload& upload = server.upload();
    if (upload.status == UPLOAD_FILE_START) {
      DEBUG_PRINT(String("Update: ") + upload.filename);
      //WiFiUDP::stop();

      if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
        Update.printError(BLYNK_PRINT);
      }
    } else if (upload.status == UPLOAD_FILE_WRITE) {
      /* flashing firmware to ESP*/
      if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
        Update.printError(BLYNK_PRINT);
      }
      BLYNK_PRINT.print(".");
    } else if (upload.status == UPLOAD_FILE_END) {
      BLYNK_PRINT.println();
      DEBUG_PRINT("Finishing...");
      if (Update.end(true)) { //true to set the size to the current progress
        DEBUG_PRINT("Update Success. Rebooting");
      } else {
        Update.printError(BLYNK_PRINT);
      }
    }
  });

  server.on("/config", []() {
    DEBUG_PRINT("Applying configuration...");
    String ssid = server.arg("ssid");
    String ssidManual = server.arg("ssidManual");
    String pass = server.arg("pass");
    if (ssidManual != "") {
      ssid = ssidManual;
    }
    String token = server.arg("blynk");
    String host  = server.arg("host");
    String port  = server.arg("port_ssl");

    String ip   = server.arg("ip");
    String mask = server.arg("mask");
    String gw   = server.arg("gw");
    String dns  = server.arg("dns");
    String dns2 = server.arg("dns2");

    bool save  = server.arg("save").toInt();

    String content;

    DEBUG_PRINT(String("WiFi SSID: ") + ssid + " Pass: " + pass);
    DEBUG_PRINT(String("Blynk cloud: ") + token + " @ " + host + ":" + port);

    if (token.length() == 32 && ssid.length() > 0) {
      configStore.setFlag(CONFIG_FLAG_VALID, false);
      CopyString(ssid, configStore.wifiSSID);
      CopyString(pass, configStore.wifiPass);
      CopyString(token, configStore.cloudToken);
      if (host.length()) {
        CopyString(host,  configStore.cloudHost);
      }
      if (port.length()) {
        configStore.cloudPort = port.toInt();
      }

      IPAddress addr;
      
      if (ip.length() && addr.fromString(ip)) {
        configStore.staticIP = addr;
        configStore.setFlag(CONFIG_FLAG_STATIC_IP, true);
      } else {
        configStore.setFlag(CONFIG_FLAG_STATIC_IP, false);
      }
      if (mask.length() && addr.fromString(mask)) {
        configStore.staticMask = addr;
      }
      if (gw.length() && addr.fromString(gw)) {
        configStore.staticGW = addr;
      }
      if (dns.length() && addr.fromString(dns)) {
        configStore.staticDNS = addr;
      }
      if (dns2.length() && addr.fromString(dns2)) {
        configStore.staticDNS2 = addr;
      }

      if (save) {
        configStore.setFlag(CONFIG_FLAG_VALID, true);
        config_save();

        content = R"json({"status":"ok","msg":"Configuration saved"})json";
      } else {
        content = R"json({"status":"ok","msg":"Trying to connect..."})json";
      }
      server.send(200, "application/json", content);

      BlynkState::set(MODE_SWITCH_TO_STA);
    } else {
      DEBUG_PRINT("Configuration invalid");
      content = R"json({"status":"error","msg":"Configuration invalid"})json";
      server.send(500, "application/json", content);
    }
  });
  server.on("/board_info.json", []() {
    DEBUG_PRINT("Sending board info...");
    const char* tmpl = BLYNK_TEMPLATE_ID;
    char ssidBuff[64];
    getWiFiName(ssidBuff, sizeof(ssidBuff));
    char buff[512];
    snprintf(buff, sizeof(buff),
      R"json({"board":"%s","tmpl_id":"%s","fw_type":"%s","fw_ver":"%s","hw_ver":"%s","ssid":"%s","bssid":"%s","last_error":%d,"wifi_scan":true,"static_ip":true})json",
      BLYNK_DEVICE_NAME,
      tmpl ? tmpl : "Unknown",
      BLYNK_FIRMWARE_TYPE,
      BLYNK_FIRMWARE_VERSION,
      BOARD_HARDWARE_VERSION,
      ssidBuff,
      WiFi.softAPmacAddress().c_str(),
      configStore.last_error
    );
    server.send(200, "application/json", buff);
  });
  server.on("/wifi_scan.json", []() {
    DEBUG_PRINT("Scanning networks...");
    int wifi_nets = WiFi.scanNetworks(true, true);
    while (wifi_nets == -1) {
      delay(20);
      wifi_nets = WiFi.scanComplete();
    }
    DEBUG_PRINT(String("Found networks: ") + wifi_nets);

    String result = "[\n";
    if (wifi_nets) {
      
      // Sort networks
      int indices[wifi_nets];
      for (int i = 0; i < wifi_nets; i++) {
        indices[i] = i;
      }
      for (int i = 0; i < wifi_nets; i++) {
        for (int j = i + 1; j < wifi_nets; j++) {
          if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) {
            std::swap(indices[i], indices[j]);
          }
        }
      }

      wifi_nets = BlynkMin(15, wifi_nets); // Show top 15 networks

      // TODO: skip empty names

      char buff[256];
      for (int i = 0; i < wifi_nets; i++){
        int id = indices[i];

        const char* sec;
        switch (WiFi.encryptionType(id)) {
        case WIFI_AUTH_WEP:          sec = "WEP"; break;
        case WIFI_AUTH_WPA_PSK:      sec = "WPA/PSK"; break;
        case WIFI_AUTH_WPA2_PSK:     sec = "WPA2/PSK"; break;
        case WIFI_AUTH_WPA_WPA2_PSK: sec = "WPA/WPA2/PSK"; break;
        case WIFI_AUTH_OPEN:         sec = "OPEN"; break;
        default:                     sec = "unknown"; break;
        }

        snprintf(buff, sizeof(buff),
          R"json(  {"ssid":"%s","bssid":"%s","rssi":%i,"sec":"%s","ch":%i})json",
          WiFi.SSID(id).c_str(),
          WiFi.BSSIDstr(id).c_str(),
          WiFi.RSSI(id),
          sec,
          WiFi.channel(id)
        );

        result += buff;
        if (i != wifi_nets-1) result += ",\n";
      }
      server.send(200, "application/json", result + "\n]");
    } else {
      server.send(200, "application/json", "[]");
    }
  });
  server.on("/reset", []() {
    BlynkState::set(MODE_RESET_CONFIG);
    server.send(200, "application/json", R"json({"status":"ok","msg":"Configuration reset"})json");
  });
  server.on("/reboot", []() {
    restartMCU();
  });

#ifdef BLYNK_USE_SPIFFS
  if (SPIFFS.begin()) {
    server.serveStatic("/img/favicon.png", SPIFFS, "/img/favicon.png");
    server.serveStatic("/img/logo.png", SPIFFS, "/img/logo.png");
    server.serveStatic("/", SPIFFS, "/index.html");
  } else {
    DEBUG_PRINT("Webpage: No SPIFFS");
  }
#endif

  server.begin();

  while (BlynkState::is(MODE_WAIT_CONFIG) || BlynkState::is(MODE_CONFIGURING)) {
    delay(10);
    dnsServer.processNextRequest();
    server.handleClient();
    app_loop();
    if (BlynkState::is(MODE_WAIT_CONFIG) && WiFi.softAPgetStationNum() > 0) {
      BlynkState::set(MODE_CONFIGURING);
    } else if (BlynkState::is(MODE_CONFIGURING) && WiFi.softAPgetStationNum() == 0) {
      BlynkState::set(MODE_WAIT_CONFIG);
    }
  }

  server.stop();
  
#ifdef BLYNK_USE_SPIFFS
  SPIFFS.end();
#endif
}

void enterConnectNet() {
  BlynkState::set(MODE_CONNECTING_NET);
  DEBUG_PRINT(String("Connecting to WiFi: ") + configStore.wifiSSID);

  char ssidBuff[64];
  getWiFiName(ssidBuff, sizeof(ssidBuff));
  String hostname(ssidBuff);
  hostname.replace(" ", "-");

  WiFi.setHostname(hostname.c_str());

  if (configStore.getFlag(CONFIG_FLAG_STATIC_IP)) {
    if (!WiFi.config(configStore.staticIP,
                    configStore.staticGW,
                    configStore.staticMask,
                    configStore.staticDNS,
                    configStore.staticDNS2)
    ) {
      DEBUG_PRINT("Failed to configure Static IP");
      config_set_last_error(BLYNK_PROV_ERR_CONFIG);
      BlynkState::set(MODE_ERROR);
      return;
    }
  }

  WiFi.begin(configStore.wifiSSID, configStore.wifiPass);

  unsigned long timeoutMs = millis() + WIFI_NET_CONNECT_TIMEOUT;
  while ((timeoutMs > millis()) && (WiFi.status() != WL_CONNECTED))
  {
    delay(10);
    app_loop();
    if (!BlynkState::is(MODE_CONNECTING_NET)) {
      WiFi.disconnect();
      return;
    }
  }

  if (WiFi.status() == WL_CONNECTED) {
    IPAddress localip = WiFi.localIP();
    if (configStore.getFlag(CONFIG_FLAG_STATIC_IP)) {
      BLYNK_LOG_IP("Using Static IP: ", localip);
    } else {
      BLYNK_LOG_IP("Using Dynamic IP: ", localip);
    }

    BlynkState::set(MODE_CONNECTING_CLOUD);
  } else {
    config_set_last_error(BLYNK_PROV_ERR_NETWORK);
    BlynkState::set(MODE_ERROR);
  }
}

void enterConnectCloud() {
  BlynkState::set(MODE_CONNECTING_CLOUD);

  Blynk.config(configStore.cloudToken, configStore.cloudHost, configStore.cloudPort);
  Blynk.connect(0);

  unsigned long timeoutMs = millis() + WIFI_CLOUD_CONNECT_TIMEOUT;
  while ((timeoutMs > millis()) &&
        (!Blynk.isTokenInvalid()) &&
        (Blynk.connected() == false))
  {
    delay(10);
    Blynk.run();
    app_loop();
    if (!BlynkState::is(MODE_CONNECTING_CLOUD)) {
      Blynk.disconnect();
      return;
    }
  }

  if (millis() > timeoutMs) {
    DEBUG_PRINT("Timeout");
  }

  if (Blynk.isTokenInvalid()) {
    config_set_last_error(BLYNK_PROV_ERR_TOKEN);
    BlynkState::set(MODE_WAIT_CONFIG);
  } else if (Blynk.connected()) {
    BlynkState::set(MODE_RUNNING);

    if (!configStore.getFlag(CONFIG_FLAG_VALID)) {
      configStore.last_error = BLYNK_PROV_ERR_NONE;
      configStore.setFlag(CONFIG_FLAG_VALID, true);
      config_save();
    }
  } else {
    config_set_last_error(BLYNK_PROV_ERR_CLOUD);
    BlynkState::set(MODE_ERROR);
  }
}

void enterSwitchToSTA() {
  BlynkState::set(MODE_SWITCH_TO_STA);

  DEBUG_PRINT("Switching to STA...");

  delay(1000);
  WiFi.mode(WIFI_OFF);
  delay(100);
  WiFi.mode(WIFI_STA);

  BlynkState::set(MODE_CONNECTING_NET);
}

void enterError() {
  BlynkState::set(MODE_ERROR);
  
  unsigned long timeoutMs = millis() + 10000;
  while (timeoutMs > millis() || g_buttonPressed)
  {
    delay(10);
    app_loop();
    if (!BlynkState::is(MODE_ERROR)) {
      return;
    }
  }
  DEBUG_PRINT("Restarting after error.");
  delay(10);

  restartMCU();
}

Thanks for any kind of help in advance.

It’s the call to the restartMCU(); function here that causes the restart if the void enterConnectCloud() function in unsuccessful.

But, I’d take a step back first…

Do you actually need the Edgent dynamic provisioning functionality? if not then starting with a non-Edgent sketch would be a better plan.

If you are going to use Edgent then I’d avoid the scattergun approach of dumping code segments into the existing .h files. The more sensible approach would be to either out all of your personal code in the .ino file, or to add one or more .h files that contain your personal code and add #include commands to the .ino file so that the code can find them.

Also, the old “Keep your void loop clean” mantra applies to Blynk IoT just as much as Blynk Legacy. To make matters worse, you’ve added calls to your clunky swfeedback() function in both the void loop and the app_loop

Personally, I’d use interrupts to monitor the number of switches that you are using.

https://docs.blynk.io/en/legacy-platform/legacy-articles/keep-your-void-loop-clean

Pete.

1 Like

Thanks for your reply.

Regarding you first question whether I need dynamic provisioning or not. Yes I need it. As I have plans to give my project to friends or relatives. And the dynamic provisioning is the only reason I am using Blynk IOT.

And I also get your point of not dumping the code in existing .h file. Hence, I would create a new .h file and include it. But that would not solve the problem of restarting the esp32.

So, how can it be solved?

I’ve explained why it’s happening - it’s done by design.
If you want to change that then you could remove the all to restartMCU() but you’ll need to live with any side-effects that this causes.

Pete.

So then would it connect back to the hotspot automatically once the connection is back again?

Why not make the changes and test it?
If you modify the code to work in a different way to how it’s designed then you’ll need to do your own testing and troubleshooting.

Pete.

Okay… Thanks a lot for your quick reply. And one more thing that will be very helpful if you let me know which function call is responsible for connecting the esp32 to wifi.

Pete.

Everything is working fine with my project but sometimes on frequently switching. The esp32 seems to be not working. Power is on. But turning the switch on or off. Dosen’t switch the relays. But after restarting the esp32 using EN button or disconnecting the power, things become normal again.

Is there any idea what may be the possible cause for it.

Thanks for any kind of help in advance.

Code?
Wiring schematic?
Blynk Library version?
Blynk IoT or Legacy?
Serial monitor output when the issue occurs?

Pete.

I will take my crystal ball :rofl:

1 Like

You can find the code here:

Circuit Diagram:

Wiring Schematic:

I am using BLYNK IOT

There is no especial output in serial monitor during the issue.

I’ve merged your two topics, instead of requiring us to constantly move backwards and forwards between topics to obtain the required information.

Pete.

Your problem is almost certainly happening because you are calling your swfeedback function from your void loop instead of using a timer or using interrupts for monitoring your physical switches.

Pete.

Is it a secret sketch? :rofl:

it’s now in the first post of this topic.

Pete.

1 Like

If I were you, I’ll use interrupts as Pete said.

1 Like

Okay.

Can I use BlynkTimer for this?

What should be the appropriate time interval to call this function?

Interrupts with denounce routines would be the best approach, but if you want to use a timer then you need to work out how long your function takes to execute and call the function using a timer that gives more than enough time between cycles.
Also, you should ensure that under no situation do you do more than 10 Blynk.virtualWrites per second.

You also need to strip your code out of the Edgent .h files as I said before.

Pete.

1 Like

Okay

I got that… I will also trip out that part of code.

What would happen on doing more than 10 Blynk.virtualWrites per second?