aptpod Advent Calendar 2021の22日目を担当する、製品開発グループintdash チームの呉羽です。
以下の要件を満たした回数記録基盤を、以前に個人開発したので紹介します。
- Bluetoothで接続されたIoTボタンが押された回数を記録したい
- ボタンが押された時刻と共に永続化したい
- 永続化されたデータを集計して閲覧したい
利用したもの
- CamKix カメラシャッターボタン
- Raspberry Pi 4
- AWS (Lambda, Timestreamなど)
構築までの流れ
今回は以下の図のように、ボタンを押してから永続化される流れとなります。
IoTボタンの準備
今回はIoTボタンとしてCamKix カメラシャッターボタンを利用します。 この製品はBluetoothで接続可能なスマホのカメラシャッター向けボタンですが、実質的にはボリュームアップキーが1つあるキーボードです。価格は1000円ほど(2021/12/20確認)。
Raspberry Piの準備
IoTボタンとAWSを仲介するための機器として、今回はRaspberry Pi 4(OSはUbuntu Server)を利用します。Raspberry Piでなくとも、以下の要件を満たせば代替可能です。
- IoTボタンをBluetoothで接続可能
- インターネットを利用可能
IoTボタンとの接続
LinuxでBluetoothデバイスの管理をする際、bluetoothctl
というソフトウェアを用います。広く利用されているため接続手順は省略します。
IoTボタン押下時の処理
IoTボタンが押下された際、後述するAmazon API GatewayのURLを叩くことで、AWSとの橋渡しを行います。
今回はevdev-triggerを利用し、接続されたデバイスの特定のキーが押下された時にコマンドを実行させます。以下のような設定ファイルを用意すれば、IoTボタン押下時に、curl
コマンドが実行されます。
# physical id of device phys: a1:b2:c3:d4:e5:f6 triggers: # Key is the input event code to trigger the command. 115: command: ["curl", "https://example.com"]
evdev-triggerはフォアグラウンドで動作するソフトウェアなので、supervisorによりバックグラウンドとして常に動作させておきます。以下がsupervisorの設定ファイル例です。
# cat /etc/supervisor/conf.d/evdev-trigger.conf [program:evdev-trigger--camkix] command=/usr/local/bin/evdev-trigger --config /etc/evdev-trigger/camkix.yml autorestart=true
AWSの準備
最後にAWS上で以下を構築します。
- Amazon Timestreamによる記録の永続化
- API Gatewayによる記録実行URLの実装
- 集計結果をAmazon SNSを通じてメール通知
実装コードやCloudFormationのテンプレートはGitHubで公開しているため、以下の手順でデプロイ可能です。 https://gist.github.com/hareku/30023706e854015bfa289bd4a2081022
Amazon Timestreamによる記録の永続化
今回はデータの保存先としてAmazon Timestreamを利用します。保存先として、他にDynamoDBも候補として挙げられますが、Timestreamは後述する集計機能を提供しているため、今回はTimestreamを選択します。
Timestreamは時系列データベースで、AWS SDKを通して容易に扱えます。 今回のGo言語による実装コードはgithub.com/hareku/go-timestreamerで公開しており、Lambdaのエントリーファイルはcmd/simple/lambda/record/main.goです。
API Gatewayによる記録実行URLの実装
上述のLambdaをHTTPプロトコル経由で実行させるために、Amazon API Gatewayを用います。 また不特定多数から呼び出されないよう、API Gatewayが提供しているAPIキーを設定することが推奨されます。
集計結果をAmazon SNSを通じてメール通知
TimestreamはSQL-likeな集計機能を提供しています。そこで集計結果を以下の手順で通知させます。
- CloudWatch Eventsで定期的にLambdaを実行する
- 実行したLambda上でTimestreamの集計SQLを発行し、結果をAmazon SNSのトピックへ送信する
- Amazon SNSのトピックを購読しているメールアドレスに集計結果が送信される
以下のように、一日ごとの総記録回数がプレーンテキスト形式のメールで送信されます。
2021-11-27: 7 2021-11-26: 4 2021-11-25: 5 ....
今回は以下のようなクエリをTimestreamに投げました。
SELECT bin(time, 24h) as date, SUM(measure_value::bigint) as count FROM "db"."meas" WHERE time between ago(30d) and now() GROUP BY bin(time, 24h) ORDER BY date DESC
Timestreamは時系列関連の関数が多く実装されており、簡潔に集計することが出来ました。慣れ親しんだSQLで表現力高く書けますので、気になる方はAWSドキュメントのTimestreamを使った集計のSQL例の一読をおすすめします。
今回実装した集計用Lambdaのエントリーファイルはcmd/simple/lambda/publish-sns/main.goです。
まとめ
以上が、IoTボタンによる回数記録基盤の構築の流れです。例に挙げたコードでは、AWSの利用料金は月に1ドルも掛からないため(2021/12/20確認)、低コストで運用が可能です。