LoginSignup
6
4

More than 3 years have passed since last update.

Firebase Cloud FunctionsでMQTT Publisherを作ってみた

Last updated at Posted at 2020-09-04

Firebase Cloud FunctionsでMQTT Publisherを作ってみた

VR空間とIoTデバイスをMQTTで接続する仕組みを構築するにあたり、Firebase Cloud FunctionsでMQTT Publisherを作ることができないか試してみたところ、うまくいったので忘れない内に記事にします。

ちなみに、以下が作ったものです!普段はVR関係の活動をしていますので、ご興味があればフォローよろしくお願いします!

やりたいこと

以下が、やりたいことです。

  • FirebaseにWebAPIを構築する

  • WebAPIにGETメソッドでアクセスすると、クエリパラメーター message の内容が、MQTT Brokerへ送信される。

事前準備

Firebase開発環境の構築

事前にFirebaseプロジェクトの作成やツールの導入をお願いします。

こちらがわかりやすいのでオススメです。

Cloud Functions + ExpressでサーバレスAPIを実装

従量課金制のプランにする

完全無料のSparkプランだと外部ドメインのサーバーにアクセスすることができないので、MQTT Brokerへ接続することができません。

あらかじめ、従量課金制のBlazeプランに変更しておく必要があります。(こればっかりはどうしようもないです。。。)

mqttのインストール

以下のコマンドでexpressとmqttをインストールしておいてください。

npm install express
npm install mqtt

サンプルコード

index.jsに以下のように書きます。定数の箇所は適宜、ご自身の環境に合わせて変更してください。

const functions = require('firebase-functions');
const express = require("express");
const app = express();
const mqtt = require('mqtt');

// 定数
const broker = 'mqtt://example.com';
const topic = 'example';

// MQTTでメッセージを送信する
const publishMessage = (message) => {
    // Brokerに接続する
    const client = mqtt.connect(mqttBroker);
    client.on('connect', () => {
        // メッセージをBrokerへ送信する
        client.publish(topic, message, null, (err) => {
            if (err) {
                console.error(err);
            }

            // Brokerとの接続を切断する
            client.end();
        });
    });
}

// GETコントローラー
app.get('/publish', (req, res) => {
    const message = req.query.message;    
    if(message){
        // メッセージをPublishする
        publishMessage(message);

        return res.send('Success!');
    }else{
        return res.send('Error!');
    }
});

const api = functions.https.onRequest(app);
module.exports = { api };

これをデプロイすれば動くようになります!

解説

こちらの関数を解説します。

// MQTTでメッセージを送信する
const publishMessage = (message) => {
    // Brokerに接続する
    const client = mqtt.connect(mqttBroker);
    client.on('connect', () => {
        // メッセージをBrokerへ送信する
        client.publish(topic, message, null, (err) => {
            if (err) {
                console.error(err);
            }

            // Brokerとの接続を切断する
            client.end();
        });
    });
}

こちらの関数では、以下の3つの処理を一気に実施しています。

  • Brokerと接続
  • Brokerへメッセージの送信
  • Brokerとの接続を切断

つまり、関数が呼ばれる度に、Brokerとの接続・切断を繰り返すことになり、非常に効率が悪いです。

しかし、Firebase Cloud Functionsでは、Brokerとの接続を維持することが難しかったため、このようなスタイルになりました。

たとえば、以下のコードのように、関数外でBrokerとの接続処理を書いてみても、うまく動きませんでした。
(厳密には app.get の外です)

// Brokerに接続する
const client = mqtt.connect(mqttBroker);
client.on('connect', () => {});

// MQTTでメッセージを送信する
const publishMessage = (message) => {
    // メッセージをBrokerへ送信する
    client.publish(topic, message, null, (err) => {
        if (err) {
            console.error(err);
        }
    });
}

さいごに

本記事作成にあたり、以下の記事を参考にさせていただきました。ありがとうございました。

6
4
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
6
4