MacroDroid から受け取った位置情報データを Cloud Functions for Firebase 経由で Firebase Cloud Firestore に記録するメモ

MacroDroid から受け取った位置情報データを Cloud Functions for Firebase 経由で Firebase Cloud Firestore に記録するメモです。

MacroDroid の標準 GET リクエストアクションで位置情報を送って Cloud Functions for Firebase 経由でデータを記録するメモ では Realtime Database に保存していたので、 Cloud Firestore にも保存してみます。

Cloud Firestore の準備をします

2021/02/19 の情報で進めます。

今回使っていた自分のプロジェクトでは Cloud Firestore 使ってなかったので準備します。すでに準備できている方は不要です。

image

Cloud Firestore でデータベースの作成をクリックします。

image

本番環境モードにします。Firebase 内部でやり取りするので、テストモードにしなくても簡単につながります。

image

ロケーションを設定して、有効にするをクリックします。私の場合は us-central 以外が選択できなかったので、それにしました。

image

Cloud Firestore のデータ画面が表示され作成されました。

コレクションとドキュメントの準備

image

コレクションの開始をクリックします。

image

コレクション ID は macrodroid を設定して次へクリック。

image

最初のドキュメントの追加では、

  • ドキュメントID
    • locations
  • フィールド 緯度
    • 名前 lat
    • タイプ number
    • 値 123
  • フィールド 経度
    • 名前 lon
    • タイプ number
    • 値 456
  • フィールド 作成日時
    • 名前 CreateAt
    • タイプ 文字列
    • 値 CreateAt

と入力して保存します。これで、データを記録するコレクションとドキュメントの準備ができました。

Functions を書き換える

MacroDroid の標準 GET リクエストアクションで位置情報を送って Cloud Functions for Firebase 経由でデータを記録するメモ で使った手元の Functions 環境の index.js を書き換えます。

const functions = require("firebase-functions");

// 
const admin = require("firebase-admin");
admin.initializeApp();

// Firestore を使えるようにする
const db = admin.firestore();

// 今回の処理
exports.macroDroid = functions.https.onRequest(async (request, response) => {
  functions.logger.info("macroDroid logs!", {structuredData: true});

  const locationQuery = request.query.location;
  
  functions.logger.info(`locationQuery ${locationQuery}`, {structuredData: true});

  // カンマ区切りなので分ける
  const locationData = locationQuery.split(",");
  const lat = locationData[0];  // 1つめのデータが緯度
  const lon = locationData[1]; // 2つめのデータが経度
  const d = new Date();
  const dateISO = d.toISOString();  // ISO タイプスタンプ

  const message = `lat ${lat} lon ${lon} dateISO ${dateISO}`;
  functions.logger.info(message, {structuredData: true});
  
  // Realtime Database への書き込み
  /*
  admin.database().ref("/macrodroid").push({
    lat:Number(lat),
    lon:Number(lon),
    CreateAt:dateISO
  }).then(() => {
    response.send(message);
  });
  */

  // Firestore への書き込み
  // macrodroid コレクションにドキュメント ID は自動 ID で加える
  const locationsRef = db.collection('macrodroid').doc();
  await locationsRef.set({
    lat:Number(lat),
    lon:Number(lon),
    CreateAt:dateISO
  });

  // 返答
  response.send(message);
  
});

以下を変更しています。

  • Firestore を使えるようにする const db = admin.firestore(); の記述
  • 今回は await/async を使ってみたかったのでonRequest を async に
    • functions.https.onRequest(async (request, response) => {
  • Realtime Database への書き込み部分はコメントアウト
    • 変化を分かりやすくしたいだけなので、消しても大丈夫です

そして、Firestore への書き込みの記述です。macrodroid コレクションにドキュメント ID は自動 ID で加えています。

  // Firestore への書き込み
  // macrodroid コレクションにドキュメント ID は自動 ID で加える
  const locationsRef = db.collection('macrodroid').doc();
  await locationsRef.set({
    lat:Number(lat),
    lon:Number(lon),
    CreateAt:dateISO
  });

  // 返答
  response.send(message);

こちらで上書きして書き換えたら、はじめに: 最初の関数の記述、テスト、デプロイ を参考に「本番環境に関数をデプロイする」を参考に、

firebase deploy --only functions

というコマンド打って本番環境に関数をデプロイします。

動かしてみます

まず、ブラウザからテストしてみましょう。

Function の URL に ?location=123,456 をくっつけてアクセスします。仮に https://us-central1-myproject-sample.cloudfunctions.net/macroDroid であれば、 https://us-central1-myproject-sample.cloudfunctions.net/macroDroid?location=123,456 でアクセスします。

image

アクセスができて、

image

Cloud Firestore で見てみると自動IDでどんどん保存されています。

image

つづいて、MacroDroid でのテストです。

MacroDroid の標準 GET リクエストアクションで位置情報を送って Cloud Functions for Firebase 経由でデータを記録するメモ で設定した GET リクエスト先は変わらないので、そのままマクロを試すを実行してみます。

image

Cloud Firestore で見てみると無事に位置情報が保存されています。