Envío mensajes de nube a dispositivo con IoT Hub (Java)

IoT Hub de Azure es un servicio totalmente administrado que permite la comunicación bidireccional confiable y segura entre millones de dispositivos y una solución de back-end.

En este artículo aprenderá a:

  • Envío de mensajes de nube a dispositivo (C2D), desde el back-end de la solución, a un único dispositivo a través de IoT Hub

  • Reciba mensajes de nube a dispositivo en un dispositivo.

  • Solicitar acuse de recibo (comentarios), desde el backend de su solución, para los mensajes enviados a un dispositivo desde IoT Hub

Nota

Las características descritas en este artículo solo están disponibles en el nivel estándar de IoT Hub. Para obtener más información sobre los niveles Básico y Estándar o Gratis de IoT Hub, consulte Elección del nivel adecuado de IoT Hub para la solución.

Al final de este artículo, ejecutará dos aplicaciones de consola de Java:

  • HandleMessages: una aplicación de dispositivo de ejemplo incluida con el SDK de IoT de Microsoft Azure para Java, que se conecta al centro de IoT y recibe mensajes de la nube al dispositivo.

  • SendCloudToDevice: envía un mensaje de nube a dispositivo a la aplicación de dispositivo mediante IoT Hub y, luego, recibe su confirmación de entrega.

Nota

IoT Hub tiene soporte SDK para muchas plataformas de dispositivos y lenguajes (C, Java, Python y JavaScript) a través de los SDK de dispositivo IoT de Azure.

Para más información sobre los mensajes de nube a dispositivo, consulte Envío de mensajes de nube a dispositivo desde un centro de IoT.

Prerrequisitos

  • Suscripción a Azure. Si no tiene una suscripción a Azure, cree una cuenta gratuita antes de empezar.

  • Una instancia de IoT Hub en la suscripción de Azure. Si aún no tiene un centro, puede seguir los pasos descritos en Creación de un centro de IoT.

  • Un dispositivo registrado en su centro de IoT. Si aún no ha registrado un dispositivo, regístrelo en Azure Portal.

  • En este artículo se usa un código de ejemplo del SDK de Azure IoT para Java.

    • Descargue o clone el repositorio del SDK desde GitHub en la máquina de desarrollo.
    • Asegúrese de que Java SE Development Kit 8 está instalado en su máquina de desarrollo. Asegúrese de seleccionar Java 8 en Long-term support (Soporte técnico a largo plazo) para obtener descargas de JDK 8.
  • Maven 3

  • Asegúrese de que está abierto el puerto 8883 del firewall. En el ejemplo de dispositivo de este artículo se usa el protocolo MQTT, que se comunica mediante el puerto 8883. Este puerto puede estar bloqueado en algunos entornos de red corporativos y educativos. Para más información y para saber cómo solucionar este problema, consulte el artículo sobre la conexión a IoT Hub (MQTT).

Obtener la cadena de conexión del dispositivo

En este artículo, ejecutará una aplicación de ejemplo que simula un dispositivo, que recibe mensajes de la nube al dispositivo enviados a través de IoT Hub. La aplicación de ejemplo HandleMessages incluida con el SDK de IoT de Microsoft Azure para Java se conecta al centro de IoT y actúa como su dispositivo simulado. En el ejemplo se usa la cadena de conexión principal del dispositivo registrado en el centro de IoT.

Para obtener la cadena de conexión principal de un dispositivo registrado en el centro de IoT, siga estos pasos:

  1. En Azure Portal, seleccione Grupos de recursos. Seleccione el grupo de recursos donde se encuentra el centro y, a continuación, seleccione el centro en la lista de recursos.

  2. En el panel izquierdo del centro de IoT, en Administración de dispositivos, seleccione Dispositivos.

  3. En la lista de dispositivos, seleccione el dispositivo adecuado.

  4. Copie la Cadena de conexión principal y guarde el valor.

    Captura de pantalla que muestra cómo recuperar la cadena de conexión principal de un dispositivo registrado en su centro de IoT en Azure Portal.

