While developing IoT devices for a few years now for various projects, we faced one challenge in all of them: how do we test and debug our cloud while having no IoT device ready?
These IoT projects usually start with a kickoff, where we learn what the IoT device is supposed to do and how we want to integrate it, followed by designing an architecture including the IoT device and cloud and how they will communicate with each other. We are using a lot of Azure IoT services which enables us to have fast iterations and off the shelf device-2-cloud / cloud-2-device communication. Starting the developing cycle afterwards includes the hardware-, embedded software-, cloud infrastructure, backend- and frontend development. All components are developed simultaneously so you would have to wait for the IoT device to be finished to validate your cloud setup.
A typical Azure IoT architecture could look like this:
Obviously, it is never this simple but should give an idea for what we want to test and debug. Please keep in mind that this is just an example and there are a lot of other ways to ensure device-2-cloud / cloud-2-device communication. Find below a quick overview of the services:
- Device Provisioning Service: It is crucial that only IoT devices manufactured by our customers are able to communicate with our cloud, therefore the DPS service has multiple options to ensure this. For example, it holds an intermediate certificate and does a mutual authentication with devices which try to authenticate. If it succeeds, it will send back an IoT Hub URL to the device which is now able to communicate with the IoT Hub.
- IoT Hub: The IoT Hub enables MQTT connections to devices that can then send data on various routes which are linked to Event Hubs. It also offers functionalities like the Direct Methods and Device Twins.
- Direct Method: Basically, a translation from HTTP to MQTT which enables our backend to send commands/data to the device.
- Device Twin: A device usually has some sort of state which is replicated to the cloud using the Device Twin. The Device Twin distinguishes between the actual and desired state. The device updates the actual state, while the cloud has control overwriting to the desired state. Both sides may access the Twin and Azure is keeping care of ensuring that these are (eventually) up to date whenever one side makes a change. Unfortunately, it has a 32 kB size limit for the state, which is sometimes just not enough.
- Event Hub: The IoT Hub itself behaves mostly like a message broker and RPC provider. In order to retain messages until they are read and organize multiple consumers for individual messages, a common strategy is to use a message queue. Luckily, the Azure Event Hub is doing exactly that.
- AKS Backend: Backend hosted in Kubernetes. This is where the domain logic resides. While the infrastructure defines how the cloud communicates with IoT devices and can be seen in various projects, the domain logic defines what is communicated and how to react, which differs significantly from project to project.
The first IoT projects by grandcentrix developed these kinds of clouds without having an IoT device available and therefore no good tooling to test the developed features. So the developers created their own project-specific Device Simulators. Depending on the project, they were able to hold a state and respond on Direct Methods with defined values and were also able to send data, like telemetry in an interval. They were written in different programming languages, using arbitrary tools and frameworks. They didn’t share the same name and oftentimes were simple shell scripts (and, to be honest, rather messy). But: they got the job done. Nevertheless, we felt like we could improve that. Instead of reinventing the wheel for every project, why not introduce a general-purpose Device Simulator which can be used to support the development of many different IoT projects?