この記事は更新から24ヶ月以上経過しているため、最新の情報を別途確認することを推奨いたします。
はじめに
Azure IoT Hubにおいては、デバイス側からIoT Hub側にメッセージを送るという、デバイス→IoT Hubという方向のデータ送信がほとんどですが、稀にデバイス側でIoT Hub側からのメッセージを受信したい事があります。
今回は、Raspberry pi 3BへインストールしたIoT Hub ClientでIoT Hub側からのメッセージを受信する方法について、具体的な例を示した記事があまりないので、ここに記載します。
Raspberry Pi 3へIoT Clientの導入
まずはRaspberry Pi 3にIoT Hub clientを導入します。
Pythonでデバイスをハンドリングするので、pipを用いて以下のパッケージをインストールします。
pip install azure-iothub-device-client
pip install azure-iothub-service-client
IoT Hubへデバイスの登録
IoT Hubへメッセージを送りたいデバイスを登録します。
このあたりの詳細は、Microsoftの公式ページを参照してください。
IoT Hubからのメッセージを受けるプログラムの作成
IoT Hubからメッセージを受けられるようにプログラムを書きます。
基本的にはIoT Hubにメッセージを送る際と同様、iothub_clientをimportして、必要なdefを書いていくのですが、メッセージを受ける場合に必要となるのが、receive_message_callbackです。IoT Hubからのメッセージを受信すると、このコールバックが呼び出されるので、ここに必要な処理を書いていきます。
以下は、トイレIoT用に書いたプログラムからの抜粋です。
Azure IoT Hub側からのメッセージを受けて、Raspberry PiのGPIOをOn/Offさせるプログラムになっています。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Program name: hc_connect.py
# Copyright by Inteligence Business Solutions Inc.
# Programed by Hideaki Maruno
# Ver 1.1 2017-09-13
# coding: UTF-8
import iothub_client
~略~
def receive_message_callback(message, counter):
global receive_callbacks
# connection IDとGPIO ポートの変換テーブル
io_table =
{'1':'35','2':'36','3':'37','4':'38','5':'40','6':'37','7':'38','8':'40'}
dt = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
buffer = message.get_bytearray()
size = len(buffer)
logfile = open('hc_connect.log','a')
print >> logfile, (" %s Received Message [%d]:" % (dt, counter))
message_data = buffer[:size].decode('utf-8')
print >> logfile, (" %s Data: <<<%s>>> & Size=%d" % (dt, message_data, size))
map_properties = message.properties()
key_value_pair = map_properties.get_internals()
if message_data == 'TimeUpdate':
# 経過時間による通知
try:
hall_computer_name = key_value_pair["HallComputerName"]
connection_id = key_value_pair["ConnectionID"]
iothub_ack = key_value_pair["iothub-ack"]
print >> logfile, (u" %s hc_connect.py: %s" % (dt, message_data))
print >> logfile, (u" %s hc_connect.py: HallComputerName: %s") % (dt, hall_computer_name)
print >> logfile, (u" %s hc_connect.py: ConnectionID: %s") % (dt, connection_id)
print >> logfile, (u" %s hc_connect.py: iothub-ack: %s") % (dt,iothub_ack)
print >> logfile, (u" %s hc_connect.py: subprocess start" % (dt))
proc = subprocess.Popen(['python','./gpio_switch.py',io_table[connection_id],'1'])
except:
print (" %s hc_connect.py: Properties not correct. \"%s\"") % (dt, key_value_pair)
print >> logfile, (u" %s hc_connect.py: Properties not correct. \"%s\"") % (dt, key_value_pair)
elif message_data == 'CountUpdate':
# 利用回数による通知
try:
area_id = key_value_pair["AreaID"]
hall_computer_name = key_value_pair["HallComputerName"]
connection_id = key_value_pair["ConnectionID"]
iothub_ack = key_value_pair["iothub-ack"]
print >> logfile, (u" %s hc_connect.py: %s" % (dt, message_data))
print >> logfile, (u" %s hc_connect.py: AreaID: %s") % (dt,area_id)
print >> logfile, (u" %s hc_connect.py: HallComputerName: %s") % (dt, hall_computer_name)
print >> logfile, (u" %s hc_connect.py: ConnectionID: %s") % (dt, connection_id)
print >> logfile, (u" %s hc_connect.py: iothub-ack: %s") % (dt, iothub_ack)
print >> logfile, (u" %s hc_connect.py: subprocess start" % (dt))
proc = subprocess.Popen(['python','./gpio_switch.py',io_table[connection_id],'1'])
except:
print (" %s hc_connect.py: Properties not correct. \"%s\"") % (dt, key_value_pair)
print >> logfile, (" %s hc_connect.py: Properties not correct. \"%s\"") % (dt, key_value_pair)
else:
# 未知の通知
print (" %s hc_connect.py: Message \"%s\" is not supported. \"%s\"") % (dt, message_data, key_value_pair)
print >> logfile, (" %s hc_connect.py: Message \"%s\" not supported. \"%s\"") % (dt, message_data, key_value_pair)
print >> logfile, (" %s hc_connect.py: Error" % (dt))
counter += 1
receive_callbacks += 1
print >> logfile, (" %s Total calls received: %d" % (dt,receive_callbacks))
logfile.close()
return IoTHubMessageDispositionResult.ACCEPTED
補足
- デバイスへのメッセージ送信は、Freeプランでもサポートされているので簡単に実験できます。
- このサンプルプログラムでは、実際のGPIOの操作は外部プログラムを呼んで行っています。この部分をほかのプログラムに差し替えれば、Raspberry Pi 上で動作するどんなプログラムでも実行できるので、様々応用できると思います