LoginSignup
6
7

More than 3 years have passed since last update.

Azure IoT Hub に Mosquitto™ から MQTT なげてみる

Last updated at Posted at 2020-04-25

はじめに

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個くらい作っておくか

create_devices.sh
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

pub.sh

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

sub.sh

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 しつづけます

10pubs.sh

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 コマンド入れないと

SASトークンを環境変数に設定

export SAS_TOKEN=$(az iot hub generate-sas-token -n HubTK101 | jq -r .sas)

メトリック

ポータルでみることができる

image.png

あなたがみるかもしれないエラー

エラー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 しておく

シリーズ


  1. @ekzemplaro さんのこのエントリをかなり参考にさせていただきました → Azure IoT Hub に mosquitto で接続  

  2. これいらないかも。なくても動いているように思える。IoT Hubは作った時にデフォルトでポートがあいてるかも... 

  3. トークンの se= の部分が有効期限(エポック表記)、ざっと計算したたところデフォルトだと発行から 60分 が有効期限。そら遊んでいると無効になるわ。 トークンを発行するコマンド(いろんな言語の関数ある)を定期的に叩くの前提と考える 

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7