Xenon attempting to connect to cloud/wifi when parameters are set for offline state

Hello all,

Currently I am having an issue of my Xenon attempting to connect to the cloud or some other network when the system is set to be in an offline state. Let me explain the setup and contingencies for this project. An Argon and Xenon have been setup on a network where there is access to the cloud and they function properly. Eventually, this system will be moved to a managed network where the Argon will not be able to access the cloud, but managed WiFi access is available. This WiFi will be used by the npt-time library in order to provide accurate time for the project. The issue that I am running into is when I configure the Argon to only use wifi and not connect to the cloud (SYSTEM_MODE(SEMI_AUTOMATIC), WiFi.on(), WiFi.connect(), Mesh.on()) along with the Xenon only using mesh (Mesh.on(), Mesh.connect()) the Xenon upon startup flashes green slowly then flashes green rapidly and remains that way, thus halting the entire program. I searched through documentation and I assume the rapid green flash means that it is attempting to connect to the wifi or other network, or finalizing the mesh connection. I’ve looked at a lot of articles in this board regarding Xenon in an offline state, but none of them seem to work. The code on the Argon works perfectly and delivers the intended result. I have included a simple code below that gives the same result.

Argon:

#include <ntp-time.h>

NtpTime* ntpTime;

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

void setup() {
  WiFi.on();
  WiFi.connect();
  Mesh.on();
  ntpTime = new NtpTime(60);
  ntpTime->start();
}

void loop() {
  //Time Variables
  struct epochMillis now;  //holds the unix epoch time to millisecond resolution
  ntpTime->nowMillis(&now);  //get the current NTP time
}

Xenon:

SYSTEM_MODE(SEMI_AUTOMATIC);

void setup() {
    Mesh.on();
    Mesh.connect();
}

void loop() {

}

Thank you for any help!

Try using SYSTEM_MODE(MANUAL) instead.

You may want to add a waitFor(WiFi.ready, 30000) before starting the NTP object (assuming you got a true return value of the call).

1 Like

And you may also want to use SYSTEM_THREAD(ENABLE).

Thank you for the prompt reply’s. I have stripped down the code to a bare minimum and the error is still occurring. Now, the status led on the Argon is breathing blue (mesh on) and when the Xenon comes online it starts at white, then blinks green, then fast blinks green forever. I have tried SYSTEM_MODE as manual and semi automatic, along with adding SYSTEM_THREAD(ENABLED). Below is the code I am using.

Argon

SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);

void setup() {
    Mesh.on();
}

void loop() {

}

Xenon

SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);

void setup() {
    Mesh.on();
    Mesh.connect();
}

void loop() {

}

I am unsure if this is a related issue or not, but I found a similar issue here: https://github.com/particle-iot/device-os/issues/1877 Whenever Mesh.connect() is invoked, the Xenon attempts to connect to the cloud (fast blinking green) even when the system mode is set to manual and system thread is enabled. Can anyone give the example above a try to see if this a hardware issue or a software issue? I am using the latest 1.4.2 firmware.

You’d also have to call Mesh.connect() on the Argon in order to actually create the network for the node to join.

However, I think the issue is actually the gateway not the Xenon.
When I flash this code to both devices

#if (Wiring_WiFi)
  SYSTEM_MODE(AUTOMATIC);    
#else
  SYSTEM_MODE(MANUAL);    
#endif
SYSTEM_THREAD(ENABLED);

const char *eventName = "test";

void setup() {
  Mesh.on();
  Mesh.connect();
  Mesh.subscribe(eventName, test);
  pinMode(D7, OUTPUT);
  digitalWrite(D7, HIGH);
  waitUntil(Mesh.ready);
}

void loop() {
  if (!digitalRead(BTN)) {
    Mesh.publish(eventName, System.deviceID());
    delay(500);
  }
}

