#4【RaspberryPiとGoogle Homeでスマートホーム化】hubot調整編

RaspberryPi

ラズパイでスマートホーム化の第4回目です。

第3回目ではGoogleHomeとラズパイを連携して、音声コマンドによって家電を操作できるようにしました。
第3回目をまだ見ていない人は以下のリンクからどうぞ。

しかし、今のままだと運用するには厳しいので今回は微調整を行っていきます。
今回でスマートホーム化は最終章となります。

今回の記事はYoutubeにもアップロードしているので、合わせてご覧ください。

問題点・課題

一応前回までの記事でスマートホーム化は完了しているのですが、運用するにあたっての問題点や課題がいくつかあります。

まずは絶対に対応しなければならない課題として、トークンの有効期限問題あります。
これはHubotを起動してから1時間経つと接続に失敗する問題です。

2つ目は必須の問題ではないのですが、解決した課題です。
それはラズパイ本体の起動時にHubotが起動しない点です。いちいちコマンドを打って起動しなければならないのは面倒なので、サービスに登録します。これは1つ目の問題の解決にもなるのでどうせなら一緒に対応してしてしまいましょう。

トークンの有効期限切れ

まずは1つ目。
トークンの有効期限かどうかは不明ですが、TypeTalkアダプターで起動したHubotがい時間経過すると401エラーを吐き出して接続エラーになります。

HTTPの401エラーをWikiで確認してみると認証エラーのようです。

401 Unauthorized
認証が必要である。Basic認証やDigest認証などを行うときに使用される。
たいていのブラウザはこのステータスを受け取ると、認証ダイアログを表示する。

HTTPステータスコード

IDとパスワードの組み合わせが不適切だと出るエラーです。とはいってもIDやパスワードは入力していないのでやっぱりトークンの期限切れかなとは思います。

TypeTalkのサイトを見てもいまいち対処法がわからなかったので、定期的にHubotを再起動して対応しようと思います。根本的な原因はわかりませんが、起動直後は普通に接続ができるので定期的な再起動を行う方向にします。

定期的な再起動を行う方法として、第1回目で紹介したcronを使用します。
cronをインストールしていない人は次のコマンドでインストールしておいてください。

$ sudo apt-get update
$ sudo apt-get install cron

cronは定期的なプログラムの実行をすることができるプログラムです。これを使ってトークンの有効期限が切れる前に、再起動を行うようにします。
1時間でトークンの有効期限が切れるので、念のため30分ごとに再起動するようにします。1時間ごとでも問題ないように思いますけどね。

再起動用のシェルを組んでcronに登録してもよいのですが、どうせならcronの設定や後々の管理が楽になり、もう1つの課題も影響するのでサービスの登録を行います。

ラズパイ再起動時の挙動

先ほども言った通り、ラズパイ本体を一度停止してしまうとHubotが停止してしまします。頻繁に再起動しないといっても、その度にコマンドを打ちこむのも面倒だし、忘れてしまう可能性もあるので、自動で起動するようにしようと思います。

ラズビアンはsystemdでサービスを管理しているので、systemdにスクリプトを作成してサービスを管理します。

Hubotのサービス登録

それではsystemdへのサービス登録について説明します。

サービスを登録する方法として、起動、停止、再起動の引数に応じて処理を分ける管理用のシェルと、引数を指定した起動用、停止用、再起動用の3つの実行シェルを作成していきます。

管理シェルの作成

まずはHubotのシェルスクリプトを修正します。シェルはHubotディレクトリ内のbinフォルダ内にあります。とりあえずバックアップを取ってから編集しましょう。

このシェルは、TypeTalkアダプターを指定したHubotをバックグラウンドで起動するものとなっております。
編集後の黄色い部分はそれぞれの環境に合わせて編集してください。

バックアップの取得
$ cp /home/[ユーザー]/hubot/bin/hubot /home/[ユーザー]/hubot/bin/hubot_bk
シェルスクリプトの編集
$ vim /home/[ユーザー]/hubot/bin/hubot
実行権限の編集
$ chmod 755 /home/[ユーザー]/hubot/bin/hubot
編集前
/home/[ユーザー]/hubot/bin/hubot

!/bin/sh
set -e
npm install
export PATH="node_modules/.bin:node_modules/hubot/node_modules/.bin:$PATH"
exec node_modules/.bin/hubot --name "homebot" "$@"
編集後
/home/[ユーザー]/hubot/bin/hubot

