AWS IoT Core Topic RuleでMQTTトピックからIDを取り出す

  • AWS
  • IoT

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

AWS IoT CoreのTopic Ruleで、MQTTトピックの一部(デバイスIDやセッションIDなど)を取り出したかったので、SQLで使える関数を調べた。

結論

  • topic(): マッチしたMQTTトピック文字列全体を返す
  • topic(n): / 区切りで n番目(0-based)のセグメントを返す
  • 正規表現で加工したい場合は regexp_replace(input, pattern, replacement) を使う。これは置換用の関数であって、キャプチャグループを取り出す関数ではない

やりたかったこと

v1/thing/{deviceSerial}/boot/{session} みたいなトピック構成で、deviceSerial と session だけ取り出したかった。

実際に使える書き方

セグメントを取り出すだけなら topic(n) で十分だった。

SELECT
topic(2) AS deviceSerial,
topic(4) AS sessionId
FROM
'v1/thing/+/boot/+'

v1/thing/ABC123/boot/SESSION001 というトピックにpublishされた場合、インデックスは以下のようになる。

インデックス 値
topic(0) v1
topic(1) thing
topic(2) ABC123
topic(3) boot
topic(4) SESSION001

正規表現での加工が必要な場合は regexp_replace() を使う。AWSのリファレンスアーキテクチャのコードでも、こういう形で使われているのを見つけた。

SELECT
regexp_replace(topic(), '^[^/]*/[^/]*/', '') AS remainder
FROM
'v1/thing/+/boot/+'

先頭から2セグメント分を削って残りだけ取り出す、みたいな使い方。キャプチャグループを直接返す関数ではなく、あくまで置換なので、狙った部分だけ抜き出したいなら正規表現の書き方を工夫する必要がある。

気づき

  • topic(n) は CDK の公式サンプル(aws_cdk.aws_iot_alpha.TopicRuleProps)でも SELECT topic(2) as device_id, year, month, day FROM 'device/+/data' という形で使われていて、実運用でも普通に使われている書き方らしい
  • ペイロードにID情報を重複して入れず、トピック文字列を正として扱う設計自体はIoT的にもAWS的にも妥当な方向性