void test(const char* name, const char* data) {
  if (!System.deviceID().equals(data)) {
    digitalWrite(D7, !digitalRead(D7));
#if (Wiring_WiFi)
    if (digitalRead(D7)) {
      Particle.connect();  // this alone seems not enough, although it shoule be!
      // *** this helps to reconnect but should NOT be required really ***
      //WiFi.on();
      //WiFi.connect();  
      //if (waitFor(WiFi.ready, 60000)) 
      //  Particle.connect();
      //else
      //  digitalWrite(D7, LOW);
      // *** this helps to reconnect but should NOT be required really ***
    }
    else {
      //Particle.disconnect();
      //WiFi.disconnect();
      WiFi.off();
    }
#endif
  }
}

the Argon will start breathing cyan and the Xenon will breathe green (expected behaviour).
Whenever pushing the MODE button on the Argon, the Xenon’s D7 LED will toggle, signalling a working mesh connection.
When pushing MODE on the Xenon the Argon will also be toggling the D7 LED but also toggle the cloud connection state causing the RGB LED of both devices to go into fast blinking green, where the Argon should actually go into breathing white (WiFi off) and the Xenon should be unaffected and carry on breathing green.
Also another MODE press on the Xenon should cause the Argon to reestablish the connection, but that doesn’t seem to work either - both device keep blinking green forever - the Argon doesn’t even try to connect to WiFi (depsite rapid blinking green).

At appears as if the gateway would be actively telling the nodes that it has lost connection and “instructing” them to alter their RGB signal but not actually do anything other than that.

I wonder what @rickkas7 would think of this behaviour.

I wonder what @rickkas7 would think of this behaviour.

Does anyone have any updates on this topic or discovered a workaround?

@rickkas7 - would you mind commenting on the above?

Having an issue- Trying to setup just the mesh network with Argon/Xenon, without Wifi and particle connect. I tried the following code on the Argon. I see rapid blinking green. Xenon doesn’t connect to mesh. I tried both SYSTEM_MODE (MANUAL) and SYSTEM_MODE (SEMI_AUTOMATIC).

//SYSTEM_MODE(MANUAL);
SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

void setup() {
  WiFi.off();
  Mesh.on();
  Mesh.connect();
  waitUntil(Mesh.ready);
  pinMode(D7, OUTPUT);
  digitalWrite(D7, 1);
  Serial.println("Base  Ready!");
}

void loop() {
  delay(1000);
  digitalWrite(D7, !digitalRead(D7));
}

Has the mesh been created already (does it show upon in the console as a mesh) with the argon as gateway and the xenon as a member? If not this must be done with the argon online for this to complete.

If you have done this and the xenon is flashing green, it means it cannot find the internet (and it would be correct in your example above)

https://docs.particle.io/tutorials/device-os/led/xenon/#looking-for-internet

Thanks for your comments @shanevanj. Yes, the mesh was already created and was working in the AUTOMATIC mode, before I attempted the changes.

After a few more iterations, I have some success. I added Particle.disconnect() on Xenon and Argon, and found a few more things to keep in mind.

On the Argon side, it starts with only the mesh turned on and WiFi turned off, every 60 seconds, turns on the WiFi and pushes a Particle.publish. There may be several redundant/ unnecessary lines, but I wanted to get things working first. On the Argon side, I still see rapid green blink, although mesh and Wifi switch on and off correctly. mesh publishes from Xenon are received correctly. I verified WiFi is switched off by measuring the current on Li+ pin (7mA). The very first Particle publish takes 4 minutes for some reason and thereafter publishes every minute, can’t explain why

SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);
String mystring;
int i=0;
const char *eventName = "test";
void RcvMsg1(const char *event, const char *data)
{
  mystring=data;
  Serial.print(mystring);
  Serial.println();
}

void setup() { 
  /* following added for mesh only mode */
  Particle.disconnect();
  WiFi.disconnect();
  WiFi.off();  
  Mesh.on();
  Mesh.connect();
  waitUntil(Mesh.ready);
  
  pinMode(D7, OUTPUT);
  Mesh.subscribe("msg_station1", RcvMsg1);
  Serial.println("Base Ready!");
}

