Blynk is blocking if internet is down

Hello everyone,
i’m wonderig if there is a way to prevent Blynk Library from blocking the whole programm if the internet connection is down. Please mind, that this only appears if WiFi is up and running, but the default gateway has no connection to the internet (LAN is fine, WAN is down). I tried all suggestions in other topics (setting timeout, constantly checking if blynk is connected) but the programm keeps freezing.
Current setup: Sonoff Smart Socket S20 with custom firmware. The physical button toggles the output, as same as blynk does. If internet goes down, i’m unable to either switch on or off the output. Really frustrating if you can’t turn your light off without internet.
I hope somebody can reproduce the error and/or can provide a solution.
PS: I am local server 0.26.3.
Kind regards

Let’s see the Connection Management techniques you have tried.

Hello, this is the code i’m currently using. I tried to modify the timeout in Blynk.connect() to multiple values, but there was no success for me.
Edit: I think the guy in this thread is having the same problem: Code isn’t working without connected Blynk
Thanks in advance!

    #include <Arduino.h>
    #include <Blynk/BlynkApi.h>
    #include <Blynk/BlynkHandlers.h>
    #include <Blynk/BlynkParam.h>
    #include <Blynk/BlynkProtocol.h>
    #include <BlynkSimpleEsp8266.h>
    #include <c_types.h>
    #include <DallasTemperature.h>
    #include <Esp.h>
    #include <ESP8266WiFi.h>
    #include <include/wl_definitions.h>
    #include <OneWire.h>
    #include <WiFiManager.h>
    #include <cmath>
    #include "../SmartTempMeter/SimpleTimer-master/SimpleTimer.h"

    char auth[] = "[token]";
    char server[] = "[server]";
    int32 interval = 1000;
    int32 blynkInterval = 5000;
    boolean relayState;
    const int relay = 12;
    const int led = 13;
    const int button = 0;
    int buttonState = 1;         // current state of the button
    static long startPress = 0;

    OneWire oneWire(14);
    DallasTemperature sensors(&oneWire);
    double_t temperature;
    SimpleTimer tempTimer;
    SimpleTimer wifiTimer;
    SimpleTimer checkTimer;

    void blinkLed() {
    	digitalWrite(led, 0);
    	delay(20);
    	digitalWrite(led, 1);
    }

    void checkBlynk() {
    	if (WiFi.status() == WL_CONNECTED) {
    		if (!Blynk.connected()) {
    			//WiFi ok, trying to connect to blynk
    			Blynk.connect(3000);
    		}
    	}
    	if (WiFi.status() == 1) {
    //no WiFi connection
    	}
    }

    void handleTemperatures() {
    	if (Blynk.connected()) {
    		sensors.requestTemperatures();
    		temperature = sensors.getTempCByIndex(0);
    		int16_t validation = (int16_t) (temperature);
    		if (validation > -126) {
    			Blynk.virtualWrite(V20, temperature);
    		}
    		//Serial.println(digitalRead(0));
    		/*GPOC = 1 << 13; //set gpio13 off LED is now active
    		 delay(10);
    		 GPOS = 1 << 13; //set gpio13 on LED is now off*/
    		//Blynk.syncAll();
    	}
    }

    void sendWifi() {
    	if (Blynk.connected())
    		Blynk.virtualWrite(3, map(WiFi.RSSI(), -105, -40, 0, 100));
    }

    void setup() {
    	Blynk.config(auth, server);
    	delay(100);
    	if (WiFi.status() == WL_CONNECTED)
    		Blynk.connect(3000);

    	sensors.begin();
    	checkTimer.setInterval(blynkInterval, checkBlynk);
    	tempTimer.setInterval(interval, handleTemperatures);
    	wifiTimer.setInterval(interval, sendWifi);

    	//Blynk.begin(auth, ssid, pass, server);

    	pinMode(button, INPUT);
    	pinMode(relay, OUTPUT);
    	pinMode(led, OUTPUT);
    	digitalWrite(led, 1);
    	digitalWrite(relay, 0);
    }

    void toggleRelay() {
    	if (relayState == 0) {
    		digitalWrite(relay, 1);
    		relayState = digitalRead(relay);
    		if (Blynk.connected())
    			Blynk.virtualWrite(V4, map(relayState, 0, 1, 0, 255));
    	} else {
    		digitalWrite(relay, 0);
    		relayState = digitalRead(relay);
    		if (Blynk.connected())
    			Blynk.virtualWrite(V4, map(relayState, 0, 1, 0, 255));
    	}
    	blinkLed();
    }

    void toggleRelayOff() {
    	digitalWrite(relay, 0);
    	relayState = digitalRead(relay);
    	if (Blynk.connected())
    		Blynk.virtualWrite(V4, map(relayState, 0, 1, 0, 255));
    	blinkLed();
    }

    void toggleRelayOn() {
    	digitalWrite(relay, 1);
    	relayState = digitalRead(relay);
    	if (Blynk.connected())
    		Blynk.virtualWrite(V4, map(relayState, 0, 1, 0, 255));
    	blinkLed();
    }

    BLYNK_WRITE(V0) //Button Widget is writing to pin V0
    {
    	int pinData = param.asInt();
    	if (pinData == 1) {
    		toggleRelayOn();
    	}
    }
    BLYNK_WRITE(V1) //Button Widget is writing to pin V1
    {
    	int pinData = param.asInt();
    	if (pinData == 1) {
    		toggleRelayOff();
    	}
    }
    BLYNK_WRITE(V2) //Button Widget is writing to pin V2
    {
    	int pinData = param.asInt();
    	if (pinData == 1) {
    		toggleRelay();
    	}
    }

    void handleButton() {
    	int currentState = digitalRead(button);
    	if (currentState != buttonState) {
    		if (buttonState == LOW && currentState == HIGH) {
    			long duration = millis() - startPress;
    			if (duration < 1000) {
    				toggleRelay();
    			} else if (duration < 5000) {
    				ESP.reset();
    			} else if (duration < 10000) {
    				WiFiManager wifiManager;
    				wifiManager.setTimeout(300);
    				if (!wifiManager.startConfigPortal("OnDemandAP",
    						"esp-config")) {
    					for (int var = 0; var < 100; ++var) {
    						blinkLed();
    					}

    					delay(3000);
    				}
    			}
    		} else if (buttonState == HIGH && currentState == LOW) {
    			startPress = millis();
    		}
    		buttonState = currentState;
    	}
    }

    void loop() {
    	checkTimer.run();
    	if (Blynk.connected()) {
    		Blynk.run();
    		tempTimer.run();
    		wifiTimer.run();
    	}
    	handleButton();
    }

