Raspberry PiでFirebaseのFirestoreを介して外部と通信するために、最初はNode.jsのライブラリでやろうとがんばってたけど、1日やっても下記エラーが出てダメそうなので、LED部分と同じくPythonでやる。
Node.jsでのエラー
Node.jsはaptで入れて、nでv10を入れたもの、公式からLinux Binaries (ARM) ARMv6を入れて動かしたけど同じだった。認証部分でコケてしまうがまったく同一のファイルでPixelbookのDebian上で動いた。
(node:873) UnhandledPromiseRejectionWarning: FetchError: request to https://www.googleapis.com/oauth2/v4/token failed, reason: connect ENETUNREACH 172.217.161.42:443 - Local (0.0.0.0:0) at ClientRequest.<anonymous> (/home/pi/led8/node_modules/node-fetch/lib/index.js:1455:11) at ClientRequest.emit (events.js:198:13) at TLSSocket.socketErrorListener (_http_client.js:392:9) at TLSSocket.emit (events.js:198:13) at emitErrorNT (internal/streams/destroy.js:91:8) at emitErrorAndCloseNT (internal/streams/destroy.js:59:3) at process._tickCallback (internal/process/next_tick.js:63:19) (node:873) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:873) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Pythonの準備
pipのインストールは省略。
公式通り入れて
firebase.google.com
サンプルコードを動かす。キーファイルはjsの時と同じものを利用した。
import firebase_admin from firebase_admin import credentials cred = credentials.Certificate("path/to/serviceAccountKey.json") firebase_admin.initialize_app(cred)
PythonでFirestoreにクエリする
今回は特定のコレクションの最新のドキュメントを1件取得し続けたいので下記のようなコードとなった。
import firebase_admin from time import sleep from firebase_admin import credentials from firebase_admin import firestore cred = credentials.Certificate("accountKey.json") firebase_admin.initialize_app(cred) client = firestore.client() # 監視したいコレクション 今回はドキュメントがtimestampを持ってるので並び替えしとく collection_ref = client.collection('path', 'to', 'parent_document')\ .order_by('timestamp', direction='DESCENDING')\ .limit(1) # 更新があったときのコールバック用関数 def update_callback(docs, changes, read_time): print('changes', changes) print('read_time', read_time) for doc in docs: print(doc.id, doc.to_dict()) # 監視の開始、サブプロセスで動く watcher = collection_ref.on_snapshot(update_callback) print(watcher) # メインプロセスはとりあえずWhileしとく。sleep()をかませないとCPU利用率が高くなるので適度につけとく。 while True: sleep(1)
実行して、Firebaseのコンソールでドキュメントを追加したところ、ほぼリアルタイムで反応したのを確認できた
pi@raspberrypi:~/led8 $ python3 firestore.py <google.cloud.firestore_v1.watch.Watch object at 0xb5fe5610> changes [<google.cloud.firestore_v1.watch.DocumentChange object at 0xb5674350>] read_time 2019-07-01 02:40:33+00:00 aXPGdePvZFzc5nA6S4RE {'timestamp': DatetimeWithNanoseconds(2019, 7, 2, 15, 0, tzinfo=<UTC>)} changes [<google.cloud.firestore_v1.watch.DocumentChange object at 0xb56742f0>, <google.cloud.firestore_v1.watch.DocumentChange object at 0xb5674350>] read_time 2019-07-01 02:41:05+00:00 yWwK3RmSt49EhZazqICW {'timestamp': DatetimeWithNanoseconds(2019, 7, 3, 15, 0, tzinfo=<UTC>)}