Run the main loop also if no wifi is availibe

maybe i just dont get something but:

setup: i have a working project i added IOT capabillety by switching nano to nano IOT ( and some parts 3v3 etc.
the project works fine until i get out of reach of the wifi . the project includes a Display so i can use it without IOT but it completly gets stuck if i "simulate" a not working connection by changing SSID or PASS
is there a exemple on how to use
ArduinoCloud.begin <- in void setup()
wiithout blocking void loop() completly? what does ArduinoCloud.begin return?

Show us the code you are using.

Probably, you have to have a time out in setup so if, after a certain time elapses when no connection has been established, a flag, say called offline, is set and the connection attempt is abandoned. In the loop(), you will somehow use this flag to prevent any periodic attempts to re-establish a connection.

void setup() {

  initProperties();
  ArduinoCloud.begin(conMan);
  setDebugMessageLevel(4);
  ArduinoCloud.printDebugInfo();
  //conMan is the connection manager called in thing prop
  conMan.addCallback(NetworkConnectionEvent::CONNECTED, onNetworkConnect);
  conMan.addCallback(NetworkConnectionEvent::DISCONNECTED, onNetworkDisconnect);
  conMan.addCallback(NetworkConnectionEvent::ERROR, onNetworkError);

//setup pinmode display etc know to work code cut out
}

void loop() {

  serialtoarray(); //gets my data loops always
  ButtonCheck();
  menuinteraktion();

 u8g2.firstPage();
  do {
    drawMenu();
   } while ( u8g2.nextPage() );
  

  conMan.check();
  ArduinoCloud.update();
  
  
}

this is the main.cpp setup
in the thingProperies.h only

#include <ArduinoIoTCloud.h>
#include <Arduino_ConnectionHandler.h>
//Thin ID and SSID etc 

void onInnOTChange();

String innOT;

void initProperties(){

  ArduinoCloud.setThingId(THING_ID);
  ArduinoCloud.addProperty(innOT, READWRITE, ON_CHANGE, onInnOTChange);

}

WiFiConnectionHandler conMan(SSID, PASS);


//what to do if connection is lst etc
void onNetworkConnect() {
  Serial.println(">>>> CONNECTED to network");
}

void onNetworkDisconnect() {
  Serial.println(">>>> DISCONNECTED from network");
}

void onNetworkError() {
  Serial.println(">>>> ERROR");
}
...

Do you suspect it is blocking here in the loop() if there is no connection ?

I don't know this particular platform, but I guess these callback routines are stubs:

void onNetworkError() {
  Serial.println(">>>> ERROR");
}

and would probably be a good place to set global variables which you can test in the loop() to see if it is safe to start attempting to make a connection to the "cloud".

it does not reach the cloud.update function if the network does not get connected it never goes into main loop.

and would probably be a good place to set global variables which you can test in the loop() to see if it is safe to start attempting to make a connection to the "cloud".

yes exactly i dont need network but i need the code to run always
but i can not use Iot connection handler and stuff, if i dont set them up in void Setup()
with ArduinoCloud.begin();
Or so i think, does someone know a good source for dokumentation? the arduinoIOT stuff seem to be not that much documented (not that good as i am used to for Arduino)

The documentation is here: ArduinoIoTCloud/src at master · arduino-libraries/ArduinoIoTCloud · GitHub
and here: Arduino_ConnectionHandler/Arduino_ConnectionHandler.h at master · arduino-libraries/Arduino_ConnectionHandler · GitHub

You can check the status of the connection with conman.check() as you have done so in the loop, but testing the return code. Maybe you can do it early in setup() and, if it shows a failure, don't use any of the commands which depend on a connection. It returns a value indicating the status of the connection:

enum class NetworkConnectionState : unsigned int {
  INIT          = 0,
  CONNECTING    = 1,
  CONNECTED     = 2,
  DISCONNECTING = 3,
  DISCONNECTED  = 4,
  CLOSED        = 5,
  ERROR         = 6
};

so you could possibly do a test like:

if (  conMan.check() != NetworkConnectionState::CONNECTED  ) {
    // we are not connected
}

Hopefully, someone with practical experience with this platform can say some more.

addet the code, and changed :

if (  conMan.check() == NetworkConnectionState::INIT ) { Serial.println("INIT");}
if (  conMan.check() == NetworkConnectionState::CONNECTING ) { Serial.println("CONNECTING");}
if (  conMan.check() == NetworkConnectionState::CONNECTED ) { Serial.println("CONNECTED");}

also some serial prints at the start and end of loop it gets clearer, the loop is actualy running!
just for every conMan.check() the loop gets delayed for a few seconds and that every loop so it behaves stuck (and all my deboundcing serial and display stuff is not working but it actually loops

would a proper workaround be:

 -- void setup()
##setup internet and stuff
-- void loop()
##if conected reset timer
#else timer interrupt to 10min or so than recheck 
#run normal code every loop
-- void setup()
##setup internet and stuff
-- void loop()
##if conected reset timer
#else timer interrupt to 10min or so than recheck 
#run normal code every loop

Something like that could work to limit the blocking activity if the loop does get entered but conman.check() blocks too long when it runs and also runs too often.
If you discover early on (by some method) that there is no connection, you could also completely disable the call to conman.check() in the loop. That would mean, however, that if there was no connection at the start, it would not attempt to automatically restore the connection within that session even if one became available.

There may also be methods for setting timeouts so, for example, conman.check() did not block for so long.

right. for the moment i have to dig myself throu the timer interrupt theme...
and i could also live with the interruption every 10minutes, ( so only checking if it is connected ans storing that in a vairable. ) also: i figured if it does connect conman.check runs in less then 5ms it only delays in case of no connection

also without interrupts you could ensure the check code ran only every 10 minutes :

void loop() {
  //
  // . . . 
  
  static uint32_t lastCheckAtMs = 0 ;
  const uint32_t cmTimeoutMs = 600000UL ; // 10 minutes

  if ( millis() - lastCheckAtMs > cmTimeoutMs ) {
    conMan.check();
    ArduinoCloud.update();
    lastCheckAtMs = millis() ;
  }
  
  // . . . 
  //

}
1 Like

jep also works. but 6weeks later it rolles over xD okay jea that should not be a problem...

Thanks a lot!!

This construct does survive the millis() rollover...

if ( millis() - lastCheckAtMs > cmTimeoutMs ) { . . .

This does not although it looks OK at first glance and works most of the time . . .

if ( lastCheckAtMs + cmTimeoutMs < millis() ) { . . .

But, anyway, for most practical purposes both are OK.