Carga de archivos desde un dispositivo a la nube con Azure IoT Hub

En este artículo se explica cómo:

  • Use las funcionalidades de carga de archivos de IoT Hub para cargar un archivo en Azure Blob Storage mediante un dispositivo Azure IoT y SDK de servicio.
  • Notifique a IoT Hub que el archivo se cargó correctamente y cree un servicio back-end para recibir notificaciones de carga de archivos de IoT Hub mediante los SDK del servicio Azure IoT.

En algunos escenarios, no se pueden asignar fácilmente los datos que los dispositivos envían en los mensajes del dispositivo a la nube de un tamaño relativamente reducido que acepta IoT Hub. Las funcionalidades de carga de archivos en IoT Hub permiten mover datos grandes o complejos a la nube. Por ejemplo:

  • Vídeos
  • Archivos grandes con imágenes
  • Datos de vibración muestreados con alta frecuencia
  • Cierto tipo de datos procesados previamente

Dichos archivos se suelen procesar por lotes en la nube mediante herramientas como Azure Data Factory o la pila Hadoop. Cuando necesite cargar archivos desde un dispositivo, todavía puede usar la seguridad y confiabilidad de IoT Hub. Este artículo le muestra cómo.

El objetivo de este artículo es servir de complemento a los ejemplos de SDK ejecutables a los que se hace referencia desde este artículo.

Para más información, vea:

Importante

La funcionalidad de carga de archivos de los dispositivos que usan la autenticación de la entidad de certificación X.509 está disponible como versión preliminar pública, y se debe habilitar el modo de vista previa. Está disponible con carácter general en dispositivos que usan la autenticación de huella digital X.509 o la atestación de certificado X.509 con el servicio de aprovisionamiento de dispositivos de Azure. Para obtener más información acerca de la autenticación X.509 con IoT Hub, consulte Certificados X.509 compatibles.

Requisitos previos

  • Una instancia de IoT Hub. Algunas llamadas al SDK requieren la cadena de conexión principal de IoT Hub, así que anótela.

  • Un dispositivo registrado. Algunas llamadas al SDK requieren la cadena de conexión principal del dispositivo, así que anótela.

  • Permiso Conexión del servicio de IoT Hub: para recibir mensajes de notificación de carga de archivos, el servicio back-end 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 más información, consulte Conexión a un centro de IoT.

  • Configure la carga de archivos en el centro de IoT mediante la vinculación de una cuenta de Azure Storage y un contenedor de Azure Blob Storage. Puede configurarlos mediante Azure Portal, la CLI de Azure o Azure PowerShell.

Información general

Este procedimiento contiene dos secciones:

  • Carga de un archivo desde una aplicación de dispositivo
  • Recepción de una notificación de carga de archivos en una aplicación back-end

Carga de un archivo desde una aplicación de dispositivo

En esta sección se describe cómo cargar un archivo desde un dispositivo a un centro de IoT mediante la clase DeviceClient en el SDK de Azure IoT para .NET.

Siga este procedimiento para cargar un archivo desde un dispositivo al centro de IoT:

  1. Conexión al centro de IoT
  2. Obtención de un URI de SAS desde el centro de IoT
  3. Carga del archivo en Azure Storage
  4. Notificación al centro de IoT del estado de carga de archivos

Conexión del dispositivo

Llame a CreateFromConnectionString para conectarse al dispositivo. Pase la cadena de conexión principal del dispositivo.

AMQP es el protocolo de transporte predeterminado.

static string connectionString = "{device primary connection string}";
deviceClient = DeviceClient.CreateFromConnectionString(connectionString);

Obtención de un URI de SAS desde el centro de IoT

Llame a GetFileUploadSasUriAsync para obtener detalles de carga de archivos. El URI de SAS se usa en el siguiente paso para cargar un archivo de un dispositivo en Blob Storage.

const string filePath = "TestPayload.txt";
using var fileStreamSource = new FileStream(filePath, FileMode.Open);
var fileName = Path.GetFileName(fileStreamSource.Name);
var fileUploadSasUriRequest = new FileUploadSasUriRequest
{
    BlobName = fileName
};

