以前、IoTボタンのクリックでS3に直接ファイルを保存する仕組みを構築しましたが、今回は受信したデータに対して何らかの処理を加えたいため、構成を「IoT Core → Lambda → S3」に変更しました。その際、予期せぬエラーに遭遇し、少しばかり時間を費やしてしまいました。本記事では、その時の状況と解決策を備忘録としてまとめます。
当初作成したLambda関数はこちらです。
import json
def lambda_handler(event, context):
try:
IoT Coreから送信されたJSONを受け取る
payload = json.loads(event['body'])
print(payload)
# 項目を抽出
return{
'statusCode': 200,
'body': json.dumps({
'message': 'Success'
})
}
except Exception as e:
print(f"Error: {e}")
return {
'statusCode': 500,
'body': json.dumps({
'message': 'Internal Server Error'
})
}
シンプルにLambdaでIoT Coreからの情報を受信するだけのコードを作成したつもりでした。受信した値から加工に必要な項目の抽出は後回しにし、動作テストを実施したところ、以下のエラーが発生しました。
Error: 'body'
Lambda関数が期待していたイベントの構造と、実際にIoT Coreから送信されたイベントの構造が異なっていたことが原因です。AWS IoT CoreからLambdaに送信されるイベントの構造は、HTTPリクエストのようなbodyを持つ構造ではないため、event['body']
にアクセスしようとするとエラーが発生します。実際にどのような構造になっているか確認するために、処理の冒頭に以下のようにログ出力処理を追加し、再度テストしてみました。
import json
def lambda_handler(event, context):
print("イベント:", event) # ★★★ 追加 ★★★
try:
IoT Coreから送信されたJSONを受け取る
payload = json.loads(event['body'])
print(payload)
# 項目を抽出
return{
'statusCode': 200,
'body': json.dumps({
'message': 'Success'
})
}
except Exception as e:
print(f"Error: {e}")
return {
'statusCode': 500,
'body': json.dumps({
'message': 'Internal Server Error'
})
}
CloudWatch Logsで確認したイベントの内容から、IoTボタンの情報はイベントのルート直下にキーと値のペアで格納されていることが分かりました。
{'credentialsId': 'AWS-IAM-role-credentials-IoT-Publish', 'operatorId': 'OPXXXXXXXXXX', 'destination': {'provider': 'aws', 'service': 'aws-iot', 'resourceUrl': 'https://XXXXXXXXXX', 'payloadsOnly': False, 'sendPayloadsAsBinary': False}, 'sourceProtocol': 'udp', 'clickType': 1, 'clickTypeName': 'SINGLE', 'batteryLevel': 1, 'binaryParserEnabled': True, 'timestamp': 1744067245812, 'imsi': 'XXXXXXXXXX', 'imei': 'XXXXXXXXXX'}
今回の場合、直接ボタンの情報が渡されているため、それぞれの項目に直接アクセスすることが可能です。そのため、例えばIoT ボタンがどのようにクリックされたかを取得したい場合は、以下のコードで実現できました。
import json
def lambda_handler(event, context):
try:
# 項目を抽出
clickTypeName = event['clickTypeName']
print("クリックタイプ:", clickTypeName)
return{
'statusCode': 200,
'body': json.dumps({
'message': 'Success'
})
}
except Exception as e:
print(f"Error: {e}")
return {
'statusCode': 500,
'body': json.dumps({
'message': 'Internal Server Error'
})
}
コメント