この記事は赤外線LEDを積んだRaspberry Piでスマートルームをつくる(実装編)の続きです。
- 設計・部品調達編
- 動作テスト編
- エアコンのリモコン信号解析編
- 基板実装編
- API/chatbot実装編←イマココ
ハードウェアを実装してソフトウェアの世界に持ち込めばこっちのもの。
というわけでこの記事では製作した赤外線リモコンを操作したり環境情報を取得できるようにしていきたいと思います。
エアコンのリモコン信号をつくる
まずは赤外線リモコンの信号を解析する記事で得られた結果をもとにエアコン用の信号を作っていきます。
解析に利用したirrp.pyがPython製なのでPythonでスクリプトを作成します。
解析した内容に対するパラメータからデータを生成し、それをパルスの継続時間のシーケンスに変換して再生してもらう形で実装したソースが以下になります。
クラス内ではカスタマーコードを[17, 218, 7]
と記述していますが最後の7はパリティ(4bits)です。結局固定値なのでサボりました。codeメソッド内での変数dataは0番目以外は8ビット整数としてデータを入れています。
今回エアコンの制御をするために以下のパラメータを用意しました。
- 運転ON/OFF
- 運転モード(自動/冷房/暖房/ドライ/送風)
- 設定温度(自動: -5~+5度, 冷房: 18~32度, 暖房: 14~30度, ドライ: -2~+2度)
- 送風強さ(0~5, ただし-1ならば自動)
- スイングON/OFF
これを上記スクリプトのcode
メソッドで指定することでデータ部分のパルス列を生成します。実際に利用する際にはAEHAフォーマットに合わせるためにpack
メソッドを経由してフレームとして変換したものを送出します。このpack
メソッドでは、先行している固定フレームも合わせて符号化しています。
APIの作成
Raspberry Pi上でリクエストを待ち受けるAPIを作ります。
サーバ用フレームワークにはbottleを採用しています。赤外線LEDの方はirrp.py
を参考にしながら信号を生成するように、温度センサはスイッチサイエンスさんのサンプルを参考に値を取得するように改変して組み込んだ上でAPIへのアクセスに応じて呼び出す形で実装しました。
エアコン操作用のエンドポイントではリクエストフォームにwork
が定義されているか否かで運転のON/OFFを指定します。
このときの赤外線信号の送出に使うGPIOピンの番号はIR_WRITE_PIN
環境変数で指定します。
APIのソース一式は以下のリポジトリにアップロードしています。
https://github.com/paralleltree/myroom
動作確認
スクリプトを保存したら起動してみます。
$ IR_WRITE_PIN=19 python3 server.py
実際に温度センサのエンドポイントを叩いてみた結果がこちらです。
温度、湿度、気圧の測定値が得られていることがわかります。
同様にエアコン操作用のエンドポイントを叩いた結果がこちらです。
このレスポンスでは赤外線信号を送出した事実しかわからないので外出時には正常にエアコンまで届いたか判別できませんが、温度センサを活用しつつ運用でカバーしていくことにしました。
botの作成
トークンの取得
APIができたので続いてSlack上で対話するbotを作成していきます。まずはSlackのCustom IntegrationsからBot用のアクセストークンを取得します。
スクリプトの作成
トークンを取得したらRubyでslack-ruby-client
を使ってbotを作っていきます。Gemfileはこんな感じ。
source "https://rubygems.org"
gem 'slack-ruby-client'
gem 'async-websocket'
gem 'eventmachine'
gem 'faye-websocket'
スクリプトではSlackサーバへの接続設定を行った後にDMへ流れてくるメッセージを順次処理していきます。
単純なパターンマッチングに引っかけて対応するイベントを発火させるだけの人工無能ですが以下のような感じになります。API_BASE
環境変数には先ほどbottleを使って建てたAPIのエンドポイントを指定します。
今回はRaspberry Pi上で動作させるのでhttp://localhost:8080
になります。
動作テスト
スクリプトを保存したら動作を確認します。
$ IR_WRITE_PIN=19 python3 server.py &
$ bundle install --path vendor/bundle
$ API_BASE="http://localhost:8080" SLACK_TOKEN="token" bundle exec ruby bot.rb
センサとLEDのAPIを先にバックグラウンドで立ち上げてからbotスクリプトを実行します。
Slackのサーバと接続が確立できたらチノちゃんに部屋の温度を聞いてみます。
チノちゃんに部屋の温度が聞けるようになりました pic.twitter.com/lpQQmY99dI
— ぱらつり (@paralleltree) 2019年1月7日
続いてエアコンを入れてもらいます。
チノちゃんにエアコンつけてもらえるようになりました!!!! pic.twitter.com/YvxEVgERvc
— ぱらつり (@paralleltree) 2019年1月14日
というわけで実際にチノちゃんから部屋の温度を聞いたりエアコンをつけてもらえるようになりました。エモい。
実際はsshのコネクションを張ったままにするわけにもいかないので、以下のようにcrontabでRaspberry Piの起動に合わせてサーバを立ち上げたりするといいでしょう。
@reboot sh -c 'cd repos/myroom && IR_WRITE_PIN=19 python3 server.py > /dev/null &'
@reboot sh -c 'cd repos/myroom && API_BASE="http://localhost:8080" SLACK_TOKEN="token" bundle exec ruby bot.rb > /dev/null &'
認証周り
今回はホームからSlackのサーバに接続したので自宅用のドメインやIPアドレスいらずで操作ができ、かつ「Slackにログインする」ことが実質的なユーザ認証となっています。特にAPIをパブリックに公開する場合はサーバ側でトークンなどを設定して認証を実装しないと第三者からエアコンをいじられかねないので注意が必要です。
まとめ
というわけでチノちゃんと同棲気分を味わえるようになりました!最高だな?
こうやって嫁を錬成する方法があるのか…
— ±20 (@puramai20) 2019年1月14日
みなさんもぜひ嫁を錬成してみてください。