blynkkk / blynk-library

Blynk library for IoT boards. Works with Arduino, ESP32, ESP8266, Raspberry Pi, Particle, ARM Mbed, etc.
https://blynk.io
MIT License
3.81k stars 1.38k forks source link

BlynkFatal() ends up in for (;;) {} locking up device and causing wdt #559

Closed I-Connect closed 10 months ago

I-Connect commented 2 years ago

Hi,

We are running Blynk on an ESP32 connecting via a GSM module.

I am working on reconnecting GPRS in case of errors like a failure on the provider side. Basically I continuously run a check on the gprs connection in the same task that handles Blynk.run():

void blynkControllTask(void* pvParameters) {
  BlynkNodeSim7000* BlynkNodeSim7000Obj = reinterpret_cast<BlynkNodeSim7000*>(pvParameters);
  BlynkNodeSim7000::BlynkMsg msg;

  BlynkNodeSim7000Obj->connectGprs();
  BlynkNodeSim7000Obj->update();

  if (Blynk.connected() && xQueueReceive(BlynkNodeSim7000Obj->blynkQueue, &msg, ( TickType_t ) 0 ) ) {
    BlynkNodeSim7000Obj->virtualWrite(msg.vPin, msg.value);
  }
  delay(10);
}

bool BlynkNodeSim7000::connectGprs() {
  bool result = 0;
  if (!gsmGps->isGprsConnected()) {
    if (restartModem()) {
      if (takeGsmSerialSemaphore("connect GPRS")) {
        if (Blynk.connectNetwork(gprsApn, gprsUser, gprsPw)) {
          modemRestartCounter++;
          queueVpinIntMsg(253, modemRestartCounter);
          result = 1;
        } else {
          log_e("GPRS connect failed");
        }
        giveGsmSerialSemaphore();
      }
    }
  }
  return result;
}

bool BlynkNodeSim7000::restartModem() {
  bool result = 0;
  if (takeGsmSerialSemaphore("restart modem")) {
    if (gsmGps->testAT()) {
      result = gsmGps->restart();
    } else {
      log_e("communication with modem failed");
    }
    giveGsmSerialSemaphore();
  }

  if (!result) {
    log_w("Failed to restart modem");
  }
  return result;
}

bool BlynkNodeSim7000::update() {
  bool result = false;
  if (takeGsmSerialSemaphore("blynk update")) {
    result = Blynk.run();
    giveGsmSerialSemaphore();
  }
  return result;
}

Problem is that when Blynk.connectNetwork() fails on for instance line 79 in BlynkGsmClient.h: BLYNK_FATAL(BLYNK_F("Register in network failed"));

it results in:

void BlynkReset()
{
  for (;;) {}
}
#endif

Which crashes the MCU for me on a wdt.

How can we circumvent this or could you build an option to overrule _BLYNK_USE_DEFAULT_RESET. As the define is in the same cpp as it is being used in I am unable to change (undef) this without editing the Blynk library

thx!

I-Connect commented 1 year ago

bump

I forgot all about this and again spent 3 hours due to this endless loop causing a wdt reset somewhere.

Can you please at least put a log in the BlynkReset() method showing an endless loop is entered halting any tasks executing it.

thx

I-Connect commented 1 year ago

furthermore, these methods are defined as "noreturn" inBlynkDebug.h halting the code still even if you remove the endless loop

void BlynkReset() BLYNK_NORETURN;
void BlynkFatal() BLYNK_NORETURN;
vshymanskyy commented 10 months ago

BlynkFatal() was designed to fail this way.

You can use a generic Arduino Client example, and implement your own network maintenance routine: https://github.com/blynkkk/blynk-library/blob/master/examples/Boards_ArduinoClient/ESP8266_ESP32/ESP8266_ESP32.ino