1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-11-01

まえがき

「世界中の人に、のあちゃん・えくくん(猫)と遊んでもらいたい」
そんな思いから、世界中のパソコンやスマホを通して、ペットののあちゃん・えくくんとコミュニケーションがとれるものを作ってみました。
本当は猫じゃらしを振り回してもらいたかったのですが、まずはLEDを点灯させるだけの「光をともす」をやってみたいと思います。

↑ のあちゃんとえくくん ↓のあちゃんに光が灯される図

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

Arduinoにプログラムを書き込む

シリアル通信で"n"が入力されたらLEDが光り、"f"が入力されたらLEDが
消えるというコード。

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でシリアルポートを制御できるようになる。

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

//-----------------------------------------------
// 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タグ内を書き換えるだけ。

<!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ページのイメージ↓

さいご

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

あとがき

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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?