BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

ESP8266: How to properly connect and maintain connection to Blynk local server?


#1

I’m trying to find a way to connect to and maintain connection from an ESP8266 to a Blynk local server. Currently my device is connecting to the Blynk server fine, if it’s been without power a while. But in development, I’m having problems with connecting when making alterations to the code and reflashing the device. It seems to be related with the device still being present in the ASUS wifi router device list in some way. The result is that the ESP8266 gets stuck on “Connecting to [SSID]…”.

So I wondered if there is a recommended way to:

  1. Attempt to connect to wifi at startup.
  2. If wifi connection attempt fails, retry to connect to wifi.
  3. If wifi connection is successful, connect to local Blynk server.
  4. If Blynk local server connection attempt fails, retry to connect to Blynk server.
  5. If Blynk local server connection is successful, start doing normal stuff (read sensors and push to Blynk local server, etc.).
  6. While doing normal stuff, check that both wifi connection and Blynk server connection is OK. If one of them fails, attempt to reconnect.

It dawns on me when writing this that a connection handler with a state machine might not be a bad idea. Has this already been done perhaps?


#2

some code pieces that might be useful:


void reconnectBlynk() {
  if (!Blynk.connected()) {

    Serial.println("Lost connection");
    if(Blynk.connect()) {
      Serial.println("Reconnected");
    }
    else {
      Serial.println("Not reconnected");
    }
  }
}

void loop() {
  timer.run(); 
  if(Blynk.connected()) { Blynk.run(); }
  ArduinoOTA.handle();                            // direct over the air update
}

and in void setup():

timer.setInterval(30*1000, reconnectBlynk); //run every 30s

#3

Looking into examples/More/HandleDisconnect/ could also help:


/*************************************************************
  Download latest Blynk library here:
    https://github.com/blynkkk/blynk-library/releases/latest
  Blynk is a platform with iOS and Android apps to control
  Arduino, Raspberry Pi and the likes over the Internet.
  You can easily build graphic interfaces for all your
  projects by simply dragging and dropping widgets.
    Downloads, docs, tutorials: http://www.blynk.cc
    Sketch generator:           http://examples.blynk.cc
    Blynk community:            http://community.blynk.cc
    Follow us:                  http://www.fb.com/blynkapp
                                http://twitter.com/blynk_app
  Blynk library is licensed under MIT license
  This example code is in public domain.
 *************************************************************
  This example shows how to keep WiFi connection on ESP8266.
 *************************************************************/

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial


#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "YourAuthToken";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "YourNetworkName";
char pass[] = "YourPassword";


int lastConnectionAttempt = millis();
int connectionDelay = 5000; // try to reconnect every 5 seconds

void setup()
{
  // Debug console
  Serial.begin(9600);

  Blynk.begin(auth, ssid, pass);
}

void loop()
{
  // check WiFi connection:
  if (WiFi.status() != WL_CONNECTED)
  {
    // (optional) "offline" part of code

    // check delay:
    if (millis() - lastConnectionAttempt >= connectionDelay)
    {
      lastConnectionAttempt = millis();

      // attempt to connect to Wifi network:
      if (pass && strlen(pass))
      {
        WiFi.begin((char*)ssid, (char*)pass);
      }
      else
      {
        WiFi.begin((char*)ssid);
      }
    }
  }
  else
  {
    Blynk.run();
  }
}

#4

Thanks a bunch for the tips. I have already searched this a while, and I struggled with finding a solid and updated way of doing this. Some of the threads I found had tips on how to handle reconnection, only to state later on that changes in either Blynk or ESP8266 code caused it to not work anymore.

So I ended with writing my own connection handler. I’ve tested it for a while now, and it seems to handle both wifi and Blynk server crashes well. I haven’t had any “stuck” situations so far, at least. If you see any issues with this, please let me know.

#define BLYNK_PRINT Serial // Defines the object that is used for printing
//#define BLYNK_DEBUG        // Optional, this enables more detailed prints

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>

SimpleTimer connectionHandlerTimer;

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "auth";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "ssid";
char pass[] = "pass";

typedef enum {
	CONNECT_TO_WIFI,
	AWAIT_WIFI_CONNECTION,
	CONNECT_TO_BLYNK,
	AWAIT_BLYNK_CONNECTION,
	MAINTAIN_CONNECTIONS,
	AWAIT_DISCONNECT
} CONNECTION_STATE;

