##Raspberry Piとカメラモジュール、Slackbotで遠隔から写真が撮れる仕組みを作ってみた。
Pythonとラズパイの勉強がしてみたく、とりあえず何か意味のあるものをと思って挑戦した。
カメラモジュールで写真を撮るところ以外はラズパイ以外でも同じ事が出来るはずなので、画像投稿Botなどには流用できると思う。
##使ったもの
Raspberry Pi 3 Model B+
3B+が必須ではないが、初心者なので一番いろいろ出来そうなものをチョイス。
インターネットを使った制作では、無線LANが最初から使えるのがいろいろと便利かと。
OV5647 HDカメラモジュール
いろいろ見たけど違いがわからなかったので手頃なものを購入。
説明よく読んだら3B+は対応機種に入っていなかったが、普通に使えた。
洗濯バサミ
家にあるもの。カメラを固定するのに使用。
##まずはSlackbotから
以下記事を参考にSlackbotを作成。
PythonのslackbotライブラリでSlackボットを作る
ほぼそのまま流用させて頂き、/pluginsのmy_mention.pyは以下の必要最小限の形に変更。
from slackbot.bot import respond_to
#写真を撮る
@respond_to('写真')
def takepicture_func(message):
message.send('写真を撮ったつもり')
これで、Slackbotにメンションで”写真”を含むメッセージを送るとリアクションが返ってくるようになる。
##次にRaspberryPiで写真を撮る
またしても以下を参考にさせて頂き、必要な箇所だけ抜き出す。
PythonでRaspberry Pi カメラを制御する
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に画像をアップロードする方法
Slackbotのモジュールを使うのかと思っていたら、使うのはRequestsというモジュールだった。
HTTPライブラリだそうで。また勉強します。
Slackbotとは別なので、改めてbotのトークンを指定する必要がある。
投稿先のチャンネルIDも指定という事なので、今のところいろんなチャンネルからメンション送っても画像を返してくるチャンネルは一つになる筈。
いつかメンション元のチャンネルID取得して返したいと思いつつ、今はこのまま。
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)
##これらを組み合わせて完成
ほぼそのままだけど、こんな感じで。
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)
少し工夫したのは、画像投稿時のタイトルを画像のタイムスタンプにした事。
今の実装だと画像ファイルは常に同名で上書きされるので、万が一写真が撮れていない場合過去に撮影した画像を投稿してしまう(その代わりNot Foundにはならない)
そうした場合に異変に気付けるよう、画像の作成日時を取得しタイトルに出すようにした。