Recepción de mensajes en la aplicación de dispositivo

En esta sección, ejecute la aplicación de dispositivo de ejemplo HandleMessages para recibir mensajes de C2D enviados a través del centro de IoT. Abra un nuevo símbolo del sistema y vaya a la carpeta azure-iot-sdk-java\iothub\device\iot-device-samples\handle-messages, en la carpeta donde expandió el SDK de Java para Azure IoT. Ejecute los siguientes comandos y reemplace el valor del marcador de posición {Your device connection string} por la cadena de conexión del dispositivo que copió del dispositivo registrado en el centro de IoT.

mvn clean package -DskipTests
java -jar ./target/handle-messages-1.0.0-with-deps.jar "{Your device connection string}"

La siguiente salida procede de la aplicación de dispositivo de ejemplo después de que se inicie correctamente y se conecte al centro de IoT:

5/22/2023 11:13:18 AM> Press Control+C at any time to quit the sample.
     
Starting...
Beginning setup.
Successfully read input parameters.
Using communication protocol MQTT.
2023-05-23 09:51:06,062 INFO (main) [com.microsoft.azure.sdk.iot.device.transport.ExponentialBackoffWithJitter] - NOTE: A new instance of ExponentialBackoffWithJitter has been created with the following properties. Retry Count: 2147483647, Min Backoff Interval: 100, Max Backoff Interval: 10000, Max Time Between Retries: 100, Fast Retry Enabled: true
2023-05-23 09:51:06,187 DEBUG (main) [com.microsoft.azure.sdk.iot.device.ClientConfiguration] - Device configured to use software based SAS authentication provider
2023-05-23 09:51:06,187 INFO (main) [com.microsoft.azure.sdk.iot.device.transport.ExponentialBackoffWithJitter] - NOTE: A new instance of ExponentialBackoffWithJitter has been created with the following properties. Retry Count: 2147483647, Min Backoff Interval: 100, Max Backoff Interval: 10000, Max Time Between Retries: 100, Fast Retry Enabled: true
2023-05-23 09:51:06,202 DEBUG (main) [com.microsoft.azure.sdk.iot.device.DeviceClient] - Initialized a DeviceClient instance using SDK version 2.1.5
Successfully created an IoT Hub client.
Successfully set message callback.
2023-05-23 09:51:06,205 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttIotHubConnection] - Opening MQTT connection...
2023-05-23 09:51:06,218 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt] - Sending MQTT CONNECT packet...
2023-05-23 09:51:07,308 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt] - Sent MQTT CONNECT packet was acknowledged
2023-05-23 09:51:07,308 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt] - Sending MQTT SUBSCRIBE packet for topic devices/US60536-device/messages/devicebound/#
2023-05-23 09:51:07,388 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.Mqtt] - Sent MQTT SUBSCRIBE packet for topic devices/US60536-device/messages/devicebound/# was acknowledged
2023-05-23 09:51:07,388 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttIotHubConnection] - MQTT connection opened successfully
2023-05-23 09:51:07,388 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - The connection to the IoT Hub has been established
2023-05-23 09:51:07,404 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - Updating transport status to new status CONNECTED with reason CONNECTION_OK
2023-05-23 09:51:07,404 DEBUG (main) [com.microsoft.azure.sdk.iot.device.DeviceIO] - Starting worker threads
2023-05-23 09:51:07,408 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - Invoking connection status callbacks with new status details

CONNECTION STATUS UPDATE: CONNECTED
CONNECTION STATUS REASON: CONNECTION_OK
CONNECTION STATUS THROWABLE: null

The connection was successfully established. Can send messages.
2023-05-23 09:51:07,408 DEBUG (main) [com.microsoft.azure.sdk.iot.device.transport.IotHubTransport] - Client connection opened successfully
2023-05-23 09:51:07,408 INFO (main) [com.microsoft.azure.sdk.iot.device.DeviceClient] - Device client opened successfully
Opened connection to IoT Hub. Messages sent to this device will now be received.
Press any key to exit...

