レファレンス
まずはいろんな記事を参考にしていきます。2018年3月11日現在、Azure IoT Hub
で検索したところ、71件見つかりました。同じようにチュートリアルをやっていた(しかも1か月前に!)記事はしっかり確認しました。
ただ、Raspberry Piはなかったので、そこをどうしようかと・・。
チュートリアル開始!
ということで、シミュレートしたデバイスでチュートリアル開始。
準備
このチュートリアルではPythonを使いますが、なんとかVisual Studio
内で実現できるよう、いろいろ準備をしました。というか、「Azure の開発」「Python 開発」をインストールしました。
Azure IoT Hubの作成
「無料試用版」サブスクリプションで、他のリソースは全て削除した状態で始めます。まずはリソースの作成から。
次に、F1 - Free
(デフォルトではS1
が選択されている)に変更して、リソース名、リソースグループを設定、場所も西日本
に変更して作成します。
こちらが作成中の画面。
で、こちらが作成完了した画面。
その後、以下のように進み、接続文字列をコピーします。これは後々、ソースコード内で使用します。(ソースコードを作ってから・・)
プロジェクトの作成
空のPythonアプリケーション
プロジェクトを作成し、azure-iothub-device-client
とazure-iothub-service-client
を入れておきます。2018年3月11日時点では1.3.0が最新でした。
デバイスIDの作成
追加
→新しい項目
から空の Python ファイル
をCreateDeviceIdentity.py
として追加します。CONNECTION_STRING
は先ほどの接続文字列です。
で、実行して成功すると、次のような画面がでます。
import sys
import iothub_service_client
from iothub_service_client import IoTHubRegistryManager, IoTHubRegistryManagerAuthMethod
from iothub_service_client import IoTHubDeviceStatus, IoTHubError
### TODO:ここは変える!
CONNECTION_STRING = "<接続文字列>"
DEVICE_ID = "MyFirstPythonDevice"
def print_device_info(title, iothub_device):
print ( title + ":" )
print ( "iothubDevice.deviceId = {0}".format(iothub_device.deviceId) )
print ( "iothubDevice.primaryKey = {0}".format(iothub_device.primaryKey) )
print ( "iothubDevice.secondaryKey = {0}".format(iothub_device.secondaryKey) )
print ( "iothubDevice.connectionState = {0}".format(iothub_device.connectionState) )
print ( "iothubDevice.status = {0}".format(iothub_device.status) )
print ( "iothubDevice.lastActivityTime = {0}".format(iothub_device.lastActivityTime) )
print ( "iothubDevice.cloudToDeviceMessageCount = {0}".format(iothub_device.cloudToDeviceMessageCount) )
print ( "iothubDevice.isManaged = {0}".format(iothub_device.isManaged) )
print ( "iothubDevice.authMethod = {0}".format(iothub_device.authMethod) )
print ( "" )
def iothub_createdevice():
try:
iothub_registry_manager = IoTHubRegistryManager(CONNECTION_STRING)
auth_method = IoTHubRegistryManagerAuthMethod.SHARED_PRIVATE_KEY
new_device = iothub_registry_manager.create_device(DEVICE_ID, "", "", auth_method)
print_device_info("CreateDevice", new_device)
except IoTHubError as iothub_error:
print ( "Unexpected error {0}".format(iothub_error) )
return
except KeyboardInterrupt:
print ( "iothub_createdevice stopped" )
if __name__ == '__main__':
print ( "" )
print ( "Python {0}".format(sys.version) )
print ( "Creating device using the Azure IoT Hub Service SDK for Python" )
print ( "" )
print ( " Connection string = {0}".format(CONNECTION_STRING) )
print ( " Device ID = {0}".format(DEVICE_ID) )
iothub_createdevice()
シミュレーション対象デバイス アプリの作成
Pythonコードの用意
[IoTHub Device Connection String]
は、上記の例だとHostName=akr-hub.azure-devices.net;DeviceId=MyFirstPythonDevice;SharedAccessKey=84NkAiOeObqRmfHXyYmIRdRA9BF5ruQIoa5ifNcjZbY=
みたいな感じになります。
import random
import time
import sys
import iothub_client
from iothub_client import IoTHubClient, IoTHubClientError, IoTHubTransportProvider, IoTHubClientResult
from iothub_client import IoTHubMessage, IoTHubMessageDispositionResult, IoTHubError, DeviceMethodReturnValue
# ここ、変えるよ!
CONNECTION_STRING = "[IoTHub Device Connection String]"
# choose HTTP, AMQP or MQTT as transport protocol
PROTOCOL = IoTHubTransportProvider.MQTT
MESSAGE_TIMEOUT = 10000
AVG_WIND_SPEED = 10.0
SEND_CALLBACKS = 0
MSG_TXT = "{\"deviceId\": \"MyFirstPythonDevice\",\"windSpeed\": %.2f}"
def send_confirmation_callback(message, result, user_context):
global SEND_CALLBACKS
print ( "Confirmation[%d] received for message with result = %s" % (user_context, result) )
map_properties = message.properties()
print ( " message_id: %s" % message.message_id )
print ( " correlation_id: %s" % message.correlation_id )
key_value_pair = map_properties.get_internals()
print ( " Properties: %s" % key_value_pair )
SEND_CALLBACKS += 1
print ( " Total calls confirmed: %d" % SEND_CALLBACKS )
def iothub_client_init():
# prepare iothub client
client = IoTHubClient(CONNECTION_STRING, PROTOCOL)
# set the time until a message times out
client.set_option("messageTimeout", MESSAGE_TIMEOUT)
client.set_option("logtrace", 0)
client.set_option("product_info", "HappyPath_Simulated-Python")
return client
def iothub_client_telemetry_sample_run():
try:
client = iothub_client_init()
print ( "IoT Hub device sending periodic messages, press Ctrl-C to exit" )
message_counter = 0
while True:
msg_txt_formatted = MSG_TXT % (AVG_WIND_SPEED + (random.random() * 4 + 2))
# messages can be encoded as string or bytearray
if (message_counter & 1) == 1:
message = IoTHubMessage(bytearray(msg_txt_formatted, 'utf8'))
else:
message = IoTHubMessage(msg_txt_formatted)
# optional: assign ids
message.message_id = "message_%d" % message_counter
message.correlation_id = "correlation_%d" % message_counter
# optional: assign properties
prop_map = message.properties()
prop_text = "PropMsg_%d" % message_counter
prop_map.add("Property", prop_text)
client.send_event_async(message, send_confirmation_callback, message_counter)
print ( "IoTHubClient.send_event_async accepted message [%d] for transmission to IoT Hub." % message_counter )
status = client.get_send_status()
print ( "Send status: %s" % status )
time.sleep(30)
status = client.get_send_status()
print ( "Send status: %s" % status )
message_counter += 1
except IoTHubError as iothub_error:
print ( "Unexpected error %s from IoTHub" % iothub_error )
return
except KeyboardInterrupt:
print ( "IoTHubClient sample stopped" )
if __name__ == '__main__':
print ( "Simulating a device using the Azure IoT Hub Device SDK for Python" )
print ( " Protocol %s" % PROTOCOL )
print ( " Connection string=%s" % CONNECTION_STRING )
iothub_client_telemetry_sample_run()
nodeプロジェクトの用意
iothub-explorerをnodeプロジェクトに入れて、プロジェクトから立ち上げようとしたけど失敗。
なんか色々もう・・。
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Web\External
(ワークロードからNode.js開発をインストールするとデフォルトで入る)にPATH張って、コマンドプロンプトを管理者権限で立ち上げて、npm install -g iothub-explorer
いれました。ごめんなさい。
総仕上げ
iothub-explorer monitor-events MyFirstPythonDevice --login "<接続文字列>"
で受け口作ります。
Visual Studio側からSimulatedDevice.py
を起動します。
そしたら、なんかいい感じになります(たぶん)。
あと、ポータルからみても動いてて楽しい。
参考
ちなみに、Python用のバックグラウンドアプリケーション(IoT)を使ってみようと奮戦したのですが、うまくいきませんでした。
何をやってもno module named
だとか、ImportError: DLL load failed: %1 is not a valid Win32
だとか色々怒られます・・。
たぶん、実行時のPythonが特殊なものを使っているので、ライブラリを正しく読めていないのか、多重で読んでしまっているのか・・。はたまたターゲットを正しく設定してあげないといけないのか・・。正直、うまくいきませんでした。残念。
終わりに
運用環境のコードでは、一時的な障害処理に関する MSDN の記事で推奨されているように、再試行ポリシー (指数関数的バックオフなど) を実装することをお勧めします。
とのことです。とりあえずは終わり。
リソースグループごと削除するのを忘れないようにしてください(忘れてもいいようにFreeにしたけども)。
以上。