Python
RaspberryPi
Slack
motion

はじめてのRaspberry PIで監視カメラを作ってみた。

More than 3 years have passed since last update.


はじめに

最近、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にます。

daemon off



・動画も必要無いので止めます。

ffmpeg_output_movies off

・頻繁に画像を書き出すため、SDカードが劣化してしまう恐れがあるので、メモリー領域に写真を書き出すようにします。

(注意:事前にtmp以下をメモリ領域に変更しています。)

target_dir /tmp/motion

とりあえずmotionの設定はこれで終わりです。

この時点で、sudo motion -c /etc/motion/motion.conf でmotionを実行して、

動体検知で/tmp/motion 以下に写真が書き出されている事が確認出来ます。

簡単ですね。

しかし、ここからが本番です。

完成には、写真を自動でSlackに投稿し、私自身が携帯で通知を受け取れるようにならないといけません。

では、ここからがこの記事のメインになります。

これからSlackの設定をしていきます。


Slackの設定

先にSlackのアカウント登録を済ましておきます。

そうしたら、SlackToken発行ページからAPI用のTokenを発行します。

d4bdbe01-b0e3-9831-10d1-0c395ac7aae1.png

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に投稿できる事を確認できました。

スクリーンショット 2015-12-06 0.00.06.png

ちなみ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>

ちゃんと変わってることが確認できました。

スクリーンショット 2015-12-05 23.56.44.png


画像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なる項目が。。。

6785ecb9-746a-0d95-575b-dc902a1b9d2a.png

開くとちゃんと上がってました!

スクリーンショット 2015-12-06 1.59.13.png

なるほど、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>

できました!

1af3f838-f7e3-765c-c406-2b4342d394eb.png

(*ちなみに右下の小さく出ている四角い枠が動体検知した場所になります)

これで、APIの確認は完了したので、いよいよmotionと連携していきます。


motion連携

次にmotionで検知したら、slackに投稿するために、motion側にイベント処理を指定していきます。

どうやって指定するかというと、motionにはイベント時に意図したスクリプトを指定し、実行させる為の下記optionが存在します。


on_event_start

動体検知時に起動するスクリプトを指定できます

on_event_end

動体検知終了時に起動するスクリプトを指定できます

on_picture_save

写真をsaveする度に起動するスクリプトを指定できます

on_movie_start

動画の撮影開始時に起動するスクリプトを指定できます

on_movie_end

動画の撮影終了時に起動するスクリプトを指定できます

今回はon_picture_saveを利用して、Slackに投稿させる事にします。

ちなみにどうやって、ファイルパスを指定するのか調べたところ、

こちらのサイトに引数でファイル情報が渡されるとありました。


※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の方はというと。。。

キタ━━━(゚∀゚).━━━!!!

成功です!!どんどん来るよーー!!!

6b155334-b635-acc5-a46e-95cbd8b62d29.png


検証

では実際に設置してみて、監視カメラとして検証してみたいと思います。

100均で適当にプラスチックケースを買ってきて、それをケースにします。

IMG_4008.jpg

では外に設置してみます。

バッチリです!まさかこの風貌で監視カメラだと疑う人はいないでしょう。

全く怪しまれる事もなさそうなので、まずは監視カメラとして問題はなさそうです。笑


IMG_4010.jpg

ちょうどそこに怪しい人影が。。。

するとSlackに通知が!

スクリーンショット 2015-12-23 16.07.37.png

バッチリです!

しかも思ったより結構きれいに撮れてます!

これで監視カメラは完成になります。


まとめ

初めて、RaspberryPIを触ってみましたが、こんなに簡単に監視カメラが実現できた事にビックリでした。

ちなみに今回、本当は赤外線カメラモジュールを使うつもりだったのですが、うまく起動できなくて、結局間に合いませんでした。orz

あと、撮影の度にSlackに投稿するので、通知などが結構すごい事になってしまいますorz

ですので、いずれは赤外線カメラモジュールを使用して、写真自体はクラウドストレージ等に保存して、それをSlackで通知する様にしたいなと思います。

では明日はhamano_tさんにバトンタッチです。

明日はいよいよクリスマス、AdventCalendarも締めとなります。

締め前日に初心者の投稿で恐縮でしたが、読んでくれてありがとうございました^^


追記

後日、外出先から携帯でペットを動画監視できるようにしました。

こちらも是非参考にしてみてください^^

Raspberry Piで赤外線カメラモジュールを使ってみる

Raspberry Piに外部ネットワークからアクセスできる様にして外から携帯でペットを監視する方法