目的
AWS IoT Core のルールエンジンでは、SQLライクな構文を使って JSON メッセージを処理できます。
今回は、送信元によって JSON のフィールド名が異なる場合でも、1つのSQLルールで吸収できるかを検証しました。
フィールド名の差異の吸収の実施
ルールの作成
最初にルールの作成を実施します。下記のようなSQLステートメントを作成しました。
payload部分のlight項目がない(undefined)場合項目名lを使用します。ある場合は項目名lightを使用します。両方とも最終的には、lllの項目名でSQSに送信されるようにしています。ちなみに、{topic名}には、Iotのモノが送信してくるTopic名をしています。
その後、ルールアクションでSQSを選択して、IAMロールの作成を実施すれば、完了です。
SQSを指定する場合、SQS側のアクセスポリシーの設定も適切にする必要があります。
SELECT CASE isUndefined(light)
WHEN true THEN l
ELSE light END as lll
FROM "{topic名}"
トピックへ発行を実施する
turnがonの場合、light項目名でpublishして、offの時は、lでpublishするコードを作成しました。
該当の箇所のみを切り出しているので、そのままでは動作しません。mqtt_connectionを作成して、connectする必要があります。
try:
data = json.loads(payload)
turn = data["turn"]
if turn == "on":
message = {
"light": "on"
}
mqtt_connection.publish(topic=TOPIC,
payload=json.dumps(message),
qos=mqtt.QoS.AT_LEAST_ONCE)
else:
message = {
"l": "off"
}
mqtt_connection.publish(topic="data/meguro/1/111111",
payload=json.dumps(message),
qos=mqtt.QoS.AT_LEAST_ONCE)
except Exception as e:
print("Error:", e)
確認
上が l フィールド、下が light フィールドで送信された例です。
どちらも lll フィールドとしてSQSに到達しており、期待通りの動作を確認できました。
まとめ
IoT Core の SQLルールエンジンは、CASE や isUndefined() などの関数を使うことで、異なる構造のJSONにも柔軟に対応できることが分かりました。
公式のドキュメントを見てみるとほかにも便利そうな機能があるので、調べてみたいとおもいます。
なお、JSON構造が異なるメッセージを送信する場合、Topic自体を分けてそれぞれに対応したルールを作成する方が、運用保守性の面では望ましいケースもあります。今回のような処理が適しているかどうかは、ケースバイケースで判断する必要があります

