見出し画像

【GASでIoT】GASとラズパイでおこなう、お手軽データ・ロギング&フィードバック制御〔解説編3〕~ラズパイ側での、温度センサ DS18B20の読み取りとGASへの送受信~

この記事のシリーズでは、Googole Apps Script(GAS)を利用して、日常生活を便利にする事をテーマにしています。

GASへのアクセスは、通常はキーボードから文字情報で行いますが、「Raspberry Pi(ラズベリーパイ)」というシングルボードコンピュータを介することで、文字以外の情報をインプットする事ができます。

今回インプットする情報は「温度」で、この情報を利用して電気なべの温度をコントロールしよう、というのがテーマです。

先回までで、ラズベリーパイにという、セットアップが大変楽な1-wire仕様の温度センサ DS18B20を 接続するまでを解説しました。


今回の記事は、温度センサで読み取った値をGASに送信する方法についての紹介です。


HTTPSを介した、シングルボードコンピュータとGASとの通信について


今回のシステムでは、ラズベリーパイを「クライアント」と見立てて、サーバーに見立てた「GAS」との通信によって電気なべを制御します。

以前の記事でご紹介したシステム全体図を再掲しましょう。

この様な事例ではラズベリーパイをサーバー側として、ラズベリーパイにアクセスして制御している事が多いのです。

しかし、この様にラズベリーパイをサーバー側ではなくクライアント側とすると、ラズベリーパイへの不正なアクセスを避けたり、運転途中で制御を変えるといった柔軟な運用ができます。

URLを介したGASへのアクセス

このシステムでは、ラズベリーパイがGASへアクセスする事でデータの受け渡しが始まります。

Google Apps Script は、「デプロイ」とよばれる手続きをすることで、HTTPSではじまるURLと紐づける事ができ、このURLにアクセスすることでGASを起動する事ができますので、この仕組みを利用してアクセスします。

「デプロイ」など、基本的なGASアプリの作り方については、以下の記事から始まる記事でご紹介しています。

記事がブログでは細切れなので、拙文ながら冊子の形に資料化したものも作ってみました。(読みやすい様に縦書きにしてみました)

以下の記事でご紹介しています。ご興味を持たれましたらどうぞ・・・

ラズベリーパイからGASへの情報引き渡し

アクセスした際に最初におこなう事は、ラズベリーパイ側からGASへデータ情報を引き渡す事です。

この時、「マクロコード」と呼ばれる付加情報をURLに付け加えてアクセスする事で、アクセス先に情報を引き渡せます。

マクロコードは以下のルールで使用します。

・「?」をURLの後ろに付け加えて始める
・「変数名=値」のテキストを追加する
・「&」でつなぐ事で、2つ以上の変数とデータを引き渡し可能

図解?するとこんな感じです。

このマクロコードを利用することで、文字ベースの情報であれば簡単に情報を引き渡す事が可能です。


GASからラズベリーパイへのレスポンス受け取り

今回のシステムでは、電気なべの制御は、GASからの指示で行います。

そのため、ラズベリーパイは、温度データをGASへ引き渡したあと、GASで判断した制御情報を、GASからのレスポンスとして受け取る必要があります。

「レスポンス」というと、一般的には下図の様に、HTML文書の形で返される場合が多いのですが・・・

・・・今回は、単なるテキストデータをレスポンスします。

GASのプログラムでテキストのレスポンスは簡単にできます。


コードの詳細は引き続きご説明しますが、以上の方法で、ラズベリーパイからGASへの通信および情報のやりとりをします。

HTTPS通信~OSを搭載しているタイプのシングルボード・コンピュータでないとGASとの通信はむずかしい~

ここで、少し脇道にそれますが、GASへアクセスする時のURLで用いられる、HTTPS通信について触れておきます。

日常生活を少し便利にするためのGASですが、このGASを活かすために使うラズベリーパイという製品は、少し高いですね?

同じシングルボード・コンピュータであればもっと安いものがあるのに、どうしてラズベリーパイに固執するのだろう・・・とお思いの方も居るかもしれません。

その理由は、ラズベリーパイの様な、OSを搭載したタイプのシングルボード・コンピュータでないと、HTTPSをURLにもった相手とは通信が難しいからなのです。

WEBアドレスの元祖・・HTTP通信

WEB上の通信は、もともとは HTTP~ではじまる、末尾に「S」がないURLで行われていました。

このタイプのURLであれば、OSを搭載しないタイプのシングルボード・コンピュータである、Arduiono(アールデュイーノ)※や、

※有線LANのみ

その互換機でWiFiモジュールを搭載したESP32が使えます。



これらは非常に安価で、店舗によっては1000円以下で調達できます。

しかし、残念ながら、GASが用いているHTTPS通信がこれらの製品では難しいのです。

できない事はないのですが、SSL認証の中身をプログラム内に記載する必要があります。SSL認証の中身を取得するのも、プログラムに盛り込むのも、なかなか骨が折れます。 色々トライしたのですが、リクエストは何とかなったもレスポンスを得ることが難しく、諦めた次第です。

セキュリティ対策したHTTPS通信

HTTPではじまるURLで普及したWEB通信ですが、普及するにつて、アクセス先が虚偽のサーバであったり、通信内容が盗み見られるという、セキュリティ上の問題が出てきました。

そこで、「SSL認証」という、通信のセキュリティを境界した仕組みができました。この仕組みを使用している通信はHTTPSで始まるURLとなり、GASものこのタイプのURLを利用しています。

この通信は、不正確なのを承知でご説明すると以下の様なものです。

①クライアントがサーバにアクセスします。

②すると、レスポンスが送られる前に、まず暗号化のための鍵が返されます。

③戻った鍵を再び返して、鍵をクライアントとサーバで共有します。

