Sprint 7: Particle.publish() released! Let's build a cloud-connected motion detector

The wait is over! You can now publish data from the Spark Core through the Cloud.

Here’s the blog post:

http://blog.spark.io/2014/03/11/spark-publish/

Here’s the Particle Docs reference:
https://docs.particle.io/reference/firmware/electron/#particle-publish-

Don’t want to go to the blog? Well stick around here and let’s chat through it.

Last Friday, we wrapped up Sprint 7 on our team. We released a number of minor bug fixes and improvements, but the one major feature that we delivered is Particle.publish(). Here are some examples:

// The most basic event, without data.
Particle.publish("motion-detected");
 
// Some events require additional data.
Particle.publish("temperature", "19 F");  
 
// You can set a TTL to persist data in the cloud...
Particle.publish("lake-depth/1", "28", 21600);
 
// ...and make events private for secure applications.
Particle.publish("front-door-unlocked", NULL, 60, PRIVATE);

Up until now, the only way to communicate with the Spark Core was to ask it something. You could remotely call a function using Particle.function(), such as calling the brew() function on a connected coffee-maker to brew a cup of coffee on the fly. Or you could store the temperature in a local variable temp, and then check the temperature with Particle.variable(), and ask for the temperature at any time.

But what if you want the Spark Core to talk to you? Enter Particle.publish(). This feature lets you publish events from the Spark Core, which can be subscribed to through the API. Events are published to a topic, and can be public or private.

To showcase this feature, I’m going to build a Particle-powered motion detector, using an off-the-shelf PIR sensor. Here’s the hardware:

If you’re following along, here’s a Fritzing diagram showing how the components are wired.

My goal is to have this motion detector inform me when it detects motion (natch). Perhaps it could even text me through Twilio? Hello, ad hoc security system.

First, I’ll connect my Spark Core to my Wi-Fi network. I’m going to use the recently released Particle CLI. Once the CLI is installed through npm install -g particle-cli, I can start to play.

Now my Core is connected to the internet and to the Cloud, which I know because its little LED is breathing cyan. Breathing = happy and alive.

Next, it’s time to develop my firmware. Adafruit has some great resources for using these sensors.

I threw together a quick 50-line application that will publish to the Cloud every time motion is detected. I chose particle-hq/motion as the topic; our team will use the top-level particle-hq topic for data generated at our office. You can find a gist of the code here.

/*
 * Connected sensor
 * Particle.publish() + PIR motion sensor = awesome
 * Thanks to Adafruit for the reference and inspiration
 */

int inputPin = D0;              // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status
int calibrateTime = 10000;      // wait for the thingy to calibrate

void setup() {
  pinMode(inputPin, INPUT);     // declare sensor as input
  Serial.begin(9600);
}

void loop(){
  if (calibrated()) {
    readTheSensor();
    reportTheData();
  }
}

bool calibrated() {
  return millis() - calibrateTime > 0;
}

void readTheSensor() {
  val = digitalRead(inputPin);
}

