Azure IoT Hub を使用してデバイスからクラウドにファイルをアップロードする

この記事では、次の方法を示します。

  • Azure IoT のデバイスとサービスの SDK、および IoT Hub のファイル アップロード機能を使って、ファイルを Azure Blob Storage にアップロードします。
  • Azure IoT サービス SDK を使って、ファイルが正常にアップロードされたことを IoT Hub に通知し、IoT Hub からファイル アップロード通知を受け取るバックエンド サービスを作成します。

一部のシナリオでは、デバイスが送信するデータを、IoT Hub が受け付ける比較的小さな device-to-cloud メッセージに、簡単にマップすることはできません。 IoT Hub のファイル アップロード機能を使うと、大きいデータまたは複雑なデータをクラウドに移動できます。 次に例を示します。

  • ビデオ
  • イメージを含む大きなファイル
  • 高頻度でサンプリングされる振動データ
  • 何らかの形式の前処理済みデータ

これらのファイルは通常、Azure Data FactoryHadoop スタックなどのツールを使ってクラウドでバッチ処理されます。 デバイスからファイルをアップロードする必要がある場合も、IoT Hub のセキュリティと信頼性を利用できます。 この記事では、その方法について説明します。

この記事は、この記事内から参照される実行可能な SDK サンプルを補完するためのものです。

詳細については、以下を参照してください:

重要

X.509 証明機関 (CA) 認証を使用するデバイスのファイル アップロード機能はパブリック プレビュー段階であり、プレビュー モードを有効にする必要があります。 これは、Azure デバイス プロビジョニング サービスで x.509 拇印認証または x.509 証明書の構成証明を使用するデバイスで一般提供されています。 IoT Hub での X.509 認証の詳細については、「サポートされている X.509 証明書」を参照してください。

前提条件

  • IoT ハブ SDK の一部の呼び出しでは、IoT Hub のプライマリ接続文字列が必要であるため、接続文字列を記録しておきます。

  • 登録済みのデバイス。 SDK の一部の呼び出しでは、デバイスのプライマリ接続文字列が必要であるため、接続文字列を記録しておきます。

  • IoT Hub のサービス接続アクセス許可: ファイル アップロード通知メッセージを受け取るには、バックエンド サービスにサービス接続アクセス許可が必要です。 既定では、どの IoT Hub も、このアクセス許可を付与する service という名前の共有アクセス ポリシーがある状態で作成されます。 詳しくは、「IoT ハブに接続する」をご覧ください。

  • Azure ストレージ アカウントAzure Blob Storage コンテナーをリンクして、IoT ハブでファイルのアップロードを構成します。 これらの構成は、Azure portalAzure CLI、または Azure PowerShell を使って行うことができます。

概要

この使い方には、2 つのセクションが含まれています。

  • デバイス アプリケーションからファイルをアップロードする
  • バックエンド アプリケーションでファイル アップロード通知を受け取る

デバイス アプリケーションからファイルをアップロードする

このセクションでは、Azure IoT SDK for .NET の DeviceClient クラスを使って、デバイスから IoT ハブにファイルをアップロードする方法を説明します。

デバイスから IoT ハブへのファイルのアップロードは、次の手順で行います。

  1. IoT Hub に接続する
  2. IoT ハブから SAS URI を取得する
  3. ファイルを Azure Storage にアップロードする
  4. ファイルのアップロード状態を IoT ハブに通知する

デバイスに接続する

CreateFromConnectionString を呼び出して、デバイスに接続します。 デバイスのプライマリ接続文字列を渡します。

AMQP は既定のトランスポート プロトコルです。

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

IoT ハブから SAS URI を取得する

GetFileUploadSasUriAsync を呼び出して、ファイルのアップロードの詳細を取得します。 SAS URI は、次のステップでデバイスから 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();

ファイルを Azure Storage にアップロードする