@7net this issue comes up fairly regularly and the solution has been provided several times.
All you need is millis(), while() and break. Look through the following sketch.

/* NoBlynkBlock.ino by Costas for https://community.blynk.cc/t/blynk-is-blocking-if-internet-is-down/16809
will recover from server or router going down   

*/

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char ssid[]   = "xxx";
char pass[]   = "xxx";
char auth[]   = "xxx";
char server[] = "blynk-cloud.com";

BlynkTimer timer;
unsigned int myServerTimeout  =  3500;  //  3.5s server connection timeout (SCT)
unsigned int myWiFiTimeout    =  3200;  //  3.2s WiFi connection timeout   (WCT)
unsigned int functionInterval =  7500;  //  7.5s function call frequency   (FCF)
unsigned int blynkInterval    = 25000;  // 25.0s check server frequency    (CSF)

void setup()
{
  Serial.begin(115200);
  Serial.println();
  if(WiFi.status() == 6){
    Serial.println("\tWiFi not connected yet.");
  }
  timer.setInterval(functionInterval, myfunction);// run some function at intervals per functionInterval
  timer.setInterval(blynkInterval, checkBlynk);   // check connection to server per blynkInterval
  unsigned long startWiFi = millis();
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    if(millis() > startWiFi + myWiFiTimeout){
      Serial.println("\tCheck the WiFi router. ");
      break;
    }       
  }
  Blynk.config(auth, server);
  checkBlynk();
}

void myfunction(){
  Serial.println("\tLook, no Blynk  block.");
  if(WiFi.status()== 3){
    Serial.println("\tWiFi still  connected.");
  }
  if(Blynk.connected()){
    Blynk.virtualWrite(V11, millis() / 1000);
  }
}