④ここまで済んだら、ようやく通信が始まります。情報は互いに暗号化の鍵を掛けて(金庫に入れて流すイメージ)、受け取った側は同じ鍵で金庫を開けて中身を取り出します。

以上の手続きをOSの無いESP32の様なシングルボード・コンピュータで実装するのは(できない事はないのでしょうが)非常に難しく、鍵を扱う部分でかなりのプログラムが必要になるはずで、アマチュアの域を超える内容かと思います。

ラズベリーパイであれば、OSが処理してくれるので、ユーザはこの部分で何もする必要がありません。

ラズベリーパイを使うのは、こうした理由からです。

温度センサの値を読み出して、GASに投じるプログラム~Raspberry Pi(ラズベリーパイ)側~

それでは、温度センサの値を読み出してGASに投じるまでのラズベリーパイ側のプログラムをご紹介します。

1-wire仕様のセンサの値の読み出しは、以下ブログなどを参考にしました。この場を借りて御礼申し上げます。

ライブラリのインポート

まずはいくつかのライブラリをインポートします。ライブラリは基本的には標準で備わっており、外部からファイルはダウンロードしないで済むはずで、プログラム中で宣言するだけです。

#---時間を利用するためのライブラリ
import time

#---WEBにリクエストを投じるためのライブラリ
import requests
import sys

#---GPIOを利用するためのライブラリ
import RPi.GPIO as GPIO

#---1Wireを利用するためのライブラリ
import os
import glob
from time import sleep

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

GPIOの準備

外部のリレー(SSR)へ、ON/OFFの信号を送るため、GPIOのピンを使うので、GPIOを宣言します。

1-wireで既に、4番ピンなどは予約ずみなので、バッティングしない様、なるべく後ろの番号である26番ピンを今回は使う事にしました。

#---GPIOの準備

GPIO.setmode(GPIO.BCM)
 #GPIO2を出力モードに設定 
GPIO.setup(26, GPIO.OUT)

実物では、SDカードを上にした状態で以下の囲みの位置のピンです。

1-wireを設定し、同時にGPIOを設定することは、あまり推奨されていない様で、実行させるとワーニングが出ます。(そのまま実行されますが)


読み出すファイルの設定

1-wireでは、所定のフォルダが自動生成されて、ここにデータが書き込まれますが、そのファイルを設定します。

#--読み出すファイルの設定

#---1WireのDS18B20温度センサの記録フォルダ
base_dir = '/sys/bus/w1/devices/'

#---28で始まるフォルダ
device_folder = glob.glob(base_dir + '28*')[0]

#---記録ファイル
device_file = device_folder + '/w1_slave'

これは、要するに以下のW1_slaveというファイルを設定しているのです。

対象ファイルから温度データを抽出する関数

読み出すファイルを設定したら、このファイルから1行ずつ読み込んで、温度を記載しているテキストを抽出する関数を作成します。

以下では、read_temp_raw( ) という関数で1行単位で読み込みます。

次いで、read_temp( ) とう関数で、「t=」を含む行において、「t=」以降の文字列を抽出しています。

# 温度ファイルのデータを取得する関数
def read_temp_raw():
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines

# 温度データのみを取り出して返す関数
def read_temp():
    lines = read_temp_raw()

    # 温度データ行のみを取り出して返す関数
    # 最後の3行文字がYESでない行を取得
    while lines[0].strip()[-3:] != 'YES':
        sleep(0.2)
        lines = read_temp_raw()

    #「t=」の文字位置を取得 
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        #「t=」以降の文字を取得 
        temp_string = lines[1][equals_pos + 2:]
        # 取得した文字を1000で割ると温度となる
        temp_c = float(temp_string) / 1000.0
        return temp_c

これは、ファイルを開いて 以下の「t= 」の部分を温度として抽出して、これを1000で割っている訳です。

15秒置きに繰り返し温度を取得

ここまで出来たら、ループを使って、15秒毎に処理を繰り返しで行う記述をします。

try:
    while True:
        #---温度
        thrm = read_temp()
        print(thrm)

        #---URLにアクセス
        print('Accesing to GAS...')
        r = requests.get("https://script.google.com/macros/s/★デプロイID★/exec?thrm=" + str(thrm))

・・中略・・・

        #---15秒待つ
        sleep(15)

except KeyboardInterrupt:
    pass

重要部分は以下の1行です。

r = requests.get("https://script.google.com/macros/s/★デプロイID★/exec?thrm=" + str(thrm))

上記の1行で、GASにマクロコード付きでアクセスし、同時にレスポンスをという変数に格納しています。

マクロコードは ?thrm=" + str(thrm) の部分です

さきほどから触れている、HTTPSへのアクセスとレスポンス取得が、以下のたった一文で記述されている点にご注目!。

レスポンス= requests.get(URL)

GASのレスポンスに従って、GPIOピンをHigh/Lowする

GASから取得したレスポンスは、以下の一文でテキストとして取り出せます。

r.text

これを使って、GPIOを操作します。

プトグラムは以下です。


        #---レスポンスをコンソールに表示
        print(r.text)

        #---レスポンスに応じたGPIOピンのH/L
        #---rが「On」なら赤いピンをHighにする
        if(r.text == 'On'):
            GPIO.output(26, GPIO.HIGH)     #----GPIO2の出力をHigh(3.3V)にする
        else:
            GPIO.output(26, GPIO.LOW)     #----GPIO2の出力をLow(0V)にする


        #---15秒待つ
        sleep(15)

except KeyboardInterrupt:
    pass

長くなりましたので、ここで一旦切ります。

GAS側のプログラムは、次回の記事でご説明します。


この記事が気に入ったらサポートをしてみませんか?