ラズパイで測定した室内環境をwebでみれたら便利だな、と思ってラズパイからFirebaseにpushできるかやってみました。
データベースとしてはRealtime Databaseでも可能ですが、ここではFirestoreを使ってみました。
目的
ラズパイで測定した室内環境をwebで見れるようにしたいtl;dr
・ラズパイで温湿度・気圧を測定・FirebaseのCloud FirestoreにPythonでpush
・Javascriptでhtmlに表示
温湿度・気圧の測定
ラズパイでの温湿度・気圧の測定は過去記事参照です。s51517765.hatenadiary.jp
s51517765.hatenadiary.jp
FirebaseのCloud Firestoreを使う
Firebaseのプロジェクトは作成済みとします。Pythonからpushするので、秘密鍵を作成します。
秘密鍵はPythonスクリプトと同じフォルダに置いておくものとし、ファイル名は
serviceAccountKey.json
とします。コマンドライン(ターミナル)でFirebase Admin SDKというPythonのクライアントライブラリをインストールします。
$pip3 install --upgrade firebase-admin
Windowsでもラズパイ(Raspbian)でもpip3一発ですが、ラズパイの場合は、アップデート・アップグレードをしておくほうがよさそうです。
$sudo apt-get update $sudo apt-get upgrade $pip3 install pip
ちなみにラズパイZeroではfirebase-adminのインストールがどうやってもうまくいきません。ググると解決済みのようですが…(ラズパイ3ではOKでどちらもOSとしては【Raspbian GNU/Linux 9.13 (stretch)】)
** ここで止まる ** Building wheels for collected packages: grpcio Running setup.py bdist_wheel for grpcio ... \
github.com
chinoppy.hatenablog.com
バイナリリンクも無くなってる(泣
Pythonスクリプトはサンプルを参考に↓のように作成しました。
import datetime import firebase_admin from firebase_admin import credentials from firebase_admin import firestore # Use a service account cred = credentials.Certificate('serviceAccountKey.json') firebase_admin.initialize_app(cred) db = firestore.client() def setTemp(Temp=25, Hum=55, Pres=1000): Date = datetime.datetime.now() # キーを日付時刻で作成 ref = db.collection('Database').document(str(Date)) ref.set({ u'Pres': Pres, u'Hum': Hum, u'Temp': Temp, }) maxLength = 20 def resizeDatabase(): ref = db.collection('Database') docs = ref.stream() dataSize = 0 for doc in docs: print(doc.id, doc._data) dataSize += 1 if dataSize == 1: firstDateId = doc.id if dataSize > maxLength: deleteDoc(firstDateId) def deleteDoc(id): db.collection('Database').document(id).delete() if __name__ == '__main__': setTemp() resizeDatabase()
firebase.google.com
firebase.google.com
setTemp()
では実際にはセンサーから取得した環境値を受け取ります(ここでは省略)。resizeDatabase()
はデータが増えすぎても仕方がないので、一定数を超えたら古いものを削除するようにしました。
コレクション名は”Database”とし、日付時刻をid(key)にデータを作成します。
コンソールからデータの削除はドキュメントを選択し、メニューを開くことでも可能です。
JavascriptでFirestoreのデータを呼び出す
このようにして格納したFirestoreのデータをwebページに表示します。初期化はRealtime Databaseのときと同様で、インスタンスを
var db = firebase.firestore();
のように呼び出します。データを取得するところもサンプルコードを参考にですが、データidは
doc.id
ですが、dataはdoc.data().Temp
のように取得します。このあたりがちょっとマニュアル見てもよくわからず試行錯誤しました。インスタンスの生成や初期化のところもだいぶ違うように思うのですが…。
<!DOCTYPE html> <html> <head> <title>室温推移</title> <meta http-equiv="content-type" charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"><!-- スマホ用の表示拡大 --> <meta name="robots" content="noindex" /> <link rel="stylesheet" type="text/css" href="css.css"> <!-- The core Firebase JS SDK is always required and must be listed first --> <script src="https://www.gstatic.com/firebasejs/5.8.6/firebase.js"></script> <script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-firestore.js"></script> <script> // Your web app's Firebase configuration var firebaseConfig = { apiKey: "******", authDomain: "*****.firebaseapp.com", databaseURL: "https://*****.firebaseio.com", projectId: "*****", storageBucket: "*****.appspot.com", messagingSenderId: "****", appId: "*****" }; // Initialize Firebase firebase.initializeApp(firebaseConfig); var db = firebase.firestore(); function ListLoad() { var List1 = document.getElementById("List1"); //データを取得 db.collection("Database").get().then((querySnapshot) => { querySnapshot.forEach((doc) => { console.log(`${doc.id} : ${doc.data().Temp} ℃, ${doc.data().Hum} %RH, ${doc.data().Pres} hPa`); var element = document.createElement("li"); element.innerHTML = doc.id + " : " + doc.data().Temp + "℃, " + doc.data().Hum + "%RH, " + doc.data().Pres + "hPa"; List1.append(element); }); }); } window.onload = function () { ListLoad(); }; </script> </head> <body> <h1>室温推移</h1> <form id="form1"> <ul id="List1"></ul> </form> </body> </html>
完成
あとは、グラフを表示するようにしたい。ラズパイゼロでもなんとか動くようにしたい。