ファイルを Azure Storage にアップロードするには:

  1. ファイル アップロード URI を渡して、blockBlobClient オブジェクトを作成します。

  2. UploadAsync メソッドを使い、SAS URI を渡して、ファイルを Blob Storage にアップロードします。 必要に応じて、BLOB アップロード オプションとキャンセル トークン パラメーターを追加できます。

Azure Blob クライアントは、ファイルを Azure Storage にアップロードするプロトコルとして、常に HTTPS を使います。

この例では、BlockBlobClient に SAS URI を渡して Azure Storage ブロック BLOB クライアントを作成し、ファイルをアップロードします。

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

ファイルのアップロード状態を IoT ハブに通知する

CompleteFileUploadAsync を使い、FileUploadCompletionNotification オブジェクトを渡して、デバイス クライアントがアップロードを完了したことを IoT Hub に通知します。 IsSuccess フラグは、アップロードが成功したかどうかを示します。 通知が送信された後、IoT ハブはアップロードに関連付けられているリソース (SAS URI) を解放します。

ファイル アップロード通知が有効になっている場合、IoT ハブは、ファイル アップロード通知用に構成されているバックエンド サービスに、ファイル アップロード通知メッセージを送信します。

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);

SDK のファイル アップロード サンプル

SDK には、このファイル アップロード サンプルが含まれています。

バックエンド アプリケーションでファイル アップロード通知を受け取る

IoT ハブからファイル アップロード通知メッセージを受け取るバックエンド サービスを作成できます。

ServiceClient クラスには、サービスがファイルアップロード通知を受け取るために使用できるメソッドが含まれています。

ファイル アップロード通知を受け取るには:

  1. CreateFromConnectionString を呼び出して、IoT ハブに接続します。 IoT ハブのプライマリ接続文字列を渡します。
  2. CancellationToken を作成します。
  3. GetFileNotificationReceiver を呼び出して、通知レシーバーを作成します。
  4. ReceiveAsync を含むループを使って、ファイル アップロード通知を待機します。

次に例を示します。

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);
}

概要

この使い方には、2 つのセクションが含まれています。

  • デバイス アプリケーションからファイルをアップロードする
  • バックエンド アプリケーションでファイル アップロード通知を受け取る

デバイス アプリケーションからファイルをアップロードする

このセクションでは、Azure IoT SDK for Java の DeviceClient クラスを使って、デバイスから IoT ハブにファイルをアップロードする方法を説明します。

デバイスから IoT ハブへのファイルのアップロードは、次の手順で行います。

  1. デバイスに接続する
  2. IoT ハブから SAS URI を取得する
  3. ファイルを Azure Storage にアップロードする
  4. IoT ハブにファイル アップロード状態通知を送信する

接続プロトコル

ファイル アップロード操作では常に HTTPS が使われますが、DeviceClient では、テレメトリ、デバイス メソッド、デバイス ツインなどの他のサービス用の IotHubClientProtocol を定義できます。

IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;

デバイスに接続する

DeviceClient をインスタンス化し、デバイスのプライマリ接続文字列を使ってデバイスに接続します。

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

IoT ハブから SAS URI を取得する

getFileUploadSasUri を呼び出して、FileUploadSasUriResponse オブジェクトを取得します。

FileUploadSasUriResponse には、これらのメソッドと戻り値が含まれます。 戻り値は、ファイル アップロード メソッドに渡すことができます。

メソッド 戻り値
getCorrelationId() 関連付け ID
getContainerName() コンテナー名
getBlobName() BLOB 名
getBlobUri() Blob URI

次に例を示します。

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());

ファイルを Azure Storage にアップロードする

BLOB URI エンドポイントを BlobClientBuilder.buildclient に渡して、BlobClient オブジェクトを作成します。

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

uploadFromFile を呼び出して、ファイルを Blob Storage にアップロードします。

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

IoT ハブにファイル アップロード状態通知を送信する

ファイルのアップロードを試みた後で、アップロード状態通知を IoT ハブに送信します。