FileUploadSasUriResponse sasUri = await _deviceClient.GetFileUploadSasUriAsync(fileUploadSasUriRequest, System.Threading.CancellationToken cancellationToken = default);
Uri uploadUri = sasUri.GetBlobUri();

Carga de un archivo en Azure Storage

Para cargar un archivo en Azure Storage:

  1. Cree un objeto blockBlobClient y pase un URI de carga de archivos.

  2. Use el método UploadAsync para cargar un archivo en Blob Storage y pasar el URI de SAS. Si lo desea, puede agregar opciones de carga de blobs y parámetros de token de cancelación.

El cliente de blobs de Azure siempre usa HTTPS como protocolo para cargar el archivo en Azure Storage.

En este ejemplo, se pasa a BlockBlobClient el URI de SAS para crear un cliente de blobs en bloques de Azure Storage y carga el archivo:

var blockBlobClient = new BlockBlobClient(uploadUri);
await blockBlobClient.UploadAsync(fileStreamSource, null, null);

Notificación al centro de IoT del estado de carga de archivos

Use CompleteFileUploadAsync para notificar al centro de IoT que el cliente del dispositivo completó la carga, pasando un objeto FileUploadCompletionNotification. La marca IsSuccess indica si la carga se realizó correctamente o no. Después de recibir una notificación, el centro de IoT liberará los recursos asociados a la carga (el URI de SAS).

Si se habilitan las notificaciones de carga de archivos, el centro de IoT envía un mensaje de notificación de carga de archivos a los servicios back-end configurados para la notificación de carga de archivos.

var successfulFileUploadCompletionNotification = new FileUploadCompletionNotification
{
    // Mandatory. Must be the same value as the correlation id returned in the sas uri response
    CorrelationId = sasUri.CorrelationId,

    // Mandatory. Will be present when service client receives this file upload notification
    IsSuccess = true,

    // Optional, user defined status code. Will be present when service client receives this file upload notification
    StatusCode = 200,

    // Optional, user-defined status description. Will be present when service client receives this file upload notification
    StatusDescription = "Success"
};

await _deviceClient.CompleteFileUploadAsync(successfulFileUploadCompletionNotification);

Ejemplo de carga de archivos del SDK

El SDK incluye este ejemplo de carga de archivos.

Recepción de una notificación de carga de archivos en una aplicación back-end

Puede crear un servicio back-end para recibir mensajes de notificación de carga de archivos desde el centro de IoT.

La clase ServiceClient contiene métodos que los servicios pueden usar para recibir notificaciones de carga de archivos.

Para recibir una notificación de carga de archivos:

  1. Llame a CreateFromConnectionString para conectarse al centro de IoT. Pase la cadena de conexión principal del centro de IoT.
  2. Cree un CancellationToken.
  3. Llame a GetFileNotificationReceiver para crear un receptor de notificaciones.
  4. Use un bucle con ReceiveAsync para esperar a la notificación de carga de archivos.

Por ejemplo:

using Microsoft.Azure.Devices;
static ServiceClient serviceClient;
static string connectionString = "{IoT hub connection string}";
serviceClient = ServiceClient.CreateFromConnectionString(connectionString);

// Define the cancellation token
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;

// Create a notification receiver
var notificationReceiver = serviceClient.GetFileNotificationReceiver();
Console.WriteLine("\nReceiving file upload notification from service");

// Check for file upload notifications
while (true)
{
    var fileUploadNotification = await notificationReceiver.ReceiveAsync(token);
    if (fileUploadNotification == null) continue;
    Console.ForegroundColor = ConsoleColor.Yellow;
    Console.WriteLine("Received file upload notification: {0}", 
        string.Join(", ", fileUploadNotification.BlobName));
    Console.ResetColor();
    await notificationReceiver.CompleteAsync(fileUploadNotification);
}

Información general

Este procedimiento contiene dos secciones:

  • Carga de un archivo desde una aplicación de dispositivo
  • Recepción de una notificación de carga de archivos en una aplicación back-end

Carga de un archivo desde una aplicación de dispositivo

