En éste segundo artículo de la serie en la que vamos a profundizar en toda la temática de IoT, vamos a detallar uno a uno los diferentes elementos y componentes de los que está compuesta una solución “tipo” de IoT en Azure, como son las soluciones preconfiguradas de las que hablábamos en el artículo anterior.
En éste caso, vamos a centrarnos en el IoT Hub.
El Azure IoT Hub será, como su nombre indica, el centro de todas las soluciones que creemos o ideemos cuya cloud sea Azure. Es, literalmente, el centro de actividad de IoT de Azure, y para compararlo con otro elemento de Azure el cual ya lleva más tiempo disponible y es más conocido, vendría a ser como un Event Hub, al cual se han hecho unas modificaciones y añadidos para que sea más específico para nuestros desarrollos con IoT.
Hablando a grandes rasgos, el IoT Hub nos permite comunicarnos de forma bidireccional con todos nuestros dispositivos IoT que tengamos conectados y registrados, pudiendo a la vez conectar otros elementos de Azure como un trabajo de análisis de flujos de datos (un Stream Analytics) para que lean de él los mensajes y así poder realizar un procesado inicial o un guardado en una base de datos.
En la página oficial de Azure IoT Hub podremos encontrar mucha más información además de ejemplos.
Comparación IoT Hub vs Event Hub
Uno de los principales usos de IoT Hub es recopilar telemetría de dispositivos. Por este motivo, IoT Hub a menudo se compara con Azure Events Hubs. Al igual que el Centro de IoT, Centros de eventos de Azure es un servicio de procesamiento de eventos que ofrece entrada de telemetría y eventos en la nube a escala masiva, con una latencia baja y una confiabilidad alta.
Sin embargo, los servicios tienen muchas diferencias las cuales se pueden ver con detalle en éste enlace.
No obstante, tampoco es raro usar IoT Hub y Event Hubs en la misma solución, ya que el IoT Hub controla la comunicación del dispositivo a la nube, y los Events Hubs controlan la entrada de eventos de última fase en motores de procesamiento en tiempo real.
Ejemplo práctico
Una vez hemos visto qué es y para qué sirve el IoT Hub, vamos a ver de forma práctica cómo crearlo y configurarlo, qué parámetros son relevantes y debemos tener a mano, y un ejemplo sencillo de envío de mensajes al IoT Hub. Para ver más en detalle todo esto, existe un tutorial más detallado de Microsoft aquí.
Creación IoT Hub
Para empezar, accederemos al portal de Azure (http://portal.azure.com) y crearemos el IoT Hub, el cuál podremos encontrar en el apartado Internet of Things.
En la siguiente pantalla configuraremos todos los parámetros que se nos indican, siendo necesario prestar especial atención a los siguientes (si no elegimos nivel de servicio gratuito, en cuyo caso no podremos modificarlos):
- IoT Hub Units: Unidades de IoT Hub. En caso de tratarse de una aplicación en producción con un volumen muy alto de dispositivos, nos podría interesar aumentar éstas unidades.
- Device-to-cloud partitions: Éste parámetro fijará las particiones que tendremos de entrada para recibir mensajes de los distintos dispositivos. En éste caso, no particionaremos por el PartitionKey como en los Event Hub, sino que los mensajes se colocarán en una partición u otra en función de su deviceId. Por defecto está a 4 (2 en nivel gratuito), aumentándolo mejoraremos la eficiencia de lectura cuando tengamos varios lectores de mensajes, aunque no variará el throughput de entrada total.
A partir de ahora, el hostname de nuestro IoT Hub será HOSTNAME.azure-devices.net, siendo HOSTNAME el nombre que hayamos elegido para nuesto IoT Hub. Para obtener otro de los datos que necesitamos para conectarnos al Hub, nos iremos al apartado Shared Access Policies, y de ellas a iothubowner.
Mediante éstas Shared Access Policies es como gestionaremos los permisos que tendrán los dispositivos que se conecten al Hub, por lo que podremos modificar las que hay o añadir nuevas. Finalmente, buscaremos, y copiaremos la Connection string—primary key de la que nos interese para nuestro dispositivo en cuestión, en éste caso iothubowner.
Creación de la identidad del dispositivo
Un dispositivo no puede conectarse al IoT Hub si no tiene una entrada en su registro de identidades. Por ello, antes de crear una aplicación para conectar un dispositivo y enviar mensajes, necesitaremos registrar el dispositivo. Si tuviéramos una interfaz web desarrollada con una funcionalidad similar a la que nos ofrecen las soluciones preconfiguradas de Azure IoT Suite, podríamos crearlo desde allí, pero en éste caso optaremos por hacerlo con una aplicación de consola.
Para ello, seguiremos los pasos indicados a continuación:
- Crearemos una aplicación de consola, y la llamaremos por ejemplo CreateDeviceIdentity.
- Añadiremos el paquete de NuGet Azure IoT service SDK (Microsoft.Azure.Devices).
- Modificaremos el código de Program.cs para que quede de la siguiente forma:
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; namespace CreateDeviceIdentity { class Program { static RegistryManager registryManager; static string connectionString = "{IOT_HUB_CONNECTIONSTRING}"; static void Main(string[] args) { registryManager = RegistryManager.CreateFromConnectionString(connectionString); AddDeviceAsync().Wait(); Console.ReadLine(); } private static async Task AddDeviceAsync() { string deviceId = "myFirstDevice"; Device device; try { device = await registryManager.AddDeviceAsync(new Device(deviceId)); } catch (DeviceAlreadyExistsException) { device = await registryManager.GetDeviceAsync(deviceId); } Console.WriteLine("Generada device key: {0}", device.Authentication.SymmetricKey.PrimaryKey); } } }
Reemplazando {IOT_HUB_CONNECTIONSTRING} por la cadena de conexión de nuestro IoT Hub con los permisos correspondientes (en nuestro caso la de iothubowner).
- Ejecutar la aplicación. Debemos anotar el Device Key que nos devuelva por pantalla, ya que lo usaremos en nuestro dispositivo.
Envío de mensajes de dispositivo a la nube
Una vez ya tenemos el dispositivo registrado, procederemos a realizar dos aplicaciones: una aplicación que leerá los mensajes de dispositivos del IoT Hub y una aplicación de consola que envíe mensajes al IoT Hub.
Para la primera, seguiremos los siguientes pasos:
- Crearemos una aplicación de consola, a la que llamaremos, por ejemplo, ReadDeviceToCloudMessages.
- Añadiremos el paquete de NuGet Azure Service Bus (WindowsAzure.ServiceBus).
- Modificar el código de Program.cs para que quede de la siguiente forma:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.ServiceBus.Messaging; using System.Threading; namespace ReadDeviceToCloudMessages { class Program { static string connectionString = "{IOT_HUB_CONNECTIONSTRING}"; static string iotHubD2cEndpoint = "messages/events"; static EventHubClient eventHubClient; static void Main(string[] args) { Console.WriteLine("Receive messages. Ctrl-C to exit.\n"); eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, iotHubD2cEndpoint); var d2cPartitions = eventHubClient.GetRuntimeInformation().PartitionIds; CancellationTokenSource cts = new CancellationTokenSource(); System.Console.CancelKeyPress += (s, e) => { e.Cancel = true; cts.Cancel(); Console.WriteLine("Exiting..."); }; var tasks = new List<Task>(); foreach (string partition in d2cPartitions) { tasks.Add(ReceiveMessagesFromDeviceAsync(partition, cts.Token)); } Task.WaitAll(tasks.ToArray()); } private static async Task ReceiveMessagesFromDeviceAsync(string partition, CancellationToken ct) { var eventHubReceiver = eventHubClient.GetDefaultConsumerGroup().CreateReceiver(partition, DateTime.UtcNow); while (true) { if (ct.IsCancellationRequested) break; EventData eventData = await eventHubReceiver.ReceiveAsync(); if (eventData == null) continue; string data = Encoding.UTF8.GetString(eventData.GetBytes()); Console.WriteLine("Message received. Partition: {0} Data: '{1}'", partition, data); } } } }
Reemplazando igualmente {IOT_HUB_CONNECTIONSTRING} con el mismo valor de antes.
Finalmente, crearemos la aplicación que simulará un dispositivo enviando mensajes al IoT Hub. Para ellos seguiremos los siguientes pasos:
- Crearemos una aplicación de consola, a la que llamaremos, por ejemplo, SimulatedDevice.
- Añadiremos el paquete de NuGet Azure IoT device SDK (Microsoft.Azure.Devices.Client).
- Modificar el código de Program.cs para que quede de la siguiente forma:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Azure.Devices.Client; using Newtonsoft.Json; namespace SimulatedDevice { class Program { static DeviceClient deviceClient; static string iotHubUri = "{IOT_HUB_CONNSTRING}"; static string deviceKey = "{DEVICE_KEY}"; static void Main(string[] args) { Console.WriteLine("Simulated device\n"); deviceClient = DeviceClient.Create(iotHubUri, new DeviceAuthenticationWithRegistrySymmetricKey("myFirstDevice", deviceKey), TransportType.Mqtt); SendDeviceToCloudMessagesAsync(); Console.ReadLine(); } private static async void SendDeviceToCloudMessagesAsync() { double avgWindSpeed = 10; // m/s Random rand = new Random(); while (true) { double currentWindSpeed = avgWindSpeed + rand.NextDouble() * 4 - 2; var telemetryDataPoint = new { deviceId = "myFirstDevice", windSpeed = currentWindSpeed }; var messageString = JsonConvert.SerializeObject(telemetryDataPoint); var message = new Message(Encoding.ASCII.GetBytes(messageString)); await deviceClient.SendEventAsync(message); Console.WriteLine("{0} > Sending message: {1}", DateTime.Now, messageString); Task.Delay(1000).Wait(); } } } }
Reemplazando, como antes el valor de {IOT_HUB_CONNECTIONSTRING}, y en éste caso el valor de {DEVICE_KEY} por el device key que hayamos obtenido en el registro del dispositivo.
Una vez hecho todo esto, si arrancamos ambas aplicaciones, veremos algo como lo siguiente:
Y en el portal de Azure, en el apartado de Usage, veremos el número de mensajes enviados.
Además de los mensajes de dispositivo a nube, existe otro tipo que son los de nube a dispositivo, principalmente mensajes de control para que el dispositivo pueda modificar parámetros o realizar acciones predeterminadas. Para más información o ejemplos consultar ésta guía.
Siguientes pasos
En el siguiente artículo, hablaremos en detalle acerca de Stream Analytics, un servicio que nos permite obtener los datos del IoT Hub y hacer un procesado inicial de ellos, pudiendo luego enviarlos a distintos destinos.