FileUploadCompletionNotification オブジェクトを作成します。 correlationIdisSuccess ファイル アップロード成功状態を渡します。 ファイルのアップロードが成功したときは isSuccesstrue 値を渡し、そうでないときは false を渡します。

ファイルのアップロードが失敗した場合でも、FileUploadCompletionNotification を呼び出す必要があります。 IoT ハブで同時にアクティブにできる SAS URI の数は固定です。 ファイルのアップロードが完了したら、他の SAS URI を生成できるように、SAS URI を解放する必要があります。 この API で解放されなかった SAS URI は、IoT ハブで SAS URI に対して構成されているが有効期間に基づいて、最終的に自動的に解放されます。

この例では、成功状態を渡しています。

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

クライアントを閉じる

client リソースを解放します。

client.closeNow();

バックエンド アプリケーションでファイル アップロード通知を受け取る

ファイル アップロード通知を受け取るバックエンド アプリケーションを作成できます。

ファイル アップロード通知アプリケーションを作成するには:

  1. IoT Hub サービス クライアントに接続する
  2. ファイル アップロード通知をチェックする

ServiceClient クラスには、サービスがファイルアップロード通知を受け取るために使用できるメソッドが含まれています。

IoT Hub サービス クライアントに接続する

IotHubServiceClientProtocol オブジェクトを作成します。 接続では、AMQPS プロトコルが使われます。

createFromConnectionString を呼び出して IoT ハブに接続します。 IoT ハブのプライマリ接続文字列を渡します。

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

ファイル アップロードの状態を調べる

ファイル アップロードの状態を調べるには:

  1. getFileUploadNotificationReceiver オブジェクトを作成します。
  2. open を使って IoT ハブに接続します。
  3. receive を呼び出して、ファイル アップロードの状態を調べます。 このメソッドは、fileUploadNotification オブジェクトを返します。 アップロード通知を受け取った場合は、fileUploadNotification メソッドを使ってアップロード状態フィールドを表示できます。

次に例を示します。

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();

SDK のファイル アップロード サンプル

Java でのファイル アップロードについては 2つのサンプルがあります。

パッケージをインストールする

関連するコードを呼び出す前に、azure-iot-device ライブラリをインストールする必要があります。

pip install azure-iot-device

azure.storage.blob パッケージは、ファイルのアップロードを実行するために使われます。

pip install azure.storage.blob

デバイス アプリケーションからファイルをアップロードする

このセクションでは、Azure IoT SDK for Python の IoTHubDeviceClient クラスを使って、デバイスから IoT ハブにファイルをアップロードする方法を説明します。

デバイスから IoT ハブへのファイルのアップロードは、次の手順で行います。

  1. デバイスに接続する
  2. Blob Storage の情報を取得する
  3. Blob Storage にファイルをアップロードする
  4. アップロードの状態を IoT ハブに通知する

ライブラリをインポートする

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

デバイスに接続する

デバイスに接続するには:

  1. create_from_connection_string を呼び出して、デバイスのプライマリ接続文字列を追加します。

  2. connect を呼び出して、デバイス クライアントを接続します。

次に例を示します。

# 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()

Blob Storage の情報を取得する

get_storage_info_for_blob を呼び出して、リンクされた Azure ストレージ アカウントに関する情報を IoT ハブから取得します。 この情報には、ホスト名、コンテナー名、BLOB 名、および SAS トークンが含まれます。 get_storage_info_for_blob メソッドは、notify_blob_upload_status メソッドで使われる correlation_id も返します。 correlation_id は、ユーザーが作業している BLOB を IoT Hub でマークする方法です。

# 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)

Blob Storage にファイルをアップロードする

Blob Storage にファイルをアップロードするには:

  1. from_blob_url を使って、BLOB URL から BlobClient オブジェクトを作成します。
  2. upload_blob を呼び出して、ファイルを Blob Storage にアップロードします。

この例では、blob_info 構造体を解析して、BlobClient の初期化に使う URL を作成します。 次に、upload_blob を呼び出して、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)

