Dealing with internet outages

So I’m working on integrating Blynk for monitoring a high-reliability system (aeroponics) and I’m trying to figure out how to keep the timer running and keep the control loop working during internet outages.

All the sensor data is local and Blynk is just being used for remote monitoring and variable adjustment. With legacy Blynk the whole system would stall until reconnection, posing a hazard to the plants in the system.

Is there a connection management routine in new Blynk for dropped connections or should I implement the system controller on another microcontroller and link the two with hardware serial?

Hey there, you can specify some offline routines in your sketch that will keep working even if the internet connection drops.

Blink Legacy and Blynk IoT are both capable of working well in offline e mode, if you write your code well.
The primary starting point is to use Blynk.config and Blynk.connect rather than Blynk.begin. This is because Blynk.begin is a blocking function, and code execution will cease if a connection to WiFi or the Blynk server can’t be established.

It’s something that’s been discussed many times on this forum, you just need to do a quick search.

Pete.

Ah, I’d seen something to that effect but couldn’t get it working and wondered if anything had changed with the new version. Documentation between versions is confusing me a lot, but I’ll keep trying. I’m guessing Blynk timers are entirely OTA and I’ll need to use hardware timers to achieve an offline mode?

No you don’t need any hardware timers to achieve the offline mode

Oh, perfect!

I’m meeting the same problem as I had on old Blynk, though. I have the routine configured like such, but when I intentionally put a wrong ssid in, the Blynk.connectWiFi() command will block the loop forever trying to connect…

void setup() {
    //stuff
    Blynk.config(auth);
    Blynk.disconnect();
}
void loop() {
    if(!Blynk.connected()) {Blynk.connectWiFi(ssid, pass);}
    Blynk.run();
    Serial.println("still running");
}

Why are you doing this?

I wouldn’t use this method, I’d use a standard WiFi connect routine instead.

Don’t put stuff like this in your void loop.

Pete.

I had just seen the Blynk.disconnect() in setup done elsewhere.

Standard WiFi connection routine like this? I had assumed it needed to be done through the Blynk object.

   WiFi.begin(ssid, password);

The “still running” bit was just to see if the loop got stuck haha. Thanks for the quick responses though!

Try this :

/*************************************************************
  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

/* Fill-in your Template ID (only if using Blynk.Cloud) */
#define BLYNK_TEMPLATE_ID   "YourTemplateID"


#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();
  }
}

Happy to say it’s working but I’m getting a new error:

[105215] Connecting to blynk.cloud:80
[E][WiFiGeneric.cpp:739] hostByName(): DNS Failed for blynk.cloud

Have we moved to a different domain? I’m using the standard

  Blynk.config(auth);

Blynk.connect() would make much more sense.

No, not on its own. You need to do a loop (but not a while loop) that tries to connect maybe 20 times then sets a flag for online/offline mode depending on the outcome.

As I said, there are plenty of examples.

Pete.

Working! Thanks for all the help. Code here for others:

char ssid[] = "myssid";
char pass[] = "mypass";
int connectionDelay = 1000*60; //1 Minute between reconnect attempts
int lastConnectionAttempt = millis();
bool online = false;

void setup()
{
  Blynk.config(auth);
  WiFi.begin(ssid, pass);
  int timeout = millis();
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    if (millis() - timeout >= 10000) {break;} //10 second timeout
  }
  Blynk.connect(10000); //10 second timeout
}

void loop()
{
  if (WiFi.status() != WL_CONNECTED && millis() - lastConnectionAttempt >= connectionDelay) {
    WiFi.begin(ssid, pass);
    int timeout = millis();
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
      if (millis() - timeout >= 10000) {break;} //10 second timeout
    }
    Blynk.connect(10000); //10 second timeout
    if (WiFi.status() == WL_CONNECTED) {online = true;}
    else {online = false;}
    lastConnectionAttempt = millis();
  }
  Blynk.run();
}

That’s not a very neat or efficient way to do it, and the logic is flawed because you are assuming that a WiFi connection automatically equals a Blynk server connection.

You should be using timers and two flags to test your online status - set when WL_CONNECTED and Blynk.connected are true.

Pete.

Right, I see. Tough love though :’( How’s this look?

void testConnection() {
  if (WiFi.status() != WL_CONNECTED || !Blynk.connected()) {
    online = false;
    if (millis() - lastConnectionAttempt >= connectionDelay) {
      WiFi.begin(ssid, pass);
      int timeout = millis();
      while (WiFi.status() != WL_CONNECTED && (millis() - timeout < 10000)) {
        delay(500);
        Serial.print(".");
      }
      Blynk.connect(10000); //10 second timeout
      if(Blynk.connected()) {online = true;}
    }
  }
}

void setup() {
  Blynk.config(auth);
  testConnection();
}

void loop() {
  testConnection();
  Blynk.run();
}

I don’t believe in explaining how to re-invent the wheel when this topic has been discussed in great detail numerous times before, and I’m not going to spend time doing your searches for you!

From a logic perspective it’s better, but I’d do it with a timer rather than a millis comparison, and as I said earlier it’s better to use a for loop rather than a while loop.

Pete.