En esta sección se describe cómo cargar un archivo desde un dispositivo a un centro de IoT mediante la clase DeviceClient desde el SDK de Azure IoT para Java.

Siga este procedimiento para cargar un archivo desde un dispositivo al centro de IoT:

  1. Conexión del dispositivo
  2. Obtención de un URI de SAS desde el centro de IoT
  3. Carga del archivo en Azure Storage
  4. Envío de una notificación de estado de carga de archivos al centro de IoT

Protocolo de la conexión

Las operaciones de carga de archivos siempre usan HTTPS, pero DeviceClient puede definir el IotHubClientProtocol para otros servicios como telemetría, método de dispositivo y dispositivo gemelo.

IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;

Conexión del dispositivo

Cree una instancia del DeviceClient para conectarse al dispositivo mediante la cadena de conexión principal del dispositivo.

String connString = "{IoT hub connection string}";
DeviceClient client = new DeviceClient(connString, protocol);

Obtención de un URI de SAS desde el centro de IoT

Llame a getFileUploadSasUri para obtener un objeto FileUploadSasUriResponse.

FileUploadSasUriResponse incluye estos métodos y valores devueltos. Los valores devueltos se pueden pasar a los métodos de carga de archivos.

Método Valor devuelto
getCorrelationId() Identificador de correlación
getContainerName() Nombre del contenedor
getBlobName() Blob name (Nombre de blob)
getBlobUri() Identificador URI de blob

Por ejemplo:

FileUploadSasUriResponse sasUriResponse = client.getFileUploadSasUri(new FileUploadSasUriRequest(file.getName()));

System.out.println("Successfully got SAS URI from IoT hub");
System.out.println("Correlation Id: " + sasUriResponse.getCorrelationId());
System.out.println("Container name: " + sasUriResponse.getContainerName());
System.out.println("Blob name: " + sasUriResponse.getBlobName());
System.out.println("Blob Uri: " + sasUriResponse.getBlobUri());

Carga del archivo en Azure Storage

Pase el punto de conexión de URI de blob a BlobClientBuilder.buildclient para crear el objeto BlobClient.

BlobClient blobClient =
    new BlobClientBuilder()
        .endpoint(sasUriResponse.getBlobUri().toString())
        .buildClient();

Llame a uploadFromFile para cargar el archivo en Blob Storage.

String fullFileName = "Path of the file to upload";
blobClient.uploadFromFile(fullFileName);

Envío de una notificación de estado de carga de archivos al centro de IoT

Envíe una notificación de estado de carga al centro de IoT después de un intento de carga de archivos.

Cree un objeto FileUploadCompletionNotification. Pase el estado correcto de carga de archivos correlationId y isSuccess. Pase un valor true de isSuccess cuando la carga de archivos se haya realizado correctamente, false cuando no.

FileUploadCompletionNotification debe llamarse incluso cuando se produce un error en la carga de archivos. El centro de IoT tiene un número fijo de URI de SAS que se puede activar en un momento dado. Una vez que haya terminado con la carga de archivos, debe liberar el URI de SAS para que se pueda generar otro URI de SAS. Si un URI de SAS no se libera a través de esta API, se libera finalmente en función de cuánto tiempo se configuran los URI de SAS para vivir en un centro de IoT.

En este ejemplo se pasa un estado correcto.

FileUploadCompletionNotification completionNotification = new FileUploadCompletionNotification(sasUriResponse.getCorrelationId(), true);
client.completeFileUpload(completionNotification);

Cierre el cliente

Libere los recursos de client.

client.closeNow();

Recepción de una notificación de carga de archivos en una aplicación back-end

Puede crear una aplicación back-end para recibir notificaciones de carga de archivos.

Para crear una aplicación de notificación de carga de archivos:

  1. Conéctese al cliente del servicio del centro de IoT
  2. Busque una notificación de carga de archivos

La clase ServiceClient contiene métodos que los servicios pueden usar para recibir notificaciones de carga de archivos.

Conéctese al cliente del servicio del centro de IoT

Crear un objeto IotHubServiceClientProtocol. La conexión usa el protocolo AMQPS.