!/bin/sh
who=$(whoami)
if [ "${who}" != "pi" ]; then
echo "Usage: bin/hubot (start|stop|restart|status). Please again.\n"
exit 1;
fi
set -e
NVM_BIN=/usr/local/node-v6.11.2-linux-armv7l/bin/
export PATH="$NVM_BIN:$PATH"
start() {
npm install
export PATH="node_modules/.bin:node_modules/hubot/.bin:$PATH"
export HUBOT_TYPETALK_CLIENT_ID="xxxxxxxxxxxxxxxxxxxxxxxxxx"
export HUBOT_TYPETALK_CLIENT_SECRET="xxxxxxxxxxxxxxxxxxxxxxxxxx"
export HUBOT_TYPETALK_ROOMS="xxxxxx"
forever start -c coffee node_modules/.bin/hubot -a typetalk
}
stop () {
forever stop node_modules/.bin/hubot
}
restart() {
forever restartall
}
status() {
forever list
}
case "$1" in
"stop" )
stop
;;
"restart" )
restart
;;
"start" )
start
;;
"status" )
status
;;
esac

上記のシェルを簡単に説明すると、引数に応じて起動、停止、再起動、ステータス表示を行うものとなって言います。case “$1” in の部分で引数に応じた関数を実行するようになっています。
statusという関数も用意していますが、今回は使いません。

実行シェルの作成

Hubotの管理用シェルの作成が終わったので、次は起動、停止、再起動用の実行シェルを作ります。

実行シェルの保存ディレクトリの作成
$ mkdir /home/p/[ユーザー]/hubot/shell
$ cd /home/p/[ユーザー]/hubot/shell
起動用シェル
$ vim /home/[ユーザー]/hubot/shell/homebot_start.sh

!/bin/sh
DIR="/home/[ユーザー]/hubot"
cd $DIR
./bin/hubot start
停止用シェル
$ vim /home/[ユーザー]/hubot/shell/homebot_stop.sh

!/bin/sh
DIR="/home/[ユーザー]/hubot"
cd $DIR
./bin/hubot stop
再起動用シェル
$ vim /home/[ユーザー]/hubot/shell/homebot_restart.sh

!/bin/sh
DIR="/home/[ユーザー]/hubot"
cd $DIR
./bin/hubot restart
実行権限の変更
$ chmod 755 /home/[ユーザー]/hubot/shell/*

サービスの登録

いよいよサービスの登録を行います。systemdはunitというものでサービスを管理していますのでunitファイルを作成します。unitファイルといっても、技術内容にルールはありますが、普通のテキストファイルです。
ちなみに自作のunitファイルは/etc/systemd/system/配下に作成するようです。

systemdのunitファイル作成
$ vim /etc/systemd/system/homebot.service

[Unit]
# サービスの名前
Description = homebot
# network.targetが起動した後にhomebotサービスを起動
Wants=network.target

[Service]
# 実行するユーザとグループ
User=pi
Group=pi
# systemctl start homebot.serviceコマンド実行時の処理
ExecStart = /home/[ユーザー]/hubot/shell/homebot_start.sh
# systemctl stop homebot.serviceコマンド実行時の処理
ExecStop = /home/[ユーザー]/hubot/shell/homebot_stop.sh
# systemctl restart homebot.serviceコマンド実行時の処理
ExecReload = /home/[ユーザー]/hubot/shell/homebot_restart.sh
Restart=always
Type=forking

[Install]
WantedBy = multi-user.target

unitファイルの作成が完了したら、設定ファイルの再読み込みを行います。
その後サービスを起動してみて、正常に起動できればラズパイの起動と同時にHubotも自動起動するようにしましょう。
次のコマンドを参照してください。

# 設定ファイルを編集したら再読み込みを行う
$ systemctl daemon-reload

homebot.serviceの起動
$ sudo systemctl start homebot.service

homebot.serviceの停止
$ sudo systemctl stop homebot.service

homebot.serviceの再起動
$ sudo systemctl restart homebot.service

homebot.serviceのステータス確認
$ sudo systemctl status homebot.service

hubotデーモンの確認
$ forever list

homebot.serviceの自動起動
$ sudo systemctl enable homebot.service

おまけ 自動起動の解除
$ sudo systemctl disable homebot.service

正常に起動しない場合はステータス確認コマンドを実行してエラー内容を確認しましょう。もしくはHubotのデーモンのログを確認してエラーがないか確認します。

これで課題である、ラズパイ起動時のHubot自動起動は解決しました。

トークンエラーの対応 -cronの登録-

最後にcronへ30分ごとにHubotが再起動するように登録を行います。

cronの編集
$ crontab -e

最終行に追記
# 毎時0分と30分にhubot再起動コマンドを実行
0,30 * * * * sudo systemctl restart homebot.service

トークンエラーもとりあえず解決しました。

とりあえず、以上で調整も完了です。しかし、foreverのログを見てみるとWebSocketへの接続が定期的にタイムアウトする問題が残っていたりします。20~30秒待機すれば再接続するのですが、接続が切れている間に指示したコマンドは処理されないので、ちょっと不便なんですよね。
この辺りはまだ対処法や原因が特定できていないので、調査は続けていきたいと思います。

個人的にはタイムアウト問題は残っていますが、個人的にはそこまで大きな問題ではないのでスマートホーム化できて満足です。
また便利な内容を見つけたら追記していきますので、よろしくお願いします。

スポンサーリンク

コメント

タイトルとURLをコピーしました