RaspberryPi: A computer that with the help of its embedded GPIO ports supports the connection of sensors and actuators. Due to its native Linux operating system it is possible to run a NET Core application that connects easily with Azure IoT Hub.
Azure IoT Hub: As part of the cloud services provided by Microsoft, the Azure IoT Hub is a specialized solution to provide bi-directional communication with any device. It mainly allows to process messages and send commands to connected devices. It also provides an administration interface which allows us to easily manage IoT devices, as well as seamlessly connects to other Azure products.
Azure Stream Analytics: This Azure products goes hand in hand with the Azure IoT Hub. It integrates with it to enable real time analytics on any data captured by the connected IoT devices.
Azure Cosmos DB: This is a storage solution that allows long term data persistence. It is a multi-model and multi-API product, which means that it is possible to store any type of data from documents to traditional table data and query it with multiple approaches such as SQL or MongoDB.
Azure WebApp: This is a service to host web applications on the cloud. It provides the necessary infrastructure to develop in many languages and to run and scale apps easily on Windows or Linux VM’s. Due to its easy integration to Visual Studio publishing it is ideal for creating apps that can be built and deployed in just a couple of seconds.
Azure IoT Hub
One of the most important pieces of the whole application is the Azure IoT Hub. In order to have a working prototype we need to be able to create one directly through the Azure Portal. This process is completely transparent and easy to follow.
After creating an IoT Hub several options are presented. One of the most important is the ability to manage devices directly from the portal. By clicking on the IoT Devices option, we can create a new device. Once done, we are ready to proceed coding the client app.
RaspberryPi Client App
It is necessary to first install the NET Core runtime on Raspbian so that the client App can run. Because it is not in the scope of this article to collect data from the real world, the temperature sensor and refrigerant flow control will be simulated by software. The application will create temperature sensor data and send it to the Azure IoT Hub on a periodic basis. It will also listen to messages coming in from the Azure IoT Hub that will instruct the device to perform actions accordingly. In this case a simulated refrigerant flow will be received and printed to the console.
The following is the main routine of the application which instantiates a mock temperature sensor as well as a mock refrigerant flow actuator and creates an object that will serve as the connection to the Azure IoT Hub. After that it wakes up every ‘n’ seconds, reads a temperature measurement, sends it to the IoT hub and listens for any command coming in to the device and acts accordingly.
The most important piece of this code is the actual implementation of the IHubManager
which handles the communication to the IoT hub. This component is in charge of starting a connection via the DeviceClient class. This class lives inside the Microsoft.Azure.Devices.Client namespace which can be obtained via a nuget package and is initialized as follows:
When connecting to the Azure IoT Hub, the DeviceClient handles all authorization and authentication based on the specified connection string which can be found for every device on the Azure IoT Hub management screen. This is included in an appsettings.json file on the same directory as the application and contains the following:
It is important to notice that as the time of this writing the implementation of the DeviceClient class is still constantly changing and that some of the supported transport types such as AMQP or MQTT were not working as expected. Therefore for the current application communication over websockets was preferred. Please also notice that all other classes related to the Azure IoT Hub data manipulation such as TransportType and Message need to come from the Microsoft.Azure.Devices.Client.The reason why this is important will be specified further on.
Once the connection has been opened then we can proceed and use the DeviceClient object to get and send commands to the IoT hub as follows:
As soon as the client app is compiled and running in the RaspberryPi, we can proceed and code the web api.
This is a NET Core app which is deployed as a WebApp in Azure. The purpose of the web api application is to offer the possibility to interact in real time with the IoT Hub and to be able to retrieve the messages that were sent from the device to the cloud, as well as to provide an endpoint to send commands to any of the listening clients. The API will also be able to interact directly with the IoT Hub to query the list of existing devices.
In order to carry out these operations a new implementation of the IHubManager class is needed. This will be very similar to the one already existing for the RaspberryPi client, however the most important difference is that this time the classes belonging to the Microsoft.Azure.Devices namespace will be used. It is very important not to confuse both namespaces as they offer completely different functionality, mainly differing in the way the communication flows (device-to-cloud vs cloud-to-device).
In order to initialize the connection the ServiceClient class needs to be used. This class provides functionality to send messages to a specific device and needs to be initialized as follows:
Another class that is provided by the Microsoft.Azure.Devices namespace is the RegistryManager class which provides functionality to directly interact with the IoT Hub and exposes operation such as querying devices, as well as the ability to create and manage existing ones. Initialization of this class is very similar and is as follows:
Both of these two objects require for initialization a connection string value which case can be found in the management screens for the Azure IoT Hub. The connection string will not be device specific as it will interact directly with the hub and not with a specific client:
Once all configuration has been loaded and the RegistryManager and ServiceClient objects have been initialized, a sample implementation for the IHubManager can be specified as follows:
As seen in the previous code snippet, running a query is a very simple process that allows easy manipulation of the devices and giving the application access to properties such as the device status, last connection time, and any other properties found in the device twin. However, it is very important that even though the twin contains information about the connection state of the device, this field should not be used in production environments to implement any type of device heartbeat implementation. Instead a heartbeat pattern should be implemented.
Streaming Analytics Job
Because the Azure IoT Hub works as a message broker it will only be useful in real time scenarios where messages need to be distributed from the device to the cloud or vice versa. Although the Azure IoT Hub provides message retention between one to seven days, it will only deliver any pending message when the missing recipient is connected. Once such recipient acknowledges the message reception, then it will no longer stay in memory of the IoT Hub.
Therefore, whenever there is a need to perform any data analysis on the messages that go through the hub, we need to add a new Azure product to our application. This is what the streaming analytics jobs are for. They add the ability to perform custom actions on the data as it goes through the IoT hub on real time.
For this sample application, we are interested in having a historic backup of the temperature data so that it can be viewed in a graph at any point in time. This can be accomplished by linking an Azure Cosmos DB instance to the Azure IoT Hub via an Streaming Analytics Job. Please be advised that as the time of this writing there is no support to integrate the Azure Stream Analytics with an Azure Cosmos DB using MongoDB API and therefore the SQL API was used. .
Once the Streaming Analytics Jobs has been created it will be just a matter of declaring the IoT Hub as an input and the Cosmos DB as an output from the management portal and then declare a query that applies to all incoming messages as follows:
Upon starting the Streaming Job and running the client app on any RaspberryPi it is possible to confirm that the received messages which contain the temperature data as well as other important information such as the device id origin of the message are being logged into the configured database:
Now we are able to query the data contained in the Cosmos DB by any consuming application. In this particular case an API endpoint was provided by the Web API through the usage of the DocumentDB Nuget Package.
The purpose of this UI is just to provide an interface to interact with the Web API designed earlier. It provides the ability to send messages to a specific device in real time as well as show a chart of the temperature measurements. The implementation of this UI is out of the scope of this article. The final product can be appreciated as follows: