There’s a lot of buzz about the Internet of Things, or IoT. This catchphrase is designed to encompass a whole range of embedded devices that connect to cloud servers to act more intelligently than they could on their own.
The Internet of Things exists in all sorts of settings — commercial, industrial, even in the backcountry — but there is particular focus these days on home automation. All sorts of Things in the home are being connected: light switches, security cameras, thermostats, refrigerators, moisture sensors, and more. It’s nearly impossible to think up a possible category of home automation where someone isn’t offering an IoT-style product. In fact, we’re currently working on several.
For most IoT products, there is an Internet-connected app that the end-user uses to control and monitor the Thing. This is a powerful model, for two reasons: It can lead to a simpler Thing, because most or all control can be done through a smartphone app or web page, thus reducing the user interface needed on the device. And two, it can lead to a smarter Thing, because of the possibility for tremendous integration with all sorts of data available on the Internet.
Networking in the residential environment can be difficult, especially if your business model involves selling beyond the tech-savvy engineering community. One problem that comes up is how to design the Thing to connect back to the Cloud Server — how does the Thing phone home? It’s tricky because usually we are trying to balance the following factors:
- Because of home firewalls, it’s normally easy for the Thing to connect out to the Server. It’s trickier for the Server to connect directly to the Thing.
- It’s typically a requirement that the Thing responds quickly when the user changes a setting on his or her smartphone app.
- We also want the Cloud Server to be capable of efficiently supporting lots (at least hundreds of thousands) of simultaneously connected Things.
There are three fundamental ways for the Thing to phone home:
- Polling. This is by far the easiest to implement and most universal, but it’s also the most limited. In this scenario, all connections are outbound from the Thing to the Server. The Thing periodically connects to the Server — usually to a RESTful API — and, in one transaction, uploads its current status and requests any queued commands. Polling is problematic for two reasons. One, returning results or error status from the queued commands requires another round-trip to the Server (and leads to code complexity on the Server, which must track the outstanding command state). Two, more importantly, the latency is high: There is an undesirable delay between when the user issues a command on his app, and when the Thing responds to that command. That delay can be mitigated by having the Thing poll more frequently; but then we start to run into trouble with scaling the Server to handle lots of Things.
- Maintain an Open Socket. In this alternate approach, the Thing still initiates the connection, but then holds it open — typically using websockets. You then create a bidirectional protocol between the Thing and the Server that allows either side to initiate a command over the open socket, which results in fast response times when the user issues a command from the app. On the minus side, this approach (at least using websockets) can require more resources to implement on the Thing side. Furthermore, it can quickly run into scalability concerns on the Server — though it’s probably more efficient than polling, depending on your polling interval.
- Bi-directional Push. Most connected devices spend a lot of their time in a “nothing-changed” state. So by far the most efficient and scalable case is a bi-directional push, where the Thing connects to the Server only with a relatively infrequent heartbeat message, or when it has something new to report. This direction is a single call to a RESTful API and is simple to implement. The reverse direction (Server to Thing) is equally important, and it’s hard. There are various ways to punch holes through the firewalls common in houses, although most are over UDP instead of TCP, and none of them is completely reliable because of the diversity of home router technology out in the wild. So if you implement bi-directional push, the Thing needs to be able to fall back to one of the first two methods if it doesn’t work.
I’m unaware of anyone who has deployed the bi-directional push approach in production — but again very few Things have hit the level of commercial success where server-side scalability becomes super important. I expect that to change within the next year.