07 Jan 2019 Duct-taping things to the internet with Google’s IoT Core
During my time with an energy company, I worked in a team which had a set of unicorn fairy lights. Jokingly I suggested that they should have individual RGB LEDs which could tell the status of the app, the weather and… next thing I know I’ve built a set of internet connected RGB unicorn lights. This is a short description of how I built them; but first a short video of them in action….
How majestic are those? I’d be jealous… if I didn’t have 40 more RGB LEDs spare. I should also point out this is not the most efficient way to do this, or even possibly the best way to do this. You could equally just have a JSON file in a Google Cloud Storage bucket that you poll every 5 mins. But where would the fun be in that?
Each of the lights contains the ubiquitous (at least in the world of flashy RGB lights) WS2811 chip. They are connected in a long chain to the PWM pin on a Raspberry Pi Zero W via a buffer chip which is used as a level converter. See the diagram below for how I wired everything up:
The Raspberry Pi runs a small NodeJs backend which communicates with Google’s IoT-Core via MQTT. The dashboard you can see in the video is the default device registry in IoT-Core, which I’ll explain in more detail in a sec. The backend makes use of a couple of native libraries to talk to the hardware. Unsurprisingly, there are many npm packages for this, and I chose the rpi-ws281x package, as it seemed to have been mentioned in the most places. It was pretty straightforward, just requiring an array of 32bit Integers to describe the lights.
IoT Core is Google’s IOT device management product. It provides tools and infrastructure for managing IoT device configuration and the telemetry data coming back from the device. This application is slightly contrived: it has little telemetry data that needs to be processed. I’ll provide a better example in an upcoming article.
Devices in IoT Core are grouped into registries which are available in 3 regions currently. I chose asia-east-1 as it’s geographically close, but for the volume of data and devices here, I could have picked the moon and it wouldn’t have made a difference.
During the creation of the registry, you will be asked where you want the data from the device to go to. Currently the only choices are a pub/sub queue or to be ignored. In this instance I created a pub/sub queue for the telemetry as i had the intent of reporting the light status, but currently it is unused.
Next step is to create a device in the registry. IoT-Core provides two APIs for the device: one via MQTT and one via http. I chose MQTT as I wanted to subscribe the device and have updates be pushed out to it, rather than having to poll. This is secured using a JWT with an RSA public key pair registered ahead of time. Key generation and the RSA signing can prove to be challenging if you’re using super-low-end hardware, as I found out during my first attempt when I tried to use an 80MHz esp2866 micro-controller to control the lights, and ran out of code space whilst trying to run an MQTT client and RSA implementation.
Once connected, you need to subscribe to the correct queues. There are 3 to choose from: data, config, and status.
Data, as the name implies, is for data from the device; for instance if you were measuring something, then you would publish the readings to this queue. Nothing from IoT Core writes to this queue and things published to it end up on the pub/sub queue you created earlier for later processing.
Status is for device status, and is intended as a low volume queue to provide status updates about the device, rather than telemetry. Again, nothing from IoT Core writes to this queue.
Finally, the config queue is the one we’re interested in. It is the queue which IoT Core pushes device config out on. Every time a device connects, IoT-core pushes its last config out to it. If a device is restarted it will get the last configuration that it had before. Great for ensuring our lights are always showing something. If the configuration is changed, either through the Dashboard, or through the API, it is pushed to the devices via this queue: they can have their configuration updated in real-time. Just like the status queue, the config queue is intended to be low-volume, with configuration updates limited to once a second.
IoT Core provides a super convenient and secure method for managing IoT devices. Was it over-engineering for this project? Definitely. But when you need to process large amounts of real-time streaming data from devices at the edge, such as set-top boxes, electricity meters, or other IoT applications (even Unicorn lights), IoT Core would be my first choice, and I wouldn’t give it a second thought, due to its ease of use and its relatively low-cost.