Hubot
RaspberryPi
raspbian
Slack
IoT

Slackをトリガーにしてラズパイで写真を撮影する

概要

Slackにラズパイのhubotを常駐させておき、Slack上で写真撮影の指示を受けたらラズパイに接続されたカメラで写真を撮影する。

前提

  • ラズパイにWebカメラを接続して写真を撮影できること
  • ラズパイにhubotをインストールしてセットアップが済んでいること
  • Slackにラズパイのhubotを連携させていること

過去のQiita

Raspberry PiにLogicool Webcam C270 を接続してカメラ画像を取得してみる
Raspberry PiにhubotをインストールしてSlackから呼び出すまでの手順

使用するハードウェア

  • Raspberry Pi 2 Model B
  • Logicool Webcam C270

使用するソフトウェア

  • hubot
  • fswebcam

ざっくりした処理の流れ

キャプチャ.PNG

やるべきこと

  • fswebcamで写真を撮影するシェルスクリプトを作成
  • 写真撮影のシェルスクリプトを実行するcoffeeスクリプトを作成

fswebcamで写真を撮影するシェルスクリプトを作成

作成したシェルスクリプト

fswebcamに引数を渡せるようにしておく。

take_photo.sh
!/bin/sh

echo "fswebcam $@"
fswebcam $@

動作確認

take_photo.shを実行して写真を撮影できるか確認する。
WS000065.JPG

写真撮影のシェルスクリプトはOK!
WS000064.JPG

写真撮影シェルスクリプトを実行するcoffeeスクリプトを作成

試作版スクリプト

いきなり難しいことをしようとすると躓くポイントが多いので、とりあえず写真撮影用のシェルスクリプトを実行して、実行結果の出力を返すだけのcoffeeスクリプトを作成してみる。

作成したcoffeeスクリプト

Node.jsでOSのコマンドを実行したい場合は、child_processのexecで実行するらしい。

take_photo.coffee
module.exports = (robot) ->
  robot.respond /写真撮って/i, (msg) ->
    @exec = require('child_process').exec
    command = "sudo -u pi sh ./scripts/sh/take_photo.sh 001.jpg"
    msg.send "写真を撮ってるよ。ちょっと待ってね。"
    msg.send "Command: #{command}"
    @exec command, (error, stdout, stderr) ->
        msg.send error if error?
        msg.send stdout if stdout?
        msg.send stderr if stderr?

動作確認

Raspberry Piでhubotを再起動し、Slackから動作確認をする。
WS000066.JPG

撮れてる、撮れてる。
WS000067.JPG

現時点の問題としては。。。

  • 写真のファイル名が001.jpg固定になっている。年月日時分秒などのユニークなファイル名にしたい。
  • 写真の出力先がhubotのルートディレクトリになっている。写真保存用のディレクトリに保存したい。
  • 写真のサイズがデフォルトのままになっている。もっと大きめに撮影してほしい。
  • 写真を撮り終えたら、撮り終えたことをhubotから通知してほしい。

改善版スクリプト

上記の問題点を考慮して、改善版のスクリプトを作成してみた。

作成したcoffeeスクリプト

take_photo.coffee
module.exports = (robot) ->
  robot.respond /写真撮って/i, (msg) ->
    # 写真ファイルのパスとファイル名を定義
    dt = new Date()
    year = dt.getFullYear()
    month = ("0"+( dt.getMonth() + 1 )).slice(-2)
    date = ("0"+dt.getDate()).slice(-2)
    hour = ("0"+dt.getHours()).slice(-2)
    min = ("0"+dt.getMinutes()).slice(-2)
    sec = ("0"+dt.getSeconds()).slice(-2)
    file_path = "/home/pi/Pictures/"
    file_name = "#{year}#{month}#{date}#{hour}#{min}#{sec}.jpg"

    # 写真の解像度を指定
    resolution = "1280x720"

    # fswebcamコマンドを実行
    @exec = require('child_process').exec
    command = "sudo -u pi sh ./scripts/sh/take_photo.sh -r #{resolution} #{file_path}#{file_name} "
    msg.send "写真を撮ってるよ。ちょっと待ってね。"
    # msg.send "Command: #{command}"
    @exec command, (error, stdout, stderr) ->
        if error != null
            msg.send "写真撮影に失敗しちゃったよ。。。"
            return;
        msg.send "写真を撮ったよ。ファイル名は #{file_name} だよ。"

動作確認

Raspberry Piでhubotを再起動し、Slackから動作確認をする。
WS000068.JPG

指定したパスに、年月日時分秒のファイル名で写真ファイルが作成できている。
WS000069.JPG

coffeeスクリプトを書いているときの罠ポイント

JavaScriptと比べると、coffeeスクリプトの書き方はいろいろ異なるところがあるので注意。
今回作成した改善版スクリプトでちょっと嵌った罠ポイントとしては。。。

  • if句に (){} は不要
  • 関数の定義にはアロー演算子 -> を使用する
  • 日付の文字列フォーマットがよくわからん。。。

要勉強ですね。。。

次のステップ

撮影した写真をRaspberry PiのhubotからSlackに投稿してくれるようにしてみた。