Spark.subscribe Attempt

I’m trying out the new Spark.subscribe() function, and I’ve gotten pretty far but I’m missing something. The goal is I have one sparkcore detecting whether a door is open, and another sparkcore that I want to have the D7 led turn on or off when it hears the published event. It’s not working but I can’t see why. I think I am missing something about how the callbacks should work. Here’s my code:

//Program 1: Publisher
// Detects bathroom door status and publishes it
int srbs = 0;

void setup()
{
  // Register a Spark variable here
  Spark.variable("srbs", &srbs, INT);
 
  // Connect the contacte sensor to A7 and configure it
  // to be an input
  pinMode(D6, INPUT);
  pinMode(D6, OUTPUT);
}

void loop()
{
  // Keep reading the contact so when we make an API
  // call to read its value, we have the latest one
  srbs = digitalRead(D6);
  if(srbs == 1)
  {
      Spark.publish("srbs-closed");
      digitalWrite(D7,HIGH);
  }
  if(srbs == 0)
  {
      Spark.publish("srbs-open");
      digitalWrite(D7,LOW);
      
  }
  
  delay(50);
}

//Program 2: Subscriber
//subscribes to the srbs-open event srbs-closed and turn on/off D7
int light = 2;

void lighton(const char *event, const char *data)
{
    light = 1;
    digitalWrite(D7, HIGH);
}

void lightoff(const char *event, const char *data)
{
    light = 0;
    digitalWrite(D7, LOW);
}

void setup()
{
    pinMode(D7, OUTPUT);
    Spark.subscribe("srbs-open", lighton, MY_DEVICES);
    Spark.subscribe("srbs-closed", lightoff, MY_DEVICES);

}

void loop()
{
    if(light==1) digitalWrite(D7, HIGH);
    if(light==0) digitalWrite(D7, LOW); 
    delay(50);
}

Any advice?

Hmm. One suggestion, although I don’t know if this is causing your issue; you shouldn’t run Spark.publish() in a loop. Instead, attach an interrupt using attachInterrupt() so that it just fires Spark.publish() when the trigger happens. If you run Spark.publish() in a loop, messages will be dropped because otherwise you would flood our servers!

1 Like

So you are probably running afoul of the rate limiting for Spark.publish and as Zach says, interrupt driven might be better. The rule is one publish per second on average, and a burst of up to 4 is allowed.

If you change your delay(50) to delay(1000) in your first program you should get better results.

In your second subscriber program, you turn the LED on or off in both the loop and in the subscribed functions which doesn’t seem right. One or the other should work.

Just for information, you don’t need two different events since events can send parameters as well as the event name, so your could instead do:

Spark.publish("srbs","closed");
//...
Spark.publish("srbs","open");

Either way will work.

Finally there is a bug in Spark.subscribe right now that makes MY_DEVICES not be selective to just your devices. This is already fixed, but the fix is making its way through testing to the production server.

Super helpful you guys. I love this sparkcore thing. I’m excited to get this stupid thing I am working on going.So, I feel closer but still not there. When I open/close the door I still don’t see it on the second sparkcore:

int led = 0;

void light(const char *event, const char *data)
{
    if(data==“open”)
    {
        digitalWrite(D7, LOW);    
    }
    else if(data==“closed”)
    {
        digitalWrite(D7, HIGH);
    }
}

void setup()
{
    pinMode(D7, OUTPUT);
    Spark.subscribe(“srbs-status”, light, MY_DEVICES);
}

void loop()
{
    delay(1000);
}

// Create a variable that will store the status of the bathroom door
//char *srbs = “unknown”;
int srbs = 0;

void setup()
{
    // Register a Spark variable here
    Spark.variable(“srbs”, &srbs, INT);
    attachInterrupt(D0, updatestatus, CHANGE);
    // Connect the contacte sensor to A7 and configure it
    // to be an input
    pinMode(D0, INPUT);
    pinMode(D7, OUTPUT);
}

void loop()
{
    // Keep reading the contact so when we make an API
    // call to read its value, we have the latest one
    digitalWrite(D7,srbs);
    
    delay(1000);
}

void updatestatus()
{
    srbs = digitalRead(D0);
    if(srbs==1)
    {
        Spark.publish(“srbs-status”,“closed”);
    }else if(srbs==0)
    {
        Spark.publish(“srbs-status”,“open”);    
    }
    
}

1 Like

By the way, if you want to know if I’m in the bathroom, go here: http://answerjack.com/projects/sparkcore/bathroom.php
hahahaha - digital potty humour - hahahaha

2 Likes

Looks like the bathroom is open right now! I will be right over :smiley:

1 Like

Just wanted to pop in a side note! I fixed some issues recently with the “MY_DEVICES” filtering not working properly, and I’ll be rolling out that fix in our next production update, which should happen fairly soon (In the coming days)

Thanks!
David

I’m still having a problem with the Spark.subscribe part of this. It doesn’t seem to be able to find the published event.

@rosshere, I could not compile the code you posted without errors. The void light() definition is missing some ‘*’ qualifiers and should be:

void light(const char *event, const char *data)
{
...
}

Did you verify that your publish is working ?

Sorry, haven’t rolled out this update to production yet, our sprint ends tomorrow, so it should go up in the next few days.

Thanks,
David

Sorry I probably posted a bad version of the code. Here is what’s running on the two sparkcores now, but it still doesn’t catch the subscribe event. I have tried taking out the MY_DEVICES param, but that doesn’t help:

// -----------------
// Send Bathroom Door Status
// -----------------

int srbs = 0;

void setup()
{
    Spark.variable("srbs", &srbs, INT);
    attachInterrupt(D0, updatestatus, CHANGE);
    pinMode(D0, INPUT);
    pinMode(D7, OUTPUT);
}

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

void updatestatus()
{
    srbs = digitalRead(D0);
    if(srbs==1)
    {
        Spark.publish("srbs-status","closed");
    }else if(srbs==0)
    {
        Spark.publish("srbs-status","open");    
    }else
    {
        Spark.publish("srbs-status","unknown");
    }
}



// -----------------
// Read Bathroom Door Status
// -----------------

int led = 0;

void light(const char *event, const char *data)
{
    
    if(data=="open")
    {
     digitalWrite(D7, LOW);    
    }
    else if(data=="closed")
    {
     digitalWrite(D7, HIGH);
    }
    else
    {
     digitalWrite(D7, LOW);
    }
}

void setup()
{
    pinMode(D7, OUTPUT);
    Spark.subscribe("srbs-status", light, MY_DEVICES);
}

void loop()
{
    delay(1000);
}

Hi @rosshere

First off, I fixed the formatting of the code your post. The thing for code is to put three grave accents and then cpp (6 characters) on a separate line above your code, and then three grave accents on a separate line below your code. If you edit your post above, you can see what that looks like, but it is hard to type here.

In your subscription function your are comparing the incoming pointer to the data to a constant string “open” or “closed”. You could convert this to Arduino String objects or use the C string functions like this:

if (strcmp(data,"open"))
{
  digitalWrite(D7,LOW);
} else if (strcmp(data,"closed"))
{
  digitalWrite(D7,HIGH);
} else {
  digitalWrite(D7,LOW);
}
...

You can obviously simplify this logic but putting the “closed” case first and then the else is always the same.

1 Like

Thanks for the help (especially BKO)! I got this working and thought I’d post the final working code for posterity:

Bathroom Door Status Publisher:

// -----------------
// Send Bathroom Door Status
// -----------------

int srbs = 0;

void setup()
{
    Spark.variable("srbs", &srbs, INT);
    //attachInterrupt(D0, updatestatusclosed, FALLING);
    //attachInterrupt(D0, updatestatusopen, RISING);
    attachInterrupt(D0, updatestatus, CHANGE);
    pinMode(D0, INPUT);
    pinMode(D7, OUTPUT);
}

void loop()
{
    digitalWrite(D7,srbs);
    delay(500);
}

void updatestatus()
{
    srbs = digitalRead(D0);
    if(srbs==1)
    {
        Spark.publish("srbs-status","closed");
    }else
    {
        Spark.publish("srbs-status","open");    
    }
}

Bathroom Door Status Subscriber:

// -----------------
// Read Bathroom Door Status
// -----------------

int led = 1;
char const *dataout = "unknown";

void light(const char *event, const char *data)
{
    if(strcmp(data,"closed"))
    {
     led = 1;
    }
    else
    {
     led = 0;
    }
    digitalWrite(D7, led);
    dataout = data;
}

void setup()
{
    pinMode(D7, OUTPUT);
    Spark.subscribe("srbs-status", light, MY_DEVICES);
    Serial.begin(9600);
}

void loop()
{
    digitalWrite(D7, led);
    if (dataout)
      Serial.println(dataout);
    else
      Serial.println("NULL");       
    
    delay(500);
}
2 Likes