Introducción a la administración de dispositivos (Java)

Las aplicaciones de back-end pueden usar primitivos de Azure IoT Hub, como dispositivos gemelos y métodos directos, para iniciar y supervisar de forma remota las acciones de administración de dispositivos en los dispositivos. Este artículo muestra cómo una aplicación back-end y una aplicación para dispositivo pueden funcionar a la vez para iniciar y supervisar el reinicio remoto de un dispositivo mediante 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.

Use un método directo para iniciar acciones de administración de dispositivos (por ejemplo, reinicio, restablecimiento de fábrica y actualización de firmware) desde una aplicación back-end en la nube. El dispositivo es responsable de:

  • Controlar la solicitud del método enviada desde IoT Hub.

  • Iniciar la acción específica del dispositivo correspondiente en el dispositivo.

  • Proporcionar actualizaciones de estado mediante las propiedades notificadas a IoT Hub.

Puede usar una aplicación de back-end en la nube para ejecutar consultas de dispositivos gemelos para informar sobre el progreso de las acciones de administración de los dispositivos.

Este artículo muestra cómo crear:

  • dispositivo simulado: una aplicación de dispositivo simulado con un método directo que reinicia el dispositivo e informa de la última hora de reinicio. Los métodos directos se invocan desde la nube.

  • reinicio de desencadenador: una aplicación Java que llama al método directo en la aplicación de dispositivo simulado mediante su centro de IoT. Muestra la respuesta y las propiedades notificadas actualizadas.

Nota

Para más información sobre los SDK que puede usar para compilar aplicaciones de modo que se ejecuten en dispositivos y en el back-end de la solución, consulte SDK de IoT de Azure.

Requisitos previos

  • Una instancia de IoT Hub. Cree uno con la CLI o el Azure Portal.

  • Dispositivo registrado. Registre uno en el Azure Portal.

  • Java SE Development Kit 8. 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).

Creación de una aplicación de dispositivo con un método directo

