Azure IoT HubへのRaspberry Piでの送受信
- estoy
- 2023年11月13日
今年の5月ごろですが、GoogleでIoT Coreが使えなくなるというアナウンスがあり、急遽自宅で使っているRaspberry Piの接続先のIoTを別システムへ移行することの検討することに迫られました。。
そこで、パブリックで使えるMQTTやIoTのサービスを検討したところ、AzureのIoT Hubが無料で使えたので、こちらに移行することにしました。(HerokuもMQTTサービスあったのですが、有料化されてしまったため、やむなく断念してました。AWSの方はなんとなく除外してました。)
今回は、その際に使ったAzure IoTとクライアント側の設定について、書いていこうと思います。
Azure側の準備
ということで、まずはAzure側の準備。Azure側で必要な作業は、接続先の「1. IoT Hubの作成」と「2. 接続デバイスの登録」の2点です。まずは1点目。
IoT Hubの作成
メニュー画面からIoT Hubを選択して、作成を実施します。登録内容は主に、任意で問題ないですが、レベルを無料にすることだけは必須です。これをしないと最低でも、月10ドル掛かってしまうので注意が必要です。設定画面としては、次のような感じで作成します。
接続デバイスの登録
IoT Hubの登録ができたら、次はIoT Hubに接続するデバイスを登録します。デバイスは、作成したIoT Hubごとに登録するので、先ほど作成したIoT Hubを選択します。IoT Hubを選択後、デバイスの項目をクリックし、デバイスの追加をクリックして、実行します。
デバイスの登録画面に移動したら、大半の項目は初期値のままでも特に問題ないので、デバイスIDだけ任意の設定をしたら、保存を押してデバイスの登録を完了します。下の画像のように、デバイスの登録が終わったら、クライアントがIoT Hubに繋ぐための準備が一通り完了になります。
クライアント側の準備
Azure側の作業が終わったら、次は接続を行うクライアント側の設定になります。IoT Hubへの接続は、MQTTなどの純粋なプロトコルでもつなげますが、Azure側で言語に応じたライブラリも用意されているので、今回はPythonを使った接続で進めていきたいと思います。
(公式サイトにも参考ページが用意されており、こちらを見ながら進めています。)
ライブラリのインストール
ということで、まずはライブラリのインストール。次のコマンドでPythonで使うために必要なライブラリをRaspberry Piにインストールします。
pip install azure-iot-device
認証情報の確認・接続用スクリプトの作成
次は、アプリから、IoTHubに繋ぐためのスクリプトの準備です。IoTHubに繋ぐためには、デバイスごとの認証情報が必要となるため、まずはそれを確認します。デバイスの認証情報は先ほど作成したAzure IoTHubのデバイスから確認できるので、以下の画面を開き、赤枠部分の内容を確認・コピーします。
認証情報をコピーしたら、以下のサンプルアプリの「接続文字列」の部分に貼り付けて準備完了です。
(サンプルアプリは、Microsoftのgit-hubで公開されているものに若干手を加えたものになっています。)
サンプルアプリ
import os
import random
import time
from azure.iot.device import IoTHubDeviceClient, Message
#ここをプライマリ接続文字列の値に変える
CONNECTION_STRING = "接続文字列"
# Define the JSON message to send to IoT Hub.
TEMPERATURE = 20.0
HUMIDITY = 60
MSG_TXT = '{{"temperature": {temperature},"humidity": {humidity}}}'
RECIEVED_MESSAGE = 0
#受信時の処理
def message_handler(message):
global RECIEVED_MESSAGE
global COMMANDS
RECIEVED_MESSAGE += 1
print("")
print("Message recieved")
for property in vars(message).items():
print(" {}".format(property))
# Handling Message
try:
msg = message.data.decode('utf-8')
print(msg)
except Exception as e:
print(e)
#送信処理
def run_telemetry_sample(client):
print("IoT Hub device sending periodic messages")
client.connect()
while True:
# Build the message with simulated telemetry values.
temperature = TEMPERATURE + (random.random() * 15)
humidity = HUMIDITY + (random.random() * 20)
msg_txt_formatted = MSG_TXT.format(temperature=temperature, humidity=humidity)
message = Message(msg_txt_formatted)
# Add a custom application property to the message.
# An IoT hub can filter on these properties without access to the message body.
if temperature > 30:
message.custom_properties["temperatureAlert"] = "true"
else:
message.custom_properties["temperatureAlert"] = "false"
# Send the message.
print("Sending message: {}".format(message))
client.send_message(message)
print("Message successfully sent")
time.sleep(10)
def main():
print("IoT Hub Quickstart #1 - Simulated device")
print("Press Ctrl-C to exit")
# Instantiate the client. Use the same instance of the client for the duration of
# your application
client = IoTHubDeviceClient.create_from_connection_string(CONNECTION_STRING)
# Run Sample
try:
#受信時の処理の登録
client.on_message_received = message_handler
run_telemetry_sample(client)
except KeyboardInterrupt:
print("IoTHubClient sample stopped by user")
finally:
# Upon application exit, shut down the client
print("Shutting down IoTHubClient")
client.shutdown()
if __name__ == '__main__':
main()
通信の実施
準備ができたら、実際に上のスクリプトを動かします。接続情報に問題がなければ、以下の送信結果のように、IoTHubに対して、ランダムな値の気温、湿度の情報を送信してくれます。
逆にIoTHub側から、クライアント側に送信をすると、受信結果のようにその結果をクライアント側でメッセージを確認することができました。(IoTHubのデバイス画面から簡単にメッセージを送ることができるので、そこからメッセージを送って試しています。)
こんな感じで、IoT Hubでの接続を試して、無事自宅のIoT環境をAzureに移行することができました。
(補足).Raspberry Piで詰まったこと
今回、私はクライアントをRaspberry Pi 3Bで繋いだのですが、OSがBusterだからか、Pythonで接続アプリを起動しようとしたとき、次の2点ではまりました。
- OpenSSLのバージョンアップ
- 信頼する認証局の証明書ファイルの変更
1点目に関しては、Pythonのライブラリの一部がOpenSSLのバージョンが「1.1.1」以上である必要があるらしく、通常インストールされているOpenSSLでは処理が失敗してしまいました。そのため、OpenSSLのモジュールをダウンロードし、ビルド・インストールを実行する必要があります。
2点目に関しては、Azureへの接続時に起こっているようで、作成したサンプルアプリで接続しても、sslエラーが吐かれて、接続に失敗すると言うものでした。これもOpenSSLの設定である、「信頼する認証局の証明書」の一覧ファイルが古いままであることが原因みたいでしたので、「環境変数SSL_CERT_FILE」に対して、Pythonの「certifi」ライブラリの証明書を指定するように設定しました。
上記2点の設定で、Raspberry Piからも無事Pythonにて、Azure IoTに繋ぐことができました。