Cloud functions

Particle.subscribe()

Particle.subscribe, subscribe

Subscribe to events published by devices.

This allows devices to talk to each other very easily. For example, one device could publish events when a motion sensor is triggered and another could subscribe to these events and respond by sounding an alarm.

SerialLogHandler logHandler;
int i = 0;

void myHandler(const char *event, const char *data)
{
  i++;
  Log.info("%d: event=%s data=%s", i, event, (data ? data : "NULL"));
}

void setup()
{
  Particle.subscribe("temperature", myHandler);
}

To use Particle.subscribe(), define a handler function and register it, typically in setup().


You can register a method in a C++ object as a subscription handler.

#include "Particle.h"

SerialLogHandler logHandler;

class MyClass {
public:
    MyClass();
    virtual ~MyClass();

    void setup();

    void subscriptionHandler(const char *eventName, const char *data);
};

MyClass::MyClass() {
}

MyClass::~MyClass() {
}

void MyClass::setup() {
    Particle.subscribe("myEvent", &MyClass::subscriptionHandler, this);
}

void MyClass::subscriptionHandler(const char *eventName, const char *data) {
    Log.info("eventName=%s data=%s", eventName, data);
}

// In this example, MyClass is a globally constructed object.
MyClass myClass;

void setup() {
    myClass.setup();
}

void loop() {

}

You should not call Particle.subscribe() from the constructor of a globally allocated C++ object. See Global Object Constructors for more information.

Each event delivery attempt to a subscription handler uses one Data Operation from your monthly or yearly quota. Setting up the subscription does not use a Data Operations. You should take advantage of the event prefix to avoid delivering events that you do not need. If poor connectivity results in multiple attempts, it could result in multiple Data Operations, up to 3. If the device is currently marked as offline, then no attempt will be made and no Data Operations will be incurred.

If you have multiple devices that subscribe to a hook-response but only want to monitor the response to their own request, as opposed to any device in the account sharing the webhook, you should include the Device ID in the custom hook response as described here. This will assure that you will not consume Data Operations for webhooks intended for other devices.

Particle.subscribe(System.deviceID() + "/hook-response/weather/", myHandler, MY_DEVICES);

A subscription works like a prefix filter. If you subscribe to "foo", you will receive any event whose name begins with "foo", including "foo", "fool", "foobar", and "food/indian/sweet-curry-beans". The maximum length of the subscribe prefix is 64 characters.

Received events will be passed to a handler function similar to Particle.function(). A subscription handler (like myHandler above) must return void and take two arguments, both of which are C strings (const char *).

  • The first argument is the full name of the published event.
  • The second argument (which may be NULL) is any data that came along with the event.

Particle.subscribe() returns a bool indicating success. It is OK to register a subscription when the device is not connected to the cloud - the subscription is automatically registered with the cloud next time the device connects.

See special webhook events for more details about handling multipart responses from a webhook in your subscription handler.

  • A device can register up to 4 event handlers. This means you can call Particle.subscribe() a maximum of 4 times; after that it will return false. On some versions of Device OS on some devices the limit may be higher.

  • Particle.publish() and the Particle.subscribe() handler(s) share the same buffer. As such, calling Particle.publish() within a Particle.subscribe() handler will overwrite the subscribe buffer, corrupting the data! In these cases, copying the subscribe buffer's content to a separate char buffer prior to calling Particle.publish() is recommended.

  • You can call Particle.subscribe from setup() or from loop(). The subscription list can be added to at any time, and more than once. The subscriptions are only updated once loop is running, however. During setup() the subscription will not yet be active. Very old versions of Device OS (prior to 1.0.0) may behave differently.


Prior to August 2020, you could subscribe to the public event stream using ALL_DEVICES. This is no longer possible as the public event stream no longer exists. Likewise, MY_DEVICES is no longer necessary as that is the only option now.

// This syntax is no longer necessary
Particle.subscribe("the_event_prefix", theHandler, MY_DEVICES);
Particle.subscribe("the_event_prefix", theHandler, ALL_DEVICES);

  • Unclaimed devices can only be used in a product.
  • Unclaimed devices can send product events.
  • Unclaimed devices can receive function calls and variable requests from the product.
  • Unclaimed devices can receive events using Particle.subscribe as of March 2023. This was not previously possible.

The behavior of unclaimed product devices with respect to subscribing to events changed in March 2023:

  • Prior to March 2023, claiming was required if the device firmware subscribed to events on-device. This is no longer necessary.
  • You still need to claim a device is if you are using a webhook in the sandbox of the user who claimed the device. It is recommended that you use product webhooks instead, which do not require claiming.
  • If you are using a device with Mark as Development device, you may want to claim the device to your account so you can easily OTA flash it from Particle Workbench or other development environments.
  • If you previously had firmware that subscribed to events but was the device was unclaimed, the events previously disappeared. This is no longer the case and the device will now start receiving those events, and each event will count as a data operation.
  • Claiming is still allowed, if you prefer to continue to use claiming, but not recommended.

Additionally:

  • Publishes are not end-to-end confirmed. Even if the Particle.publish returns true, there is no guarantee that any recipient (another device, webhook, or SSE) will receive it.
  • It is possible to receive an event more than once. The most common reason is a lost ACK, which will cause the device to send the event again. Storing a unique identifier in the event payload may help code defensively for this possibility.
  • It is possible that events will arrive out-of-order. The most common cause is retransmission, but it can also occur because events can flow through different redundant servers, each with slightly difference latency, so it's possible that two event sent rapidly will arrive out-of-order as well. This is common for multi-part webhook responses.
  • It is possible that even if Particle.publish returns false, the event will still be received by the cloud later. This occurs because the 20-second timeout is reached, so false is returned, but the event is still buffered in Device OS and will be retransmitted if the reconnection to the cloud succeeds.