Updating apps running on hundreds of IoT devices
Project: a system for updating the apps running on hundreds of IoT devices
Tech Stack: NodeJS, ExpressJS, React, Redux, RxJS, Webpack, ImmutableJS, SocketIO, MongoDB, MQTT (EMQ Broker)
During my two years spent working at Viriciti, a Dutch company that develops a monitoring system for electric buses, I had to work on a complex system used to update multiple apps running on hundreds of devices mounted on buses driving all around the world.
The apps were of different kinds, for example, there was one for device monitoring (ex. CPU, memory, processors, etc…), one for changing the device’s settings and the most important one for reading real-time bus data and send it to the cloud. Each of these apps is running in Docker containers, so it’s really easy to update them when a new version is available.
Even though this may be easily done manually for a single device when dealing with hundreds of them the story is completely different. The big challenge that I had to face was: “What’s the best way to update the apps, easily, safely and continuously?”
The idea that led the systems’ design was its push-based fashion, that is, the device should not need to request new updates, for then pulling them from a remote origin, but instead, the updates are pushed to the devices, which must automatically update.
The system is composed of two main components. A web app with a dashboard providing an overview of the (apps) state of the devices and a set of functionalities to configure the updating process. A device application, acting as an interface between the device itself and the docker-layer and responsible for upgrading the other apps correctly (even itself).
The following diagram provides an overview of the system’s architecture:
Web App (Dashboard)
The dashboard provides an overview of the (apps) state of all devices running on the field and a set of functionalities to configure the updating process. Each device has its own details page, showing the installed apps and their status, but also providing a set of commands (ex. restart, delete) to perform over the apps remotely.
The dashboard also provides a configuration page, where it is possible to manage the apps repository (in our case, the Docker Registry). This page shows an overview of all the applications available for installation on the devices, and it keeps track of what’s the latest installed version on them. Each app can be downgraded or upgraded to a different version, and automatically all the devices would reflect the change!
The device client-component has the only responsibility to listen and execute actions coming from the web app and to broadcast its state over MQTT. Most importantly, it includes an algorithm to update correctly the device’s application layer using the Docker API.
All the communication between the device app and the web app is made via MQTT, using the library device-mqtt. device-mqtt is used to perform RPC (Remote Procedure Call) using MQTT, and I explained here what’s the reasoning behind it.
Shortly, the MQTT broker (EMQ) is used to both store the state of all the devices (installed apps, online/offline, etc…) and to send actions from the web app to the device(s). Each of these actions can receive a response immediately or any time in the future, thanks to MQTT nature.
Do you have any questions about this project? Drop me a message at firstname.lastname@example.org