ESP8266 hangs in Cayenne.loop when WiFi Connection is lost

I have set up an ESP8266 to control a heater for some plants in my garden. The logic is, that the heater should switch on, once the temperature drops below 0°C and switches off again, once the temperature goes above 5°C. As the ESP8266 is physically located in the garden, the WiFi connection is not totally reliable, sometimes it fails for some time. That’s why I kept the control logic for switching on and off in the microcontroller code instead of using an event trigger by Cayenne. Cayenne is used to display temperature and status information and to control some other, less critical things (addtitional sensors and switches to turn garden lights on/off). The problem that I have is, that once the WiFi connection gets lost, it seems that the ESP8266 hangs in the “Cayenne.loop()” function and effectively does nothing else anymore. This means, that the heating function will not work during off-line. Is there a way around this?

Would using interrrupts be a good idea or does anybody have another suggestion? Here is my code (only an extract with the relevant parts):

#include <OneWire.h>
#include <DallasTemperature.h>
// WiFi network info.
char ssid = “…”;
char wifiPassword = “…”;
// Cayenne authentication info.
char username = “uuuuuuuuuuuu”;
char password = “ppppppppp”;
char clientID = “ccccccccc”;
float p; // temperature
byte h=1 ; // heater
OneWire ds_2(5); // Temperature sensor
DallasTemperature sensor_Palme(&ds_2);

void setup() {
Serial.begin(9600);
Cayenne.begin(username, password, clientID, ssid, wifiPassword);
sensor_Palme.begin();
pinMode(D5, OUTPUT); // heater relay
digitalWrite(D5, HIGH); // relay off
}

void loop() {
Cayenne.loop(); // System hangs here when WiFi connection is lost!
sensor_Palme.requestTemperatures();
p=sensor_Palme.getTempCByIndex(0);
Cayenne.virtualWrite(8, p); //Display Temperature
if (p<0) {h=0;} // heater on
if (p>5) {h=1;} // heater off
digitalWrite (D5, h);
Cayenne.virtualWrite(10, h); // Display heater status
}

@mike2506red have a look at this Arduino Online/Offline Override

Does not work for me. Here is the trial code I put in:

//#define CAYENNE_DEBUG
#define CAYENNE_PRINT Serial

#include <CayenneMQTTESP8266.h>
#include <RCSwitch.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// WiFi network info.
char ssid = “sssss”;
char wifiPassword = “ppp”;

// Cayenne authentication info.
char username = “uuuu”;
char password = “6pppp”;
char clientID = “cccc”;
float p=5; // temperatur palme
long lastMillis = 0;
boolean onlineStatus=false;
OneWire ds_2(5); // GPIO5: Sensor Palme
DallasTemperature sensor_Palme(&ds_2);

void setup() {
Serial.begin(9600);
Serial.println(“starting”);
Cayenne.begin(username, password, clientID, ssid, wifiPassword);
sensor_Palme.begin();
}

CAYENNE_CONNECTED(){onlineStatus=true;}
CAYENNE_DISCONNECTED(){onlineStatus=false;}

void loop() {
if (onlineStatus==true)
{Cayenne.loop();
Serial.print(“Online”);}
else{ Serial.println(“Offline”); }

}

When I run this, the system permanently prints “Online”, even when the connection gets lost. Means “onlineStatus” is never set to false. In the post, something is mentioned about “editing a Keyword file”. I have no clue what that means. Do you have concrete information, what file to edit and what needs to be changed in that file? Maybe that is the problem, because the Arduino IDE highlights the “CAYENNE_CONNECTED” text, while it does not hightlight the “CAYENNE_DISCONNECTED” text, which seems strange to me. A short explanation of these “CAYENNE_CONNECTED” and “CAYENNE_DISCONNECTED” would also help. Where and when is the code executed, that would set the onlineStatus to true or false?

search for a file “BlynkProtocol.h” in arduino folder. open and remove the comments on ALL the lines like this: //BlynkOnDisconnected(); There are 5 or six or so from memory and save it.

I did edit the “BlynkProtocl.h” and removed the comment slashes in the 6 lines where BlynkOnDisconnected() was found. No change. Continues to give me “online” message, once the WiFi is off, I get no status “offline”. Here is the output I see, when I switch off WiFi:

[20918] Connected to WiFi
[20918] IP: 192.168.178.52
[20918] Connecting to mqtt.mydevices.com:1883
[21199] Connected
Online
Online
Online
Online
Online
Online
Online
Online
[43109] Disconnected
[43109] Connecting to mqtt.mydevices.com:1883
[49933] Network connect failed
[57957] Network connect failed

So no recognition of the “offline” status.

1 Like

i am not sure where you are going wrong. @rsiegel can you help here with this.

I think I got it. There is a much simpler solution. All I need is this:

if (WiFi.status() == WL_CONNECTED) { Cayenne.loop(); }

This works for me now!

No - I need to take that back. It does not work reliably. Sometimes it works, sometimes it does not. I guess it only works, if the WiFi is lost, while the ESP8266 executes outside of the Cayenne.loop. If WiFi is lost, while ESP8266 executes already inside the Cayenne.loop it still hangs. Also using ticker and interrupt does not work, because after executing the ISR routine, the control is simply returned to the Cayenne.loop, and the system continues to hang…Any other ideas?

My suggestion would be to start a millis timer and reset the timer every loop. if it hangs for more than x seconds call a reset for the board.