Llame a createFromConnectionString para conectarse al centro de IoT. Pase la cadena de conexión principal del centro de IoT.

private static final String connectionString = "{IoT hub primary connection string}";
private static final IotHubServiceClientProtocol protocol = IotHubServiceClientProtocol.AMQPS;
ServiceClient sc = ServiceClient.createFromConnectionString(connectionString, protocol);

Comprobación del estado de carga de archivos

Para comprobar el estado de carga de archivos:

  1. Cree un objeto getFileUploadNotificationReceiver.
  2. Use abrir para conectarse al centro de IoT.
  3. Llame a receive para comprobar el estado de carga de archivos. Este método devuelve un objeto fileUploadNotification. Si se recibe un aviso de carga, puede ver los campos de estado de carga mediante métodos fileUploadNotification.

Por ejemplo:

FileUploadNotificationReceiver receiver = sc.getFileUploadNotificationReceiver();
receiver.open();
FileUploadNotification fileUploadNotification = receiver.receive(2000);

if (fileUploadNotification != null)
{
    System.out.println("File Upload notification received");
    System.out.println("Device Id : " + fileUploadNotification.getDeviceId());
    System.out.println("Blob Uri: " + fileUploadNotification.getBlobUri());
    System.out.println("Blob Name: " + fileUploadNotification.getBlobName());
    System.out.println("Last Updated : " + fileUploadNotification.getLastUpdatedTimeDate());
    System.out.println("Blob Size (Bytes): " + fileUploadNotification.getBlobSizeInBytes());
    System.out.println("Enqueued Time: " + fileUploadNotification.getEnqueuedTimeUtcDate());
}
else
{
    System.out.println("No file upload notification");
}

// Close the receiver object
receiver.close();

Ejemplos de carga de archivos del SDK

Hay dos ejemplos de carga de archivos Java.

Instalar paquetes

La biblioteca azure-iot-device debe instalarse antes de llamar a cualquier código relacionado.

pip install azure-iot-device

El paquete azure.storage.blob se usa para realizar la carga de archivos.

pip install azure.storage.blob

Carga de un archivo desde una aplicación de dispositivo

En esta sección se describe cómo cargar un archivo desde un dispositivo a un centro de IoT mediante la clase IoTHubDeviceClient desde el SDK de Azure IoT para Python.

Siga este procedimiento para cargar un archivo desde un dispositivo al centro de IoT:

  1. Conexión del dispositivo
  2. Obtención de información de Blob Storage
  3. Carga del archivo en Blob Storage
  4. Notificación al centro de IoT del estado de carga

Importación de bibliotecas

import os
from azure.iot.device import IoTHubDeviceClient
from azure.core.exceptions import AzureError
from azure.storage.blob import BlobClient

Conexión del dispositivo

Para conectarse al dispositivo:

  1. Llame a create_from_connection_string para agregar la cadena de conexión principal del dispositivo.

  2. Llame a connect para conectar el cliente del dispositivo.

Por ejemplo:

# Add your IoT hub primary connection string
CONNECTION_STRING = "{Device primary connection string}"
device_client = IoTHubDeviceClient.create_from_connection_string(CONNECTION_STRING)

# Connect the client
device_client.connect()

Obtención de información de Blob Storage

Llame a get_storage_info_for_blob para obtener información de un centro de IoT sobre una cuenta de Azure Storage vinculada. Esta información incluye el nombre de host, el nombre del contenedor, el nombre del blob y un token de SAS. El método get_storage_info_for_blob también devuelve un correlation_id, que se usa en el método notify_blob_upload_status. El correlation_id es la forma que tiene IoT Hub de marcar en qué Blob está trabajando.

# Get the storage info for the blob
PATH_TO_FILE = "{Full path to local file}"
blob_name = os.path.basename(PATH_TO_FILE)
blob_info = device_client.get_storage_info_for_blob(blob_name)

Carga de un archivo en Blob Storage

Para cargar un archivo en Blob Storage:

  1. Use from_blob_url para crear un objeto BlobClient a partir de una dirección URL de blob.
  2. Llame a upload_blob para cargar el archivo en Blob Storage.

