System Thread Enable is not working

electron
Tags: #<Tag:0x00007f1ca3ab42c8>

#1

Hey All,

I want to use SYSTEM_THREAD(ENABLED); to keep background application loop running all the time.

My main loop() function reads data from serial port. Everything works fine when the cellular signal is available. But when the cellular signal goes off (LED blinks green on the electron), the loop() function is getting blocked. And it stops reading data from serial. How can i make loop function running all the time to read data from serial??

I added the following line at the top of the code:
SYSTEM_THREAD(ENABLED);

But it is still blocking the loop() function.

Where should i put SYSTEM_THREAD(ENABLED); ??

  1. Inside setup() function
  2. Outside setup() function
  3. Where???

Thank you in Advance


#2

@d.chauhan, you placement is correct (outside both setup() and loop()). However, if you are not checking for cloud connectivity (eg. Particle.connected()) prior to call Cloud functions, the code may block. So, your loop() code needs to be connection “aware”. One approach is to run in SEMI_AUTOMATIC mode and have your code decide when it connects vs not.


#3

It still blocks the serial port and loop. The partial code is below:

#include "Particle.h"

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);

void setup() {
  // GPIO enable
  //  Particle.publish(some data);
}

void loop() {
  Cloud::loop(); // Reads data from serial and publish it
  if (!Particle.connected() || Cloud::rssi < -120){
    Particle.connect();
    status(LED::red);
  }
  else if (Cloud::rssi < -90) {
    status(LED::yellow);
  }
  else {
    status(LED::green);
  }
}

#4

What happens in this function? Is the publish in this function wrapped in a if (particle.connected()) block like @peekay123 suggests?


#5

Cloud::loop(); // Reads data from serial and publish it

This will be your problem. Publish depends on the system thread and is potentially blocking, especially in instances where the Particle cloud connection is not available.

@rickkas7 developed a library you may find helpful at https://github.com/rickkas7/PublishQueueAsyncRK


#6

Wrapping publishes in Particle.connected() is helpful but not sufficient protection against blocking. It normally takes an initial failing publish (which can block) for the cloud connection to drop.


#7

Can you please explain

Wrapping publishes in Particle.connected() is helpful but not sufficient protection against blocking

I am having a problem tracking down an issue on a photon where the device sometimes freezes up when the wifi credentials stored are for a WAP that is out of range. Sometimes it works fine and just sails on as it should and now since 1.0.0 it sometimes doesn’t. I have been relying on testing Particle.connected() as THE way to avoid calling functions that would block given there is no Cloud connection. Is there an alternative or 100% test you can recommend?


#8

Huge Success :muscle:
Loop for reading data from the serial is working perfectly without blocking. The cellular connection is also robust.

void loop() {
  Cloud::loop();
  if (!Particle.connected())
  {
    Particle.connect();
    status(LED::red);
  }
}

The above code is managing the cloud connection in semi_automatic mode.
Changed the logic of publishing data inside Cloud::loop()
New logic

If ( particle connected)
{ publish data }

Strange Observations
Somehow when i try to access particle.variable, it starts throwing Bummer! Failed to fetch variable error more frequently with the semi_automatic mode.
Also, The Ping in the particle console also fails a lot.

Is there any connection of semi_automatic mode with this issues?? Or am i handling the cloud connection wrong??

Thank you all for the help.


#9

You indiscriminately call Particle.connect() every loop iteration without giving the code any time to actually connect before the next call. Why not implement a wait period?


#10

The general model provided in https://github.com/rickkas7/PublishQueueAsyncRK for off-loading potentially blocking operations (such as a Particle.publish) to a background thread is very useful. In my applications that have strict non-blocking requirements I will often use the main application thread, a publish thread, and third background thread to handle other potentially blocking operations.


#11

@joel, I sniff best practices and examples! Can you contribute some? :wink:


#12

Thanks for the advice and I second what @peekay123 has requested by way of examples. I will take a look at the link. We definitely need some ‘model’ answers as to how to develop reliable connected apps.

A reliable method for handling all conditions of WiFi (or cellular) comms is what I am after that does not impact the main application unduly (short or managed interrupts are OK - like at startup).

I would also love to understand what situations with WiFi connection missing and where Particle.connect() would not have been called could cause a true to be returned from Particle.connected()? I am suspecting a timing issue because whenever I have the SerialLogHandler on I cannot reproduce the issue!

Under the scenario I described of WiFi out of range, is it therefore best to test for WiFi.ready() and then Particle.connected() rather than just Particle.connected().

Lastly, something has changed in device OS 1.0.X from 0.8.0-RC.11 that has changed the behaviour??


#13

@ninjatill Should i add delay before calling particle.connect() but inside the if condition?

When the cellular is working perfectly, i can see all data being published. It means that the cellular connection is fine. But at this time, ping is still failing as well as the particle.variable. How this can happen?? How can i make ping response faster?


#14

I was thinking more like this from the docs:

https://docs.particle.io/reference/device-os/firmware/xenon/#waitfor-

// SYNTAX
waitFor(condition, timeout);

// wait up to 10 seconds for the cloud connection to be connected.
if (waitFor(Particle.connected, 10000)) {
    Particle.publish("weather", "sunny");
}

Or call Particle.connect(), then use a millis()-based timer to wait for 10 seconds or so before calling Particle.connect() again. A straight-up delay is not generally good coding practice.


#15

If the project becomes larger, it might be worth writing a ‘wrapper’ function to the publish function so that the check for active connection is always made before calling the Particle publish function - that way, to do the check can’t accidentally be forgotten.

Blocking appears to be such a common problem for anyone new to the Particle system - would it not make sense to put the necessary checks for avoiding blocking into the underlying library functions? For example: within ‘publish’ a check for an active/valid connection could be made and FAIL returned if unsuccessful.