ロコガイド テックブログ

「地域のくらしを、かしこく、たのしく」する、株式会社ロコガイドの社員がいろいろな記事を書いています。

「地域のくらしを、かしこく、たのしく」する、株式会社ロコガイドの技術部ブログです。
主にトクバイ・ロコナビのサービス開発について発信しています。

「混雑ランプボタン」の裏側に迫る!ボタンデバイスとAWS Lambdaでお手軽IoT 〜デバイスセットアップ編〜

eyecatch こんにちはこんにちは!バックエンドグループの id:ar_tama です。最近はひょんなことからKotlinを愛でています。

さて、3ヶ月ほど前になりますが、ロコガイドはお店・施設の混み具合がひと目で分かる混雑ランプという機能をリリースしました。
これはトクバイ(またはロコガイド)の管理画面からワンクリックで混み具合を発信可能、というお手軽さがウリのひとつなのですが、
更に簡便化したい!という声を受け、「アプリ」と「ボタン型端末」での提供も行っています

今回はその「ボタン型端末」をセットアップした際のノウハウやハマリポイントなどをお伝えします。

「混雑ランプボタン」に使用した端末

当初のざっくりとした要件は:*1

  • 使用者の手元に届いたら、「電池を入れるだけ」で運用が開始できること
    • ネットワークのセットアップを挟まない=LTE内蔵のデバイスがベスト
  • 「空き」「やや混み」「混み」が表現できること
    • 1つのデバイスで3種類を表現 or 3つのデバイスを1施設と紐付ける

これらを満たすデバイスとして、以下の2種類を使用して実装しました。

Enterprise Buttonのほうが大量発注しやすくコスト面で有利だったことから、現在はこちらを主力として使用しています。

個人的には身構えていたよりずっと簡単に設定・運用ができてとても感動しました。
どちらもサクッとセットアップが行えるため、連携するシステムの複雑度にもよりますが、初動には1~2日あれば十分かと思います。
※ ボタンからLambda関数を呼び出し、そこから更に既存のシステム(混雑ランプの更新シーケンス)を呼び出す、という形で連携しています

SORACOM LTE-M Button powered by AWS

AWSのコンソール、もしくはアプリからセットアップすることで使い始めることが可能、というお手軽デバイスです。
値付けが少々特殊で、本体価格に1年間のサブスク(or 1500回分のボタンクリックのクレジット)が含まれています*2
AWS ButtonのメリットはなんといってもAWSの他サービスとの接続性とそのお手軽さで、SES, Lambda等をポチポチするだけで呼び出すことができます。
他サービスからLambdaを呼ぶ際によくつまずくのが権限周りだと思うのですが、IoT 1-click上で設定するとそのあたりも自動で解決してくれます。これはありがたいですね。

AWS IoT 1-clickの画面
ポチポチだけで接続先が選べる

※ より詳しくはサンプルなどをご覧ください

パラメータとプレイスメント

以下はLambda関数(event引数)に渡ってくる値のサンプルです。

{
  "deviceInfo": {
    "deviceId": "XXX",
    "type": "button",
    "remainingLife": 99.666664,
    "attributes": {
      "projectRegion": "us-west-2",
      "projectName": "project-name",
      "placementName": "project-name-00000-1",
      "deviceTemplateName": "LambdaFunctionName"
    }
  },
  "deviceEvent": {
    "buttonClicked": { "clickType": "SINGLE", "reportedTime": "2020-05-12T01:43:45.558Z" }
  },
  "placementInfo": {
    "projectName": "project-name",
    "placementName": "project-name-00000-1",
    "attributes": { "mode": "single", "color": "red" },
    "devices": { "LambdaFunctionName": "XXX" }
  }
}

AWS IoT 1-click独自の概念に「プレイスメント」というものがあります。
デバイスと固有の設定値の紐付け、と理解していますが、基本的にはこのプレイスメントに設定した値を見ながらシステムと連携していくことになります。

ボタンのクリックタイプ(一度押し・二度押し・長押しの3種類)は deviceEvent.buttonClicked.clickType
プレイスメントの値は placementInfo.attributes で取れることが確認できますね。

トクバイ(ロコガイド)では、このプレイスメントに動作モード・対象施設のIDを設定することで、クリックタイプによって混み具合を判別できるようにしています。
プレイスメントにはデフォルト値を設定することも可能なので、端末に値を設定し忘れた!などのミスを防げる仕組みにもなっています。

気になりポイント

デバイス登録が若干面倒

後述のEnterprise Buttonに比べると、デバイス登録のシーケンス(登録画面を開き待受状態にしてからボタンをポチする)が若干……いやかなり……面倒でした。
登録作業が自分ひとりで完結するならまだよいのですが、デバイスが分散している場合、電話などで「今!今ポチッとしてください!」などと指示するおもしろ場面が発生してしまいます。

AWS・ソラコムコンソールの2重登録の手間

仕組み上しょうがないところではあるんですが……
ソラコムコンソールに登録せずに使用すると更新が効かないので、AWS・ソラコム双方のコンソールに端末を登録する必要があります*3
後述のEnterprise Buttonは購入からアクティベーションまでがワンストップなので、幾分か楽ですね。

