Una sinfonía en C#

Un pequeño aporte a la comunidad de habla hispana.

IoT: ¿Cómo enviar mensajes MQTT a Azure IoT Hub?

No voy a descubrir nada diciendo que Arduino es la plataforma más popular para desarrollo de electrónica para el usuario “común”, por facilidad, por precio, por disponibilidad de información, herramientas, etc.

Si hablamos de contar con capacidad de conectarnos a una red inalámbrica con Arduino nos viene a la mente el ESP8266, este pequeño chip de bajo costo que soporta 802.11 b/g/n y cuenta con un stack TCP completo, pudiendo incluso trabajar por su cuenta gracias a que también tiene un microcontrolador incorporado. Un proyecto que nació poco después basado en el mismo chip es NodeMCU que es una plataforma para IoT que utilizar el ESP8266 y utiliza LUA como lenguaje (en realidad NodeMCU es el firmware no el hardware, pero lo vamos a usar de modo indiferente) en este caso gracias al trabajo de la comunidad existe un plugin para poder programar en C desde el IDE de Arduino que es justamente lo que vamos a hacer. Otra ventaja del hardware es que se puede conseguir por muy poco dinero y tenemos todo, wifi, entras / salidas digitales, analógicas, UART, etc.

Tener soporte MQTT en NodeMCU

La forma más común de contar con soporte para MQTT con mensajes bidireccionales y demás es utilizar la biblioteca PubSubClient y ya, funciona muy bien y no hay mucho que agregar así que eso es lo que vamos a hacer.

Acá podemos ver un ejemplo simple que nos proporciona la gente del equipo de desarrollo.

Enviando mensajes a Azure

En Azure tenemos dos servicios para recibir eventos en cantidad, Event Hubs y IoT Hub, bien, cuál usar es simple de decidir más allá de ponernos con comparativas de rendimiento y escalabilidad ocurre que Event Hubs hasta este día no soporta MQTT, así que vamos a usar IoT Hub.

Configurar IoT Hub y el cliente

Vamos a utilizar el código de ejemplo del PubSubClient y configurarlo para poder enviar mensajes, también ser podrán recibir, esta parte es un poco “mágica” porque no hay mucha información sobre los parámetros de la conexión, vamos a ver el código de ejemplo paso a paso donde tenemos que reemplazar valores y cosas.

const char* ssid = "........";
const char* password = "........";
const char* mqtt_server = "broker.mqtt-dashboard.com";

en ssid ponemos el nombre de nuestra red, en password la contraseña, esto es simple, ahora empiezan los datos raros.

en mqtt_server tenemos que poner el nombre de nuestro IoTHub, este nombre es <nombre de nuestro iothub>.azure-devices.net, en mi caso es “testesp.azure-devices.net”, quedaría así:

const char* ssid = "MI_RED";
const char* password = "PASSWORD_DE_MI_RED";
const char* mqtt_server = "testesp.azure-devices.net";

Agregar el cliente seguro de WIFI

Ya que IoTHub utiliza TSL tenemos que utilizar la versión segura de la biblioteca de conexión con la Wifi, entonces hacemos dos cambios, agregamos la referencia

#include <wificlientsecure.h>

y reemplazar la declaración de la clase WiFiClient por WiFiClientSecure así:

WiFiClientSecure espClient;

PubSubClient client(espClient);

Cambiar el puerto de conexión de MQTT

Por defecto se utilizar el puerto 1883 pero Azure utiliza 8883, quedaría así:

client.setServer(mqtt_server, 8883);

Configurando los datos de conexión

Esta es la parte más tricky, vamos a localizar la línea donde se hace la conexión

if (client.connect(clientId.c_str()))

Primero que nada vamos a utilizar otra sobrecarga, para utilizar la que recibe: deviceID, Usuario y password estos tres datos los obtenemos del siguiente modo:

El deviceID lo creamos en el IoTHub

image

En mi caso TestDevice

El usuario es simple, es el mismo nombre del nuestro IoTHub que usamos al principio con el nombre del device después, en mi caso es así:

testesp.azure-devices.net/TestDevice

Ahora viene la parte rara, en donde iría la password tenemos que poner un connection string SAS que hay que generar, la forma más simple de hacerlo es la siguiente:

Descargar el IoT hub device explorer de acá, una vez instalado volvemos al portal de Azure y buscamos la parte de Shared Access Policies, creamos una policy nueva o usamos una existente (depende de qué queremos) pero en todo caso, una vez que tenemos una vamos al detalle y copiamos el connection string de primary ( o el otro, es igual) y eso lo pegamos en el device explorer y presionamos “Generate SAS

image

Y ese SAS que se genera es justamente el password que tenemos que usar, tal cual está, entonces quedaría todo así:

if (client.connect("TestDevice", "testesp.azure-devices.net/TestDevice","SharedAccessSignature sr=testesp.azure-devices.net&sig=KKKKKKKKKKKKKKK%3D&se=1548536586&skn=blabla"))

Con esto podemos conectarnos al IoTHub, para enviar mensajes se hace publish, pero a un topic específico, en el caso de nuestro dispositivo el nombre es devices/<nombre del device>/messages/events/ tenemos que reemplazar la línea que dice:

client.publish("outTopic", "hello world");

por

client.publish("devices/TestDevice/messages/events/", "hello world");

Y para poder recibir es algo similar, cambiamos donde dice

client.subscribe("inTopic")

por

client.subscribe("devices/TestDevice/messages/devicebound/#")

Donde TestDevice es el nombre de nuestro dispositivo por supuesto

Por último, cambiar el tamaño máximo de paquetes del MQTT de la biblioteca PubSubClient:

Ya que el connection string es tan largo el máximo por defecto no nos será suficiente, tenemos que ir a buscar donde tenemos instalada la biblioteca PubSubCliente y cambiarla así:

MQTT_MAX_PACKET_SIZE 256

Y con eso ya está, ahora podemos compilar en el IDE, cargar el programa en el dispositivo, abrir el monitor serie y si todo a bien deberíamos ver que envía mensajes

image

Excelente, con esto será suficiente para enviar y recibir desde NodeMCU a Azure IoT Hub. Dejo el ejemplo de código modificado acá

Nos leemos.

Loading