void checkBlynk() {
  if (WiFi.status() == WL_CONNECTED)  
  {
    unsigned long startConnecting = millis();    
    while(!Blynk.connected()){
      Blynk.connect();  
      if(millis() > startConnecting + myServerTimeout){
        Serial.print("Unable to connect to server. ");
        break;
      }
    }
  }
  if (WiFi.status() != 3) {
    Serial.print("\tNo WiFi. ");
  } 
  Serial.printf("\tChecking again in %is.\n", blynkInterval / 1000);
  Serial.println(); 
}

void loop()
{
  if (Blynk.connected()) {Blynk.run();}
  timer.run();
}
4 Likes

very useful sketch, thanks for sharing!

@wanek please note the code is not fully ESP32 compliant, read it will not work.
ESP32’s have different WiFi libraries so this is for the ever popular ESP8266.
There is another new thread with some of my old code being used for ESP32 but as far as I can tell it’s not fully functional.

1 Like

as to date i think 90% of members on this forum use esp82 based boards, it is still very useful :wink:

1 Like

i have some questions, just for clearing things up:

  1. at the beginning of setup:
    if (WiFi.status() == 6) Serial.println("\tWiFi not connected yet. ");
    but i think this condition is always true at the begining, so it could be just:
    Serial.println("\tWiFi not connected yet. "); ?

  2. you are using both
    WiFi.status() == 3 and WiFi.status() == WL_CONNECTED to check wifi connection (in different places in the sketch). these are the same actually, or there is some difference? also, i didn’t see WL_CONNECTED defined anywhere in your sketch, it is some define in the library? i.e. actually WL_CONNECTED == 3 ?

  3. in the checkBlynk() function, every Blynk.connect(); attempt takes only ~2 second. but in the docs it says the default timeout value is 30 seconds. why it is the difference?

[1350064] Connecting to blynk-cloud.com:8442
[1352071] Connecting to blynk-cloud.com:8442
[1354076] Connecting to blynk-cloud.com:8442
[1356082] Connecting to blynk-cloud.com:8442
  1. ESP’s remember WiFi credentials when powered off so the check is to see if it knows the details for our AP, maybe it does maybe it doesn’t. So no you can’t just print, “not connected” because it might be.

  2. AFAIK they are the same, just different syntax. And the == 3 syntax is part of what the ESP32 doesn’t use.

  3. Never been convinced that the docs / library are correct when it comes to the timeout. That’s one reason I use my own. In my old code it used Blynk.connect(x) but now I have dropped the x in place of the default, whatever that is.

HTH

I have an ESP32 if anything you want to test on it.

1 Like
  1. this means that they connect to the last used wifi anyway? so, there is not mandatory to call WiFi.begin(ssid, pass);?

  2. i found this in the esp library:

    WL_IDLE_STATUS      = 0,
    WL_NO_SSID_AVAIL    = 1,
    WL_SCAN_COMPLETED   = 2,
    WL_CONNECTED        = 3,
    WL_CONNECT_FAILED   = 4,
    WL_CONNECTION_LOST  = 5,
    WL_DISCONNECTED     = 6
  1. i see, but if one do not know how the default timeout works / or how long it is, maybe you set myServerTimeout to 3500, expecting that your code will hang max 3.5 seconds. but actually a single Blynk.connect(); will take 30 seconds, than your non-blynk code will hang for 30 seconds, instead of 3.5…

@vshymanskyy, can you please explain this behaviour of the Blynk.connect(); function? the 30 seconds in the docs is outdated, or why takes only ~2 second to execute?

Yes.

No it’s mandatory because you might have moved location or changed AP credentials etc.

Yes that’s the mapping of response codes.

Dunno, I just use my code and all is fine.

Thanks for the offer, I’ll remember that if I ever get round to looking at the '32.

Thanks, i’ll give it a try.
After some research, i think this my problem is another. In this sketch the connect timeout is 3 seconds. Checking if the button on my S20 is pressed, takes only a few milliseconds. Thus, it seems it feels like the board is “frozen”.
I think i am actually searching for a kind of multithreading or i’ll have to use interrupts. I tried this with mqtt, which worked fine, because pubsub library seems to be more lightweight (could depend on the mqtt protocol and the implemetation in detail).
Sorry for my late answer, i had a lot of stuff to do since then.
Anyway, thank you very much!

but why it takes so long to check a digital signal?
it should be much faster. try to use interrupts.