マイコン温度通知システムの製作6 データベース情報の表示2

前回からの続きです。

firestoreの操作がどうしてもできないのでチュートリアルを学ぶことにしました。

firebaseのメニューからドキュメント>サンプルを選択し、FriendlyEatsというサンプルを選択します。

チュートリアルを実践します。

別アプローチ

しかしチュートリアルを実践してもそのファイルが複雑で、求めていた部分(Firestoreのデータベースから情報を取得して表示)がわからなかったので別のアプローチをとることにしました。

ネット上で似たようなことをしている人を探しましたが、上手くマッチしませんでした。

そこで、半端だったJavascriptを学習し、わかっている部分を修正しました。

そうしたところ、ようやくローカルで動いてfirestoreのデータベースの値が表示できました。

・動いたコード

// Firebase SDKをインポート
const firebase = require('firebase/compat/app');
require('firebase/compat/firestore');

// Firebaseプロジェクトの設定
const firebaseConfig = {
apiKey: "xxx",
authDomain: "xxx.firebaseapp.com",
projectId: "xxx",
storageBucket: "xxx.appspot.com",
messagingSenderId: "xxx",
appId: "xxx",
};

// Firebaseを初期化
firebase.initializeApp(firebaseConfig);

// Firestoreを初期化
const db = firebase.firestore();

// コレクションからデータを取得して表示
const temperatureDataRef = db.collection('xxx');
temperatureDataRef.get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
const data = doc.data();
console.log(`MAC Address: ${data.macAddress}, Temperature: ${data.temperature}, timestamp: ${data.timestamp}`);
});
});

・実行結果

[Running] node "/Users/firebase/public/app.js"
MAC Address: 08d1f9e822ec, Temperature: 29.5, timestamp: Timestamp(seconds=1701245474, nanoseconds=113000000)
MAC Address: 08d1f9e822ec, Temperature: 29.5, timestamp: Timestamp(seconds=1701245738, nanoseconds=502000000)
MAC Address: 08d1f9e822ec, Temperature: 29.5, timestamp: Timestamp(seconds=1701275510, nanoseconds=78000000)
MAC Address: 08d1f9e822ec, Temperature: 29.5, timestamp: Timestamp(seconds=1701268643, nanoseconds=32000000)
MAC Address: 08d1f9e822ec, Temperature: 29.5, timestamp: Timestamp(seconds=1701276498, nanoseconds=252000000)

ここから日付の表示形式やhtmlにデータを渡す修正などをしていきます。

Firebaseにデプロイしても動かない

Node.jsはバックエンド、フロントエンドはJavascriptと違うため、上記のコードをデプロイしてもブラウザでは表示を確認できませんでした(上記はNode.js)。

つまり以下のようにズレていたのです。

  • 書いていたコード:Node.js
  • Code Runnerのデバッガ:Node.js
  • Visual Studio Codeのデバッガ:Node.js
  • hostingにデプロイすべきコード:フロントエンドJavascript

そのため、コードをフロントエンド用のjavascriptに書き直します。

フロントエンドJavascriptのデバッグ

Chromeの表示>開発/管理>デベロッパーツールからデバッグができます。

アクセス拒否エラー

Node.jsの記述ではデータベースからデータを読み込めていましたが、フロントエンドJavascriptにしてから以下のエラーがブラウザで出ていました。

Uncaught (in promise) FirebaseError: Missing or insufficient permissions. at serializer.ts:153:10 at Eu.onMessage (persistent_stream.ts:581:25) at persistent_stream.ts:461:21 at persistent_stream.ts:514:18 at async_queue_impl.ts:135:7 at async_queue_impl.ts:186:14

Firestoreの設定でセキュリティのルールを変更した覚えはなかったのですが、確認するとfalseになっていたのでtrueに修正しました。

なぜこうなったかというと、ローカルのルートディレクトリのfirestore.rulesが以下のようになっていたからです。

・firestore.rules

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

このファイルの記述がfalseだったので、firebase deploy コマンドで全部をデプロイしたとき、ルールも一緒にfalseに更新されていました。

ようやくデータベースの値が表示できた

上記のルール設定を変更し、デプロイしたところようやくデータベースの値をブラウザで表示できました。

以下はそのコードです。

・index.html

<!DOCTYPE html>
<html>
<head>
<title>Temperature Data</title>
<!-- Firebaseの設定 -->
<script src="https://www.gstatic.com/firebasejs/9.0.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/9.0.0/firebase-firestore-compat.js"></script>
</head>
<body>
<h1>Temperature Data</h1>
<div id="display"></div>
<script src="script.js"></script>
</body>
</html>

・script.js


// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "xxx",
  authDomain: "xxx.firebaseapp.com",
  projectId: "xxx",
  storageBucket: "xxx.appspot.com",
  messagingSenderId: "xxx",
  appId: "xxx",
};

// Firestoreのタイムスタンプを指定タイムゾーンの時刻にフォーマットする関数
function formatTimestampInTimeZone(timestamp, timeZone) {
  const date = new Date(timestamp.seconds * 1000);  // FirestoreのTimestampをDateオブジェクトに変換
  const formatter = new Intl.DateTimeFormat('ja-JP', {
    timeZone: timeZone,
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  });
  return formatter.format(date);
}

// Firebase、Firestoreを初期化
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();

// temperatureDataコレクションからデータを取得して表示
const temperatureDataRef = db.collection('temperatureData');
temperatureDataRef.get().then((querySnapshot) => {
  querySnapshot.forEach((doc) => {
      const data = doc.data();
      const formattedTimestamp = formatTimestampInTimeZone(data.timestamp, "Asia/Tokyo");
      document.getElementById('display').textContent = data.macAddress;
  });
});

今後は、すべてのデータを表示、グラフで描画することをやっていきます。

タイトルとURLをコピーしました