En este ejemplo se analiza la estructura de blob_info para crear una dirección URL que usa para inicializar un BlobClient. A continuación, llama a upload_blob para cargar el archivo en Blob Storage.

try:
    sas_url = "https://{}/{}/{}{}".format(
        blob_info["hostName"],
        blob_info["containerName"],
        blob_info["blobName"],
        blob_info["sasToken"]
    )

    print("\nUploading file: {} to Azure Storage as blob: {} in container {}\n".format(file_name, blob_info["blobName"], blob_info["containerName"]))

    # Upload the specified file
    with BlobClient.from_blob_url(sas_url) as blob_client:
        with open(file_name, "rb") as f:
            result = blob_client.upload_blob(f, overwrite=True)
            return (True, result)

except FileNotFoundError as ex:
    # catch file not found and add an HTTP status code to return in notification to IoT hub
    ex.status_code = 404
    return (False, ex)

except AzureError as ex:
    # catch Azure errors that might result from the upload operation
    return (False, ex)

Notificación al centro de IoT del estado de carga

Use notify_blob_upload_status para notificar al centro de IoT el estado de la operación de Blob Storage. Pase el correlation_id obtenido por el método get_storage_info_for_blob. El centro de IoT usa el correlation_id para notificar a cualquier servicio que pueda estar escuchando una notificación con respecto al estado de la tarea de carga de archivos.

En este ejemplo se notifica al centro de IoT una carga de archivos correcta:

