こんにちは、Misocaのとよし(@toyoshi)です。
この記事は、Misoca Advent Calendar 2017 の19日目の記事です。
前はちょっとした作業の自動化の話をしたのですが、今回も面倒な作業を自動化する話を書きます。
タイトルのとおり遠隔で写真がとれるようにした話なのですが、私はWebカメラといえばケンブリッジ大学のどこかの研究室のコーヒー残量をチェックしたことがある世代です。あれからもう24年ぐらい経っているようです。「まじで?」と思った人はこの記事にいいねしてください。会社のアドベントカレンダーのKPIはいいね数です。
さて、本題を始めます。
やったこと
こういうのを作って(手前がラズベリーパイです)
こういう結果が得られるようにしました。
toyoshi take photo
とSlackに書き込むと写真が撮影されてSlackに投稿されます。
動機
どうしてこのようなものを作ったかというと、弊社に1日に1回ぐらい見るのだけどどうしてもオンライン化できずに目視しなければいけないものがあったからでした。
例えばこういうものだと思ってください。
- コーヒー豆の残量
- 壁に掲示しているカンバン(Misocaではまず紙でやってみて習慣化したらTrelloなどに移すことがあります)
- リモートから会議室に人がいるかどうか確認したい
皆さんも外的な要因によってどうしても目視しないといけないものってありますよね?
準備
ラズベリーパイとカメラを買います。大人なのでコンプリートスターターキットというケースやLANケーブルとか電源もセットになってるやつを買いました。少し高いですがもう今月末には36歳なのでメリットしか感じませんでした。
ラズパイ用のカメラは初代の安いカメラと、v2という性能のいいカメラがありますが、今回は様子がわかればいいだけなので安い方を選びました。
- Amazon | Raspberry Pi3 コンプリートスターターキット (Standard) | Physical Computing Lab | PCアクセサリ・サプライ
- Amazon.co.jp: サインスマート Raspberry Pi 用 カメラモジュール Camera Module for ラズベリーパイ: パソコン・周辺機器
方法
Raspberry Piのセットアップ
引用:https://www.raspberrypi.org/blog/introducing-pixel/
コンプリートキットなのでOSインストール済みのSDカードが付属しています。自宅のテレビに繋いで電源を入れたらいきなりLinuxのデスクトップ環境が立ち上がって驚きました。ゲームを確認したらマインクラフトが入っていたので遊びました。ScratchやPythonも入っていていきなりプログラミングも楽しめます。こどものころこんなものがもらえたらすごく嬉しかっただろうなと思いました。
カメラ
むき出しの状態で売っています。専用ケースも売っていますがカメラの価格より高いので諦めました。セロファンテープで固定しています。
コマンドラインからのコマンド
接続したカメラで写真を撮影するにはraspistill
コマンドを使います。
raspistill -o cam.jpg
てな感じで写真をお手軽に撮影できます。
参考:raspistill - Raspberry Pi Documentation
Slackからの命令受付と、投稿
Slackからラズパイに命令するにはRubotyを使いました。RubotyはRuby製のbotフレームワークです。Rubotyを使うと簡単にSlackからの入力を受け取って返答するbotが作成できます
参考
- Ruboty って何?どうやって動かすの? Hubot と何が違うの?どっちを使えばいいの? #ruboty #chatops - Qiita
- スタンドファームのbotの紹介 - Misoca開発ブログ
今回だと写真を撮影し、RubotyからSlackのAPIを叩いて画像を送るだけです。写真を撮影するメソッドはこんな感じになります。
def pi_camera_upload(message)
message.reply('撮影してくるから、ちょっと待ってね') # 写真を撮影するのに1秒ぐらいかかるので返答
Dir.mktmpdir do |dir|
file_name = "#{dir}/image.png"
begin
system(`raspistill -rot 90 -t 500 -w 800 -h 800 -o #{file_name}`) # 90度回転させて、500ms後に800x800で撮影する。
rescue
message.reply('写真の撮影ができなかったよ')
return
end
end
end
これをgemにしてrubotyに読み込ませます。RubotyはGemで拡張して使うので、自分でGemとして公開するか、Githubにアップロードするか、Gistに公開する(GistでGemを公開する - Qiita)などして使います。
Gemとして公開しなくても、Gemfileで
gem 'pi-photo', path: '/Users/me/path/to/pi-photo'
みたいにローカルファイルを指定することもできます。
自動起動・デーモン化
あとはRubotyを自動起動する設定が必要です。init.d
に書いたりするのかと調べてみましたが、Systemd
を使うととても簡単にサービス化できるようだったのでそれを採用しました。これを使うことにより再起動した時も、予期せぬ理由でプログラムが停止した時も自動でプログラムを起動してくれます。
下記のようなRubotyの起動スクリプトを用意しておく
#!/bin/bash
HOME=/home/toyoshi
PATH=$HOME/.rbenv/shims:$PATH
cd $HOME/ruboty
RUBOTY_ENV=production bundle exec ruboty --dotenv >/var/log/ruboty.log 2>&1
/etc/systemd/system/ruboty.service
というファイルを作ってServiceとして定義。
[Unit]
Description = Ruboty Daemon
[Service]
ExecStart = /home/toyoshi/start_up_ruboty.sh
Restart = always
Type = simple
[Install]
WantedBy = multi-user.target
これでファイル名であるruboty
がサービスとして登録されるので、有効化すれば自動で起動するようになる。
$ sudo systemctl enable ruboty # 最初は無効化されているので有効化する
$ sudo systemctl start ruboty # 初回だけ手動でスタート
参考:Systemdを使ってさくっと自作コマンドをサービス化してみる - Qiita
最後に
ここまでやって遠くにあるものをSlackから写真撮影して取得できるようになりました。個人的にはこれまで立ち上がって作業してたのが不要になったのが便利でした。そして24年前のケンブリッジ大学のコーヒーマシンと同じようなことができたことが小さな小さな人生の目標を一つ達成したようで幸せな気持ちになりました。
明日は@yoshokuの「Ethereumのローカルネットワーク上で独自コインを送金する」という話です。Misoca Advent Calendarで公開されますのでお楽しみに。