[AWS CDK] SlackとRaspberry PiでエアコンをONにする仕組みを作った(涼しい家に帰宅できるぞ!!)
外出から帰って自宅が暑いと嫌です。でもエアコン付けっぱなしも電気代的な意味で嫌です。
そこで、「自宅に帰る1時間ぐらい前に、エアコンをONにできないか?」と考え構築してました。
仕組み自体は約1年前に構築済ですが、AWSの画面ポチポチで作成していたので、AWS CDK(Cloud Development Kit)を使って作り直してみました。
目次
- 構成
- 補足
- Raspberry Piに学習リモコンを装着した様子
- 環境
- リポジトリ構成
- AWSの環境構築
- API仕様
- AWS CDKのインストール
- AWS CDKプロジェクトの構築
- Lambdaコードを書く!
- インフラをコードで書く!!!
- ビルドする
- デプロイする
- Slackアプリの構築
- チャンネル作成
- Slackアプリの作成
- Slash Commandsの作成
- Slash Commandsのインストール
- Raspberry Piのスクリプト作成
- Raspberry Pi用のフォルダ作成
- IoTエンドポイントの取得
- 設定ファイルの作成
- メインスクリプトの作成
- Raspberry Piの環境構築
- 証明書の作成 & ダウンロード
- Raspberry Piにファイル類をコピー
- 証明書フォルダの作成
- ライブラリのインストール
- 学習リモコンにエアコンONを学習させる
- 開始コマンド
- 終了コマンド
- 動作確認!!!
- さいごに
- 参考
構成
SlackのSlash Commandsが叩くWebAPIを作成し、Lambdaがコマンド解析してIoT CoreのTopicにPublishします。
Raspberry PiはTopicをSubscribeしており、命令に従ってエアコンをONにします。
なお、Raspberry Pi用の赤外線学習リモコンを使っています。
補足
- 実際のエアコンがAWSに接続されていないため、Device Shadowは使っていません
- Device Shadowとエアコンの状態不一致を考えるのがめんどくさい
- APIの応答が3秒以内というSlackの仕様がありますが、3秒未満で処理は完了するため、3秒以上の経過は未考慮です
- 考慮するなら、処理用のLambdaを非同期で実行させてからすぐ応答します
- 非同期のLambdaでは、「遅延応答用のURL」に対して応答します
Raspberry Piに学習リモコンを装着した様子
他のGPIOは使えなくなりますが、とてもコンパクトで置き場所にも困りません。
環境
- Mac
- macOS Mojave 10.14.6
- Python 3.6
- Raspberry Pi 3 Mobile B+
- Raspbian 9.4
- Python 3.6
- ほか
- AWS CDK 1.3.0 (build bba9914)
- npm 6.9.0
- node 10.16.1
リポジトリ構成
下記のように、Raspberry Pi環境とAWS環境を分けています。
$ tree -L 2 . ├── RaspberryPi │ ├── cert │ ├── config.ini │ └── main.py └── aws ├── bin ├── cdk.json ├── cdk.out ├── lib ├── node_modules ├── package-lock.json ├── package.json ├── src └── tsconfig.json
AWSの環境構築
API仕様
APIは下記を用意します。
Method | Path |
---|---|
POST | /control |
AWS CDKのインストール
インストール済みの場合はSkipしてください。
$ npm install -g aws-cdk
AWS CDKプロジェクトの構築
HomeControl
フォルダを作成し(あとでaws
にリネームしてます)、その中にCDKプロジェクトを構築します。
$ mkdir HomeControl $ cd HomeControl $ cdk init app --language=typescript
必要なライブラリをインストールします。
$ npm install --save @aws-cdk/aws-iot $ npm install --save @aws-cdk/aws-lambda $ npm install --save @aws-cdk/aws-apigateway $ npm install --save @aws-cdk/aws-iam $ npm install --save-dev aws-sdk
Lambdaコードを書く!
まずはファイルを作ります。
$ mkdir -p src/lambda/iot_publish $ touch src/lambda/iot_publish/app.ts
続いてコードを下記にします。本人確認等はひとまず省略してます。
インフラをコードで書く!!!
lib/home_control-stack.ts
を下記にします。
ビルドする
$ npm run build
デプロイする
Lambdaコード格納用のS3バケットを作るcdk bootstrap
は、最初の1回だけでOKです。
$ cdk bootstrap $ cdk deploy
スタック作成が完了すると、エンドポイント(WebAPIのアドレス)が表示されるので、メモしておきます。
Outputs: HomeControlStack.HomeControlApiEndpointxxxxx = https://yyyyyyy.execute-api.ap-northeast-1.amazonaws.com/prod/
Slackアプリの構築
チャンネル作成
専用のチャンネルを作成します。
Slackアプリの作成
SlackのYour Appsにアクセスし、「Create New App」を選択します。
適当に入力します。
Slash Commandsの作成
「Slash Commands」を選択します。
「Create New Command」を選択します。
適当に入力します。
Request URL
は、さきほど作成したエンドポイントと作成したAPIのリソース名を入力します。
項目 | 内容 |
---|---|
Command | /control |
Request URL | https://yyyyyyy.execute-api.ap-northeast-1.amazonaws.com/prod/control |
Short Description | 自宅の家電を操作します |
Usage Hint | aircon on |
Slash Commandsのインストール
左側のメニューから「Basic Information」を選択し、続けて「Install App to Workspace」を選択します。
権限を確認し、「インストール」を選択します。
Raspberry Piのスクリプト作成
あとでコピーするため、Raspberry Pi上で作業しなくても大丈夫です。
Raspberry Pi用のフォルダ作成
$ mkdir RaspberryPi $ cd RaspberryPi
IoTエンドポイントの取得
取得してメモしておきます。
$ aws iot describe-endpoint --endpoint-type iot:Data-ATS { "endpointAddress": "xxxxx-ats.iot.ap-northeast-1.amazonaws.com" }
設定ファイルの作成
config.ini
を作成し、下記とします。ENDPOINT
はさきほど取得した値です。
[AWS_IOT_CONNECT] ROOT_CA = ./cert/AmazonRootCA1.pem PRIVATE_KEY = ./cert/private.pem.key CERTIFICATE = ./cert/certificate.pem.crt.txt [AWS_IOT_CORE] CLIENT_ID = home_control_raspberry_pi ENDPOINT = xxxxx-ats.iot.ap-northeast-1.amazonaws.com PORT = 8883 TOPIC = HomeControl/RaspberryPi
メインスクリプトの作成
main.py
を作成し、下記とします。
Raspberry Piの環境構築
「証明書の作成 & ダウンロード」以外は、Raspberry Pi上で作業します。
証明書の作成 & ダウンロード
ブラウザでAWSにログインし、作成したIoT Thingsを開きます。
続いて、「セキュリティ」の「証明書の作成」を選択します。
作成された証明書などをダウンロードし、「有効化」をしたのち、「ポリシーをアタッチ」を選択します。
- このモノの証明書
- プライベートキー
- AWS IoTのルートCA (Amazon ルート CA 1)
さきほど作成したポリシーを選択し、「完了」を選択します。
Raspberry Piにファイル類をコピー
Raspberry PiとPCを接続し、先ほど作成したファイル類をRaspberry Piにコピーします。
証明書フォルダの作成
$ mkdir cert
上記フォルダ内にダウンロードした証明書などを格納します。
最終的に次のようになっていればOKです。
$ tree -L 2 . ├── cert │ ├── AmazonRootCA1.pem │ ├── certificate.pem.crt.txt │ └── private.pem.key ├── config.ini └── main.py
ライブラリのインストール
$ pip install AWSIoTPythonSDK $ pip install rpi.gpio
学習リモコンにエアコンONを学習させる
Raspberry Pi用の赤外線学習リモコンの説明書に従って実施します。
必要に応じて、Pythonスクリプト(main.py)のPIN番号定義を修正します。下記の混在に注意してください。
- 学習リモコンのSW番号
- Raspberry PiのGPIO
- Raspberry PiのPIN
開始コマンド
SSH接続を解除してもバックグラウンド実行してほしいため、nohup
を使用しています。また、GPIOの制御にはsudo
が必要です。
$ nohup sudo python main.py > output.log &
終了コマンド
スクリプト終了時にGPIO.cleanup()
を実行する必要があるため、finish.txt
が在る場合に終了させています。
$ touch finish.txt
動作確認!!!
Slackで/control aircon on
と入力して実行します。
反応が返ってきて、、、実際にエアコンがONになりました!!!
さいごに
AWS CDKとTypeScriptは初めて使いましたが、CloudFormationやAWS SAMと比べて、非常に便利&楽だと思いました。
YAMLの構成(階層)と微妙に異なるので慣れるまで大変そうですが、TypeScriptの型とエディタの補完機能が便利すぎます!!
AWS CDKの良い勉強になりました。これから積極的に使っていきたいです。
参考
- AWS Cloud Development Kit
- AWS Cloud Development Kit (AWS CDK)
- AWS CDK Tools
- API Reference
- AWS SDK for JavaScript
- Class: AWS.Iot
- Class: AWS.IotData
- AWS
- パブリッシュ/サブスクライブポリシーの例 | AWS
- describe-endpoint | AWS CLI
- ほか
- Slash Commands | Slack API
- AWS CDK が GA! さっそく TypeScript でサーバーレスアプリケーションを構築するぜ【 Cloud Development Kit 】 | Developers.IO