Tried this already. Does not work either, as the “Cayenne.begin” routine, which is executed during setup is also written in a way, that it hangs up indefinitely, if no WiFi is present. Besides that, I found that the ESP8266 does not reset reliably neither with ESP.restart() nor with ESP.reset() - there are several discussions of this problem in various forums.

I examined the Cayenne libraries. In the CayenneArduinoMQTTClient.h, there is a function “connect()”, which contains a do/while loop, that looks like the one causing the problem:

do {/ attempt to connect; delay(1000); /}
while (error != MQTT_SUCCESS);

it looks to me, that if I could replace this with an equivalent for-loop, which counts up to 10 executions, this could work as some timeout, if after 10 seconds there is still no connection possible. I just have not figured out, how to jump out of the Cayenne.loop function in that case. Would be grateful, if anybody has an idea here - unfortunately I am not very skilled in programming…

I will take a look at it and see what I can come up with. I modified the blynk connection method to do that over here so it should be possible.

Yes, I have seen a few people posting about this. Might be better to just put the ESP is deep sleep mode (also in the link above)

This must be an MQTT issues since I don’t remember seeing that behavior in the blynk connection method. Again, I’ll take a look and see if I can get it working.

I really need to update the battery powered ESP project page so maybe I’ll take some time to update it to the officially supported MQTT connection method while I’m testing these things.

Any progress, I’m working a esp8266 project and worried about the same issue …

Hello community. Im from Russia. At first sorry for my english.
Now i working at my project - smart fan with remote control on esp8266 node mcu 12e. Fan relay controls at main (loop) of sketch.
I planned to use cayenne for remote monitoring.

But faced with problem:

When internet - is ok, everything is ok. But when internet connection is lost, all sketch is freezing.

After many trying i understand that freezed cayenne.loop.

I try to use enable flag ( ping 8.8.8.8) - is a little better. But sometimes freze still.

Is anybody knows how solve this problem?
Is anybody knows alternative method to sent information to cayenne server.
Because problem with looping in checking internet connection in cayenne loop.

Internet is the most important when doing IOT project. So when the internet is lost, you cannot remote monitor your project.

I have solved this with an Interrupt Service Routine (ISR), which is executed every 2 seconds. If the system is hung up in the Cayenne loop, a watchdog counter is incremented each time the ISR is called. After the counter reaches 4 (means the system hangs in the Cayenne loop for 8 seconds), key variables are written to the EEPROM and the ESP8266 executes a reset by software. If the internet still is not available after restart, at least the setup code gets executed, before the system again hangs in the “cayenne.begin” loop and 8 seconds later another reset occurs. This game is continued until the internet comes back and normal execution resumes. The problem with the hung up Cayenne loop is, that it never recovers, even when the internet connection comes back. This ISR solution solves that problem. Credit for that solution goes to Andreas Spiess (#33 Internet of Things with ESP8266 #5: Watchdogs, Timers & Stability - YouTube) Here are the relevant code pieces:

#include <CayenneMQTTESP8266.h>
#include <EEPROM.h>
#include <Ticker.h>  // Watchdog timer

// other definitions
volatile int watchdogCount = 0; 
Ticker secondTick;

void setup() {
  EEPROM.begin(16); // Reserviere 16 bytes EEPROM
  EEPROM.get(0,var1);
  EEPROM.get(4,var2);
  // further setup code
  secondTick.attach(2, ISRwatchdog); // Call Watchdog ISR every 2 seconds
  Cayenne.begin(username, password, clientID, ssid, wifiPassword);
  }

void loop() {
  watchdogCount = 0;
	Cayenne.loop(); 
  // Program Loop code //
 }


void ISRwatchdog() {
  watchdogCount++;
  if ( watchdogCount >3 ) {
     EEPROM.put(0,var1);
     EEPROM.put(4,var2);
     EEPROM.end(); // commits write to EEPROM
     ESP.reset(); // resets ESP8266
  }
}
1 Like

Great work @mike2506red and the guy with swiss accent. though how can the project run locally?

Well, as you say, @shramik_salgaonkar, it makes no sense to run an IOT project without internet connection. However, often there are situations in which the WiFi connection fails for just a few minutes. And there the solution has 2 benefits:

  1. Even though the internet hangs, the ESP8266 can execute some critical code in the first part of the init-routine (before the cayenne.begin statement). In my case reading a temperature value and taking action to keep that temperature, even though there is no internet connection. Of course I cannot manipulate the temperature target through the Cayenne interface nor monitor the actual temperature, but at least the value is kept within the target range during the internet downtime.

  2. And this is the more important part: Usually the WiFi connection just fails for a few minutes - either there is a router problem or the signal becomes weak for some reason. However, once the internet connection is lost, the cayenne.loop will hang indefinitely - even after the WiFi connection recovers. The only way to get the program back running is to physically press the reset button on the ESP8266 - not a good solution. First, it can potentially take a long time, until the user notices the hangup, second some important variables might get lost and third the ESP8266 might not be easy to reach.

2 Likes

Thank you very much for you answer. But i dint understand. This method only for restarting. But how control ( read sensor and control relay) in period from 0-8 sec. it is not imposible ind this method?
I didnt understand…

Ok i have lost_internet_key_var , why i can not put cayenne.begin() in IF(lost_internet_key_var =1) statement?

And i worried about session writing Eeprom memory? After 2 seconds? Lifetime esp will be not more 1 year… am i right?

not possible in this method.

what do you mean by this?

yes, with 100,000 write cycles. it will eventually die.