En esta sección, creará una aplicación de consola de Java que simula un dispositivo. La aplicación escucha la llamada al método directo de reinicio desde IoT Hub y la responder inmediatamente. Luego, la aplicación se suspende unos instantes para simular el proceso de reinicio antes de usar una propiedad notificada para notificar a la aplicación back-end trigger-reboot que se completó el reinicio.

  1. En la carpeta dm-get-started, cree un proyecto Maven denominado simulated-device con el comando siguiente en el símbolo del sistema:

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

  3. Con un editor de texto, abra el archivo pom.xml de la carpeta simulated-device y agregue la dependencia siguiente al nodo dependencies. Esta dependencia le permite usar el paquete iot-service-client en la aplicación para comunicarse con la instancia de IoT Hub:

    <dependency>
      <groupId>com.microsoft.azure.sdk.iot</groupId>
      <artifactId>iot-device-client</artifactId>
      <version>1.17.5</version>
    </dependency>
    

    Nota

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

  4. Agregue la siguiente dependencia al nodo dependencies. Esta dependencia configura una instrucción NOP para la fachada de registro de Apache SLF4J, que usa el SDK de cliente de dispositivo para implementar el registro. Esta configuración es opcional, pero si la omite, es posible que vea una advertencia en la consola al ejecutar la aplicación. Para más información sobre el registro en el SDK de cliente de dispositivo, consulte Registro en el archivo Léame Ejemplos para el SDK de dispositivo IoT de Azure para Java.

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-nop</artifactId>
      <version>1.7.28</version>
    </dependency>
    
  5. Agregue el nodo build después del nodo dependencies. Esta configuración indica a Maven que use Java 1.8 para compilar la aplicación:

    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.3</version>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
          </configuration>
        </plugin>
      </plugins>
    </build>
    
  6. Guarde y cierre el archivo pom.xml.

  7. Con un editor de texto, abra el archivo de origen simulated-device\src\main\java\com\mycompany\app\App.java.

  8. Agregue las siguientes instrucciones import al archivo:

    import com.microsoft.azure.sdk.iot.device.*;
    import com.microsoft.azure.sdk.iot.device.DeviceTwin.*;
    
    import java.io.IOException;
    import java.net.URISyntaxException;
    import java.time.LocalDateTime;
    import java.util.Scanner;
    import java.util.Set;
    import java.util.HashSet;
    
  9. Agregue las siguientes variables de nivel de clase a la clase App . Reemplace {yourdeviceconnectionstring} por la cadena de conexión de dispositivo que vio cuando registró un dispositivo en IoT Hub:

    private static final int METHOD_SUCCESS = 200;
    private static final int METHOD_NOT_DEFINED = 404;
    
    private static IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;
    private static String connString = "{yourdeviceconnectionstring}";
    private static DeviceClient client;
    
  10. Para implementar un controlador de devolución de llamada para los eventos de estado de método directo, agregue la clase anidada siguiente a la clase App:

    protected static class DirectMethodStatusCallback implements IotHubEventCallback
    {
      public void execute(IotHubStatusCode status, Object context)
      {
        System.out.println("IoT Hub responded to device method operation with status " + status.name());
      }
    }
    
  11. Para implementar un controlador de devolución de llamada para los eventos de estado de dispositivo gemelo, agregue la clase anidada siguiente a la clase App:

    protected static class DeviceTwinStatusCallback implements IotHubEventCallback
    {
        public void execute(IotHubStatusCode status, Object context)
        {
            System.out.println("IoT Hub responded to device twin operation with status " + status.name());
        }
    }
    
  12. Para implementar un controlador de devolución de llamada para los eventos de propiedad, agregue la clase anidada siguiente a la clase App:

    protected static class PropertyCallback implements PropertyCallBack<String, String>
    {
      public void PropertyCall(String propertyKey, String propertyValue, Object context)
      {
        System.out.println("PropertyKey:     " + propertyKey);
        System.out.println("PropertyKvalue:  " + propertyKey);
      }
    }
    
  13. Para implementar un subproceso que simule el reinicio del dispositivo, agregue la clase anidada siguiente a la clase App. El subproceso se suspende durante cinco segundos y luego establece la propiedad notificada lastReboot:

    protected static class RebootDeviceThread implements Runnable {
      public void run() {
        try {
          System.out.println("Rebooting...");
          Thread.sleep(5000);
          Property property = new Property("lastReboot", LocalDateTime.now());
          Set<Property> properties = new HashSet<Property>();
          properties.add(property);
          client.sendReportedProperties(properties);
          System.out.println("Rebooted");
        }
        catch (Exception ex) {
          System.out.println("Exception in reboot thread: " + ex.getMessage());
        }
      }
    }
    
  14. Para implementar el método directo en el dispositivo, agregue la clase anidada siguiente a la clase App. Cuando la aplicación simulada recibe una llamada al método directo de reinicio, devuelve una confirmación al autor de la llamada y luego inicia un subproceso para procesar el reinicio:

    protected static class DirectMethodCallback implements com.microsoft.azure.sdk.iot.device.DeviceTwin.DeviceMethodCallback
    {
      @Override
      public DeviceMethodData call(String methodName, Object methodData, Object context)
      {
        DeviceMethodData deviceMethodData;
        switch (methodName)
        {
          case "reboot" :
          {
            int status = METHOD_SUCCESS;
            System.out.println("Received reboot request");
            deviceMethodData = new DeviceMethodData(status, "Started reboot");
            RebootDeviceThread rebootThread = new RebootDeviceThread();
            Thread t = new Thread(rebootThread);
            t.start();
            break;
          }
          default:
          {
            int status = METHOD_NOT_DEFINED;
            deviceMethodData = new DeviceMethodData(status, "Not defined direct method " + methodName);
          }
        }
        return deviceMethodData;
      }
    }
    
  15. Modifique la signatura del método main para generar las excepciones siguientes:

    public static void main(String[] args) throws IOException, URISyntaxException
    
  16. Para crear una instancia de DeviceClient, reemplace el código del método main por el código siguiente:

    System.out.println("Starting device client sample...");
    client = new DeviceClient(connString, protocol);
    
  17. Agregue el código siguiente al método main para empezar a escuchar las llamadas al método directo:

    try
    {
      client.open();
      client.subscribeToDeviceMethod(new DirectMethodCallback(), null, new DirectMethodStatusCallback(), null);
      client.startDeviceTwin(new DeviceTwinStatusCallback(), null, new PropertyCallback(), null);
      System.out.println("Subscribed to direct methods and polling for reported properties. Waiting...");
    }
    catch (Exception e)
    {
      System.out.println("On exception, shutting down \n" + " Cause: " + e.getCause() + " \n" +  e.getMessage());
      client.close();
      System.out.println("Shutting down...");
    }
    
  18. Agregue el código siguiente al método main para apagar el simulador de dispositivos:

    System.out.println("Press any key to exit...");
    Scanner scanner = new Scanner(System.in);
    scanner.nextLine();
    scanner.close();
    client.close();
    System.out.println("Shutting down...");
    
  19. Guarde y cierre el archivo simulated-device\src\main\java\com\mycompany\app\App.java.

  20. Compile la aplicación simulated-device y corrija los errores. En el símbolo del sistema, vaya a la carpeta simulated-device y ejecute el comando siguiente:

    mvn clean package -DskipTests
    

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

