2016-01-12

This post is contributed by Charlie Key, CEO and Co-Founder of Structure. Structure is an Internet of Things platform that makes it simple to build connected experiences and solutions. Charlie has been working with Node.js for a number of years and is now using it to power the world of IoT.

The world of JavaScript continues to drive into new areas. Technologies like Node.js have allowed for rapid expansion on the server side, and now into the world of the Internet of Things. Node.js can now be ran on a variety of embedded devices, like the Intel Edison. Communicating with embedded devices has always been possible but now with Node.js and protocols like MQTT it's easier than ever.

In this post, we'll take a look at how to take advantage of these two technologies (Node.js and MQTT) to send simple messages and build a simple garage opener application. This is only one of the possibilities for this type of communication.

MQTT itself is a very simple publish / subscribe protocol. It allows you to send messages on a topic (you can think of these as channels) passed through a centralized message broker. The whole protocol is very lightweight on purpose. This makes it easy to run on embedded devices. Nearly every microcontroller has a library available for it to send and receive MQTT messages. Below you can see the basics of MQTT communication.



Now, let's imagine we want to build a remote garage opener using MQTT now. The first thing we need to do is plan what messages we need to send between our garage door and the remote controller. To keep this example simple, we're going to say that we simply need to be able to open and close the door. The architecture for this in real life might look like:



The door itself can be in several states. These are 'open', 'closed', 'opening', and 'closing'. A real door might have another state for 'paused' but we're not worried about that today.

Our application today will be broken into two files, one for the garage and one for the controller. I'll include the file name at the top of any code snippets. To get things started, we need to include the mqtt npm library and set the broker we'll be using. There are many open brokers to use for testing; I'm going to use broker.hivemq.com. Again, this is only for testing - don't run a production workload through it. This should be at the top of both files.

Next up, we'll add some code to connect to the broker. Once connected we'll create a topic (channel) that will be used to communicate whether the garage door is connected to the system. On the door side, this is publishing a message to a topic and on the controller side it's subscribing to the topic. Also, at this time, we'll add a local variable to keep track of the current state of the garage door. You'll notice that we're prefixing of our topics with 'garage/'. This is simply for organizational purposes; you could name these whatever you'd like.

On the controller side, we not only need to subscribe to the topic, we need to add a message listener to take action when a message is published. Once the message is received, we check the value and keep track to whether the door is connected to the overall system using a variable.

So far the door and controller only know if the door is connected to the system. We can't take any action just yet. To make sure that the controller in the system knows going on with the door let's add a function to send the current door state. This function looks like the following:

To make use of this function, we'll add to our initial garage connect call.

Now that the garage door can update tell everyone it's current state, the controller needs to update it's garageState variable. However, at this time let's update the message handler to call separate functions for the different incoming topics. This will improve our code structure a bit. The fully updated file follows.

At this point, our controller can keep up to date with the garage door state and connection status. It's probably a good time to start adding some functionality to control our door. The first thing we'll do is have the garage start listening for messages telling it to open and close. This again updates the connect call for the garage.

We now need to add a message listener to our garage door.

For the controller, we'll add the ability to send an open message or close message. These are two simple functions. In a real application these two functions would be called from outside input (a web application, mobile app, etc...). For this example, we'll call them with a timer just to test the system. The additional code for this follows.

The code above includes the open and close functions. They make sure that the garage is actually connected to the system and not already in the requested state. That gives us the final code for our controller which can be viewed below.

Now the garage door must do something with these messages. Again, we'll use a switch statement to route the different topics. Once the message has been received the door will attempt to handle it by checking to make sure it can go to that state. It will then go to the transitional state (opening, closing), send an update message, and finally go to resting state (open, closed). For testing purposes, this last part is done on a timer. In reality, the system would be waiting for the hardware to signal it's completed.

The open and close request handlers can be added to the end of the file.

With these functions, we now have a fully functioning garage system. To test you should start the controller then immediately after the garage door. The controller will send an open command after 5 seconds of starting and a close command after 20 seconds.

The final thing I'd recommend is to make our garage door update it's connected status when the application closes for any reason. This exit cleanup code is based on a stackoverflow answer and modified to send a mqtt message. This can be dropped at the end of the garage file. All of this combined leaves us with the final garage file.

With that, we're finished with our garage door controller. I challenge you to take this to the next level. A few modifications and an Intel Edison would let you setup a full remote garage opener. The full source code for this example is available on Github as well.

That'll do it for this initial tutorial. There are additional options and capabilities in MQTT including SSL and username / password authentication to beef up security.

If you liked this post and are interested in where Node.js is going there's a fantastic conference coming up, Node Community Convention. There will be great talks on topics including the Internet of Things, scaling systems, and more.

Show more