アップロードの状態を IoT ハブに通知する

notify_blob_upload_status を使って、Blob Storage の操作の状態を IoT ハブに通知します。 get_storage_info_for_blob メソッドで取得した correlation_id を渡します。 correlation_id は、ファイル アップロード タスクの状態に関する通知をリッスンしている可能性があるサービスに通知するために、IoT ハブによって使われます。

この例では、ファイルのアップロードが成功したことを IoT ハブに通知します。

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

デバイス クライアントをシャットダウンする

クライアントをシャットダウンします。 このメソッドを呼び出すと、それ以降のクライアント呼び出しの試みでは、ClientError が発生します。

device_client.shutdown()

SDK のファイル アップロード サンプル

この SDK には、ファイル アップロードのサンプルが 2 つ含まれています。

概要

この使い方には、2 つのセクションが含まれています。

  • デバイス アプリケーションからファイルをアップロードする
  • バックエンド アプリケーションでファイル アップロード通知を受け取る

デバイス アプリケーションからファイルをアップロードする

このセクションでは、Azure IoT SDK for Node.js の azure-iot-device パッケージを使って、デバイスから IoT ハブにファイルをアップロードする方法を説明します。

SDK パッケージをインストールする

このコマンドを実行して、azure-iot-device デバイス SDK、azure-iot-device-mqtt@azure/storage-blob パッケージを開発用コンピューターにインストールします。

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

azure-iot-device パッケージには、IoT デバイスとやり取りするオブジェクトが含まれています。

デバイスから IoT ハブへのファイルのアップロードは、次の手順で行います。

  1. BLOB の Shared Access Signature を取得する
  2. ファイルを Azure Storage にアップロードする
  3. IoT ハブにファイル アップロード状態通知を送信する

モジュールを作成する

インストールしたパッケージを使って、クライアント、プロトコル、エラー、パスの各モジュールを作成します。

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');

IoT ハブから SAS URI を取得する

getBlobSharedAccessSignature を使って、リンクされたストレージ アカウントの SAS トークンを IoT ハブから取得します。 前提条件で説明されているように、IoT ハブは Blob Storage にリンクされています。

次に例を示します。

// 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');
}

ファイルを IoT ハブにアップロードする

デバイスから IoT ハブにファイルをアップロードするには:

  1. ストリーム パイプラインを作成する
  2. BLOB URL を構築する
  3. Blob Storage にファイルをアップロードするための BlockBlobClient を作成する
  4. uploadFile を呼び出して、ファイルを Blob Storage にアップロードする
  5. notifyBlobUploadStatus を呼び出して、アップロードが成功または失敗したことを IoT ハブに通知する

次に例を示します。

// 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);

バックエンド アプリケーションでファイル アップロード通知を受け取る

バックエンド アプリケーションを作成して、IoT Hub サービス クライアントでデバイス ファイル アップロード通知をチェックできます。

ファイル アップロード通知アプリケーションを作成するには:

  1. IoT Hub サービス クライアントに接続する
  2. ファイル アップロード通知をチェックする

IoT Hub サービス クライアントに接続する

ServiceClient クラスには、サービスがファイルアップロード通知を受け取るために使用できるメソッドが含まれています。

fromConnectionString を使って IoT ハブに接続します。 IoT ハブのプライマリ接続文字列を渡します。

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

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');

ファイル アップロード通知をチェックする

ファイル アップロード通知をチェックするには:

  1. getFileNotificationReceiver を呼び出します。 通知メッセージを受け取ったら呼び出されるファイル アップロード コールバック メソッドの名前を指定します。
  2. コールバック メソッドでファイル アップロード通知を処理します。

この例では、receiveFileUploadNotification 通知コールバック レシーバーを設定します。 レシーバーは、ファイル アップロード状態の情報を解釈して、ステータス メッセージをコンソールに出力します。

//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');
      }
    });
  });
}

SDK のファイル アップロード サンプル

この SDK には、BLOB への高度なアップロードのサンプルが含まれています。