CONNECTION_STATE connectionState;
uint8_t connectionCounter;

void ConnectionHandler(void) {
	switch (connectionState) {
	case CONNECT_TO_WIFI:
		BLYNK_LOG("Connecting to %s.", ssid);
		WiFi.begin(ssid, pass);
		connectionState = AWAIT_WIFI_CONNECTION;
		connectionCounter = 0;
		break;

	case AWAIT_WIFI_CONNECTION:
		if (WiFi.status() == WL_CONNECTED) {
			BLYNK_LOG("Connected to %s", ssid);
			connectionState = CONNECT_TO_BLYNK;
		}
		else if (++connectionCounter == 50) {
			BLYNK_LOG("Unable to connect to %s. Retry connection.", ssid);
			WiFi.disconnect();
			connectionState = AWAIT_DISCONNECT;
			connectionCounter = 0;
		}
		break;

	case CONNECT_TO_BLYNK:
		BLYNK_LOG("Attempt to connect to Blynk server.");
		Blynk.config(auth, IPAddress(192, 168, 2, 30), 8080);
		Blynk.connect();
		connectionState = AWAIT_BLYNK_CONNECTION;
		connectionCounter = 0;
		break;

	case AWAIT_BLYNK_CONNECTION:
		if (Blynk.connected()) {
			BLYNK_LOG("Connected to Blynk server.");
			connectionState = MAINTAIN_CONNECTIONS;
		}
		else if (++connectionCounter == 50) {
			BLYNK_LOG("Unable to connect to Blynk server. Retry connection.");
			Blynk.disconnect();
			WiFi.disconnect();
			connectionState = AWAIT_DISCONNECT;
			connectionCounter = 0;
		}
		break;

	case MAINTAIN_CONNECTIONS:
		if (WiFi.status() != WL_CONNECTED) {
			BLYNK_LOG("Wifi connection lost. Reconnect.");
			Blynk.disconnect();
			WiFi.disconnect();
			connectionState = AWAIT_DISCONNECT;
			connectionCounter = 0;
		}
		else  if (!Blynk.connected()) {
			BLYNK_LOG("Blynk server connection lost. Reconnect.");
			Blynk.disconnect();
			connectionState = CONNECT_TO_BLYNK;
		}
		else {
			Blynk.run();
		}
		break;

	case AWAIT_DISCONNECT:
		if (++connectionCounter == 10) {
			connectionState = CONNECT_TO_WIFI;
		}
		break;
	}
}

void setup()
{
	Serial.begin(9600);
		
	connectionHandlerTimer.setInterval(100, ConnectionHandler);
	connectionState = CONNECT_TO_WIFI;
}

void loop()
{
	connectionHandlerTimer.run();

}

#5

Often the DHCP service on the router is the problem if you reconnect too often within a short time.
This can also happen with Ethernet connections - it’s not just ESP related.

What I preferably do:

  • use a static IP for the Arduino or ESP
  • use a random MAC address. I.e. after reflashing the router sees a “new” device

#6

that makes little sense to me, but most likely my limited knowledge:

  • I though MAC addresses were hard coded (as in cannot be changed)?
  • when using a static IP address you set this usually on the router, but with an ever changing MAC address that does not work! If it possible to set a static IP on the ESP side (no clue whether that is possible) then you run into the chance of IP address conflicts! (with other devices)

@ohjohnsen: thats a really neat routine, I might borrow that from you! The 0.1s timer though seems a bit much, I usually set it to 30s. Given the nature of your routine I understand that it should run more often but 10x per s…? Would 1s not be more than enough?


#7

I do either one of these things, of course. Depending on what the device allows.
MAC on ESPs is fixed (ESP8266 Arduino core does not provide an API to change ESP8266’s WiFi MAC address. However, Espressif SDK offers an API to change the WiFi STA MAC address.).
For e.g. the Ethernet shield chaning MAC from Arduino core is possible …

Static IP with varying MAS address does not make sense. That’s clear. :wink:


#8

@wolph42 Go right ahead… :slight_smile: I plan on making the whole project open source eventually, just need to figure out how to mask ssid and password out of the committed code. :slight_smile:

Not a bad idea increasing the interval to perhaps 500 ms. or 1 second. It would probably be a good idea then to move Blynk.run() to the loop() function, rather than having it in the connection handler.


#9

@IBK Thanks for the tip. I already use a static IP. Don’t think I’ll be messing with the MAC address, though. After implementing the connection handler, I see that it takes at most a few retries before it reconnects with the wifi router. Guess the router needs to recognize the MAC address as disconnected before it allows reconnection. In any event, it’s not a problem for me anymore, since the ESP doesn’t get stuck now like it did earlier.


#10

I think I forwarded you my link of a simple example, that I belive does all this, already in another topic… but here it is again…


#11

Although the code is quite elegant, this looks like a very cumbersome way of handling the process. Look at all the code that has to be evaluated on each cycle of the void loop before the default condition (device connected, Blynk.run executed) is met.
This is going to significantly increase the liklehood of Blynk timeouts and therefore disconnections.

I don’t use Blynk in the same way as most people, but I always specify a static IP address for each individual device. I find that this makes it much easier to manage my devices and avoid having to mess around with router settings all the time.
You may also want to look at how the DHCP lease duration is configured in your router and see if reducing the lease time helps your situation.

Pete.


#12

nearly nothing! To be exact (under ‘normal’ circumstances):
1 switch eval
1 if eval
1 if else eval
1 else eval
break;

have you ever looked at the timer loop?


#13

@PeteKnight I agree when Blynk.run() resides in the else{} in the MAINTAIN_CONNECTIONS state. But I believe a better approach would be to check in loop() that state == MAINTAIN_CONNECTIONS, and then run Blynk.run(). In that case, you have only one interval delay between Blynk.connect() and Blynk.run() (given that the node connects to the Blynk server immediately).

The point was still to be able to solidly handle connection loss on both the Blynk server and the wifi connections, and then reconnect. Earlier I was plagued with the ESP locking up when connecting to wifi, and I’m not any more. That’s good enough for me. :slight_smile:


#14

@Gunner Thanks. But how will that method stand against connection loss on wifi? WiFi.begin() is run only once in the setup() function. Will Blynk.connect() handle wifi reconnection?


#15

@ohjohnsen Hi, the code suggested by @IBK works just fine. Tryed on an ESP32 connected to my iPhone’s Hotspot for easy router connect/disconnect.

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

#if defined(ESP8266)
#include <ESP8266WiFi.h>         //https://github.com/esp8266/Arduino
#include <BlynkSimpleEsp8266.h>
#else
#include <WiFi.h>                //https://github.com/esp8266/Arduino
#include <BlynkSimpleEsp32.h>
#endif

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "****";

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "iPhone";
char pass[] = "****";

int lastConnectionAttempt = millis();
int connectionDelay = 5000; // try to reconnect every 5 seconds

void setup()
{
  // Debug console
  Serial.begin(115200);

  Blynk.begin(auth, ssid, pass);
}

void loop()
{
  // check WiFi connection:
  if (WiFi.status() != WL_CONNECTED)
  {

    // check delay:
    if (millis() - lastConnectionAttempt >= connectionDelay)
    {
      lastConnectionAttempt = millis();

      // attempt to connect to Wifi network:
      if (pass && strlen(pass))
      {
        Serial.println("Lost connections. Trying to reconnect...");
        WiFi.begin((char*)ssid, (char*)pass);
      }
      else
      {
        Serial.println("Lost connections. Trying to reconnect...");
        WiFi.begin((char*)ssid);
      }
    }
  }
  else
  {
    Blynk.run();
  }
}

Results:

[20] Connecting to iPhone
[3555] Connected to WiFi
[3555] IP: 172.20.10.6
[3555] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.5.3 on ESP32

  Give Blynk a Github star! => https://github.com/blynkkk/blynk-library

[3567] Connecting to blynk-cloud.com:80
[3899] Ready (ping: 68ms).
Lost connections. Trying to reconnect...
Lost connections. Trying to reconnect...
Lost connections. Trying to reconnect...
[692733] Heartbeat timeout
[692733] Connecting to blynk-cloud.com:80
[692978] Ready (ping: 72ms).

#16

I don’t know exactly how, but all my devices reconnect anytime I have had to reboot my router.