目的

上記のようにMicrosoftドキュメントにAzure IoT SDK for Pythonではジョブ機能がサポートされていないと記載があるが、IoTHubJobManager Classが用意されているようなので実装する
Azure Functions(トリガー:EventGrid)上でダイレクトメソッドを実行するジョブを実装する
実装
デバイス側
ドキュメント通りに実装
クラウドからコールされるダイレクトメソッドの登録を行う
クラウド側
接続文字列の取得はドキュメントを参照
デバイスのダイレクトメソッドをコールするジョブを発行、ジョブ状態の監視を行う
以下実装
import sys
import uuid
import json
import logging
import datetime
import time
import azure.functions as func
from azure.iot.hub import IoTHubJobManager
from azure.iot.hub.models import CloudToDeviceMethod, CloudToDeviceMethodResult, JobRequest
CONNECTION_STRING = ''
METHOD_NAME = 'lockDoor'
METHOD_PAYLOAD = '{\'lockTime\':\'10m\'}'
def executeJob():
try:
deviceMethod = CloudToDeviceMethod(method_name=METHOD_NAME, payload=METHOD_PAYLOAD)
jobId = str(uuid.uuid4())
logging.info('job ID: %s', jobId)
jobRequest = JobRequest(job_id = jobId,
type = 'scheduleDeviceMethod', cloud_to_device_method = deviceMethod,
query_condition = 'deviceId IN [\'myDeviceId\']',
start_time = datetime.datetime.now(datetime.timezone.utc), max_execution_time_in_seconds = 30)
# 接続文字列からジョブマネージャーインスタンスを生成
jobManager = IoTHubJobManager(CONNECTION_STRING)
# ジョブ生成
jobManager.create_scheduled_job(jobId, jobRequest)
# ジョブ状態の監視
while True:
# ジョブ状態の取得
response = jobManager.get_scheduled_job(jobId)
logging.info('job status: %s', response.status)
if response.status != 'running':
break
time.sleep(5)
except Exception as ex:
logging.info('')
logging.info('Unexpected error {0}'.format(ex))
return
except KeyboardInterrupt:
logging.info('')
logging.info('IoTHubDeviceMethod sample stopped')
def main(event: func.EventGridEvent):
result = json.dumps({
'id': event.id,
'data': event.get_json(),
'topic': event.topic,
'subject': event.subject,
'event_type': event.event_type,
})
logging.info('Python EventGrid trigger processed an event: %s', result)
# ジョブ実行
executeJob()
以下ジョブのリクエスト、レスポンスで使用するクラス
ジョブに関する制限事項
- ジョブの最大数は 1 (Free および S1)、5 (S2)、10 (S3) (ドキュメント)
- Azure portal上でジョブの確認、操作ができない
懸念
cancel_scheduled_jobの仕様からジョブ発行後ジョブIDを忘れてしまった場合、ジョブのキャンセルができない、Azure portalからジョブのキャンセルも不可
アカウントがFree および S1の場合はジョブ最大数は1のため、それ以上ジョブの発行ができなくなる
最悪タイムアウトでジョブが終了するようにJobRequestのmax_execution_time_in_secondsは必ず設定しておいたほうが良いと思われる