RaspberryPi 3 Model B+でIoT監視カメラをつくる(その2GoogleDriveとLINEの設定)
RaspberryPi(ラズパイ)でIoT監視カメラ
RaspberryPi 3 Model B+とカメラ(Raspberry Pi Camera Module V2)とモーションセンサー(HC-SR501)で動きがあった時だけ録画する監視カメラを作成したときの備忘録の2回目。
1回目はRaspberryPiとカメラ、モーションセンサーとの接続に関するこちらの記事を参照。
IoT監視カメラと言うからにはインターネットに接続して情報をアップロードしたりメッセージのやりとりをしないといけない。
今回はGoogleDriveにファイルをアップロードするためのGoogleプロジェクトから認証情報の作成までとLINEからメッセージを発信する為のアクセストークンの発行に関する記事とする。
全体構成図
尚、1回目の記事でも載せているが今回も全体構成図を念の為、掲載する。
監視カメラシステムの全体構成図は以下の通り。
GoogleDriveへのアクセス
RaspberryPiのPythonのプログラムからGoogleDriveへアクセスする方法の手順は以下の通り。
- RaspberryPiにGoogleDriveにアクセスする為のモジュールのインストールする
- GoogleDeveloperでプロジェクトを作成する
- 認証情報を作成する
- APIサービスを有効化する
- 動画ファイル保存用のフォルダーを作成する
- settings.yamlを設定する
- プログラムからアクセスする
必要なモジュールのインストール
RaspberryPiからGoogleDriveにアクセスする為に必要なモジュールをインストールする。
LXTerminalからgoogle-api-python-clientを以下のコマンドでインストールする。
sudo pip3 install google-api-python-client
次にpydriveをインストールする。
pydriveは先程インストールしたgoogle-api-python-clientのラッパー(使いやすようにしたライブラリー)
sudo pip3 install pydrive
GoogleDeveloperでプロジェクトを作成する
Google Developers Consoleにアクセスする。
初めてアクセスした時には利用規約への同意を求められるので利用規約にチェックして”同意して続行”をクリックする。
プロジェクトの作成を行う。
”作成”をクリックする。
プロジェクト名欄に”SecurityCameraProject”を指定して「作成」ボタンをクリックする。
個人IDだったので場所は”組織なし”のまま変更していない。
プロジェクトが作成されたのでダッシュボードをクリックする。
ダッシュボードが表示される。
プルダウンで先ほど作成したプロジェクトが選択されている。
複数のプロジェクトを作成した場合はこちらのプルダウンでプロジェクトを切り替える。
認証情報を作成する
左上のメニューのAPIとサービスー>認証情報を選択する。
尚、OAuthの仕様はこちらを参考にした。
認証情報を作成ー>OAuthクライアントIDを選択する。
サービスアカウントキーは公開鍵と秘密鍵のペアを作成して認証する方法。
その時の記事はこちらを参照。
右側の「同意画面を設定」をクリックする。
アプリケーション名に”sk-SecurityCamera”を設定して下にスクロールする。
「保存」ボタンをクリックする。
尚、「スコープを追加」ボタンでスコープを設定できる模様。
しかし後述のsettings.yamlにてスコープを指定するのでここでは指定していない。
先程の画面に戻るので
- アプリケーションの種類:その他
- 名前:監視カメラ
を入力して「作成」ボタンをクリックする。
OAuthクライアントが作成されてクライアント IDとクライアント シークレットが表示される。
後からJSON形式でダウンロードできるのでここではコピーを取らなくても大丈夫。
”OK”をクリックする。
右のダウンロードボタンからJSONファイルのダウンロードを行い
- ファイル名:client_secret.json
でプログラムディレクトリの配下にcertディレクトリを作成して保存した。
このファイルは後述するsettings.yamlで使用する。
認証情報の作成は以上で終了。
APIサービスを有効化する
GoogleDriveに関するAPIサービスを有効化する。
ダッシュボードに戻って”APIとサービスを有効化”をクリックする。
一覧からGoogleDriveAPIを選択する。
Google Drive APIの「有効にする」ボタンをクリックする。
有効化された。
Google Drive APIの有効化は以上で終了。
動画ファイル保存用のフォルダーを作成する
録画ファイルを保存するフォルダーをマイドライブ内に作成する。
Google Driveのマイドライブにて新規ー>ドライブにてドライブ名:SecurityCameraDriveで作成する。
URLの最後の部分がフォルダーIDなので保存しておく。(プログラム内でアクセスする際に使用する)
settings.yamlを設定する
settings.yamlファイルを作成してプログラムと同一フォルダーに文字コードUTF-8で保存する。
尚、settings.yamlの仕様はこちらのページを参考にした。
client_config_backend: file
client_config_file: cert/client_secret.json
save_credentials: True
save_credentials_backend: file
save_credentials_file: cert/credentials.json
get_refresh_token: True
oauth_scope:
- https://www.googleapis.com/auth/drive.file
1行目のclient_config_backend: fileはクライアントの設定を”ファイルから読み込む”の指定。
2行目の”cert/client_secret.json”で読み込むファイル名を指定している。
前述のOAuthクライアントIDの作成でダウンロードしたJSON形式のファイルを指定している。
尚、fileを指定せずにclient_config_backend: settingsとしてsettings.yaml内にクライアントID、クライアントシークレットを直接指定する事も可能だがセキュリティ上、IDやキー関係は./cert/配下のファイルに集めてアクセス権限をしぼる事にした。
client_config_backend: settings
client_config:
client_id: xxxxxxx.apps.googleusercontent.com
client_secret: xxxxxxxx
4~6行目で認証情報の保存について指定している。
初回に認証した時の情報を保存しておき2回目から許可画面を表示をさせない。
- save_credentials: True:認証情報を保存する
- save_credentials_backend: file:ファイルに保存する
- save_credentials_file: cert/credentials.json:保存先のファイル名の指定
11行目でスコープ(アクセス可能な範囲)を指定している。
”https://www.googleapis.com/auth/drive.file”
はアプリケーションで作成したファイルに対してのみアクセス可能の指定。
スコープはセキュリティ上は最小限にしておくのが望ましい。
例えば、
”https://www.googleapis.com/auth/drive”
の指定をしてもプログラムは正常に動作する。
しかし対象ドライブに対してフルパーミッション指定になってしまうのでセキュリティ上はあまりよろしくない。
スコープについてはこちらのページを参考にした。
プログラムからアクセスする
監視カメラのプログラムの前に下記の簡易プログラムを作成してGoogleDriveにアクセスをしてみた。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import json
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
INITIAL_FILE= "./cert/initial.json" # 初期設定ファイル
try:
if __name__ == '__main__':
os.chdir(os.path.dirname(os.path.abspath(__file__))) # カレントディレクトリをプログラムのあるディレクトリに移動する
with open(INITIAL_FILE) as f: # 初期設定ファイルの読み込み
jsn = json.load(f)
folder_id = jsn["folder_id"] # folder_idの読み込み
gauth = GoogleAuth() # GoogleDrive認証
gauth.LocalWebserverAuth()
drive = GoogleDrive(gauth)
f = drive.CreateFile({'title': 'video/video.h264',
'mimeType': 'video/H264',
'parents': [{'kind': 'drive#fileLink', 'id':folder_id}]})
f.SetContentFile('video/video.h264')
f.Upload() # up-load
except KeyboardInterrupt:
pass
初期設定ファイルはJSON形式で”./cert/initial.json”に作成した。
{
"folder_id": "xxxxxxxxxxxxxxxxxx",
"line_token":"yyyyyyyyyyyyyyyyy",
"location":"MyHome-West"
}
folder_idには前述の動画ファイル保存用のフォルダーIDを指定する。
line_tokenは後述のLINE Notifyから取得したトークンを指定する。
locationはカメラの設置場所を表しているが今回は未使用、次回以降の記事で説明する。
なお、settings.yamlは前述のファイルをプログラムと同一ディレクトリに保存している。
初回の認証
上記のプログラムを実行すると初回のみ認証画面が表示される。
※認証情報はsettings.yamlの設定に基づき”./cert/credentials.json”に保存される。
ログイン画面が表示されるのでログインする。
”許可”クリックする。
”許可”をクリックする。
上記の認証情報が”./cert/credentials.json”に保存されて2回目からはこのファイルが読み込まれるので上記の画面が表示されない。
ファイルのアクセス権
尚、”initial.json”と”client_secret.json”はセキュリティ上重要な項目が幾つか設定されているのでアクセス権を最小限にしておきたい。
一通り設定が終わったら以下のコマンドで所有者のRead(読み込み)権限のみに設定変更する。
sudo chmod 400 client_secret.json
sudo chmod 400 initial.json
sudo chmod 600 credentials.json
Google Driveへのファイルの書き込みに関する設定は以上で終了。
LINEとの連携
次にLINEにメッセージを送るためにLINE Notifyでアクセストークンを取得する。
LINE Notifyに接続して”ログイン”をクリックする。
メールアドレスとパスワードでログインする。
右上のアカウント名のプルダウンから”マイページ”を選択する。
下にスクロールして「トークンを発行する」ボタンをクリックする。
- トークン名:自宅監視カメラ
- 1:1でLINE Notifyから通知を受け取るを選択
「発行する」ボタンをクリックする。
発行されたトークンは前述の“./cert/initial.json”のline_tokenセクションに貼り付ける。
連携中サービスとして表示される。
以上でGoogleDriveとLINEへの事前設定は終了。
次回以降の記事でPythonのプログラムの説明をしていく。
次回の記事はこちら。
動画
この記事の内容を動画で説明しているので参考にして欲しい。
貴殿のサイトを参考に、RaspberryPi4にて自宅監視カメラを
構築しようとしております。
カメラの撮影試験等は完了して、GoogleConsoleでの諸設定も
済んでおります。
次に貴殿のサンプルPythonプログラムを自分用にアレンジして
起動させますが、以下のエラーでつまずいていまして、また、
Python自体も詳しくなくて、これからという感じです。
何かヒント等があれば助かります。
よろしくお願いいたします。
エラー内容)
~/bin $ python googledrive.py
Traceback (most recent call last):
File “/usr/local/lib/python3.7/dist-packages/pydrive/auth.py”, line 386, in LoadClientConfigFile
client_type, client_info = clientsecrets.loadfile(client_config_file)
File “/usr/local/lib/python3.7/dist-packages/oauth2client/clientsecrets.py”, line 165, in loadfile
return _loadfile(filename)
File “/usr/local/lib/python3.7/dist-packages/oauth2client/clientsecrets.py”, line 126, in _loadfile
return _validate_clientsecrets(obj)
File “/usr/local/lib/python3.7/dist-packages/oauth2client/clientsecrets.py”, line 101, in _validate_clientsecrets
prop_name, client_type))
oauth2client.clientsecrets.InvalidClientSecretsError: Missing property “redirect_uris” in a client type of “web”.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “googledrive.py”, line 19, in
gauth.LocalWebserverAuth()
File “/usr/local/lib/python3.7/dist-packages/pydrive/auth.py”, line 113, in _decorated
self.GetFlow()
File “/usr/local/lib/python3.7/dist-packages/pydrive/auth.py”, line 443, in GetFlow
self.LoadClientConfig()
File “/usr/local/lib/python3.7/dist-packages/pydrive/auth.py”, line 366, in LoadClientConfig
self.LoadClientConfigFile()
File “/usr/local/lib/python3.7/dist-packages/pydrive/auth.py”, line 388, in LoadClientConfigFile
raise InvalidConfigError(‘Invalid client secrets file %s’ % error)
pydrive.settings.InvalidConfigError: Invalid client secrets file Missing property “redirect_uris” in a client type of “web”.
すみません、時間掛けて調査しまして自己解決できました。
sanさん
コメントありがとうございます。
Google Driveの認証でエラーになっているようですね。
無事に解決できて何よりです。
エラーの解決でどうしても分からない時はプログラムを最小単位にして少しずつ正しく動くかどうかを検証していくと早道だったりしますよ😁