はじめに
最近、RaspberryPIなるものを知ったので、初めてのRaspberryPIで、
webカメラを使って動体検知する監視カメラを作ってみる事にしました。
機能概要
今回作成する機能の概要はこんな感じにします。
・動体検知をしたら写真を撮る。(今回は写真のみにします。)
・写真を撮ったら、Slackに撮った写真を自動投稿する。
これだけです。
初回なので欲張らずにシンプルな物を作ります。
今回のメインになる登場人物紹介
・RaspberryPI: 簡単に言うと小さいパソコン
・motion: 動体検知するソフト (このソフトを使えば簡単に動体検知ができるよ)
・Slack: チャットツール (SkypeとかLineとかをイメージしてもらえばOK)
・Slacker: Slackにプログラムから投稿とかする為の機能
motionの準備
まずはmotionを準備して行きます。
motion のインストール
$ sudo apt-get install -y motion
次にmotion.confの設定を変更します。
・まずは開発段階は毎回手動で起動させるためdaemonの設定をoffにます。
・動画も必要無いので止めます。
・頻繁に画像を書き出すため、SDカードが劣化してしまう恐れがあるので、メモリー領域に写真を書き出すようにします。
(注意:事前にtmp以下をメモリ領域に変更しています。)
とりあえずmotionの設定はこれで終わりです。
この時点で、sudo motion -c /etc/motion/motion.conf
でmotionを実行して、
動体検知で/tmp/motion
以下に写真が書き出されている事が確認出来ます。
簡単ですね。
しかし、ここからが本番です。
完成には、写真を自動でSlackに投稿し、私自身が携帯で通知を受け取れるようにならないといけません。
では、ここからがこの記事のメインになります。
これからSlackの設定をしていきます。
Slackの設定
先にSlackのアカウント登録を済ましておきます。
そうしたら、SlackToken発行ページからAPI用のTokenを発行します。
Tokenを作成できたら、今度はRaspberry PIにPythonのSlackライブラリ
Slackerをインストールをします。
$ sudo pip install slacker
インストールできたら、まずは対話型でTESTしてみます。
$ python
Python 2.7.9 (default, Mar 8 2015, 00:52:26)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from slacker import Slacker
>>> token = "xxxx-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxx"
>>> slacker = Slacker(token)
>>> channel_name = "#" + "general"
>>> message = 'APIだよ'
>>> slacker.chat.post_message(channel_name, message)
<slacker.Response object at 0xb64aca50>
そうすると、来ました!
無事Slackに投稿できる事を確認できました。
ちなみbotという名前が気に入らないので、にユーザー名を変えてみました。
>>> slacker.chat.post_message(channel_name, message, as_user=True)
<slacker.Response object at 0xb6bff910>
>>> slacker.chat.post_message(channel_name, message, username='test')
<slacker.Response object at 0xb64ac210>
画像UPLOAD
今回は画像投稿がメインになるので、早速画像のUPLOADを行っていきます。
slackerのREADMEを参照したところfilesクラスにupload関数が用意されているようなので、そちらを使っていきます。
$ python
Python 2.7.9 (default, Mar 8 2015, 00:52:26)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from slacker import Slacker
>>> token = "xxxx-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxx"
>>> slacker = Slacker(token)
>>> channel_name = "#" + "general"
>>> slacker.files.upload('/var/lib/motion/01-20151206004121-00.jpg')
<slacker.Response object at 0xb64b4e50>
お!エラー無し!
上がったかなと思ったけどSlack側は無反応。。。
これ、結構ハマりました^^;
よくよくSlackのページを確認してみると、メニュー?みたいな所にAll Filesなる項目が。。。
なるほど、Uploadしただけだと投稿されないんですね。
どうやら、このFilesに上がった画像をPin(Share)しないと投稿はされない様です。
Pinする
pinする為には、対象となるfile情報が必要になります。
なので、uploadした時に返り値を保存しておきます。
>>> result = slacker.files.upload('/var/lib/motion/01-20151206004057-02.jpg')
その情報を使って、Pinしてみるとエラーになった。
>>> slacker.pins.add(channel='C0G0XXXXX', file_=result.body['file']['id'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/slacker/__init__.py", line 495, in add
'timestamp': timestamp,
File "/usr/local/lib/python2.7/dist-packages/slacker/__init__.py", line 69, in post
return self._request(requests.post, api, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/slacker/__init__.py", line 61, in _request
raise Error(response.error)
slacker.Error: file_not_shared
これは、File情報の中にchannelsの指定が無いからでした。
Pinするにはファイルをuploadする時、Pinできるchannelを指定する必要があるようです。
もう一度、チャンネルを確認します。
>>> slacker.channels.list().body
{u'channels': [{u'name': u'general', u'id': u'C0G0XXXXX'....}, ....
では、次はちゃんとチャンネル指定して、UploadとPinを行います。
>>> result = slacker.files.upload('/var/lib/motion/01-20151206004057-02.jpg', channels=['C0G0XXXXX'])
>>> slacker.pins.add(channel='C0G0XXXXX', file_=result.body['file']['id'])
<slacker.Response object at 0xb64ee6b0>
できました!
(*ちなみに右下の小さく出ている四角い枠が動体検知した場所になります)
これで、APIの確認は完了したので、いよいよmotionと連携していきます。
motion連携
次にmotionで検知したら、slackに投稿するために、motion側にイベント処理を指定していきます。
どうやって指定するかというと、motionにはイベント時に意図したスクリプトを指定し、実行させる為の下記optionが存在します。
- on_event_start
- 動体検知時に起動するスクリプトを指定できます
- on_event_end
- 動体検知終了時に起動するスクリプトを指定できます
- on_picture_save
- 写真をsaveする度に起動するスクリプトを指定できます
- on_movie_start
- 動画の撮影開始時に起動するスクリプトを指定できます
- on_movie_end
- 動画の撮影終了時に起動するスクリプトを指定できます
ちなみにどうやって、ファイルパスを指定するのか調べたところ、
こちらのサイトに引数でファイル情報が渡されるとありました。
※1 motion.conf のオプション on_picture_save, on_movie_start, on_movie_end では、ファイル名がコマンドに引き渡されます($1)。
ちなみにon_picture_saveの場合、引数には撮影したファイルのpathが渡されます。
それをふまえて、Pythonスクリプトを作成。
ではconfに指定します。
# Command to be executed when a picture (.ppm|.jpg) is saved (default: none)
# To give the filename as an argument to a command append it with %f
#; on_picture_save value
on_picture_save python /home/pi/slackbot/slack_bot.py %f
次に実行権限の付与を忘れずに。
$ chmod a+x slackbot/slack_bot.py
ではmotionを起動します!
写真がsaveされていく。
sudo motion -c /etc/motion/motion.conf
~~snip~~
[1] [NTC] [ALL] motion_detected: Motion detected - starting event 1
[1] [NTC] [EVT] event_newfile: File of type 1 saved to: /tmp/motion/01-20151208222942-04.jpg
[1] [NTC] [EVT] event_newfile: File of type 1 saved to: /tmp/motion/01-20151208222942-05.jpg
[1] [NTC] [EVT] event_newfile: File of type 1 saved to: /tmp/motion/01-20151208222943-01.jpg
~~snip~~
slackの方はというと。。。
キタ━━━(゚∀゚).━━━!!!
成功です!!どんどん来るよーー!!!
検証
では実際に設置してみて、監視カメラとして検証してみたいと思います。
100均で適当にプラスチックケースを買ってきて、それをケースにします。
では外に設置してみます。
バッチリです!まさかこの風貌で監視カメラだと疑う人はいないでしょう。
全く怪しまれる事もなさそうなので、まずは監視カメラとして問題はなさそうです。笑
ちょうどそこに怪しい人影が。。。
するとSlackに通知が!
バッチリです!
しかも思ったより結構きれいに撮れてます!
これで監視カメラは完成になります。
まとめ
初めて、RaspberryPIを触ってみましたが、こんなに簡単に監視カメラが実現できた事にビックリでした。
ちなみに今回、本当は赤外線カメラモジュールを使うつもりだったのですが、うまく起動できなくて、結局間に合いませんでした。orz
あと、撮影の度にSlackに投稿するので、通知などが結構すごい事になってしまいますorz
ですので、いずれは赤外線カメラモジュールを使用して、写真自体はクラウドストレージ等に保存して、それをSlackで通知する様にしたいなと思います。
では明日はhamano_tさんにバトンタッチです。
明日はいよいよクリスマス、AdventCalendarも締めとなります。
締め前日に初心者の投稿で恐縮でしたが、読んでくれてありがとうございました^^
追記
後日、外出先から携帯でペットを動画監視できるようにしました。
こちらも是非参考にしてみてください^^
Raspberry Piで赤外線カメラモジュールを使ってみる
Raspberry Piに外部ネットワークからアクセスできる様にして外から携帯でペットを監視する方法