動機
元々は、文ちゃん(文鳥)の住んでるケージ周辺の日中の環境(温度・湿度)をモニターしたかったのが始まり。
その為、ラズパイでLチカから勉強し始めたんだけど、色々自理由をつけていつの間にかフェードアウト。。。
しばらくして、ラズパイとUSBカメラが接続できて、写真をキャプチャ出きる事を知り、
何かできそうなのでやってみようと方向転換。
よって今回の最終目標を、
写真で文ちゃんの日中の挙動をカメラで定期的に撮影し、Twitterに投稿する。そして仕事場から見て楽しむ
とした。
目次
- 使った機材
- 環境構築(ラズパイ&開発環境)
- アプリ開発
- コードの置き場所とbotの紹介
前回は、目次2. 環境構築(ラズパイ&開発環境)まで説明したので、当記事は
-
- アプリ開発
-
- コードの置き場所とbotの紹介についてまとめる。
この記事で伝えたいこと
- 仕組み
- ハマったポイント
この記事で伝えないこと
- Twitter Application Managementでアプリの登録をする手順
仕組み
- crontabはshellをキック
- shellは、記述しているPythonスクリプトを実行
- Pythonスクリプトは、設定ファイルからtwitterで作成した
- Consumer Key
- Consumer Secret
- Access Token
- Access Token Secretを読み取る。
- fswebcamを実行し、撮影を行いファイルを保存する。
- 保存したファイルを読み込む。
- twythonを使ってtweetする。
1. crontabはshellをキック
何の変哲も無い設定。
raspberrypi% crontab -l
# hour:7-18 week:mon-fri
0,30 7-18 * * 1,2,3,4,5 /home/pi/code/git/twitterSample/twitterSample.sh >/dev/null 2>&1
2. shellは、中に記述しているPythonスクリプトを実行
開発はvirtualenvで構築した環境で行っていたので、pythonを直接実行するのではなくshellでvirutalenvのコマンドを実行しPythonを実行するようにした。
# !/bin/zsh
export CURRENT_PATH=`echo $(cd $(dirname $0) && pwd)`
export ENV_NAME=twitterSample
export VIRTUALENV_PATH=$CURRENT_PATH/$ENV_NAME
source $VIRTUALENV_PATH/bin/activate
python $CURRENT_PATH/twitterSample.py
参考リンク:[Shell] $(cd $(dirname $0) && pwd) を理解する
3以降はコード内で説明
Consumer Keyなどはtwitter.configとして記述
(twitterSample) raspberrypi% cat twitter.config
[KEY]
CONSUMER_KEY = xxxxxxxxxxxxxxxxxxxx
CONSUMER_SECRET = xxxxxxxxxxxxxxxxxxxx
ACCESS_TOKEN = xxxxxxxxxxxxxxxxxxxx
ACCESS_TOKEN_SECRET = xxxxxxxxxxxxxxxxxxxx
# -*- coding: utf-8 -*-
import subprocess
import sys
import configparser
from PIL import Image
import io
import os
from twython import Twython, TwythonError
from datetime import datetime
def tweet():
// 3. Pythonスクリプトは、設定ファイルからtwitterで作成した云々の箇所
// import configparserが必要。
// twitter.configを読み込みconfig内にDictionaryとして展開。
config = configparser.ConfigParser()
config.read(os.path.dirname(os.path.abspath(__file__)) + '/twitter.config')
twitter = Twython(
config['KEY']['CONSUMER_KEY'],
config['KEY']['CONSUMER_SECRET'],
config['KEY']['ACCESS_TOKEN'],
config['KEY']['ACCESS_TOKEN_SECRET']);
#try:
# twitter.update_status(status='Tweet Sample')
#except TwythonError as e:
# print(e)
image_io = None
try:
// 4. fswebcamを実行し、撮影を行いファイルを保存するの箇所。
// import subprocessが必要。
subprocess.run('fswebcam -F 1 -S 20 -r 640x480 ' + os.path.dirname(os.path.abspath(__file__)) + '/image.jpg', shell=True, check=True)
except subprocess.CalledProcessError as e:
print(e)
else:
// 5. 保存したファイルを読み込む。
// from PIL import Imageが必要。
photo = Image.open(os.path.dirname(os.path.abspath(__file__)) + '/image.jpg');
image_io = io.BytesIO()
photo.save(image_io, format='JPEG')
image_io.seek(0)
try:
// 6. twythonを使ってtweetする。
formattedDateTime = datetime.now().strftime("%Y/%m/%d %H:%M:%S")
image_ids = twitter.upload_media(media=image_io)
twitter.update_status(status="Captured at {time}".format(time=datetime.now().strftime("%Y/%m/%d %H:%M:%S")), media_ids=[image_ids['media_id']])
except TwythonError as e:
print(e)
if __name__ == '__main__':
tweet()
ハマったポイント
読み込んだ画像を、upload_media()に指定すると失敗する。
キャプチャまではできていて、Tweetするタイミングで400 (Bad Request)が返却され失敗した。
(twitterSample) raspberrypi% python twitterSample.py
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
--- Capturing frame...
Skipping 20 frames...
Capturing 1 frames...
Captured 21 frames in 0.80 seconds. (26 fps)
--- Processing captured image...
Writing JPEG image to '/home/pi/code/git/twitterSample/image.jpg'.
Twitter API returned a 400 (Bad Request), An error occurred processing your request.
コードはtwythonのサンプルコードを元に書いていたので、
サンプルコードを見直すと以下の注意書きを発見。 これに気づいた時はサンプルよく見ろよーとツッコミ。
# If you do not seek(0), the image will be at the end of the file and
# unable to be read
image_io.seek(0)
Posting a Status with an Editing Image
python3で書いているとそんなモジュール無いYOと怒られる
ここは仕方がないので、出てきたエラーをコピーして "python3 出てきたエラー"で検索して都度置き換え。