Enviar mensajes device-to-cloud a Azure IoT Hub desde Raspberry usando Node.js y Docker (parte II - envío de mensajes)
Nota:
Este post es la continuación de la guía: “Enviar mensajes a Azure IoT Hub desde Raspberry usando Node.js y Docker (parte I – instalación)” , 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
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 servicio de Azure IoT Hub
Ingresamos a https://portal.azure.com y buscamos por “IoT Hub”.
Para esta demo vamos a elegir una servicio “Free” y elegimos la localización de nuestro recurso en un data center de Azure, recuerda que es recomendable elegir el data center mas cercano a nuestros dispositivos.
Una vez que llenemos toda la información, damos clic en crear y esperamos a que Azure terminé de instalar toda la infraestructura de nuestro nuevo servicio.
Una vez desplegado nuestro servicio de IoT Hub podremos explorar sus propiedades y llaves de conexión al servicio:
Instalar dependencias y codificar registro de dispositivo
La única manera en que un dispositivo pueda enviar mensajes Azure IoT Hub, es registrando nuestro dispositivo mediante las llaves de conexión que nos ofrece Azure. Pare registrar un dispositivo primero debemos de instalar la librería de IoT Hub para Node.js en la aplicación, lo cual esto permitirá crear una conexión segura a Azure para el registro y envió de mensajes device-to-cloud a IoT Hub
Instalar azure-iothub:
Devuelta en el ambiente de Raspberry, ingresamos el siguiente comando en la ruta de nuestra aplicación de Node.js:
$ cd projects/azure-iothub-demo/
$ sudo npm install azure-iothub -- save
Registrar aplicación en Azure IoT Hub:
Ahora lo que vamos hacer es remplazar el código que tenemos en nuestra aplicación de Node.js por el siguiente:
app.js
'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); } } }
this.init();
Lo que hace el código que ingresamos es registrar un dispositivo y desplegar su información en consola, si el dispositivo ya existe únicamente desplegamos su información en consola proveniente de Azure IoT Hub.
Probar registro de dispositivo
Para realizar la prueba de que nuestro dispositivo se puede registrar correctamente en Azure, vamos a correr la aplicación con el siguiente comando:
$ sudo node app.js
Ahora comprobamos en el portal de Azure que nuestro dispositivo realmente fue registrado:
Instalar dependencias y codificar envío de mensajes a Azure IoT Hub
Para enviar mensajes a IoT Hub se necesita las librerías “azure-iot-device y azure-iot-device-mqtt”.
Ingresamos el siguiente comando para instalar:
$ npm install azure-iot-device azure-iot-device-mqtt --save
Envío de mensajes:
Ahora lo que vamos hacer es agregar el siguiente código en nuestra aplicación de Node.js, agregando la llave primaria de conexión de nuestro dispositivo:
app.js
this.sendMessage = function(){ var clientFromConnectionString = require('azure-iot-device-mqtt').clientFromConnectionString; var Message = require('azure-iot-device').Message; var deviceConnectionString = 'yourDevice-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 { console.log('Client connected'); // Create a message and send it to the IoT Hub every second setInterval(function(){ var data = JSON.stringify({ deviceId: 'dockerNodejsDevice', msg: "Hello azure, i'm a dockerized nodejs app", date: new Date() }); var message = new Message(data); console.log("Sending message: " + message.getData()); client.sendEvent(message, printResultFor('send')); }, 1000); } }; client.open(connectCallback); } this.init(); this.sendMessage();
Al final el código de la aplicación debe quedar de la siguiente manera:
app.js
'use strict'; var iothub = require('azure-iothub'); var connectionString = 'your-iothub-primarKey-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); } } } this.sendMessage = function(){ var clientFromConnectionString = require('azure-iot-device-mqtt').clientFromConnectionString; var Message = require('azure-iot-device').Message; var deviceConnectionString = 'your-device-primarKey-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 { console.log('Client connected'); // Create a message and send it to the IoT Hub every second setInterval(function(){ var data = JSON.stringify({ deviceId: 'dockerNodejsDevice', msg: "Hello azure, i'm a dockerazed nodejs app", date: new Date() }); var message = new Message(data); console.log("Sending message: " + message.getData()); client.sendEvent(message, printResultFor('send')); }, 1000); } }; client.open(connectCallback); } this.init(); this.sendMessage();
Probar envío de mensajes:
Para probar el correcto envío de mensajes a Azure IoT Hub, vamos a correr la aplicación:
$ sudo node app.js
Crear recibidor de mensajes de IoT Hub
Una vez que hemos logrado enviar mensajes a Azure IoT Hub, podemos crear un programa que reciba estos mensajes y de alguna manera procesarlos. En nuestro caso solo vamos a recibir mensajes y los desplegaremos en la consola para probar el correcto funcionamiento del servicio de Azure y de nuestra aplicación.
$ sudo mkdir reader
$ cd reader
$ sudo npm install azure-event-hubs --save
{ "name": "azure-iothub-reader", "version": "1.0.0", "description": "docker nodejs azure iot hub reader", "main": "readIoTHubMessages.js", "scripts": { "start": "node readIoTHubMessages.js" }, "author": "Jorge Castro", "license": "ISC", "dependencies": { "azure-event-hubs": "0.0.8" } }
'use strict'; var EventHubClient = require('azure-event-hubs').Client; var deviceConnectionString = 'your-iothub-primaryKey-connectionString'; this.init = function(){ var printError = function (err) { console.log(err.message); }; var printMessage = function (message) { console.log('Message received: '); console.log(JSON.stringify(message.body)); console.log(''); }; var client = EventHubClient.fromConnectionString(deviceConnectionString); client.open() .then(client.getPartitionIds.bind(client)) .then(function (partitionIds) { return partitionIds.map(function (partitionId) { return client.createReceiver('$Default', partitionId, { 'startAfterTime' : Date.now()}).then(function(receiver) { console.log('Created partition receiver: ' + partitionId) receiver.on('errorReceived', printError); receiver.on('message', printMessage); }); }); }) .catch(printError); } this.init();
Recibir mensajes de Azure IoT Hub:
Para probar que nuestros mensajes se recibieron en Azure, vamos a correr un programa para recibir estos mensajes para luego desplegarlos en consola:
Correr app.js - envío de mensajes:
$ sudo node app.js
Correr readerIoTHubMessages.js – recibidor de mensajes:
$ sudo node readerIoTHubMessages.js
Crear contenedores Docker y correr nuestras aplicaciones
Para probar que podemos enviar y recibir mensajes desde nuestros contenedores, vamos a crear archivos Dockerfile y luego los ejecutaremos con comandos de Docker:
Crear Dockerfile de contenedor de envío de mensajes:
Crear archivo Dockerfile con los siguientes comandos:
$ cd projects/azure-iothub-demo/
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/appEXPOSE 8080
CMD [ "npm", "start" ]
Crear contenedor de envío de mensajes:
$ cd projects/azure-iothub-demo/
$ sudo docker build –t yourUser/rpi-azure-iothub-sender .
Crear Dockerfile de contenedor de recibidor de mensajes:
Crear archivo Dockerfile con los siguientes comandos:
$ cd projects/azure-iothub-demo/reader/
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
Crear contenedor para recibir de mensajes:
$ cd projects/azure-iothub-demo/reader/
$ sudo docker build –t yourUser/rpi-azure-iothub-reader .
Ahora corremos el siguiente comando para ver que nuestros contenedores fueron creados correctamente:
$ sudo docker images
Correr contenedor de envío de mensajes:
Para correr nuestro contenedor solo ingresamos el siguiente comando de Docker:
$ sudo docker run yourUser/rpi-azure-iothub-sender
Correr contenedor para recibir de mensajes:
Para correr nuestro contenedor solo ingresamos el siguiente comando de Docker:
$ sudo docker run yourUser/rpi-azure-iothub-reader
Genial!! hemos logrado enviar y recibir mensajes desde los contenedores de Docker en Raspberry. La conexión a Azure IoT Hub también se puede lograr con programas de .NET Core, Python o Java desde contenedores.
Ahora podemos enviar mensajes de telemetría o enviar mensajes personalizados mas adaptado a flujos de negocio a Azure IoT Hub. Las posibilidades son muchas, y gracias al poder de Azure podemos orquestar nuestros mensajes y extender la funcionalidad de IoT Hub para procesar estos mensajes para propósitos de analítica, predicción, almacenamiento, etc.
Una de las grandes ventajas de Azure IoT Hub es que podemos hacer una comunicación bidireccional entre nuestros dispositivos y la nube, en el siguiente articulo veremos como enviar mensajes desde la nube a nuestro dispositivo Raspberry.
Descargar código de GitHub:
https://github.com/Kodran/RPi-Docker-Azure-IoTHub
Siguientes pasos:
Comments
Post a Comment