void reportTheData() {
  if (val == HIGH) {
    if (pirState == LOW) {
      // we have just turned on
      Serial.println("Motion detected!");
      Particle.publish("particle-hq/motion");
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
    if (pirState == HIGH) {
      // we have just turned of
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
}

Now I can subscribe to the stream of events using Server-Sent Events. Using curl as an example, I type this in my terminal:

curl -H "Authorization: Bearer {ACCESS_TOKEN_GOES_HERE}" \
         https://api.particle.io/v1/events/particle-hq

and now I’m listening to a stream of events from particle-hq. Besides my own motion sensor, we’ve got a temperature sensor (69 degrees!), and will be adding more as we put together more prototypes. Since this data is public, anyone can subscribe; go to the Particle Build IDE and get your access token from the “Settings” panel, and you can subscribe to this data too!

Now I don’t just want to see a stream of data in my terminal; I want to do something with it. Luckily, Server-Sent Events are part of the HTML5 protocol, and there are interfaces available in many programming languages. Check out this tutorial from html5rocks for more information on using Server-Sent Events.

Coming soon: more features!

This is just the beginning for Particle.publish(). A few weeks from now we’ll add even more functionality, such as:

  • Setting up webhooks for events to POST a message back to your server
  • Particle.subscribe(), so that devices can talk with one another

Let us know what you think and share your Particle.publish() projects here!

11 Likes

This topic is now pinned. It will appear at the top of its category until it is either unpinned by a moderator, or the Clear Pin button is pressed.

Is that one of the options in the Tinker app? I'm assuming it's one of the digital pins. :wink:

Very cool feature. I just received 2 PIR sensors for free from a recent Parallax order so looks like I have a cool way to use them now.

Now I just have to wait for somebody to come up with a easy to follow template that shows how to take Published data and push it out via Text Message that would be very helpful for us Newbies who are just getting started with all this.

Keep up the Great work team! :rocket:

4 Likes

Does the Spark.publish() feature make it any easier for somebody to have a event trigger a Text Message to be sent to a cell phone? or a email?

I know other people have accomplished this in other ways that are beyond my understanding right now so I’m wondering if the new function could make sending a text message or email easier for us new guys?

This is great ! I could get it running also, my spark is updated the uptime (millis()) every 2 sec.
However I could get it working with curl, but not with a webpage html. My question is: how do you pass the access_token in argument in html?
In the link you provided as example, they say Note: If the URL passed to the EventSource constructor is an absolute URL, its origin (scheme, domain, port) must match that of the calling page.
I guess it doesn’t mean that we can’t connect from outside https://api.spark.io/ but then how?

2 Likes

Same question here. I found this: Yaffle/EventSource

It has a cross-domain service support…not sure if that could work. Will try!!

Yes, good question! This will make it much easier for code on your core to trigger something like a text message. We’re also testing webhooks support, which will let you register a website with the API that will listen for events for you. So a “motion” event or others would cause your page / another service’s page to be called and trigger something like a text, definitely. :slight_smile:

1 Like

Spark.publish is popular!

Well, that didn’t take long! :smiley: After rolling out Spark.publish today, the message counts quickly spiked and consumed a large chunk of server resources. We found some users publishing 2,000-4,000 messages a minute (probably by accident)!

We expected a flood of events, but it’s important everyone gets a chance to publish events.
A few hundred cores monopolizing the event stream wouldn’t be a good user experience. For that reason, (for now…) we think setting a maximum rate of 60 events a minute per core, with a burst rate of up to 4 per second, should allow for almost all use cases.

If you need to move more data / more quickly, it might make more sense to do a direct TCP / UDP socket instead of publishing an event. Please feel free to weigh in! We will continue to improve and optimize things, so this limit may change down the road.

Thanks!
David

1 Like

For the truly lazy, you can use Spark.publish() as a sort of remote Serial interface.[quote=“Dave, post:10, topic:3391”]
We found some users publishing 2,000-4,000 messages a minute (probably by accident)!
[/quote]

/me sheepishly raises hand. It may have been me. What’s a button debounce? :wink:

Maybe if the cores were limited to something closer to 16 MHz, they wouldn’t be able to spam the service so fast!

3 Likes

Great work team Spark - can’t wait to try it.

1 Like

It’s amazing what removing the “connected” barrier can enable. This product is awesome.

I’m really excited about the webhooks feature.
If you want an outsider beta tester, I’ll preparing my spark tools service for this.

1 Like

I have the same issue… CURL looks great… but how do we subscribe to events using the HTML5 examples? , if we cant instantiate the EventSource object with the sparkcore absolute URL. In addition, how do we send the Authorization Header (access token) using common HTML 5 subscription ??

I post about this same problem over here:

I can see the stream open so I don't think the URL/URI is the problem, but I never get a message or onmessage callback.

Hi @omarojo and @Fabien

I got the HTML5 code to work over in the Registering A Callback thread.

I thought registerring a callback means the spark cloud is going to make a HTTP POST I think. I don’t want HTTP POST I want direct web socket notification as Server-Sent-Events works, which is much much faster and realtime. Is there another way to tests this spark core SSE’s other than terminal ?

Hi omarojo, I use bko code and adapt it to Node.js. (in Registering A Callback thread. )

Thank you

Hi @omarojo

You open the event stream with a GET request and then you need to create a listener on that stream for your particular event. From the listener you can do anything you could normally do from web page.

whoops… @bko code is working fine ! your are right. Didn’t know it was possible to pass the access_token in the URL. As you said best way might be to make a Node.js script that runs in server so that access_token is not exposed.
Also… after this code example… Im not getting what “Registering a CallBack thread” means… do you mean the eventSource.addEventListener() ??

Hi @omarojo

The "Registering a Callback" thread is another discussion here in the forum--sorry for any confusion over the use of thread for a discussion thread and not a code thread!

1 Like