Primeros pasos con Azure IoT Hub

Desde la aparición de las primeras soluciones de dispositivos de Internet Of Things (IoT), surge la necesidad de tener un backend sólido y confiable en el que poder registrar los datos generados por los diversos dispositivos.

Actualmente Azure nos provee del Servicio de Hub de IOT (https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-what-is-iot-hub), con el que podemos comunicar bidireccionalmente y de manera segura nuestros dispositivos IoT y nuestro backend de soluciones. Con este servicio seremos capaces no sólo de hacer una gran ingesta de datos por varios dispositivos y de manera simultánea en la nube, sino que también seremos capaces de hacerlo de manera escalable y segura.

Sería una tarea titánica construir un backend propio para alojar toda esta información, así como gestionar la escalabilidad y la seguridad del mismo. Por este motivo, debemos siempre plantearnos el llevar este tipo de solución de backend a la nube.

Además, debido a la amplia gama de dispositivos que conforman todo el ecosistema de campo (Field), nos vamos a encontrar siempre con una serie de dificultades:

  • Por regla general, nos vamos a encontrar con dispositivos que se encuentran en ubicaciones remotas, donde es difícil acceder físicamente, con una conectividad, ancho de banda y autonomía limitados, por lo que minimizar el consumo de energía es crucial. Normalmente estos sistemas son operados sin intervención humana.
  • Es posible que necesiten usar protocolos de aplicación propios, personalizados o específicos de determinados sectores.
  • Pueden crearse mediante un amplio conjunto de plataformas populares de hardware y software.
  • Necesidad de acceso al dispositivo desde el backend de soluciones.

Actualmente, para resolver estas problemáticas, disponemos de Azure IOT Hub, y ésta es la solución recomendada por Microsoft, pero antes de la aparición de este servicio también era posible conectar los dispositivos a la nube, directamente a un centro de Eventos (Event hub). Sin embargo, atacar directamente a un centro de Eventos no nos permite beneficiarnos de los aspectos de seguridad y escalabilidad que IOT Hub sí nos proporciona.

Sin embargo, eso no significa que los Event Hubs hayan desaparecido como tal de la ecuación de IoT. Normalmente nos encontraremos en escenarios en los que Azure IOT Hub se configura como receptor de mensajes por parte de los diversos dispositivos de IOT, y tendremos un centro de Eventos “a continuación” del Hub que nos permitirá extraer los mensajes enviados y transformarlos mediante un Job de Stream Analytics a otras salidas para su posterior procesado por otro tipo de servicios y/o aplicaciones, como se ilustra en el diagrama anterior.

Un escenario típico puede ser aquél en el que estemos continuamente recolectando información desde Azure IOT Hub, para posteriormente procesar toda esta información mediante uno o varios Event Hubs a través de los respectivos Jobs de Stream Analytics para transformar los datos de entrada a Power BI, para, entre otras cosas, poder preparar un dashboard en tiempo real con los datos que están siendo recogidos en ese momento. Todo este proceso es ultra-rápido a fin de poder visualizar toda esta información en tiempo real y poder actuar de manera rápida y eficiente ante cualquier eventualidad indicada por el sistema.

Actualmente los Jobs de Stream Analytics permiten transformar los datos extraídos por los centros de Eventos a los siguientes formatos:

  • Base de Datos SQL
  • Almacenamiento de Blobs o de Tablas
  • Centro de Eventos
  • Service Bus
  • DocumentDB
  • PowerBI
  • Data Lake Store

En cuanto a las herramientas de las que disponemos para conectar con Azure IOT Hub, podemos encontrar un sinfín de librerías de cliente que nos facilitarán la labor a la hora de trabajar con diversos sistemas operativos y con dispositivos embebidos (los cuales serán, en la práctica, la mayoría de dispositivos que podemos encontrar).

Actualmente disponemos de SDKs ya listos para ser usados en aplicaciones de Node.js (en lenguajes .Net, Java y Javascript).

No obstante, Azure también nos provee de SDKs propios para desarrollar lo que se conoce como “Puerta de Enlace”. Básicamente, esto consiste en desarrollar el cliente de conexión contra un IOT Hub en el caso de que nos encontremos en una plataforma Linux. Podemos solventar este último paso utilizando Mono, o incluso Java o Node.Js.

 

