世界中から のあちゃん・えくくん（猫）と遊ぶ

### まえがき
「世界中の人に、のあちゃん・えくくん（猫）と遊んでもらいたい」
そんな思いから、世界中のパソコンやスマホを通して、ペットののあちゃん・えくくんとコミュニケーションがとれるものを作ってみました。
本当は猫じゃらしを振り回してもらいたかったのですが、まずはLEDを点灯させるだけの「光をともす」をやってみたいと思います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487846/1b566eff-ebae-bd6f-acfe-251398c9f505.jpeg" width="300px">
↑ のあちゃんとえくくん　↓のあちゃんに光が灯される図
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487846/f399e3ad-fade-4f48-b2eb-deff56aa1c38.jpeg" width="300px">

世界中からアクセスできる点については、ESP32を公開Webサーバーにして直接アクセスできるようにしてみたかったのですが、その辺りの知識が全く無く、色々ややこしそうだったので断念。（誰か教えてください）
Webページで入力があった場合にローカルサーバーで検知し、シリアル通信でArduinoを動かすことにしました。

### Arduinoにプログラムを書き込む
シリアル通信で"n"が入力されたらLEDが光り、"f"が入力されたらLEDが
消えるというコード。

```io
const byte LED_PIN = 5;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  while (Serial.available() > 0) {
    char value = Serial.read();
    if (value == 'n') {                 // nはON
      digitalWrite(LED_PIN, HIGH);
    } else if (value == 'f') {           // fはOFF
      digitalWrite(LED_PIN, LOW);
    } else {
      digitalWrite(LED_PIN, LOW);
    }
    Serial.println(value);
  }
}
```
### Arduinoをシリアル通信させるNode.jsプログラム
参考にさせていただいた記事
ArduinoでTwitter連携！愛しのぬいぐるみトンピーちゃんに命を吹き込んでみた
https://dotstud.io/blog/arduino-nodejs-twitter-connect/

これでNode.jsでシリアルポートを制御できるようになる。

```js
const SerialPort = require("serialport");
const port = new SerialPort("/dev/tty.xxx", {
  baudRate: 9600,
});

port.on("open", () => {
  console.log("Serial open.");
  setInterval(write, 3000);
});

port.on("data", (data) => {
  console.log(`Data from Arduino: ${data}`);
});

const write = () => {
  console.log(`Input to Arduino: ${signal}`);
  port.write(signal, (error) => {
    if (error) {
      console.error(`Error: ${error.message}`);
    }
  });
};
```

### Cloud Firestoreを使ってWebページで入力があった場合にローカルサーバーで検知する
参考にさせていただいた記事
firestore, vue.jsでリアルタイム同期のチャットを実装してみる [チュートリアル形式]
https://qiita.com/ryo2132/items/2881d8223eb2ad3050a1

Cloud Firestoreには、データベースに変更があった場合リアルタイムで分かる便利機能があるらしい。ただ、今回の場合データベースを使う必要は全く無いので、とても無駄な感じがある。

```js
//-----------------------------------------------
// firebase Admin関係
//----------------------------------------------
const admin = require("firebase-admin");
const serviceAccount = require("./xxx.json");
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://yyy.firebaseio.com",
});
const db = admin.firestore();

//-----------------------------------------------
// firestoreのデータの変更を検知する
//----------------------------------------------
const doc = db.collection("users");
const observer = doc.onSnapshot(
  (querySnapshot) => {
    querySnapshot.docChanges().forEach(change => {
      if (change.type === 'added') {
        const signal = change.doc.data().signal;
      }
    })
  },
  (err) => {
    console.log(`Encountered error: ${err}`);
  }
);
```

### Webページを作ってfirebaseにデプロイする
コードのほとんどはfirebaseが自動的に作ってくれる。主にbodyタグ内を書き換えるだけ。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Welcome to Firebase Hosting</title>

    <!-- update the version number as needed -->
    <script defer src="/__/firebase/8.0.0/firebase-app.js"></script>
    <!-- include only the Firebase features as you need -->
    <script defer src="/__/firebase/8.0.0/firebase-auth.js"></script>
    <script defer src="/__/firebase/8.0.0/firebase-database.js"></script>
    <script defer src="/__/firebase/8.0.0/firebase-messaging.js"></script>
    <script defer src="/__/firebase/8.0.0/firebase-storage.js"></script>
    <!-- initialize the SDK after all desired features are loaded -->
    <script defer src="/__/firebase/init.js"></script>

    <!-- Firebase と Cloud Firestore のライブラリをアプリに追加する -->
    <script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-firestore.js"></script>

  </head>
  <body>
    <div>
      <h2>のあちゃん と えくくんに光をともす</h2>
      <button id="on-button">
        <p>光をともしてあげる</p>
      </button>
      <button id="off-button">
        <p>光を消してあげる</p>
      </button>
    </div>
    <p id="load">Firebase SDK Loading&hellip;</p>

    <script>
      document.addEventListener('DOMContentLoaded', function() {
        try {
          let app = firebase.app();
          let features = ['auth', 'database', 'messaging', 'storage'].filter(feature => typeof app[feature] === 'function');
          document.getElementById('load').innerHTML = `Firebase SDK loaded with ${features.join(', ')}`;
        } catch (e) {
          console.error(e);
          document.getElementById('load').innerHTML = 'Error loading the Firebase SDK, check the console.';
        }
      });

      // Initialize Cloud Firestore through Firebase
      firebase.initializeApp({
        apiKey: "XXXXXX",
        authDomain: "XXXXXX",
        projectId: "XXXXXX",
      });
      const db = firebase.firestore();

      document.getElementById("on-button").onclick = 
      function () {
        const now = new Date();
        // コメントをFirestoreへ登録
        db.collection('users').add({
          signal: "n",
          createdAt: now
        })
        console.log("ONを追加")
      };

      document.getElementById("off-button").onclick =
      function () {
        const now = new Date()
        // コメントをFirestoreへ登録
        db.collection('users').add({
          signal: "f",
          createdAt: now,
        })
        console.log("OFFを追加")
      };
    </script>
  </body>
</html>
```
webページのイメージ↓
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487846/ae045ad0-ad16-f003-d780-dc6b1d9c520c.png" width="300px">

### さいご
Arduinoへの書き込み、firebaseにwebページのデプロイが終わったら、
```$ node ファイル名.js```
で動かす！


### あとがき
これで世界中の人がのあちゃん・えくくんに光を灯すことができるようになりました。