M5StackとFirebaseを連携してスマートロックみたいなものを作る！①

# できあがるもの
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/46195acf-d6dc-7048-c245-9070d239515d.gif)

# はじめに
アドベントカレンダーも残るところ10日を切りました！
この連作ではM5StackとFeliCaリーダー・ライターRC-S620S、Firebaseを駆使して遠隔からもアンロック可能なスマートロックのベースとなる機構を作っていこうと思います。
本記事ではM5StackとFirebaseのリアルタイムDBを連携させる方法について書いていこうと思います。
この2つを連携させることができれば、IoTデバイスとWebの連携なんかができるので自宅をスマートホーム化も夢ではありません！

[M5StackとFirebaseを連携してスマートロックみたいなものを作る！①](https://qiita.com/bigface00/items/87346c31d12346f85716)
[M5StackとFirebaseを連携してスマートロックみたいなものを作る！②](https://qiita.com/bigface00/items/29511d3a4425da5a499c)
[M5StackとFirebaseを連携してスマートロックみたいなものを作る！③](https://qiita.com/bigface00/items/e92f3a12ed0162c17d84)
[M5StackとFirebaseを連携してスマートロックみたいなものを作る！④](https://qiita.com/bigface00/items/d59ba7ccffce99ce259a)
[M5StackとFirebaseを連携してスマートロックみたいなものを作る！⑤](https://qiita.com/bigface00/items/590834705146e65f4826)

# 必要なもの・開発環境
- M5Stack（ESP32 Dev Module）
- Googleアカウント
- WiFi環境

M5Stackの方がスイッチとか内蔵されているので楽ですが、ESP32でも作製は可能です。
ESP32で作製していく場合に今作と同じ動作をさせるには、スイッチ等の入力できるパーツを用意して頂く必要があります。

開発にはVSCodeと拡張機能であるPlatformIOを使っていきます。

# 必要なライブラリ
- M5Stack.h
- FirebaseESP32.h

PlatformIOでライブラリをインストールする際は、左のリストから「Libraries」を選んで、
![ライブラリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/4e5497be-9468-2179-a9c0-109b9f92b1c7.png)
「Search libraries...」にインストールしたいライブラリ名を入れましょう。
![ライブラリ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/83c421fc-59f3-b28e-98b4-1ff3b7e0732e.png)
以下の2つです。
![m5stack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/88aed848-57fa-230f-31a7-3d602d51eb76.png)
![FirebaseESP32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/b51f5c76-4410-b64f-5f7d-ea47af6caccf.png)

# Firebaseでプロジェクトを作る
[Firebase](https://console.firebase.google.com/u/0/?hl=ja)のコンソールからプロジェクトを作りましょう。
作り方については、以下の記事が詳しいと思うのでそちらにお任せします。
[Firebaseプロジェクト作成方法](https://qiita.com/yoshi0518/items/25af102845ba05545f98)
プロジェクトを作ったら、hostnameと認証パスが必要になるので以下の場所から確認しましょう。
## Hostname
まず、Realtime Databaseへ移動しましょう。
![firebase_menu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/c09d331a-bcc5-6633-19f8-40a17231d452.png)
データベースを作成します。
![firebase_db.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/c3ff8b42-9097-7443-2994-816733f86cb5.png)
今回はテストモードでOKです。
![firebase_db_test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/33488a28-3873-b7bf-b3ad-31c6392d456f.png)
作製できたら、以下の赤丸部分の"https://"と最後の"/"を抜いた部分がhostnameになります。
今回だと"testestst-a7adc-default-rtdb.firebaseio.com"になりますね。
![firebase_host.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/63c85554-5923-751e-a181-4deeb6772de2.png)

## 認証パス
歯車マークから、「プロジェクトと設定」を選択。
![firebase_auth1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/9ebd9a8e-e0ed-b072-e3c6-6ff23cdb0692.png)
サービスアカウントをクリックし、
![firebase_auth2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/89059d97-baa9-5a86-234b-6176acd75937.png)
「Database secrets」をクリックして、シークレットの部分を表示すればパスを取得できます。
![firebase_auth3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271414/d864e14c-631e-fd26-c51c-4fb4266a2737.png)

これでFirebaseのリアルタイムDBの準備は完了です！

# コード全体
```c++:main.cpp
#include <Arduino.h>
#include <FirebaseESP32.h>
#include <M5Stack.h>

#define FIREBASE_HOST "FirebaseプロジェクトのHostnameを入れましょう"
#define FIREBASE_AUTH "Firebaseプロジェクトの認証パスを入れましょう"
#define WIFI_SSID "WiFiのSSID"
#define WIFI_PASSWORD "WiFiのパスワード"

FirebaseData firebaseData;

bool statusA = true;
bool statusB = true;
bool statusC = true;

bool buttonProcess(String buttonName, bool status)
{
  M5.Lcd.fillScreen(BLACK);
    if (Firebase.setBool(firebaseData, "/" + buttonName + "/", status))
    {
      //Success
      M5.Lcd.setCursor(0, 0);
      M5.Lcd.print("Set bool data success");
    }
    else
    {
      M5.Lcd.setCursor(0, 0);
      M5.Lcd.println("Error in setInt, ");
      M5.Lcd.print(firebaseData.errorReason());
    }
    M5.Lcd.setCursor(0, 20);
    M5.Lcd.print(buttonName + " was pressed!");
    return status = !status;
}

void setup()
{
  M5.begin();
  Serial.begin(115200);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  int _cursorX = 0;
  M5.Lcd.setTextFont(4);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setCursor(0, 0);
  // WiFiに接続
  M5.Lcd.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    M5.Lcd.setCursor(0 + 5 * _cursorX, 30);
    M5.Lcd.print(".");
    delay(300);
    _cursorX++;
    if (_cursorX > 320)
    {
      _cursorX = 0;
    }
  }
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.print("Connected with IP:");
  M5.Lcd.print(WiFi.localIP());
  delay(1000);
  // Firebase関連
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  Firebase.reconnectWiFi(true);
}

void loop()
{
  M5.update();
  if (M5.BtnA.wasPressed())
  {
    statusA = buttonProcess("BtnA", statusA);
  }
  if (M5.BtnB.wasPressed())
  {
    statusB = buttonProcess("BtnB", statusB);
  }
  if (M5.BtnC.wasPressed())
  {
    statusC = buttonProcess("BtnC", statusC);
  }
}
```

## WiFiとFirebaseへの接続
```c++:セットアップ関連
void setup()
{
  M5.begin();
  Serial.begin(115200);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  int _cursorX = 0;
  M5.Lcd.setTextFont(4);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setCursor(0, 0);
  // WiFiに接続
  M5.Lcd.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    M5.Lcd.setCursor(0 + 5 * _cursorX, 30);
    M5.Lcd.print(".");
    delay(300);
    _cursorX++;
    if (_cursorX > 320)
    {
      _cursorX = 0;
    }
  }
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.print("Connected with IP:");
  M5.Lcd.print(WiFi.localIP());
  delay(1000);
  // Firebase関連
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  Firebase.reconnectWiFi(true);
}
```
setup()の中でWiFiとFirebaseへの接続を行います。特に複雑なことはする必要がなく、```WiFi.begin()```と```Firebase.begin()```で接続することができます。
```Firebase.reconnectWiFI()```で、もし接続が切れた場合は再接続することができます。
もしESP32で実装する場合は、```M5.Lcd.print()```の部分を```Serial.print```等に変更してください。

## Firebaseへの書き込み
```c++:今日の記事のメインとなる部分
bool buttonProcess(String buttonName, bool status)
{
  M5.Lcd.fillScreen(BLACK);
    if (Firebase.setBool(firebaseData, "/" + buttonName + "/", status))
    {
      //Success
      M5.Lcd.setCursor(0, 0);
      M5.Lcd.print("Set bool data success");
    }
    else
    {
      M5.Lcd.setCursor(0, 0);
      M5.Lcd.println("Error in setInt, ");
      M5.Lcd.print(firebaseData.errorReason());
    }
    M5.Lcd.setCursor(0, 20);
    M5.Lcd.print(buttonName + " was pressed!");
    return status = !status;
}
```
Firebaseへの書き込みは非常に簡単です。今回の場合```Firebase.setBool()```を使うことで、
ボタンが押されたらボタンの状態をtrue/falseのbooleanで変更するというものになっています。
```Firebase.setBool()```には書き込み対象、書き込み先、書き込む内容を引数として渡します。
今回はbooleanを渡しているので```Firebase.setBool()```を使っていますが、例えばセンサ値であればintの```Firebase.setInt()```、Floatの```Firebase.setFloat```、名前などの認証情報の書き込みであればStringの```Firebase.setString()```などset以降の部分を変更することでどの型式でも書き込みが可能です。

次回はFelicaを読み取れるカードリーダーとSuica/Pasmoを使っていきます！