Raspberry Pi 3B+とSlackbotで遠隔から写真撮影

##Raspberry Piとカメラモジュール、Slackbotで遠隔から写真が撮れる仕組みを作ってみた。
Pythonとラズパイの勉強がしてみたく、とりあえず何か意味のあるものをと思って挑戦した。
カメラモジュールで写真を撮るところ以外はラズパイ以外でも同じ事が出来るはずなので、画像投稿Botなどには流用できると思う。

##使ったもの

<img src="https://qiita-image-store.s3.amazonaws.com/0/230036/92aed5b6-50b6-e62f-a4af-9221e23168c8.jpeg" width=75%>

**[Raspberry Pi 3 Model B+](https://amzn.to/2R0xRc2)**
3B+が必須ではないが、初心者なので一番いろいろ出来そうなものをチョイス。
インターネットを使った制作では、無線LANが最初から使えるのがいろいろと便利かと。

**[OV5647 HDカメラモジュール](https://amzn.to/2R0tuxC)**
いろいろ見たけど違いがわからなかったので手頃なものを購入。
説明よく読んだら3B+は対応機種に入っていなかったが、普通に使えた。

**洗濯バサミ**
家にあるもの。カメラを固定するのに使用。


##まずはSlackbotから

以下記事を参考にSlackbotを作成。
**[PythonのslackbotライブラリでSlackボットを作る](https://qiita.com/sukesuke/items/1ac92251def87357fdf6)**
ほぼそのまま流用させて頂き、/pluginsのmy_mention.pyは以下の必要最小限の形に変更。

```python:my_mention.py
from slackbot.bot import respond_to

#写真を撮る
@respond_to('写真')
def takepicture_func(message):
    message.send('写真を撮ったつもり') 
```
これで、Slackbotにメンションで”写真”を含むメッセージを送るとリアクションが返ってくるようになる。
##次にRaspberryPiで写真を撮る

またしても以下を参考にさせて頂き、必要な箇所だけ抜き出す。
**[PythonでRaspberry Pi カメラを制御する](https://iotdiyclub.net/raspberry-pi-camera-python-1/)**

```python:take_picture.py
import picamera
import time

ImagePath = '/Path/my_picture.jpg'
with picamera.PiCamera() as camera:
    camera.resolution = (1024, 768)
    camera.start_preview()
    #Camera warm-up time
    time.sleep(2)
    camera.capture(ImagePath)
```
実行するとカメラモジュールが動作し、/Pathにmy_picture.jpgという名称で撮影した画像を保存する。
##Slackへの画像アップロード

これも他と同じく、下記リンクを参考に作成する。
**[PythonでSlackに画像をアップロードする方法](https://qiita.com/tottu22/items/594e8c506ece0f8cc87c)**

Slackbotのモジュールを使うのかと思っていたら、使うのは**Requests**というモジュールだった。
HTTPライブラリだそうで。また勉強します。
Slackbotとは別なので、改めてbotのトークンを指定する必要がある。
投稿先のチャンネルIDも指定という事なので、今のところいろんなチャンネルからメンション送っても画像を返してくるチャンネルは一つになる筈。
いつかメンション元のチャンネルID取得して返したいと思いつつ、今はこのまま。

```python:upload_imagefile.py
import os
import requests

TOKEN = 'Slackbotのトークン'
ImagePath = '/Path/my_picture.jpg'
        
CHANNEL = '投稿先のチャンネルID'
TITLE = 'アップロードする画像のタイトル'
files = {'file': open(ImagePath, 'rb')}
param = {
    'token':TOKEN, 
    'channels':CHANNEL,
    'filename':"アップロードする画像の名称",
    'initial_comment': "画像と一緒に送信するメッセージ",'title': TITLE
}
requests.post(url="https://slack.com/api/files.upload",params=param, files=files)
```
##これらを組み合わせて完成

ほぼそのままだけど、こんな感じで。

```python:my_mention.py
import os
import time
import picamera
import requests
from datetime import datetime
from slackbot.bot import respond_to

TOKEN = 'Slackbotのトークン'

#写真を撮る
@respond_to('写真')
def takepicture_func(message):
    ImagePath = '/Path/my_picture.jpg'
    
    #写真の撮影(RaspberryPi)
    with picamera.PiCamera() as camera:
        camera.resolution = (1024, 768)
        camera.start_preview()
        #Camera warm-up time
        time.sleep(2)
        camera.capture(ImagePath)
    
    #画像のアップロード
    CHANNEL = 'Slackbotのトークン'
    TITLE = datetime(*time.localtime(os.path.getctime(ImagePath))[:6])
    files = {'file': open(ImagePath, 'rb')}
    param = {
        'token':TOKEN, 
        'channels':CHANNEL,
        'filename':"my_picture.jpg",
        'initial_comment': "写真を撮影しました。",'title': TITLE
    }
    requests.post(url="https://slack.com/api/files.upload",params=param, files=files)
```
こんな感じで無事に遠隔撮影成功。
<img src="https://qiita-image-store.s3.amazonaws.com/0/230036/7fcf1e0d-5574-38be-4713-d8efc26ddbf9.jpeg" width=75%>

少し工夫したのは、画像投稿時のタイトルを画像のタイムスタンプにした事。
今の実装だと画像ファイルは常に同名で上書きされるので、万が一写真が撮れていない場合過去に撮影した画像を投稿してしまう(その代わりNot Foundにはならない)
そうした場合に異変に気付けるよう、画像の作成日時を取得しタイトルに出すようにした。