Enviar mensajes cloud-to-device a Raspberry con Docker, .NET Core y Web App On Linux (parte III - Azure IoT Hub cloud-to-device API)
Nota:
Este post es la continuación de la guía: “Enviar mensajes device-to-cloud a Azure IoT Hub desde Raspberry usando Node.js y Docker (parte II - envío de mensajes)” , favor de realizar primero los paso del post antes de seguir con esta publicación.
Pre Requisitos
- Raspberry Pi2+
- Raspbian OS
- Conexión a Internet
- NPM
- Tener una suscripción de Azure
- Si no tienes una, puedes obtener un free trial
- Visual Studio 2017, obtenerlo gratis aquí.
- Docker para Windows, obtenerlo aquí.
Arquitectura de envío y procesamiento de mensajes Azure IoT Hub:
Fuente: https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-what-is-iot-hub
Descargar código de GitHub:
https://github.com/Kodran/RPi-Docker-Azure-IoTHub
Crear .NET Core Web API con soporte de Docker en Visual Studio
En Visual Studio creamos un nuevo proyecto .NET Core llamado: Azure.IoTHub.CloudToDevice.API.
Templates –> Visual C# –> .NET Core –> ASP.NET Core Web Application (.NET Core)
Luego vamos a elegir la opción de Web API con soporte a Docker activado:
Probar contenedor Docker de .NET Core localmente
Nota: antes de correr un contenedor localmente, aseguremos que “Docker for Windows” se encuentre corriendo y que nuestras particiones se encuentre compartidas. Para esto podemos ir a “Inicio –> búsqueda –> Docker for Windows:
Para crear y desplegar un contenedor localmente solo damos clic en el botón “Docker” en Visual Studio, esto disparará una tarea de compilación automática de Docker para crear y desplegar el contenedor en una maquina virtual de Hyper-V:
Una vez que termine de crear el contenedor, podemos abrir nuestra consola para verificar que efectivamente nuestro contenedor fue creado y desplegado correctamente.
Ingresamos los comandos:
docker images
docker ps
Desplegar contenedor Docker de .NET Core a Web App On Linux
Damos clic derecho en nuestro proyecto “Azure.IoTHub.CloudToDevice.API” y seleccionamos “Publish”, luego elegimos App Service Web App On Linux y desplegamos nuestro contenedor:
Probar endpoint de contenedor de Azure Web App On Linux
Para comprobar que nuestro contenedor fue desplegado correctamente en Azure, ingresamos a https://portal.azure.com y vamos a la sección de App Service:
Ahora hacemos una petición a nuestra Web API con endpoint de Azure:
Crear API para envío de mensajes cloud-to-device
En nuestro proyecto agregamos un nuevo controlador llamado: CloudToDeviceController
Ahora creamos el modelo de entrada de datos a nuestra API: “CloudToDeviceMessage.cs”:
Agregar dependencias de Azure IoT Hub
En nuestro proyecto damos clic derecho en dependencias y luego agregamos la librería de NuGet: “Microsoft.Azure.Devices”:
Codificar método POST de envío de mensajes device-to-cloud
Agregar siguiente código en nuestro controlador CloudToDeviceController.cs y la cadena de conexión de IoT Hub:
CloudToDeviceController.cs
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Azure.IoTHub.CloudToDevice.API.Model; using Microsoft.Azure.Devices; using System.Text; namespace Azure.IoTHub.CloudToDevice.API.Controllers { [Produces("application/json")] [Route("api/CloudToDevice")] public class CloudToDeviceController : Controller { private static string connectionString = "your-azureiothub-primaryKey-connectionString"; [HttpPost] public async Task
Post([FromBody]CloudToDeviceMessage message) { try { var serviceClient = ServiceClient.CreateFromConnectionString(connectionString); var commandMessage = new Message(Encoding.ASCII.GetBytes(message.Message)); await serviceClient.SendAsync(message.DeviceId, commandMessage); return new OkObjectResult(message); } catch (Exception ex) { Response.StatusCode = 500; return new ObjectResult(new Exception(ex.Message)); } } } }
Lo que hace él código es recibir un mensaje por POST y tomar el deviceId y mensaje para luego enviarlos a un dispositivo registrado en IoT Hub.
Publicar contenedor en Azure Web App On Linux
Damos clic derecho en nuestro proyecto y volvemos a publicar nuestro contenedor en Azure:
Crear recibidor de mensajes cloud-to-device IoT Hub
Una vez que hemos logrado publicar nuestro contenedor que envía mensajes a nuestros dispositivos, vamos de vuelta a la Raspberry para crear un contenedor que se va a encargar de recibir los mensajes de Azure IoT Hub.
$ cd reader
$ sudo mkdir cloudToDeviceReader
$ cd cloudToDeviceReader
- package.json
- readCloudToDeviceMessage.js
- Dockerfile
- .dockerignore
{ "name": "azure-iothub-cloudToDevice-reader", "version": "1.0.0", "description": "docker nodejs azure iot hub cloud to device reader", "main": "readCloudToDeviceMessage.js", "scripts": { "start": "node readCloudToDeviceMessage.js" }, "author": "Jorge Castro", "license": "ISC", "dependencies": { "azure-event-hubs": "0.0.8", "azure-iot-device": "^1.1.14", "azure-iot-device-mqtt": "^1.1.14", "azure-iothub": "^1.1.11" } }
'use strict'; var iothub = require('azure-iothub'); var connectionString = 'your-azure-iothub-primaryKey-connectionString'; var registry = iothub.Registry.fromConnectionString(connectionString); var device = new iothub.Device(null); this.init = function(){ device.deviceId = 'dockerNodejsDevice'; registry.create(device, function(err, deviceInfo, res) { if (err) { registry.get(device.deviceId, printDeviceInfo); } if (deviceInfo) { printDeviceInfo(err, deviceInfo, res) } }); function printDeviceInfo(err, deviceInfo, res) { if (deviceInfo) { console.log('Device ID: ' + deviceInfo.deviceId); console.log('Device key: ' + deviceInfo.authentication.symmetricKey.primaryKey); console.log('Waiting for cloud message...'); } } } this.readCloudToDeviceMessage = function(){ var clientFromConnectionString = require('azure-iot-device-mqtt').clientFromConnectionString; var Message = require('azure-iot-device').Message; var deviceConnectionString = 'your-iothub-deviceId-primaryKey-connectionString'; var client = clientFromConnectionString(deviceConnectionString); function printResultFor(op) { return function printResult(err, res) { if (err) console.log(op + ' error: ' + err.toString()); if (res) console.log(op + ' status: ' + res.constructor.name); }; } var connectCallback = function (err) { if (err) { console.log('Could not connect: ' + err); } else { client.on('message', function (msg) { console.log('Id: ' + msg.messageId + ' Body: ' + msg.data); client.complete(msg, printResultFor('completed')); }); } }; client.open(connectCallback); } this.init(); this.readCloudToDeviceMessage();
Dockerfile
FROM robotany/raspberrypi-nodejs # Create app directory RUN mkdir -p /usr/src/app WORKDIR /usr/src/app # Install app dependencies COPY package.json /usr/src/app/ RUN npm install # Bundle app source COPY . /usr/src/app EXPOSE 8080 CMD [ "npm", "start" ]
node_modules npm-debug.log
Crear y correr contenedor para recibir mensajes cloud to device
Vamos a la ruta de nuestro programa que recibe los mensajes cloud-to-device en consola y ejecutamos los siguientes comandos de Docker:
$ cd projects/azure-iothub-demo/reader/cloudToDeviceReader
$ sudo docker build –t yourUser/rpi-azure-iothub-cloud-reader .
$ sudo docker run yourUser/rpi-azure-iothub-cloud-reader
Probar envío de mensajes cloud to device
Para enviar un mensajes a nuestra Raspberry, vamos a realizar una petición POST a nuestra API.
Puedes utilizar Postman para realizar peticiones a Azure. La manera en que vamos a realizar la petición a Azure es enviando un mensaje JSON con la estructura del modelo: “CloudToDeviceMessage.cs”.
Ingresamos el endpoint de nuestra API y la petición en el cuerpo del mensaje:
Consola de contenedor de Raspberry:
Enviar otro mensaje a dispositivo:
Muchas felicidades!! haz logrado programar un flujo completo de envío de mensajes device-to-cloud y cloud-to-device usando Azure IoT Hub, Docker y Raspberry.
Azure nos ofrece una gran variedad de servicios que nos permite extender la funcionalidad de IoT Hub, entre ellas podremos encontrar procesamiento de mensajes para diversos propósitos. Les dejo algunos articulos de la documentación oficial de Microsoft donde explica como lidiar con diferentes tipos de escenarios de IoT:
- Manage cloud device messaging with iothub-explorer
- Save IoT Hub messages to Azure data storage
- Use Power BI to visualize real-time sensor data from Azure IoT Hub.
- Use Azure Web Apps to visualize real-time sensor data from Azure IoT Hub.
- Weather forecast using the sensor data from your IoT hub in Azure Machine Learning
- Device management with iothub-explorer
- Remote monitoring and notifications with Logic Apps
Descargar código de GitHub:
https://github.com/Kodran/RPi-Docker-Azure-IoTHub
Artículos relacionados:
- Enviar mensajes a Azure IoT Hub desde Raspberry usando Node.js y Docker (parte I – instalación)
- Enviar mensajes device-to-cloud a Azure IoT Hub desde Raspberry usando Node.js y Docker (parte II – envío de mensajes)
Comments
Post a Comment