2021年2月9日火曜日

Raspberry Piで温度と湿度を定期的に取得してスプレッドシートに記録する。


前回は、Pythonを用いて温度と湿度の値を取得しました。今回は、定期的にその値を取得して、Google スプレッドシートに保存してみます。ところどころ、がっつりと(笑)突っかかりましたが、先人たちの知恵をお借りしまして、何とかやりたいことができました。



流れとしては、

① スプレッドシートを準備
② Pythonからスプレッドシートへ値を書き込むための初期設定
③ Pythonスクリプトの作成
④ Google Apps Scriptの作成・トリガー設定
⑤ Pythonスクリプトのデーモン化

となります。

Raspberry Piは、Raspberry Pi 4 Model B、4GBメモリ、Raspberry Pi OS。温湿度センサーモジュールは、DHT22 AM2302。Pythonは、3系を使用しています。


① スプレッドシートを準備

まずは、スプレッドシートの準備です。PythonからRaspberry Piで測定した値を受け取るシートと、さらにその値を受け取ってログとして記録するシートの2つが必要になります。

スプレッドシート名は、任意で大丈夫です。シート名も何でもいいですが、後ほど、PythonとGASのコードで使いますので、合わせてください。

・シート名「fromPi」(Pythonからの値受け取り用)


A2、B2セルに、それぞれ測定値が書き込まれます。


・シート名「log」(「fromPi」からの値受け取り用)


「fromPi」シートのA2、B2セルに書き込まれた値がB、C列に書き込まれていきます。その際、A列にタイムスタンプも記録されます。


② Pythonからスプレッドシートへ値を書き込むための初期設定

次に、Pythonからスプレッドシートへ値を書き込むための設定です。こちら↓のブログを参考にさせていただきました。



Pythonスクリプトは、③で作成します。

基本的に、そのまま、まるっとやれば動くかと思いますので、詳細省略。

一点だけ、Pythonスクリプトのデーモン化の際に突っかかったポイントがあったのでメモしておきます。

・「gspread」「oauth2client」ライブラリのインストール

$ pip3 install gspread
$ pip3 install oauth2client

で、インストールされていた先が「/home/pi/.local/lib/python3.7/site-packages」だったのですが、これだとsystemdを使ったデーモン化の際にエラーが発生してしまいます(たぶん)。(追記 2021-6-5systemdのuserモードでデーモン化できます。)

$ sudo pip3 install gspread
$ sudo pip3 install oauth2client

sudoコマンドにて、root権限で再度実行したところ、「/usr/local/lib/python3.7/dist-packages」にインストールされまして、無事に動きました。


③ Pythonスクリプトの作成

Raspberry Piにて測定した温度と湿度の値を、スプレッドシートの「fromPi」シートに書き込むためのPythonスクリプトを作成します。

#!/usr/bin/env python3

import MyPyDHT
import time
import gspread
import json

from oauth2client.service_account import ServiceAccountCredentials

scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']

credentials = ServiceAccountCredentials.from_json_keyfile_name('JSONファイル名(絶対パスで記述)', scope)

gc = gspread.authorize(credentials)

SPREADSHEET_KEY = 'スプレッドシートID'

worksheet = gc.open_by_key(SPREADSHEET_KEY).worksheet('fromPi')

while True:
    x = 0
    while x < 1:
        try:
            humidity, temperature = MyPyDHT.sensor_read(MyPyDHT.Sensor.DHT22, 26)
            x = 1

        except:
            x = 0

    worksheet.update_cell(2,1, temperature)
    worksheet.update_cell(2,2, humidity)
    
    time.sleep(900)

書き換えが必要な箇所は、次の通りです。

・12行目「JSONファイル名(絶対パスで記述)」

②でダウンロードしたJSONファイル名を絶対パスで書きます。(例えば「/home/pi/」から書き始めます。)

python3コマンドでの実行時には、Pythonファイルと同一フォルダに入れておけば、ファイル名のみで動いていたのですが、デーモン化の際にsystemctlコマンドで起動しようとするとエラーが発生してしまいました。ああでもないこうでもないと唸り続け、絶対パスで記述したところ、さらっと動きました(笑)。


・16行目「スプレッドシートID」

スプレッドシートを開いた状態でURLの下記部分に表示されます。ちょっと長めです。

https://docs.google.com/spreadsheets/d/ここの値をコピペ/edit#gid=0


・33行目「900」

測定の間隔です。秒数ですので、900ですと15分おきの測定になります。適宜変更してください。


④ Google Apps Scriptの作成・トリガー設定

スプレッドシートの「fromPi」シートに(Pythonから)書き込まれた値を、ログとして、もう1つの「log」シートに書き込むためのGASを作成します。

var spreadsheet = SpreadsheetApp.openById("スプレッドシートID");
var fpSheet = spreadsheet.getSheetByName("fromPi");
var logSheet = spreadsheet.getSheetByName("log");

function piLog() {
  var lastRow = logSheet.getLastRow() + 1;
  var ts = new Date();
  
  var sec = 10;
  Utilities.sleep(sec * 1000);

  var te = fpSheet.getRange(2, 1).getValue();
  var hu = fpSheet.getRange(2, 2).getValue();
  
  if(te != "" && hu != "") { 
    logSheet.getRange(lastRow, 1).setValue(ts);
    logSheet.getRange(lastRow, 2).setValue(te);
    logSheet.getRange(lastRow, 3).setValue(hu);
    
    fpSheet.getRange(2, 1, 1, 2).clearContent();
  }
}

書き換えが必要な箇所は、次の通りです。

・1行目「スプレッドシートID」

Pythonスクリプトに記述したものと同じです。


次に、定期的にpiLog関数を実行するためにトリガー設定をします。

「トリガーを追加」より、

・「実行する関数を選択」→ piLog
・「デプロイ時に実行」→ Head
・「イベントのソースを選択」→ スプレッドシートから
・「イベントの種類を選択」→ 変更時
・「エラー通知設定」→ 今すぐ通知を受け取る

と、なります。

これで、「fromPi」シートに値が書き込まれるたびにpiLog関数が実行され、「log」シートに記録されていきます。



無事、動きますとこんな風になります。(テストのため、30秒間隔で測定)


⑤ Pythonスクリプトのデーモン化

最後に、Pythonスクリプトのデーモン化を行います。これにより、いちいち手動で起動する必要がなくなり、常駐プログラムとして、Raspberry Piの起動時に一緒に温度と湿度の測定が開始されます。

やり方は、こちら↓の方法を参考にさせていただきました。



概ね、そのままですので、詳細省略。

エラーが発生する場合、まずは「gspread」「oauth2client」ライブラリのインストール先と、JSONファイル名の記述部分を確認してみてください。


***

ということで、とりあえず、動いたので満足です(笑)。

今後、実際の運用時には、より安価なRaspberry Pi Zero W/WHで作りたいですね。あと、ネット回線との接続が切れた際のことも考えて、ローカルでデータベースへの格納もしておいた方が確実かなと思っています。

せっかくバッテリー駆動も可能なので、後ほど、屋外設置のための工作もしてみようと思います。

これが、しっかり運用できますと、けっこういろいろな事ができそうな気がしています。何事も一足飛びとはいきませんが、ひとつひとつ、やっていきましょう。


農園では、ただいま、鋭意植菌中です!


・関連投稿


Twitter(@nkkmd)、Instagram(@nkkmd)も日々更新中です。