En este artículo, creará un servicio back-end que invoca un método directo en un dispositivo. Para invocar un método directo en un dispositivo a través de IoT Hub, el servicio necesita el permiso Conexión del 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.

Creación de una aplicación de servicio para desencadenar un reinicio

En esta sección, creará una aplicación de consola de Java que permite:

  1. Invocar un método directo de reinicio en la aplicación de dispositivo simulado.

  2. Mostrar la respuesta.

  3. Sondear las propiedades notificadas enviadas desde el dispositivo para determinar cuándo se completa el reinicio.

Esta aplicación de consola se conecta a la instancia de IoT Hub para invocar al método directo y leer las propiedades notificadas.

  1. Cree una carpeta vacía llamada dm-get-started.

  2. En la carpeta dm-get-started, cree un proyecto de Maven denominado trigger-reboot mediante el comando siguiente en el símbolo del sistema:

    mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=trigger-reboot -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    
  3. En el símbolo del sistema, vaya a la carpeta trigger-reboot.

  4. Con un editor de texto, abra el archivo pom.xml en la carpeta trigger-reboot y agregue la dependencia siguiente al nodo dependencies. Esta dependencia le permite usar el paquete iot-service-client en la aplicación para comunicarse con la instancia de IoT Hub:

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

    Nota

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

  5. Agregue el nodo build después del nodo dependencies. Esta configuración indica a Maven que use Java 1.8 para compilar la aplicación:

    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.3</version>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
          </configuration>
        </plugin>
      </plugins>
    </build>
    
  6. Guarde y cierre el archivo pom.xml.

  7. Con un editor de texto, abra el archivo de origen trigger-reboot\src\main\java\com\mycompany\app\App.java.

  8. Agregue las siguientes instrucciones import al archivo:

    import com.microsoft.azure.sdk.iot.service.devicetwin.DeviceMethod;
    import com.microsoft.azure.sdk.iot.service.devicetwin.MethodResult;
    import com.microsoft.azure.sdk.iot.service.exceptions.IotHubException;
    import com.microsoft.azure.sdk.iot.service.devicetwin.DeviceTwin;
    import com.microsoft.azure.sdk.iot.service.devicetwin.DeviceTwinDevice;
    
    import java.io.IOException;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ExecutorService;
    
  9. Agregue las siguientes variables de nivel de clase a la clase App . Reemplace {youriothubconnectionstring} por la cadena de conexión de IoT Hub que copió anteriormente en Obtención de la cadena de conexión de IoT Hub:

    public static final String iotHubConnectionString = "{youriothubconnectionstring}";
    public static final String deviceId = "myDeviceId";
    
    private static final String methodName = "reboot";
    private static final Long responseTimeout = TimeUnit.SECONDS.toSeconds(30);
    private static final Long connectTimeout = TimeUnit.SECONDS.toSeconds(5);
    
  10. Para implementar un subproceso que lee las propiedades notificadas desde el dispositivo gemelo cada 10 segundos, agregue la clase anidada siguiente a la clase App:

    private static class ShowReportedProperties implements Runnable {
      public void run() {
        try {
          DeviceTwin deviceTwins = DeviceTwin.createFromConnectionString(iotHubConnectionString);
          DeviceTwinDevice twinDevice = new DeviceTwinDevice(deviceId);
          while (true) {
            System.out.println("Get reported properties from device twin");
            deviceTwins.getTwin(twinDevice);
            System.out.println(twinDevice.reportedPropertiesToString());
            Thread.sleep(10000);
          }
        } catch (Exception ex) {
          System.out.println("Exception reading reported properties: " + ex.getMessage());
        }
      }
    }
    
  11. Modifique la firma del método main para generar la siguiente excepción:

    public static void main(String[] args) throws IOException
    
  12. Para invocar al método directo de reinicio en el dispositivo simulado, reemplace el código en el método main por el código siguiente:

    System.out.println("Starting sample...");
    DeviceMethod methodClient = DeviceMethod.createFromConnectionString(iotHubConnectionString);
    
    try
    {
      System.out.println("Invoke reboot direct method");
      MethodResult result = methodClient.invoke(deviceId, methodName, responseTimeout, connectTimeout, null);
    
      if(result == null)
      {
        throw new IOException("Invoke direct method reboot returns null");
      }
      System.out.println("Invoked reboot on device");
      System.out.println("Status for device:   " + result.getStatus());
      System.out.println("Message from device: " + result.getPayload());
    }
    catch (IotHubException e)
    {
        System.out.println(e.getMessage());
    }
    
  13. Para iniciar el subproceso que sondea las propiedades notificadas desde el dispositivo simulado, agregue el código siguiente al método main:

    ShowReportedProperties showReportedProperties = new ShowReportedProperties();
    ExecutorService executor = Executors.newFixedThreadPool(1);
    executor.execute(showReportedProperties);
    
  14. Para poder detener la aplicación, agregue el código siguiente al método main:

    System.out.println("Press ENTER to exit.");
    System.in.read();
    executor.shutdownNow();
    System.out.println("Shutting down sample...");
    
  15. Guarde y cierre el archivo trigger-reboot\src\main\java\com\mycompany\app\App.java.

  16. Compile la aplicación de back-end trigger-reboot y corrija los errores. En el símbolo del sistema, vaya a la carpeta trigger-reboot y ejecute el comando siguiente:

    mvn clean package -DskipTests
    