El método execute de la clase AppMessageCallback devuelve IotHubMessageResult.COMPLETE. Este estado notifica a IoT Hub que el mensaje se ha procesado correctamente y que se puede quitar de la cola del dispositivo de forma segura. El dispositivo debe devolver este valor cuando el procesamiento se complete correctamente, independientemente del protocolo que utilice.

Con AMQP y HTTPS, pero no MQTT, el dispositivo también puede:

  • Abandonar un mensaje, lo que da lugar a que IoT Hub retenga el mensaje en la cola del dispositivo para su posterior consumo.
  • Rechace un mensaje, de forma que este se quite permanentemente de la cola del dispositivo.

Si se produce algo que impide que el dispositivo complete, abandone o rechace el mensaje, IoT Hub, después de un período de tiempo de espera fijo, lo pone en cola para repetir la entrega. Por este motivo, la lógica de procesamiento de mensajes de la aplicación del dispositivo debe ser idempotente, de modo que, si se recibe el mismo mensaje varias veces, se genere el mismo resultado.

Para más información sobre el ciclo de vida de los mensajes de la nube al dispositivo y sobre cómo IoT Hub procesa los mensajes de nube a dispositivo, consulte Enviar mensajes de nube a dispositivo desde un IoT Hub.

Nota

Si usa HTTPS en lugar de MQTT o AMQP como transporte, la instancia DeviceClient busca mensajes de IoT Hub con menos frecuencia (cada 25 minutos como mínimo). Para más información sobre las diferencias entre la compatibilidad con MQTT, AMQP y HTTPS, consulte Guía de comunicación de nube a dispositivo y Elección de un protocolo de comunicación.

Obtención de la cadena de conexión de IoT Hub

En este artículo, creará un servicio back-end para enviar mensajes de la nube al dispositivo a través de IoT Hub. Para enviar mensajes de nube a un dispositivo, el servicio necesita el permiso de conexión de servicio. De forma predeterminada, todas las instancias de IoT Hub se crean con una directiva de acceso compartido denominada servicio que concede este permiso.

Para obtener la cadena de conexión de IoT Hub para la directiva service, siga estos pasos:

  1. En Azure Portal, seleccione Grupos de recursos. Seleccione el grupo de recursos donde se encuentra el centro y, a continuación, seleccione el centro en la lista de recursos.

  2. En el panel de la izquierda de IoT Hub, seleccione Directivas de acceso compartido.

  3. En la lista de directivas, seleccione la directiva service.

  4. Copie la Cadena de conexión principal y guarde el valor.

Captura de pantalla que muestra cómo recuperar la cadena de conexión de su IoT Hub en el Azure Portal.

Para obtener más información sobre las directivas de acceso compartido y los permisos de IoT Hub, consulte Permisos y control del acceso.

Envío de mensajes de nube a dispositivo

