the invention of t88

工作、資格取得、データ分析のことなど

ラズパイのカメラ画像をGoogle Driveに上げる

水耕栽培器IoT化(第8回)

前回までの取り組みで、Ambientというサービスを使って、センサデータをクラウドに保存&可視化できるようになりました。

www.t88.work

今回は、カメラで取得した画像をクラウドに保存できるようにします。保存先としては、APIなどが整っていて扱いやすそうなGoogle Driveを用います。

また、少し工夫をしてAmbient上に最新の写真を表示できるようにします。これによって、Ambientだけで簡易的なダッシュボードが構築できます。

Google Driveの下準備

下記記事を参考に、pythonでGoogle Driveを扱うために必要なパッケージのインストールや、OAuth認証絡みの設定を行います。

qiita.com

基本的に、この通り進めていけば問題ないのですが、私の環境ではpythonスクリプトでエラーが出ました。

pythonスクリプト(エラー部)

  from pydrive.auth import GoogleAuth

エラー内容

Traceback (most recent call last):
  File "picture_test.py", line 4, in <module>
    from pydrive.auth import GoogleAuth
ImportError: No module named pydrive.auth

pydriveのインポートに失敗している模様。

下記コードでパッケージの探索先を明示的に加えてみたところ、エラーは解消。

import sys
sys.path.append('/home/pi/.local/lib/python2.7/site-packages/pydrive')


これでローカルのファイルをGoogle Driveにアップロードすることが出来るようになりました。

カメラで撮影&アップロード

①カメラで写真を撮影、②撮影した写真をGoogle Driveにアップロード、③ローカルに残ったファイルを削除する、pythonスクリプトを作成します。

# coding: UTF-8
import sys
sys.path.append('/home/pi/.local/lib/python2.7/site-packages/pydrive')

import os
from datetime import datetime
from picamera import PiCamera
import time
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

# 写真撮影
with PiCamera() as cam:
    cam.resolution = (1024,768)
    cam.rotation = 90 #カメラを横向きに設置したので90度回転させる
    
    # 現在時刻を取得
    tstp = datetime.now().strftime("%Y%m%d%H%M%S")
    file_name = tstp + '.jpg'
    # 写真撮影。取得した現在時刻をファイル名に設定
    cam.capture(file_name)

# google drive
gauth = GoogleAuth()
gauth.CommandLineAuth()
drive = GoogleDrive(gauth)

folder_id = 'hoge'

# 写真をアップロード
f = drive.CreateFile({'title': file_name,
                      'mimeType': 'image/jpeg',
                      'parents':[{'kind':'drive#fileLink','id':folder_id}]})
f.SetContentFile(file_name)
f.Upload()

# ローカルに保存したファイルを削除
os.remove(file_name)


これでスクリプトが走る度に写真を撮影し、Google Driveの所定のフォルダに画像ファイルを格納することができます。

Ambientに最新画像を表示

Ambientには画像を表示する機能があります。Ambientのチャネル設定の中のEmbed codeの部分にGoogle Driveの共有リンクを貼り付ければ、そのファイルを読み込んで表示してくれます。

f:id:take213uv:20190102153634p:plain


このままでは特定の画像を静的に表示するだけですが、共有リンクしたファイルを最新画像に更新すれば、Ambientの表示も最新化することが出来ます。
但し、Google Drive上では同名のファイルを上げても、上書き保存されず別ファイルとして保存されてしまうので、ファイルIDを指定して更新を掛ける必要があります。


具体的な手順としては、下記の通り。
① 蓄積用の画像ファイル(日時.jpg)とは別に、最新データ(latest.jpg)をアップロードする

② Google Drive上でlatest.jpgのファイルIDを確認する。(共有リンクの"open?id="以降の文字列がファイルID)

③ 最新データ(latest.jpg)のアップロード時にファイルIDを指定するようにスクリプトを変更する

先ほどのスクリプトには下記コードを追記することになります。

# 最新版を更新
f1 = drive.CreateFile({'title': 'latest.jpg',
                      'mimeType': 'image/jpeg',
                      'parents':[{'kind':'drive#fileLink','id':folder_id}],
                      'id': 'hoge'})
f1.SetContentFile(file_name)
f1.Upload()

4行目の'id': 'hoge'が変化点。hogeの部分にファイルIDを入れる。


実際にスクリプトを実行。Google Driveを確認。

f:id:take213uv:20190102160953p:plain
日時.jpgとlatest.jpgがアップロードされています。

さらにもう一度実行し、Google Driveを確認。
f:id:take213uv:20190102161005p:plain
新たなタイムスタンプの日時.jpgが追加、latest.jpgの画像が更新されています。


Ambientでの状況も確認(初回スクリプト実行後)

f:id:take213uv:20190102161017p:plain
右下に画像が表示されている。

スクリプト2回目実行後。
f:id:take213uv:20190102161046p:plain
画像が更新されている。

cronで定期実行

前回同様、cronで定期実行させます。

*/30 * * * * sudo python get_picture.py

とりあえず30分毎に設定しました。

おわりに

Google Driveへのファイルアップロードは思ったより手軽に出来ました。Ambientで最新画像表示もできたので、現在の状況を可視化するダッシュボードとして一応は成立したかな、という印象です。これで、いつでもどこでも野菜の生育状況が確認できる。

8月からボチボチ進めてきて、だいぶ時間が掛かりましたが、これで一通りの準備が完了しました。次回はいよいよ野菜を育て始めようと思います。


前の記事:ラズパイで取得したデータをAmbientに上げる
次の記事:IoT水耕栽培器で野菜を育てる
水耕栽培器IoT化 目次