Alibaba Cloud IoT Platform へ SORACOM Beam 経由で接続する

# はじめに

最近 Alibaba Cloud が気になってきたので、以下の記事を参考に IoT Platform へ接続してみました。
[Alibaba Cloud IoT Platform入門　MQTT通信してみた](https://www.sbcloud.co.jp/entry/2019/06/25/iotmos)
おかげですんなりと接続できたので、せっかくなので [SORACOM Beam](https://dev.soracom.io/jp/start/beam/) を経由して接続できるか試してみました。方法を記しておきます。

# 必要なもの

- Alibaba Cloud のアカウント
- SORACOM のアカウント
- SORACOM IoT SIM (私は [Plan-D](https://soracom.jp/products/sim/plan-d/) で試しました)
- SIM を取り付けるデバイス (私は [AK-020](https://soracom.jp/products/module/ak-020/) と Raspberry Pi で試しました)

# 準備

まずは[Alibaba Cloud IoT Platform入門　MQTT通信してみた](https://www.sbcloud.co.jp/entry/2019/06/25/iotmos)を参考に、PCなどから mosquitto を使って IoT Platform へ Publish してみましょう。

TLS モードを使いたかったので、[こちらのドキュメント](https://www.alibabacloud.com/help/doc-detail/73742.htm)の "Download the root.crt file of IoT Platform." とで案内されたルート証明書 (GlobalSign Root CA でした) を利用して以下のように Publish しました。TLS モードにするため `securemode=2` とするのとポートは 1883 なことに注意！

```console
mosquitto_pub -h  "[ProductKey].iot-as-mqtt.[RegionId].aliyuncs.com" \
-i "[ClientID]|securemode=2,signmethod=hmacsha1|" \
-u "[deviceName]&[ProductKey]" \
-P "[devicesercretとproductKey&deviceName&clientIdの文字列をsha1でハッシュ生成]" \
-t "/[ProductKey]/[deviceName]/user/[作成したトピック名]" \
-m '{"id":"0001","data":"hello world"}' \
--cafile ./root.crt \
-p 1883 \
-q 0
```

デバッグつけて実行した結果=>

```console
$ mosquitto_pub -d -h  "${productKey}.iot-as-mqtt.ap-northeast-1.aliyuncs.com" \
> -i "test-client|securemode=2,signmethod=hmacsha1|" \
> -u "${deviceName}&${productKey}" \
> -P "${password}" \
> -t "/${productKey}/${deviceName}/user/test_topic" \
> -m '{"id":"0001","data":"hello world"}' \
> --cafile ./root.crt \
> -p 1883 \
> -q 0
Client test-client|securemode=2,signmethod=hmacsha1| sending CONNECT
Client test-client|securemode=2,signmethod=hmacsha1| received CONNACK (0)
Client test-client|securemode=2,signmethod=hmacsha1| sending PUBLISH (d0, q0, r0, m1, '/a6swJIi3xBL/test-device/user/test_topic', ... (34 bytes))
Client test-client|securemode=2,signmethod=hmacsha1| sending DISCONNECT
```

# SORACOM Beam の設定

SORACOM Beam には以下を設定します。SORACOM Beam の使い方の基本は[ソラコムの公式ドキュメント](https://dev.soracom.io/jp/beam/send-data-using-beam/#mqtt)を見てみましょう。


| 設定項目   |       設定値 |
|:-----------|:------------------|
| 種別       | Standard MQTT broker |
| プロトコル  | MQTTS |
| ホスト名    | [ProductKey].iot-as-mqtt.[RegionId].aliyuncs.com |
| ポート番号  | 1883 |
| ユーザ名    | [deviceName]&[ProductKey] |
| パスワード  | [devicesercretとproductKey&deviceName&clientIdの文字列をsha1でハッシュ生成] |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/ec357a60-2bd9-7774-7675-7610b3979758.png)

# SORACOM Beam を経由した Publish

SORACOM Beam に認証情報をオフロードしたので、デバイスは `beam.soracom.io` へ Publish するだけです。

```console
mosquitto_pub \
-h "beam.soracom.io" \
-i "[ClientID]|securemode=2,signmethod=hmacsha1|" \
-t "/[ProductKey]/[deviceName]/user/[作成したトピック名]" \
-m '{"id":"0002","data":"hello from beam"}'
```

デバッグつけて実行した結果=>

```console
pi@raspberrypi:~ $  mosquitto_pub -d \
>  -h "beam.soracom.io" \
>  -i "test-client|securemode=2,signmethod=hmacsha1|" \
>  -t "/a6swJIi3xBL/test-device/user/test_topic" \
>  -m '{"id":"0002","data":"hello from beam"}'
Client test-client|securemode=2,signmethod=hmacsha1| sending CONNECT
Client test-client|securemode=2,signmethod=hmacsha1| received CONNACK (0)
Client test-client|securemode=2,signmethod=hmacsha1| sending PUBLISH (d0, q0, r0, m1, '/a6swJIi3xBL/test-device/user/test_topic', ... (34 bytes))
Client test-client|securemode=2,signmethod=hmacsha1| sending DISCONNECT
```

デバイスログでも送信されていることが確認できました。
IoT Platform の 監視と運用 > デバイスログ > アップストリーム分析 > MessageID > 詳細の表示
より送られたメッセージが確認できるのは便利ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/3425d33c-882b-3728-06b3-7e85d0262c69.png)

# 応用 - clientId とトピックをメタデータサービスから取得する

SORACOM Beam によってホスト名、ユーザ名、パスワード設定をデバイスからオフロードできました。
設定情報をデバイスからオフロードし、クラウド側で変更できるようにすると後からの変更にも柔軟に対応できます。
次に応用として、clientId とトピックを [SORACOM メタデータサービス](https://dev.soracom.io/jp/start/metadata/) から取得できるようにしてみましょう。

メタデータサービスへは以下のような JSON を入れておきます。

```json
{"clientId":"ClientID]|securemode=2,signmethod=hmacsha1|","topic":"/[ProductKey]/[deviceName]/user/[作成したトピック名]"}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/29ea9e52-ad2c-9195-ca49-b0652129100a.png)

これにより、デバイスから`metadata.soracom.io/v1/userdata` へ HTTP GET 要求することで保存したメタデータを取得できます。jq などで加工し引数にすれば、デバイスに clientId やトピックを覚えさせることなく IoT Platform へ Publish できるようになります。

```console
userdata=$(curl -s metadata.soracom.io/v1/userdata)
clientId=$(echo ${userdata} | jq -r .clientId)
topic=$(echo ${userdata} | jq -r .topic)
mosquitto_pub -d \
 -h "beam.soracom.io" \
 -i "${clientId}" \
 -t "${topic}" \
 -m '{"id":"0003","data":"hello from beam again!"}'
```

デバッグつけて実行した結果=>

```console
pi@raspberrypi:~ $ userdata=$(curl -s metadata.soracom.io/v1/userdata)
pi@raspberrypi:~ $ clientId=$(echo ${userdata} | jq -r .clientId)
pi@raspberrypi:~ $ topic=$(echo ${userdata} | jq -r .topic)
pi@raspberrypi:~ $ mosquitto_pub -d \
>  -h "beam.soracom.io" \
>  -i "${clientId}" \
>  -t "${topic}" \
>  -m '{"id":"0003","data":"hello from beam again!"}'
Client test-client|securemode=2,signmethod=hmacsha1| sending CONNECT
Client test-client|securemode=2,signmethod=hmacsha1| received CONNACK (0)
Client test-client|securemode=2,signmethod=hmacsha1| sending PUBLISH (d0, q0, r0, m1, '/a6swJIi3xBL/test-device/user/test_topic', ... (41 bytes))
Client test-client|securemode=2,signmethod=hmacsha1| sending DISCONNECT
```

# 終わりに

SORACOM Beam を使って Alibaba Cloud IoT Platform の認証情報をオフロードできました。ここからさらに Alibaba Cloud を活用してみたいと思います。