device_client.notify_blob_upload_status(storage_info["correlationId"], True, 200, "OK: {}".format(PATH_TO_FILE)

Apagado del cliente del dispositivo

Apague el cliente. Una vez que se llama a este método, cualquier intento de llamadas de cliente adicionales da como resultado un ClientError que se genera.

device_client.shutdown()

Ejemplos de carga de archivos del SDK

El SDK incluye dos ejemplos de carga de archivos:

Información general

Este procedimiento contiene dos secciones:

  • Carga de un archivo desde una aplicación de dispositivo
  • Recepción de una notificación de carga de archivos en una aplicación back-end

Carga de un archivo desde una aplicación de dispositivo

En esta sección se describe cómo cargar un archivo desde un dispositivo a un centro de IoT mediante la clase azure-iot-device en el SDK de Azure IoT para Node.js.

Instalación de paquetes de SDK

Ejecute este comando para instalar el SDK de dispositivo azure-iot-device, el azure-iot-device-mqtt y los paquetes @azure/storage-blob en el equipo de desarrollo:

npm install azure-iot-device azure-iot-device-mqtt @azure/storage-blob --save

El paquete azure-iot-device contiene objetos que interactúan con dispositivos IoT.

Siga este procedimiento para cargar un archivo desde un dispositivo al centro de IoT:

  1. Obtención de firmas de acceso compartido de blobs
  2. Carga del archivo en Azure Storage
  3. Envío de una notificación de estado de carga de archivos al centro de IoT

Creación de módulos

Cree módulos de cliente, protocolo, errores y ruta de acceso mediante los paquetes instalados.

const Client = require('azure-iot-device').Client;
const Protocol = require('azure-iot-device-mqtt').Mqtt;
const errors = require('azure-iot-common').errors;
const path = require('path');

Obtención de un URI de SAS desde el centro de IoT

Use getBlobSharedAccessSignature para obtener el token de SAS de la cuenta de almacenamiento vinculada desde el centro de IoT. Como se describe en los requisitos previos, el centro de IoT está vinculado a Blob Storage.

Por ejemplo:

// make sure you set these environment variables prior to running the sample.
const localFilePath = process.env.PATH_TO_FILE;
const storageBlobName = path.basename(localFilePath);
const blobInfo = await client.getBlobSharedAccessSignature(storageBlobName);
if (!blobInfo) {
throw new errors.ArgumentError('Invalid upload parameters');
}

Carga del archivo en el centro de IoT

Para cargar un archivo desde un dispositivo al centro de IoT:

  1. Cree una canalización de flujo
  2. Construya la dirección URL del blob
  3. Cree un BlockBlobClient para la carga de archivos en Blob Storage
  4. Llame a uploadFile para cargar el archivo en Blob Storage
  5. Llame a notifyBlobUploadStatus para notificar al centro de IoT que la carga se realizó correctamente o produjo un error

Por ejemplo:

// Open the pipeline
const pipeline = newPipeline(new AnonymousCredential(), {
retryOptions: { maxTries: 4 },
telemetry: { value: 'HighLevelSample V1.0.0' }, // Customized telemetry string
keepAliveOptions: { enable: false }
});

// Construct the blob URL
const { hostName, containerName, blobName, sasToken } = blobInfo;
const blobUrl = `https://${hostName}/${containerName}/${blobName}${sasToken}`;

// Create the BlockBlobClient for file upload to Blob Storage
const blobClient = new BlockBlobClient(blobUrl, pipeline);

// Setup blank status notification arguments to be filled in on success/failure
let isSuccess;
let statusCode;
let statusDescription;

const uploadStatus = await blobClient.uploadFile(localFilePath);
console.log('uploadStreamToBlockBlob success');

  try {
    const uploadStatus = await blobClient.uploadFile(localFilePath);
    console.log('uploadStreamToBlockBlob success');

    // Save successful status notification arguments
    isSuccess = true;
    statusCode = uploadStatus._response.status;
    statusDescription = uploadStatus._response.bodyAsText;

    // Notify IoT hub of upload to blob status (success)
    console.log('notifyBlobUploadStatus success');
  }
  catch (err) {
    isSuccess = false;
    statusCode = err.code;
    statusDescription = err.message;

    console.log('notifyBlobUploadStatus failed');
    console.log(err);
  }

// Send file upload status notification to IoT hub
await client.notifyBlobUploadStatus(blobInfo.correlationId, isSuccess, statusCode, statusDescription);

Recepción de una notificación de carga de archivos en una aplicación back-end

Puede crear una aplicación back-end para comprobar el cliente del servicio del centro de IoT para ver las notificaciones de carga de archivos de dispositivo.

Para crear una aplicación de notificación de carga de archivos:

  1. Conéctese al cliente del servicio del centro de IoT
  2. Busque una notificación de carga de archivos

Conéctese al cliente del servicio del centro de IoT

La clase ServiceClient contiene métodos que los servicios pueden usar para recibir notificaciones de carga de archivos.

Conéctese al centro de IoT mediante fromConnectionString. Pase la cadena de conexión principal del centro de IoT.

const Client = require('azure-iothub').Client;
const connectionString = "{IoT hub primary connection string}";
const serviceClient = Client.fromConnectionString(connectionString);

Abra la conexión al centro de IoT.

//Open the connection to IoT hub
serviceClient.open(function (err) {
  if (err) {
    console.error('Could not connect: ' + err.message);
  } else {
    console.log('Service client connected');

Busque una notificación de carga de archivos

Para comprobar si hay notificaciones de carga de archivos:

  1. Llame a getFileNotificationReceiver. Proporcione el nombre de un método de devolución de llamada de carga de archivos al que se llama cuando se reciben mensajes de notificación.
  2. Procese las notificaciones de carga de archivos en el método de devolución de llamada.

En este ejemplo se configura un receptor de devolución de llamada de notificación receiveFileUploadNotification. El receptor interpreta la información de estado de carga del archivo e imprime un mensaje de estado en la consola.

//Set up the receiveFileUploadNotification notification message callback receiver
serviceClient.getFileNotificationReceiver(function receiveFileUploadNotification(err, receiver){
if (err) {
  console.error('error getting the file notification receiver: ' + err.toString());
} else {
  receiver.on('message', function (msg) {
    console.log('File upload from device:')
    console.log(msg.getData().toString('utf-8'));
    receiver.complete(msg, function (err) {
      if (err) {
        console.error('Could not finish the upload: ' + err.message);
      } else {
        console.log('Upload complete');
      }
    });
  });
}

Ejemplo de carga de archivos del SDK

El SDK incluye un ejemplo avanzado de carga a blob.