こちら、下記3つの記事の組み合わせです。
blog.kimizuka.org
blog.kimizuka.org
blog.kimizuka.org
M5StickC Plus2でGPS座標を取得して、Cloud Firestorに送信します。
準備するもの
- M5StickC Plus2
- GPSユニット
- Arduino
- Firebaseのアカウント(Blazeプランにする必要あり)
Firebase側の実装
❶ パッケージを用意する
yarn add firebase firebase-tools
❷ package.jsonを編集する
package.json
{ "name": "functions-gps", "scripts": { "login": "firebase login", "init": "firebase init", "emulate": "firebase emulators:start", "deploy": "firebase deploy" }, "dependencies": { "firebase": "^10.13.0", "firebase-tools": "^13.15.3" } }
❸ Firebaseのコンソールからプロジェクトをつくり、Cloud Firestore、Cloud Functionsを有効にする
- ルールはテストモードで開始する
- ロケーションは近いところを選ぶ
- ロケーションは近いところを選ぶ
❹ Firebaseプロジェクトを初期化する
ログイン
yarn run login
初期化
yarn run init
初期化後、❸で作成したプロジェクトに紐付けます。
必要なものを有効化
◉ Firestore: Configure security rules and indexes files for Firestore ◉ Functions: Configure a Cloud Functions directory and its files ◉ Emulators: Set up local emulators for Firebase products
必要なエミュレータを有効化
◉ Functions Emulator ◉ Firestore Emulator
いろいろ選択肢が出てきますが、基本的にEnterを連打でOKです。
❺ コードを書く
firebase.json
{ "firestore": { "rules": "firestore.rules", "indexes": "firestore.indexes.json" }, "functions": [ { "source": "functions", "codebase": "default", "ignore": [ "node_modules", ".git", "firebase-debug.log", "firebase-debug.*.log", "*.local" ] } ], "emulators": { "functions": { "port": 5001 }, "firestore": { "port": 8080 }, "ui": { "enabled": true }, "singleProjectMode": true } }
functions/index.js
const { onRequest } = require('firebase-functions/v2/https'); const { initializeApp } = require('firebase-admin/app'); const { getFirestore } = require('firebase-admin/firestore'); initializeApp(); exports.gps = onRequest({ region: ['asia-northeast1'], }, async (request, response) => { const { doc, lat, long } = request.query; if (target && lat && long) { try { await getFirestore().collection('gps').doc(doc).set({ value: new GeoPoint(Number(lat), Number(long)) }); response.send({ doc, lat, long }); } catch (err) { logger.error(err); } } response.send({ doc: null, lat: 0, long: 0 }); });
❻ エミュレータで確認する
yarn emulate
http://127.0.0.1:4000/logs?q=metadata.emulator.name%3D%22functions%22 にアクセスすると、デプロイしたfunctionのURLが確認できます。
関数名は、http://127.0.0.1:(ポート番号)/(プロジェクト名)/(リージョン)/(関数名)となるので、
- functionsのポートを「5001」
- プロジェクト名が「functions-gps」
- リージョンが「asia-northeast1(東京)」
- 関数名が「gps」
ならば、
http://127.0.0.1:5001/functions-gps/asia-northeast1/gps
となります。
クエリパラメータで、doc、lat、lngを指定できるようにしてあるので、
http://127.0.0.1:5001/functions-gps/asia-northeast1/gps?doc=doc&lat=35.6895014&long=139.6917337
にアクセスすると、
{"doc":"doc","lat":"35.6895014","long":"139.6917337"}
というJSONを返しつつ、
Cloud Firestoreに緯度経度が保存されます。
❼ デプロイする
yarn deploy
M5StickC Plus2側の実装
Arduinoを使って、下記コードをM5StickC Plus2に書き込みます。
#include <M5StickCPlus2.h> #include <WiFi.h> #include <HTTPClient.h> #include <Arduino_JSON.h> #include <TinyGPS++.h> const char* ssid = ""; // WiFiのssid const char* password = ""; // WiFiのパスワード String gpsBaseUrl = ""; // Cloud FunctionのURL String doc = ""; // Cloud Firestoreのdocument HardwareSerial GPSRaw(2); TinyGPSPlus gps; void setup() { M5.begin(); M5.Lcd.setRotation(1); M5.Lcd.fillScreen(BLACK); M5.Lcd.setTextSize(2); GPSRaw.begin(9600, SERIAL_8N1, 33, 32); M5.Lcd.print("SSID:"); M5.Lcd.println(ssid); WiFi.begin(ssid, password); M5.Lcd.print("Connecting"); while (WiFi.status() != WL_CONNECTED) { delay(1 * 1000); M5.Lcd.print("."); } M5.Lcd.println(""); M5.Lcd.print("IP:"); M5.Lcd.println(WiFi.localIP()); } void loop() { double lat = 0; double lng = 0; M5.Lcd.setCursor(0, 0); M5.Lcd.fillScreen(BLACK); while (GPSRaw.available() > 0) { if (gps.encode(GPSRaw.read())) { break; } } if (gps.location.isValid()) { lat = gps.location.lat(); lng = gps.location.lng(); M5.Lcd.printf("lat:%.6f\n", lat); M5.Lcd.printf("lng:%.6f\n", lng); HTTPClient http; String gpsUrl = gpsBaseUrl + "?doc=" + doc + "&lat=" + String(lat, 6) + "&long=" + String(lng, 6); http.begin(gpsUrl); int httpCode = http.GET(); if (httpCode > 0) { if (httpCode == HTTP_CODE_OK) { String payload = http.getString(); JSONVar json = JSON.parse(payload); if (json.hasOwnProperty("target")) { String target = json["target"]; M5.Lcd.println(target); } } } http.end(); } else { M5.Lcd.println("ERROR:GPS"); } delay(60 * 1000); }
書き込み後、M5StickC Plus2とGPSユニットを繋げばOKです。
1分に1度、取得した緯度経度をCloud Firestoreに保存してくれるはずです。