接続の安定性

ボタンを押してからサーバに到達するまで、8〜10秒ほどのラグが生じます*4
電波状況が不安定な環境ではそれ以上かかる可能性がありますし、そもそもUDPですし、シビアに「1度押したら絶対反映されてほしい!」というユースケースには向きません。
また、たとえ電波状況が安定していても稀にデータ送信エラー(赤色点灯)が起きることがあり、これはAWS IoT側のログにも残らないためシューティングが大変難しいです……*5
※ それでも観測可能な範囲では、今のところ安定して運用できています

これはEnterprise Buttonも同様なはずのですが、両方触ってみた感じ、ややAWS Button側のほうが発生頻度が高いように思います(注:ベンチを取ったわけではなく、個人の体感です)。

SORACOM LTE-M Button for Enterprise

こちらはAWS ButtonからAWSとの連携機能を抜いたバージョン。
とはいえLambdaを呼べないわけではありませんのでご安心を。さすがにワンストップとはいきませんが、それなりに簡単に呼び出すことが可能です。

SORACOM Funkとの連携

Enterprise ButtonはSORACOM Funk(クラウドファンクションアダプタ)という関連サービスとの連携が行え、このサービスを経由してLambdaを呼び出すことが可能になっています*6
AWS ButtonはAWSのみにプラットフォームがロックインされてしまっていましたが、Funk等の関連サービスを活用することでより拡張性の高いシステムが構築できそうです。
AWS Buttonと比べてコストが低い(5,980円+ランニングコスト100円/月*7)のも魅力ですね。

パラメータとタグ

Funk経由のLambda呼び出しでは、以下のようなパラメータが渡されます。
context.clientContext.imsi等を端末の識別に使用しつつ、クリックタイプはeventから引っ張ってくる、というようなハンドリングになりますね。

context引数

{
  "clientContext": {
    "operatorId": "OP12345678",
    "coverage": "jp",
    "resourceType": "Subscriber",
    "resourceId": "123456789012345",
    "sourceProtocol": "udp",
    "srn": "srn:soracom:OP12345678:jp:Subscriber:123456789012345",
    "imsi": "123456789012345",
    "imei": "234567890123456",
    "custom": {
      "operatorId": "OP12345678",
      "coverage": "jp",
      "resourceType": "Subscriber",
      "resourceId": "123456789012345",
      "sourceProtocol": "udp",
      "srn": "srn:soracom:OP12345678:jp:Subscriber:123456789012345",
      "imsi": "123456789012345",
      "imei": "234567890123456"
    }
  }
}

event引数

{
  "clickType": 2,
  "clickTypeName": "DOUBLE",
  "batteryLevel": 1,
  "binaryParserEnabled": true
}

またEnterprise Buttonでは、プレイスメントに相当する機能は「タグ」が担うことになります。

ソラコムコンソール タグ編集画面

コンソール上からこのようにタグ情報を書き込み、SORACOM APIをLambdaから叩くことで、端末に紐付いた値を取得することが可能です。
IMSIをキーにして、自前で設定値のストアを用意してしまうのもアリだと思います*8

バイナリパーサー・Funkの設定

Funkとデバイスグループ(SIMグループ)の関連付けには、

を行う必要があります。特に後者は設定項目のセクションが違うSORACOM Air for Cellular 設定 )ため、見落とさないよう注意が必要です。

ソラコムコンソール バイナリパーサー設定

気になりポイント

端末の識別子

AWSでは端末の識別を主にDSNで行っていましたが、Enterprise Buttonではこの値は書き換え可能な「名前」またはタグの値として提供され、Lambdaには値が渡ってきません。
なのでEnterprise Buttonでは、基本的に端末の識別をIMSI*9で行います。
端末裏にはAWS Buttonと同じようにDSN(とIMEI)があり、それぞれの関連の理解には少々手間取ったりもしました。

コンソールのユーザビリティ

まだまだWork In Progressな印象が否めないところがちらほら。ユーザーとしてどんどんFBしていきたいところです 💪

おわりに

さて、「混雑ランプ」を支える「ランプボタン」実装の裏側をつらつらと書いてまいりましたが、いかがでしたでしょうか。
このエントリが「デバイスを導入してみたい」「デバイスがうまく設定できない」という方の助けになれば幸いです。

またLambdaを使うのも数年ぶりだったので、多段呼び出しの実装などサービスの進化に驚きながら実装していました。
こちらで得たtipsも続編として放流できればと思います😉

*1:安定供給性など、そのほかの考慮事項もありました

*2:要ソラコムコンソールへの登録

*3:こちらはボタンポチは不要

*4:参考1 参考2

*5:未だに原因わからず

*6:LambdaだけではなくGCP/AzureのFunctionも呼び出し可能とのこと

*7:https://soracom.jp/pricing

*8:実際、ロコガイドではそのように運用しています

*9:ややこしいですが、端末裏のIMEIではなくIMSI値。IMEIは基本的にコンソールやAPIからは参照できません