Databricks にて Azure IoT Hub に対してファイルをアップロードする方法

## 概要

Databricks にて Azure IoT SDK により Azure IoT Hub に対してファイルをアップロードする方法を共有します。

## 事前準備

### 環境構築

- Azure IoT Hub の構築 （本手順は Free tier で実施）
- Databricks （本手順は Serveless ではなく汎用コンピュートで実行）
- Azure Storage

### デバイスの作成と接続文字列の取得

Azure IoT Hub のリソース画面にて、`デバイス`タブを選択後、`+ デバイスの追加`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/32708e89-0264-4b64-b5f2-494be974a7d4.png)

`デバイス ID`に任意の値を入力し、`保存`を選択してデバイスを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/37ac238e-cbd3-48d6-82f5-68cf9038354e.png)

作成したデバイスを表示して、`プライマリ接続文字列`の`コピー済み`を選択して値をコピーします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/4f8d5549-6a72-4ff4-9e10-0e23214201f6.png)


### Azure Storage に対する Azure IoT Hub への権限付与を実施

IoT hub の画面にて、 `ID` -> `システム割り当て`を選択し、`状態`を`オン`に設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9303406a-b701-40c4-b2dd-c8455a15522f.png)

Azure Storage の画面にて、IoT Hub のマネージド ID に対して`ストレージ BLOB データ共同作成者`権限を付与します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/3483935e-6268-4218-a401-fe9c1ad90886.png)

IoT Hub の画面にて、`ファイルのアップロード` -> `Azure Storage コンテナーの選択`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d424a73d-bc45-46a8-af90-11ea31f450a1.png)

ファイルアップロード先のストレージアカウントとコンテナーを選択して、`選択`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9af46802-39dd-4478-bb1b-de9df83bfa05.png)

`保存`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e38a8a59-f3d7-4c6d-9940-a3966f8b3841.png)

## アップロードする方法

アップロードするファイルを確認します。

```python
from PIL import Image
import matplotlib.pyplot as plt

img = Image.open('/dbfs/databricks-datasets/flower_photos/daisy/100080576_f52e8ee070_n.jpg')
plt.imshow(img)
plt.axis('off')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1a46d4f7-05e3-49f1-8405-a87e224b9965.png)

必要なライブラリをインストールします。

```python
%pip install azure-iot-device -q
%pip install azure.storage.blob -q
dbutils.library.restartPython()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f74fe248-1e45-448f-b3c7-be88190afd8a.png)

下記のコードを実行して、ファイルのアップロードを実施します。

```python
device_conn_str = "HostName=iot-hub-test-001.azure-devices.net;DeviceId=qiita_test_01;SharedAccessKey=r2fxXUdn/4w9iNJdhqnIJZ+h0qxxxxx="
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/ec09d6e0-5fe4-497d-8994-206104c69df0.png)


```python
source_dir = "/dbfs/databricks-datasets/flower_photos/daisy/100080576_f52e8ee070_n.jpg"
target_dir  = f"databricks/test.jpg"
```

```python
from azure.iot.device import IoTHubDeviceClient
from azure.storage.blob import BlobClient

device = IoTHubDeviceClient.create_from_connection_string(device_conn_str)
device.connect()

info = device.get_storage_info_for_blob(target_dir)
sas  = f"https://{info['hostName']}/{info['containerName']}/{info['blobName']}{info['sasToken']}"
blob = BlobClient.from_blob_url(sas)
with open(source_dir, "rb") as fh:
    blob.upload_blob(fh, overwrite=True)

device.notify_blob_upload_status(
    correlation_id=info["correlationId"],
    is_success=True,
    status_code=200,
    status_description="OK"
)
device.disconnect()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/694a35dc-66b0-46f2-b412-1a79e0f529b5.png)

Azure Storge 上にファイルが保存されていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/6673a53d-04d8-405a-ad6b-7bb47f1dbf20.png)