Ejecución de las aplicaciones

Ya está preparado para ejecutar las aplicaciones.

  1. En un símbolo del sistema en la carpeta simulated-device, ejecute el comando siguiente para empezar a escuchar las llamadas al método de reinicio desde el centro de IoT:

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

    Aplicación de dispositivo simulado IoT Hub de Java para escuchar las llamadas al método directo de reinicio

  2. En un símbolo del sistema en la carpeta trigger-reboot, ejecute el comando siguiente para llamar al método de reinicio en el dispositivo simulado desde el centro de IoT:

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

    Aplicación de servicio IoT Hub de Java para llamar al método directo de reinicio

  3. El dispositivo simulado responde a la llamada al método directo de reinicio:

    La aplicación de dispositivo simulado IoT Hub de Java responde a la llamada al método directo

Personalizar y ampliar el dispositivo las acciones de administración del dispositivo

Las soluciones de IoT pueden expandir el conjunto definido de patrones de administración de dispositivos o permitir modelos personalizados mediante el uso de los primitivos de método de nube a dispositivo y dispositivos gemelos. Otros ejemplos de acciones de administración de dispositivos son el restablecimiento de fábrica, la actualización de firmware, la actualización de software, la administración de energía, la administración de conectividad y red, y el cifrado de datos.

Ventanas de mantenimiento del dispositivo

Normalmente, puede dispositivos para llevar a cabo acciones a la vez que minimiza las interrupciones y el tiempo de inactividad. Las ventanas de mantenimiento dle dispositivo son un patrón que se utiliza habitualmente para definir la hora en la que un dispositivo debe actualizar su configuración. Las soluciones de back-end pueden utilizar las propiedades deseadas del dispositivo gemelo para definir y activar una directiva en el dispositivo que permita una ventana de mantenimiento. Cuando un dispositivo recibe la directiva de la ventana de mantenimiento, puede usar la propiedad notificada del dispositivo gemelo para informar del estado de la directiva. La aplicación de back-end puede usar luego consultas de dispositivos gemelos para dar testimonio de cumplimiento de dispositivos y cada directiva.

Pasos siguientes

En este artículo, ha usado un método directo para desencadenar un reinicio remoto en un dispositivo. Se usaron las propiedades notificadas para notificar la última hora de reinicio del dispositivo y se consultó el dispositivo gemelo para detectar la última hora de reinicio del dispositivo desde la nube.

Para continuar con la introducción a IoT Hub y los patrones de administración de dispositivos, como la actualización basada en imágenes de un extremo a otro, consulte el Artículo de Device Update para Azure IoT Hub con la imagen de referencia para Raspberry Pi 3 B+.

Para obtener información sobre cómo ampliar la solución IoT y programar llamadas a métodos en varios dispositivos, vea Programación de trabajos en varios dispositivos.