Spark flashes red when I try to subscribe to a webhook

Take a look at the code below (sorry if it is too long). This code works fine until I add the line "Spark.subscribe(“hook-response/send_power_reading”, gotData, MY_DEVICES); " and flashing the device. After that, the device starts flashing red with the occasional single cyan then blue flash. I would then need to apply a factory reset. What am I doing wrong?

SYSTEM_MODE(SEMI_AUTOMATIC);
uint8_t retry_count = 0;
unsigned long old_time = millis();

int val = 0;
int inPin  = D0;
int outPin = D7;
int PreviousSecond = -1;
int ThisSecond = -1;
int PreviousMinute = -1;
int ThisMinute = -1;
int LoopCount = 0;
bool SensorState = false;
bool PreviousSensorState = false;
int PulseCount = 0;

void setup() {
    WiFi.on();
    pinMode(outPin, OUTPUT);
    pinMode(inPin,  INPUT);
    Time.zone(2);
    PreviousSecond = Time.second();
    Spark.subscribe("hook-response/send_power_reading", gotData, MY_DEVICES); //PROBLEMATIC LINE
}

void loop() {
    if(millis() - old_time >= 2000){        
        if(retry_count < 10){
            if(!WiFi.ready()){
                WiFi.connect();
                retry_count++;
            }
            else if (!Spark.connected()){
                Spark.connect();
                retry_count++;
            }
        }
        else{
            WiFi.off();
            retry_count = 0;
            WiFi.on();
        }
        old_time = millis();
    }

    LoopCount+=1;
    val = digitalRead(inPin);
    SensorState = !val;
    digitalWrite(outPin, SensorState); //show sensor state on little blue led
    
    //Count Pulses//
    if(SensorState != PreviousSensorState) {
        //Detect Leading Edge//
        if(SensorState==true) {
            PulseCount += 1;
        }
        ///////////////////////
        PreviousSensorState = SensorState;
    }
    ////////////////
    
    //Transmit Pulsecount at the turn of the minute//
    ThisMinute = Time.minute();
    if(ThisMinute != PreviousMinute) {
        //Spark.publish("send_power_reading");
        PreviousMinute = ThisMinute;
        PulseCount = 0;
    }
    /////////////////////////////////////////////////
    
    ThisSecond = Time.second();
    if(ThisSecond != PreviousSecond){
        PreviousSecond = ThisSecond;
        LoopCount = 0;
    }
}

void gotData(const char *name, const char *data) {
    String str = String(data);
 }

I think this is an old bug on the Core (that is fixed in the next release.)

Spark.subscribe() fails when the core isn’t online. To work around this, you can move the subscribe call to when the device is connected.

    else if (!Spark.connected()){
                Spark.connect();
                retry_count++;
                while (!Spark.connected()) SPARK_WLAN_Loop();
                Spark.subscribe("hook-response/send_power_reading", gotData, MY_DEVICES);
      }
1 Like

No luck. I am not sure it is because of the Spark being offline, since the device is breathing cyan before I flash the program and it starts blinking red as soon as the flashing is ready.

Strange. You did remove the Spark.subscribe() call from the setup() function?

Yes. I have now removed all the code related to offline usage and it is working fine. Is it possible that the problem only happens when in SEMI_AUTOMATIC?

I've made the observation that one last call to SPARK_WLAN_Loop() / Spark.process() after the while() and before subscribing does cure that problem (in my case at least it did :wink: in SEMI_AUTOMATIC too).


BTW @mdma:
Did you really mean to Spark.connect() when Spark.connected() already is TRUE?

How do I change my code to do what you are saying?

It depends what your current code looks like :wink:

But building ontop of @mdma’s code I’d do it this way

bool cloudFail = FALSE;

  ...
  if (!Spark.connected() && !cloudFail)
  {
    uint32_t ms = millis(); 
    Spark.connect();
    while(!Spark.connected() && (millis() - ms < 30000))  // 30sec timeout
    { 
      SPARK_WLAN_Loop();
      delay(100);  // checking connected() too quickly can interfere with connect()
    }
    if (Spark.connected())
    {
      SPARK_WLAN_Loop();  // once more
      Spark.subscribe("hook-response/send_power_reading", gotData, MY_DEVICES);
    }
    else
      cloudFail = TRUE;    // timed out, don't retry
  }
  ...

My Code looks exactly like the one posted in the original post.

@ScruffR, do use Spark.process() for future background processing until the non-blocking firmware is released.

On the Core (0,3.4) Spark.process() only runs the Cloud event loop - SPARK_WLAN_Loop() is needed for background connection management. It’s only with 0.4.x that SPARK_WLAN_Loop() is replaced by Spark.process() which also takes care of the connection management.

1 Like

Sorry if I ask again, but how should I change the code (shown in the original post) to accommodate the changes you mentioned?

Edit: I previously posted the same question as a reply to the wrong person. Sorry about that.

Since I don’t actually know your use cases any definite answer might still not help you :wink:
I’m not too sure what your program (especially the disconnect/connect part) should do.

But to get rid of the red flash you can simply do this:

void setup() 
{
    // WiFi.on(); // forget this, it will be done implicitly if needed
    Spark.connect();

    pinMode(outPin, OUTPUT);
    pinMode(inPin,  INPUT);
    Time.zone(2);
    PreviousSecond = Time.second();
    
    old_time = millis();
    while(!Spark.connected() && millis() - old_time < 30000)
    {
        SPARK_WLAN_Loop();
        delay(100);
    }
    SPARK_WLAN_Loop();  // once more

    if (Spark.connected())  // just to make sure we didn't timeout
        Spark.subscribe("hook-response/send_power_reading", gotData, MY_DEVICES);
}

But as I see it, your event handler has no useful effect anyway :confused:

If you could also clarify what you want to achieve with this if(millis() - old_time >= 2000) { ... }-block we might be able to come up with an alternative solution.


I’m not sure if WiFi.off() would kill your subscription or not (could try myself - but you know … :wink: ).
But if it does, you’d have to resubscribe, but then I’m not sure how often you can, before running into troubles again.
This might be worth asking @Dave or @mdma, since his post suggests to do so ;-).

1 Like

Hi @ScruffR I got that code as an answer to a previous question of mine:

The idea is to be able to start the device even when there is no wifi and then connect as soon as it becomes available.

I see, but as Kenneth said there too

This is the part I've coded out above to get rid of the red flash :wink:

After that you should be good to use your original code.

But my suspicion still stands

I doubt WiFi.off() kills the suscription, but if it did, I'd expect resubscribing too often might bring in a problem.
I recall that there was some discussion about this, but I'd have to find that thread again.