En esta sección, escribirá una aplicación de consola de Java que envía mensajes de nube a dispositivo a la aplicación del dispositivo simulado. Necesita el identificador de dispositivo del dispositivo y la cadena de conexión de IoT Hub.

  1. Cree un proyecto de Maven denominado send-c2d-messages mediante el siguiente comando en el símbolo del sistema. Observe que este es un comando único y largo:

    mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=send-c2d-messages -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    
  2. En el símbolo del sistema, vaya a la nueva carpeta send-c2d-messages.

  3. Con un editor de texto, abra el archivo pom.xml de la carpeta send-c2d-messages y agregue la siguiente dependencia al nodo dependencies . Esto le permite usar el paquete iothub-java-service-client en la aplicación para comunicarse con el servicio IoT Hub:

    <dependency>
      <groupId>com.microsoft.azure.sdk.iot</groupId>
      <artifactId>iot-service-client</artifactId>
      <version>1.7.23</version>
    </dependency>
    

    Nota

    Puede comprobar la versión más reciente de iot-service-client mediante la búsqueda de Maven.

  4. Guarde y cierre el archivo pom.xml.

  5. Con un editor de texto, abra el archivo send-c2d-messages\src\main\java\com\mycompany\app\App.java.

  6. Agregue las siguientes instrucciones import al archivo:

    import com.microsoft.azure.sdk.iot.service.*;
    import java.io.IOException;
    import java.net.URISyntaxException;
    
  7. Agregue las siguientes variables de nivel de clase a la clase App y sustituya {yourhubconnectionstring} y {yourdeviceid} por los valores anotados anteriormente:

    private static final String connectionString = "{yourhubconnectionstring}";
    private static final String deviceId = "{yourdeviceid}";
    private static final IotHubServiceClientProtocol protocol =    
        IotHubServiceClientProtocol.AMQPS;
    
  8. Reemplace el método main por el código siguiente: Este código conecta con el centro de IoT, envía un mensaje al dispositivo y luego espera una confirmación de que el dispositivo ha recibido y procesado el mensaje:

    public static void main(String[] args) throws IOException,
        URISyntaxException, Exception {
      ServiceClient serviceClient = ServiceClient.createFromConnectionString(
        connectionString, protocol);
    
      if (serviceClient != null) {
        serviceClient.open();
        FeedbackReceiver feedbackReceiver = serviceClient
          .getFeedbackReceiver();
        if (feedbackReceiver != null) feedbackReceiver.open();
    
        Message messageToSend = new Message("Cloud to device message.");
        messageToSend.setDeliveryAcknowledgement(DeliveryAcknowledgement.Full);
    
        serviceClient.send(deviceId, messageToSend);
        System.out.println("Message sent to device");
    
        FeedbackBatch feedbackBatch = feedbackReceiver.receive(10000);
        if (feedbackBatch != null) {
          System.out.println("Message feedback received, feedback time: "
            + feedbackBatch.getEnqueuedTimeUtc().toString());
        }
    
        if (feedbackReceiver != null) feedbackReceiver.close();
        serviceClient.close();
      }
    }
    

    Nota

    Para hacerlo más simple, este artículo no implementa una directiva de reintentos. En el código de producción, deberá implementar directivas de reintentos (por ejemplo, retroceso exponencial), tal y como se sugiere en el artículo Control de errores transitorios.

  9. Para compilar la aplicación send-c2d-messages con Maven, ejecute el siguiente comando en el símbolo del sistema en la carpeta simulated-device:

    mvn clean package -DskipTests
    

Ejecución de las aplicaciones

Ya está listo para ejecutar las aplicaciones.

  1. En un símbolo del sistema de la carpeta azure-iot-sdk-java\iothub\device\iot-device-samples\handle-messages, ejecute los siguientes comandos, reemplazando el valor del marcador de posición {Your device connection string} por la cadena de conexión del dispositivo que copió del dispositivo registrado en el centro de IoT. Este paso inicia la aplicación de dispositivo de ejemplo, que envía telemetría al centro de IoT y escucha los mensajes de la nube al dispositivo enviados desde el centro:

    java -jar ./target/handle-messages-1.0.0-with-deps.jar "{Your device connection string}"
    

    Captura de pantalla de la aplicación de dispositivo de ejemplo ejecutada en una ventana de la consola.

  2. En un símbolo del sistema de la carpeta send-c2d-messages, ejecute el siguiente comando para enviar un mensaje de la nube a dispositivo y esperar una confirmación de comentarios:

    mvn exec:java -Dexec.mainClass="com.mycompany.app.App"
    

    Captura de pantalla de la aplicación del servicio de ejemplo ejecutada en una ventana de la consola.

Pasos siguientes

En este artículo, ha aprendido a enviar y recibir mensajes de la nube al dispositivo.