void loop() {
  if (i==60){
    Mesh.on();
    Mesh.connect();
    waitUntil(Mesh.ready);
    WiFi.on();
    WiFi.connect();  
    waitFor(WiFi.ready, 60000);
    Particle.connect();
    delay(1000); //doesn’t work without a delay
    Particle.publish(eventName, "Testing");
    i=0;
  } 
  else{
    Particle.disconnect();
    WiFi.disconnect();
    WiFi.off();  
    Mesh.on();
    Mesh.connect();
    waitUntil(Mesh.ready);
  }  
  delay(1000);
  i++;
  digitalWrite(D7, !digitalRead(D7)); 
}

On the Xenon side, similar story, For the Mesh.publish to work, I have to repeat Mesh.on() and Mesh.connect() in the loop (in addition to the setup). With this change, it works fine.

SYSTEM_MODE(MANUAL); 
SYSTEM_THREAD(ENABLED); 
char msg[256];
int sno=0;
unsigned long cur_time;
int i;
void setup() {
  pinMode(D7, OUTPUT); 
  Particle.disconnect();
  Mesh.on();
  Mesh.connect();
  waitUntil(Mesh.ready);
}

void loop() {
    cur_time = millis(); 
    Particle.disconnect();
/* Mesh.on() and Mesh.connect() need to be repeated in the loop for it to maintain the mesh connectivity */
    Mesh.on();
    Mesh.connect();
    waitFor(Mesh.ready,30000);
    cur_time=millis()-cur_time;
    snprintf(msg, sizeof(msg),"%d:%d",sno,cur_time);
    Mesh.publish("msg_station1",msg);
    delay(1000); // needs this delay to work
    System.sleep({},{},25);
    sno++;
}

waitFor(Particle.connected, 1000) should do the trick here too.

In non-AUTOMATIC modes you shouldn't need this block in setup()

  Particle.disconnect();
  WiFi.disconnect();
  WiFi.off();  

nor should you repeatedly do that over and over every second in your loop() if not needed. Instead of your unconditional else donate an else if() or slap the disconnection commands into the same branch as your connect (with sufficient delay for the publish to execute).

/* Mesh.on() and Mesh.connect() need to be repeated in the loop for it to maintain the mesh connectivity */

That shouldn't be the case. Although this should be handled by SYSTEM_THREAD(ENABLED) you can still try adding Particle.process()` instead.

BTW, I found that the RGB LED isn't a very reliable source of information about the mesh connection state. Since adding another independent connection (mesh in addition to WiFi/Cellular) the feedback got somewhat inconsistent IMO.

Thanks for your comments @ScruffR, all your suggested changes made and verified,
Except:

I still had to retain the additional delay for it to work.

1 Like

I am seeing some unexplained behavior with Mesh.ready() on Xenon. I added a timeout code to check if mesh is ready before doing a mesh publish. In the following code, I put a timeout of 20 seconds. When the Argon is switched off (no mesh), I expect it to timeout, but it regularly comes back after 4-6 seconds with Mesh.ready()==true. Can anyone explain this? Concern is, if the Mesh.ready() is not reliable, subsequent Mesh.publish will not be reliable either, may go out before Mesh is actually ready. Appreciate any insight.

SYSTEM_MODE(MANUAL); 
SYSTEM_THREAD(ENABLED);
void setup() {
  pinMode(D7, OUTPUT); 
  Particle.disconnect();
}

void loop() {
  int i,ready;
  delay(3000);
  Mesh.on();
  Mesh.connect();
  i=0;
  ready=0;
    while(i< 200 && !ready){ // total 20 seconds timeout waiting for Mesh connect
      ready=Mesh.ready();
      Particle.process();
      i++;
      delay(100);
    }
    Serial.print(i);
    Serial.print(":");
    Serial.println(ready);
    delay(1000);
    Mesh.disconnect();
    Mesh.off();
    delay(100);
    System.sleep({},{},10);
}

Since mesh communication is using UDP broadcast - which is connectionless and indifferent to the fact whether anybody is listening - I’m not surprised Mesh.ready() reports true as it only indicates whether the local device is ready for mesh communication not necessarily whether an outside mesh exists.

You can always shout your events into the void but what you want is some kind of acknowledgement scheme between the node and the gateway.

2 Likes