はじめに
Azure IoT Hub に MQTT クライアントを接続して、データを集めて見ようと思ったが、Azureの公式ドキュメントがいまいちわかりにくい。ちょっと時間かかったので、やったことを書いておく。
先人のエントリ1を大いに参考にさせていただいた。多謝
Azure 側
IoT Hub を作成する
おもむろに IoT Hub を作成する(作成には数分かかる)
$ az iot hub create -g MyResourceGroup -n HubTK101
できたか?
$ az iot hub list -o table
Location Name Resourcegroup Subscriptionid
---------- -------- --------------- ------------------------------------
westus2 HubTK101 MyResourceGroup cf74fdf1-c705-4256-b20a-5b4a8e821537
Device を作る
Device がクライアントに対応する。これで、d0
という名前のクライアントからの接続( pub
or sub
ができるようになる)
$ az iot hub device-identity create -n HubTK101 -d d0
10個くらい作っておくか
for i in {1..10} ; do
az iot hub device-identity create -n HubTK101 -d dev$i
done
できたか?
$ az iot hub device-identity list -n HubTK101 -o table
AuthenticationType CloudToDeviceMessageCount ConnectionState DeviceEtag DeviceId LastActivityTime Status StatusUpdateTime Version
-------------------- --------------------------- ----------------- ---------------- ---------- ---------------------------- -------- -------------------- ---------
sas 0 Disconnected NzI1MjQwNDAy dev9 0001-01-01T00:00:00Z enabled 0001-01-01T00:00:00Z 2
sas 0 Disconnected NzkyNzkwMDQw dev3 0001-01-01T00:00:00Z enabled 0001-01-01T00:00:00Z 2
sas 0 Disconnected MTAzNDM5MDE2Mw== dev6 0001-01-01T00:00:00Z enabled 0001-01-01T00:00:00Z 2
sas 0 Disconnected MTIwNDk2MDc3 dev8 0001-01-01T00:00:00Z enabled 0001-01-01T00:00:00Z 2
sas 0 Disconnected MTI5NTY3NDI5 dev5 0001-01-01T00:00:00Z enabled 0001-01-01T00:00:00Z 2
sas 0 Disconnected MzQ2OTY3MzYx dev2 2020-04-22T09:14:55.2145856Z enabled 0001-01-01T00:00:00Z 2
sas 0 Disconnected NzQxNTU2Mjgz dev1 2020-04-22T04:47:08.1200577Z enabled 0001-01-01T00:00:00Z 2
sas 0 Disconnected NzA4MzgxNDg2 dev4 0001-01-01T00:00:00Z enabled 0001-01-01T00:00:00Z 2
sas 0 Disconnected Mjc3MzEwNzc= dev7 0001-01-01T00:00:00Z enabled 0001-01-01T00:00:00Z 2
sas 0 Disconnected MTc4ODcwMTI4 dev10 0001-01-01T00:00:00Z enabled 0001-01-01T00:00:00Z 2
Azure の Firewall で ポート 8883
を開けておく2
外部からのアクセスするので、ポートを開けます。セキュリティには十分気をつけましょう。
認証
ここがちょっとめんどくさい。IoT Hub の認証方法は以下の二種類があるようだ
- SASトークン(共通鍵)による認証
- X.509 証明書による認証
今回は SASトークン を使って認証する。少し前までは、SASトークンの生成にスクリプトをかいたりしているみたいだが、今は az
コマンドで生成できるようだ
az iot hub generate-sas-token -n HubTK101
{
"sas": "SharedAccessSignature sr=HubTK101.azure-devices.net&sig=sIiyFfC7Lx2GhKhjU4KZHu3Kuz4q98eOTj%2BCTJGYyWc%3D&se=1587273711&skn=iothubowner"
}
- これをクライアントから送信することで、クライアントが認証される。認証の 粒度は
Hub 単位
、クライアント単位
などいくつかの粒度で生成することができる - ポリシーを使って認可される範囲を制御できる。この例の
iothubowner
ではフルアクセスが認可される。その他のポリシーの詳細はこちら - トークン内の
sig
se
skn
sr
の意味はこちら
クライアント 側
Publish
mosquitto_pub -d -q 1 \
--capath /etc/ssl/certs/ \
-V mqttv311 \
-p 8883 \
-h HubTK101.azure-devices.net \
-i dev2 \
-u "HubTK101.azure-devices.net/dev2/api-version=2016-11-14" \
-P "SharedAccessSignature sr=HubTK101.azure-devices.net&sig=fbOALIqK3QUVm2hcp7ngIL%2ByeXdmSl3H8N4SeW1piZs%3D&se=1587532158&skn=iothubowner" \
-t "devices/dev2/messages/events/" \
-m '{"v":"hi"}'
こんな感じになれば動いていると思います
./pub.sh
Client dev2 sending CONNECT
Client dev2 received CONNACK
Client dev2 sending PUBLISH (d0, q1, r0, m1, 'devices/dev2/messages/events/', ... (10 bytes))
Client dev2 received PUBACK (Mid: 1)
Client dev2 sending DISCONNECT
Subscribe
mosquitto_sub -d -q 1 \
--capath /etc/ssl/certs/ \
-V mqttv311 \
-p 8883 \
-h HubTK101.azure-devices.net \
-i dev1\
-u "HubTK101.azure-devices.net/dev1/api-version=2016-11-14" \
-P "SharedAccessSignature sr=HubTK101.azure-devices.net&sig=fbOALIqK3QUVm2hcp7ngIL%2ByeXdmSl3U8N3SeW1piZs%3D&se=1587532158&skn=iothubowner" \
-t "devices/dev1/messages/events/"
こんな感じになれば動いていると思います
./sub.sh
Client dev1 sending CONNECT
Client dev1 received CONNACK
Client dev1 sending SUBSCRIBE (Mid: 1, Topic: devices/dev1/messages/events/, QoS: 1)
Client dev1 received SUBACK
Subscribed (mid: 1): 1
IoT Hub 側でのモニタ
メッセージが流れてくるのがみえます
$ az iot hub monitor-events --hub-name HubTK101
$ az iot hub monitor-events --hub-name HubTK101 --device-id dev2
###おまけ
10個まとめて接続テストしておく
for i in {1..10} ; do
mosquitto_pub -d -q 1 \
--capath /etc/ssl/certs/ \
-V mqttv311 \
-p 8883 \
-h HubTK101.azure-devices.net \
-i "dev$i" \
-u "HubTK101.azure-devices.net/dev$i/api-version=2016-11-14" \
-P "SharedAccessSignature sr=HubTK101.azure-devices.net&sig=YCeatCNmuqnXJ%2F0%2FOES5kI5FvHad5fdRV2f2HQC1HDk%3D&se=1587560026&skn=iothubowner" \
-t "devices/dev$i/messages/events/" \
-m '{"msg":"hi from dev$i"}'
done
10個のデバイス(クライアント)からしばらくの間 publish
してみる
これは、メッセージ送るたびにコネクションをはるのであまり効率的ではないですが... dev1
は 1分おきに、dev2
は 2分おきに...としばらくデータを publish
しつづけます
for i in {1..10} ; do
echo "Hi, I'm dev$i - the pid is $!"
while true; do
interval=$(($i * 60))
sleep $interval
mosquitto_pub -d -q 1 \
--capath /etc/ssl/certs/ \
-V mqttv311 \
-p 8883 \
-h HubTK101.azure-devices.net \
-i "dev$i" \
-u "HubTK101.azure-devices.net/dev$i/api-version=2016-11-14" \
-P "SharedAccessSignature sr=HubTK101.azure-devices.net&sig=GcFNWwkqUzslCfqn5kMiNwzEBFKFV6Cgx7lXtfQv3CE%3D&se=1587790230&skn=iothubowner" \
-t "devices/dev$i/messages/events/" \
-m '{"msg":"Hello"}'
done &
done
ssh
でログインしている場合で、ターミナル閉じても動かし続けたいときは nohup
しておくといい
$ nohup ./10pubs.sh &
SASトークンは1時間で切れるみたいなので、定期的にリフレッシュしたい。cron
かなにかで定期的に以下のようにして、10pubs.sh
は SASトークン を環境変数から取得すればいいかもしれない。この場合はクライアントにも az
コマンド入れないと
export SAS_TOKEN=$(az iot hub generate-sas-token -n HubTK101 | jq -r .sas)
メトリック
ポータルでみることができる
あなたがみるかもしれないエラー
エラー1
Client dev2 sending CONNECT
Error: A TLS error occurred.
原因: --capath
の部分の指定が間違えていた。OSのデフォルトの証明書置き場にしておくと吉
エラー2
Client dev2 sending CONNECT
Client dev2 received CONNACK
Connection Refused: not authorised.
Error: The connection was refused.
原因:おそらくSASトークンの有効期限がきれていた。再発行したら動いた3
エラー3
az iot hub: 'generate-sas-token' is not in the 'az iot hub' command group. See 'az iot hub --help'. If the command is from an extension, please make sure the corresponding extension is installed. To learn more about extensions, please visit https://docs.microsoft.com/en-us/cli/azure/azure-cli-extensions-overview
原因:az
コマンドに IoT Hub のエクステンションが入っていない。az extension add --name azure-iot
しておく
シリーズ
- DockerとMosquitto™でMQTTに触れる
- MQTTを調べている
- MQTTの通信を可視化する - shiftr.io
- Azure IoT Hub に Mosquitto™ から MQTT なげてみる
- MQTT.js でブラウザから MQTTブローカ に Pub/Sub する
-
@ekzemplaro さんのこのエントリをかなり参考にさせていただきました → Azure IoT Hub に mosquitto で接続 ↩
-
これいらないかも。なくても動いているように思える。IoT Hubは作った時にデフォルトでポートがあいてるかも... ↩
-
トークンの
se=
の部分が有効期限(エポック表記)、ざっと計算したたところデフォルトだと発行から 60分 が有効期限。そら遊んでいると無効になるわ。 トークンを発行するコマンド(いろんな言語の関数ある)を定期的に叩くの前提と考える ↩