How to Generate and Handle Events on Particle Mesh

Jared Wolff · 2019.11.24 · 5 Minute Read · particle

Main image

Deploying devices using Particle’s Cloud is easy. Publishing to the cloud is dead easy. Finding a reliable way to do the opposite can be.. complicated. This is especially true for devices that have many modes or functions. Luckily there’s a solution.

Your very own command protocol.

In this blog post, we’ll be talking about you can use them in your own code. So, by the end of the post you’ll be an expert at developing your own command set, using a FIFO/queue to process them and more.

Let’s dig in.

Why use a command set?

Using a command set has two main benefits. First, it creates a common structure to facilitate communication. This simplifies messaging between cloud and device with only a byte or two of data!

Secondly, it allows you to set up a straight forward way of processing events as they occur. You can even use these events to change the state of the device. This kind of functionality is also known as a state machine. In this example, we’ll be focusing more on sending one-off commands. That means we won’t be retaining any state which makes this example much simpler!

How do you organize them?

Organizing

First of all, we need to create the “variables” we’ll be using to represent the many states. In my practice I use a typedef enum to crate all the states. For this example, we’ll call ours Control_Command_t.

    // Constants used for recieving commands from Particle
    typedef enum {
      Party_Mode = 0,
      Sad_Mode,
    	Silent_Mode
    } Control_Command_t;

The value of each enum entry starts at 0 and increases by one for each entry. For example, Sad_Mode is equal to 1, Silent_Mode is equal to 2 and so on. If you want to override a certain number, you can also set them manually similar to Party_Mode.

Then, we’ll set up a queue for adding and removing commands as they happen. Fortunately, Particle Workbench includes the standard C++ queue.h !

    #include <queue>

A queue allows you to add objects of any type. The queue keeps each entry in sequential order. When they’re removed, it removes oldest one first. This functionality is known as FIFO or first in, first out. It’s extremely common in the programming land at all levels.

You can place your queue above your setup() function. You can see that it’s defined to use Control_Command_t. (That part is important!)

    // FIFO for events that occur. They are generated by:
    // - Self generated using timers
    // - From Particle Cloud/Customer App
    std::queue<Control_Command_t> events;

Once created, you’re ready to push events on and pop them off. We’ll jump into that in the next section.

How do you use them to shape the operation of your device?

Queue

The source of events can come in many places. Some can get generated by other embedded devices. Some are internal that occur when a timer fires. Some are generated by the cloud. In most of these cases, these events get generated by interrupt.

Interrupts occur when events happen outside of the main loop() of your program. You can set up anything to interrupt the execution of your program. For example, you can set up a GPIO to send an interrupt event if the pin changes. Another example is setting up a subscription to a cloud or mesh function.

For example, here is a cloud function that watches for a message called “party.” Upon receiving the message, queue up a Party_Mode event!

    Particle.subscribe("party",partyHandler);

Where partyHandler looks like this:

    void partyHandler() {
    	// Queue up another Party_Mode
    	events.push(Party_Mode);
    }

This will generate Party_Mode and enqueue it. This is a relatively quick operation. That means you can easily do this in an interrupt routine without bogging down your device.

But, why don’t we enable Party_Mode in partyHandler itself?

Interrupts, by nature, stop your application code from running. When they take too long to execute, other important functions can’t execute. This could lead to unresponsiveness or cause the device to fault & restart.

So where do we do the processing?

In your loop() function.

Here’s an example of what it would look like for processing events in a FIFO manor.

    void loop() {
    	// Check if event queue is not empty
    	if( !events.empty() ) {

    		// Get the next event
    		Control_Command_t event = events.front();

    		// Remove it from the queue
    	  events.pop();

    		// Print out event name:
    		Log.info("%s",Control_Command_Names[event]]);

    		// Now process the event
    	  switch (event)
    	  {
    	  case Party_Mode:
    			Log.info("Dance dance dance.");
    			break;
    		case Sad_Mode:
    			Log.info("Looks like you need a picker upper.");
    			break;
    		case Silent_Mode:
    			Log.info("Silence is golden.");
    			break;
    		default:
    			break;
    	}

    // Do some other stuff....
    }

In the example above, you can see that the front of the queue gets removed. Then, we use a switch statement to go through each possible outcome. Don’t forget the default statement if you don’t define all of the commands!

Code execution happens inside the main loop rather than the interrupt context. It’s good practice unless your application is time constrained. Using Particle Mesh devices alone for these applications is not recommended. Use an external chip like a SAMD21 to do all the dedicated high speed stuff!

Debugging

When debugging, you can an array of c-strings and use them to help identify which state you’re in. We’ll map each entry to the same value as each of the commands. Here’s an example:

    const char *Control_Command_Names[] = {
      "Party Mode",
    	"Sad Mode",
    	"Silent Mode",
    };

To use them, you can do something like this:

    Log.info("%s",Control_Command_Names[event]]);

This will cause the logger to print out the command name as a text representation. 😎👍

Conclusion

Processing events in the main loop allow for consistent and reliable device operation. Using a queue with command definitions is one way of handling many events at one time. Consider it another tool in your programming toolbox to get your projects done!

Last Modified: 2020.3.7

Subscribe here!

You may also like

Meet Pyrinas a New Way to Use Your Xenon

Talk about how Particle’s Mesh deprecation announcement, many have been left to figure out how to deploy their low power sensor networks. There was always the option of using…

Particle Mesh Deprecation Livestream Reaction

Particle held a Q&A session last week. I listened in and took some notes. I know many of you are upset. I’m not exactly pleased myself. I digress, here are a few key takeaways and…

How to Develop Particle Iot Apps Using NativeScript

If you’re developing any type of IoT product, inevitably you’ll need some type of mobile app. While there are easy ways, they’re not for production use. In this tutorial, we’ll…