A continuación, utilizaremos las librerías cliente escritas en .Net para implementar tres escenarios que necesitaremos de manera recurrente en nuestras aplicaciones de IOT:

  • Provisión de un dispositivo
  • Envío de Datos a Azure IOT Hub
  • Recibir Datos de Azure IOT Hub

 

Provisión de un nuevo dispositivo

Antes de que podamos utilizar Azure Iot Hub, debemos crear, registrar o provisionar nuestro nuevo dispositivo en la nube (https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-device-management-overview). Para ello, con nuestro Iot Hub ya previamente creado, crearemos una nueva solución de Visual Studio con una sencilla aplicación de consola. Una vez realizado este paso, accederemos al gestor de Nuget para instalar el paquete Microsoft.Azure.Devices:

nuget-iot

Una vez instalado el paquete de Nuget, escribiremos el siguiente código en nuestra aplicación de consola:

[sourcecode language=»csharp»]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Devices;
using Microsoft.Azure.Devices.Common.Exceptions;
using System.Configuration;

namespace CreateDeviceIdentity
{
class Program
{
static RegistryManager registryManager;
static string connectionString = ConfigurationManager.AppSettings[«iotHubConnectionString»];
static string _deviceName;
static void Main(string[] args)
{
System.Console.WriteLine(@»Enter the name of the new IOT Device that will be provisioned:»);
_deviceName = System.Console.ReadLine();
CreateDevice().Wait();
}

static async Task CreateDevice()
{

try
{
registryManager = RegistryManager.CreateFromConnectionString(connectionString);
var device = await registryManager.AddDeviceAsync(new Device(_deviceName));

Console.WriteLine($»Device {_deviceName} has been succesfully created. Key: {device.GenerationId}»);
Console.ReadLine();

}
catch (DeviceAlreadyExistsException ex)
{
var device = await registryManager.GetDeviceAsync(_deviceName);
System.Console.WriteLine(«There is an existing device with deviceId: » + _deviceName);
}
catch (Exception ex)
{
System.Console.WriteLine(«An error has ocurred: » + ex.ToString());
}
finally
{
Console.ReadLine();
}
}
}
}

[/sourcecode]

Utilizaremos el espacio de nombres Microsoft.Azure.Devices.Client para realizar la provisión del dispositivo.

La tarea a realizar es bastante simple y sencilla. Accederemos a una instancia del RegistryManager mediante un connection string de este tipo:

[sourcecode language=»xml»]
<add key=»iotHubConnectionString» value=»HostName={hostname};SharedAccessKeyName={keyName};SharedAccessKey={Key}=»/>;
[/sourcecode]

Hostname, keyName y Key son, respectivamente, la url de nuestro IOT Hub, el nombre de la clave de acceso y el valor de la misma. Además, keyName representa una directiva de acceso compartido, donde podremos habilitar o deshabilitar permisos de forma granular.

Posteriormente, añadiremos un nuevo dispositivo, mediante la clase Device, la cual añadiremos al RegistryManager mediante el método AddDeviceAsync. Una vez realizado todo este proceso, nuestro nuevo dispositivo de IOT habrá sido provisionado correctamente en Azure IOT Hub.

Envío de datos a la Nube

Una vez recogida la Key de nuestro nuevo dispositivo, ya estaremos en disposición de mandar datos a Azure IOT Hub. Para ello, escribiremos el siguiente código de ejemplo:

[sourcecode language=»csharp»]
public class AzureIOTHubClient : IIOTHubClient
{
string _iotHubUrl;
string _deviceKey;
DeviceClient _client;

IGeoService _geoService;

public AzureIOTHubClient(IGeoService geoService)
{
_iotHubUrl = «{iotHubUrl}»;
_deviceKey = «{deviceKey}»;
_client = DeviceClient.CreateFromConnectionString(_iotHubUrl, TransportType.Http1);

_geoService = geoService;
}

public async Task SendData<T>(T obj) where T : class
{
if (obj == null) throw new ArgumentNullException(«obj»);
try
{
var payload = new
{
deviceId = _deviceKey,
data = obj,
currentPosition = _geoService?.GetLocation()
};

var messageString = JsonConvert.SerializeObject(payload);
var message = new Message(System.Text.ASCIIEncoding.ASCII.GetBytes(messageString));

System.Diagnostics.Debug.WriteLine(«{0} > Sending message: {1}», DateTime.Now, messageString);
await _client.SendEventAsync(message);
System.Diagnostics.Debug.WriteLine(«{0} > Message Sent: {1}», DateTime.Now, messageString);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(«{0} > Error Sending Message: {1}», DateTime.Now, ex.ToString());
}

}

}
[/sourcecode]

En este caso, imaginemos que disponemos de un objeto, representado por el parámetro obj del método genérico SendData. Al invocar este método, el objeto donde hubiéramos recogido la información proveniente de los diversos sensores del dispositivo se compondría de la geo localización de un hipotético servicio que estuviera ejecutándose en el dispositivo (por ejemplo, mediante el uso de un GPS). A continuación, esa información, se serializaría a Json, y se enviaría a Azure IOT Hub mediante el método SendEventAsync de la clase DeviceClient (de la cual previamente se habría creado una instancia mediante la url de conexión a Azure IoT Hub).

En el ejemplo se muestra un cliente instanciado mediante protocolo Http. Tenemos disponibles las siguientes opciones a la hora de conectar con Azure IoT Hub:

  • HTTP
  • AMQP
  • MQTT
  • AMQP, sobre WebSocket (muy interesante para la realización de SPA’s conectadas a Azure IOT Hub, aunque MQTT también es un protocolo a tener muy en cuenta)

 

Recibir datos de Azure

Aunque el escenario más común es encontrarnos con trabajos de Stream analytics que facilitan la extracción de los datos recogidos por nuestro IOT Hub, es posible conectarse al mismo para visualizarlos en tiempo real, como mostramos en el siguiente ejemplo:

[sourcecode language=»csharp»]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.ServiceBus.Messaging;
using System.Threading;
using System.Configuration;
using Microsoft.Azure.Devices.Client;

namespace ReceiveMessageClient
{
class Program
{
static string connectionString = ConfigurationManager.AppSettings[«iotHubConnectionString»];
static EventHubClient eventHubClient;
static DeviceClient _deviceClient;
static void Main(string[] args)
{
Console.WriteLine(«Receive messages. Ctrl-C to exit.\n»);

var list = new List<ITransportSettings>();
list.Add(new AmqpTransportSettings(Microsoft.Azure.Devices.Client.TransportType.Amqp_Tcp_Only));
_deviceClient = DeviceClient.CreateFromConnectionString(connectionString, list.ToArray());
CancellationTokenSource cts = new CancellationTokenSource();

System.Console.CancelKeyPress += (s, e) =>
{
e.Cancel = true;
cts.Cancel();
Console.WriteLine(«Exiting…»);
};
ReceiveMessagesFromDeviceAsync(cts).Wait();
}

private static async Task ReceiveMessagesFromDeviceAsync(CancellationToken ct)
{

while (true)
{
if (ct.IsCancellationRequested) break;
var message = await _deviceClient.ReceiveAsync();
if (message == null) continue;

string data = Encoding.UTF8.GetString(message.GetBytes());
Console.WriteLine(«Message received. Partition: {0} Data: ‘{1}'», 0, data);
}
}
}
}

[/sourcecode]

De manera similar al resto de escenarios, crearemos un objeto DeviceClient, mediante el cual nos conectaremos por protocolo AMQP (más ligero que HTTP) para recibir un tráfico continuo de mensajes.

Utilizando el método ReceiveAsync, recibiremos todos los mensajes que están siendo recibidos por nuestro IOT Hub.

 

En resumen, Azure nos provee de un servicio muy útil, de fácil creación y despliegue, con el que podemos dar cabida a nuestras soluciones de IOT. Además, dispone de unas características de seguridad y escalabilidad del sistema out-of-the-box, de manera que tenemos que personalizar muy poco en este aspecto.

Asimismo, combinado con trabajos de Stream Analytics, podemos abrir la puerta a otro tipo de servicios y aplicaciones finales o intermedias para varios propósitos: Business Intelligence, Machine Learning, Big Data…

 

 

Si queréis comentarnos lo que sea podéis hacerlo en info@kabel.es.

También podéis seguirnos en LinkedIn y Twitter.

 

Kabel Geek


 

Deja un comentario

3 − 1 =