Skip to content

Electron と MQTT.js SDK を使用したデプロイメントへの接続

本記事では、Electron プロジェクトでの MQTT の使用方法を主に紹介し、シンプルな MQTT デスクトップクライアントの作成、およびクライアントと MQTT ブローカー間の接続、サブスクライブ、サブスクライブ解除、メッセージ送受信などの機能を実装する方法を解説します。

前提条件

Electron アプリケーションを EMQX Cloud に接続する前に、以下の前提条件を完了していることを確認してください。

  • MQTT ブローカーのデプロイ
  • Electron アプリケーションの作成

MQTT ブローカーのデプロイ

アプリケーションをEMQX Cloudに接続するには、デプロイメントを作成して設定する必要があります。

サーバレスデプロイメント

  1. EMQX Cloudコンソールでサーバレスデプロイメントを作成します。

  2. デプロイメントが作成されて稼働したら、デプロイメントの概要ページに移動し、以下を含むMQTT接続情報を確認します。

    • ブローカーアドレス

    • ポート番号(サーバレスではTLSポートのみ対応)

  3. サーバレスデプロイメントはTLS接続が必須です。概要ページからCA証明書をダウンロードし、TLS用のポート8883を使用してください。

  4. デプロイメントのアクセス制御 -> クライアント認証で、デフォルト認証(ユーザー名/パスワード)を設定します。

詳細はサーバレスポートガイドを参照してください。

Dedicated Flex または BYOC デプロイメント

  1. EMQX CloudコンソールでDedicated FlexまたはBYOCのデプロイメントを作成できます。

  2. 作成後、デプロイメントの概要ページに移動し、以下を含むMQTT接続情報を取得します。

    • ブローカーアドレス

    • MQTTおよびWebSocket用のTCPおよびTLSポート番号(TCPおよびTLS接続の両方に対応)

  3. デプロイメントのアクセス制御 -> クライアント認証で、デフォルト認証(ユーザー名/パスワード)を設定します。

詳細なポート設定については、Dedicated & BYOCポートガイドをご覧ください。

Electron アプリケーションの作成

Electron は GitHub によって開発・保守されているオープンソースのソフトウェアフレームワークです。Chromium レンダリングエンジンと Node.js ランタイムを組み合わせ、Web 技術を用いてデスクトップ GUI アプリケーションの開発を可能にします。Electron は Atom、GitHub Desktop、Light Table、Visual Studio Code、WordPress Desktop などの著名なオープンソースプロジェクトの主要な GUI フレームワークです。^1

基本的な Electron プロジェクトは、package.json(メタデータ)、main.js(コード)、index.html(グラフィカルユーザーインターフェース)の3つのファイルで構成されます。フレームは Electron の実行ファイル(Windows では electron.exe、macOS では electron.app、Linux では electron)によって提供されます。開発者はフラグの追加、アイコンのカスタマイズ、実行ファイルの名前変更や編集を自由に行えます。

新規プロジェクトの構築方法は多数ありますが、以下にいくつかの簡単な例を示します。

  • 手動で作成する場合、プロジェクトディレクトリで以下を実行します。

    shell
    cd your-project
    
    npm init
    
    npm i -D electron@latest

    また、プロジェクト構築手順については以下のドキュメントも参照してください。

    住所: https://www.electronjs.org/docs/tutorial/first-app

  • 公式テンプレートプロジェクト electron-quick-start を使った高速開発。

    住所: https://github.com/electron/electron-quick-start

    shell
      # リポジトリをクローン
      git clone https://github.com/electron/electron-quick-start
      # リポジトリに移動
      cd electron-quick-start
      # 依存関係をインストール
      npm install
      # アプリを起動
      npm start
  • React.js を使って開発可能なテンプレートプロジェクト electron-react-boilerplate による高速開発。

    住所: https://github.com/electron-react-boilerplate/electron-react-boilerplate

    shell
    git clone --depth 1 --single-branch https://github.com/electron-react-boilerplate/electron-react-boilerplate.git your-project-name
    cd your-project-name
    yarn
  • Vue.js を使って開発可能なテンプレートプロジェクト electron-vue による高速開発。vue-cli ツールを使ったプロジェクト初期化と連携します。

    住所: https://github.com/SimulatedGREG/electron-vue

    shell
    # vue-cli をインストールしボイラープレートを生成
    npm install -g vue-cli
    vue init simulatedgreg/electron-vue my-project
    
    # 依存関係をインストールしアプリを起動
    cd my-project
    yarn # または npm install
    yarn run dev # または npm run dev

本記事では、公式の electron quick start プロジェクトテンプレートを使用してプロジェクトを初期化し、例示プロジェクトを迅速に構築します。

依存関係のインストール

コマンドラインから以下を実行してインストールします。

shell
npm install mqtt --save

依存関係のインストール後、デバッグ用にコンソールを開きたい場合は、main.js のコードを修正し、win.webContents.openDevTools() のコメントアウトを解除してください。

javascript
// DevTools を開く
mainWindow.webContents.openDevTools()

この場合、ローカルにインストールした MQTT.js モジュールは、フロントエンドビルダーでフロントエンドページをパッケージ化しない限り、renderer.js に直接読み込むことはできません。ビルドツールを使う方法のほかに、以下の2つの方法があります。

  1. webPreferencesnodeIntegration を true に設定する。このプロパティがあると、webview 内で Node 統合が有効になり、requireprocess といった Node API を使って低レベルのシステムリソースにアクセス可能です。Node 統合はデフォルトで無効です。

    javascript
    const mainWindow = new BrowserWindow({
      width: 800,
      height: 600,
      webPreferences: {
        nodeIntegration: true,
        preload: path.join(__dirname, 'preload.js'),
      },
    })
  2. preload.js で MQTT.js モジュールをインポートする。Node 統合が無効でも、このスクリプトはすべての Node API にアクセス可能です。ただし、このスクリプトの実行が完了すると、Node 経由で注入されたグローバルオブジェクトは削除されます。

  3. MQTT.js モジュールをメインプロセスでインポートし接続する。Electron では、ipcMainipcRenderer モジュールを使い、開発者定義の「チャネル」を介してプロセス間通信を行います。これらのチャネルは任意の名前を付けられ、双方向に通信可能です。使用例は IPC チュートリアル を参照してください。

接続

より直感的に説明するため、例の主要な接続コードは renderer.js ファイルに記述します。セキュリティを考慮し、インストールした MQTT モジュールは Node.js API の require メソッドを使い、preload.js ファイルで読み込みます(上記方法2)。また、この方法でグローバルの window オブジェクトに注入します。

注意: Context isolation (contextIsolation) は Electron 12 以降デフォルトで有効です。preload スクリプトはレンダラーに付随する window グローバルを共有しますが、contextIsolation により preload スクリプトから直接 window に変数をアタッチできません。

そのため、webPreferencescontextIsolation: false を設定して無効化します。

js
const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: false, // バージョン 12.0.0 以上はデフォルトで有効
    }
  })

これにより、renderer.js で読み込んだモジュールに直接アクセス可能になります。

  • MQTT モジュールのインポート例
javascript
// preload.js
const mqtt = require('mqtt')
window.mqtt = mqtt

TCP ポートで接続

クライアント ID、ユーザー名、パスワードを以下のコードで設定します。クライアント ID は一意である必要があります。

js
const clientId = 'emqx_vue3_' + Math.random().toString(16).substring(2, 8)
const username = 'emqx_test'
const password = 'emqx_test'

以下のコードでクライアントと MQTT ブローカー間の接続を確立します。

js
const client = mqtt.connect('mqtt://broker.emqx.io:1883', {
  clientId,
  username,
  password,
  // ...その他のオプション
})

TCP セキュアポートで接続

TLS/SSL 暗号化が有効な場合、接続のパラメーターオプションは TCP ポート接続時と同様です。プロトコルを mqtts に変更し、正しいポート番号を指定するだけで構いません。

以下のコードでクライアントと MQTT ブローカー間の接続を確立します。

js
const client = mqtt.connect('mqtts://broker.emqx.io:8883', {
  clientId,
  username,
  password,
  // ...その他のオプション
})

WebSocket ポートで接続

MQTT の WebSocket は接続パスとして /path を統一的に使用し、接続時に指定する必要があります。EMQX ブローカーは /mqtt をパスとして使用しています。

そのため、WebSocket 接続時はポート番号の変更とプロトコルを ws に切り替えるだけでなく、/mqtt パスも追加する必要があります。

以下のコードでクライアントと MQTT ブローカー間の接続を確立します。

js
const client = mqtt.connect('ws://broker.emqx.io:8083/mqtt', {
  clientId,
  username,
  password,
  // ...その他のオプション
})

WebSocket セキュアポートで接続

TLS/SSL 暗号化が有効な場合、接続のパラメーターオプションは WebSocket ポート接続時と同様です。プロトコルを wss に変更し、正しいポート番号を指定するだけで構いません。

以下のコードでクライアントと MQTT ブローカー間の接続を確立します。

js
const client = mqtt.connect('wss://broker.emqx.io:8084/mqtt', {
  clientId,
  username,
  password,
  // ...その他のオプション
})

サブスクライブとパブリッシュ

トピックのサブスクライブ

サブスクライブするトピックと対応する QoS レベル(任意)を設定し、MQTT.js の subscribe メソッドを呼び出してサブスクライブ操作を行います。

javascript
function onSub() {
  if (client.connected) {
    const { topic, qos } = subscriber
    client.subscribe(
      topic.value,
      { qos: parseInt(qos.value, 10) },
      (error, res) => {
        if (error) {
          console.error('Subscribe error: ', error)
        } else {
          console.log('Subscribed: ', res)
        }
      }
    )
  }
}

トピックのサブスクライブ解除

サブスクライブ解除時は、不要になったトピックと対応する QoS(任意)を渡す必要があります。

https://github.com/mqttjs/MQTT.js#mqttclientunsubscribetopictopic-array-options-callback

javascript
function onUnsub() {
  if (client.connected) {
    const { topic } = subscriber
    client.unsubscribe(topic.value, (error) => {
      if (error) {
        console.error('Unsubscribe error: ', error)
      } else {
        console.log('Unsubscribed: ', topic.value)
      }
    })
  }
}

メッセージのパブリッシュ

メッセージをパブリッシュする際は、対応するトピックとメッセージ内容を MQTT ブローカーに通知する必要があります。

https://github.com/mqttjs/MQTT.js#mqttclientpublishtopic-message-options-callback

javascript
function onSend() {
  if (client.connected) {
    const { topic, qos, payload } = publisher
    client.publish(topic.value, payload.value, {
      qos: parseInt(qos.value, 10),
      retain: false,
    })
  }
}

メッセージの受信

javascript
// onConnect 関数内
client.on('message', (topic, message) => {
  const msg = document.createElement('div')
  msg.setAttribute('class', 'message-body')
  msg.innerText = `${message.toString()}\nOn topic: ${topic}`
  document.getElementById('article').appendChild(msg)
})

MQTT ブローカーからの切断

クライアントによる能動的な切断

https://github.com/mqttjs/MQTT.js#mqttclientendforce-options-callback

javascript
function onDisconnect() {
  if (client.connected) {
    client.end()
    client.on('close', () => {
      connectBtn.innerText = 'Connect'
      console.log(options.clientId + ' disconnected')
    })
  }
}

接続のテスト

ここまでで、Electron で作成した MQTT 5.0 クライアントツール - MQTTX(こちらも Electron で作成)を使って、メッセージの送受信をテストします。

MQTTX からクライアントにメッセージを送信すると、メッセージが正しく受信されていることが確認できます。

electronmessage.png

自作クライアントから MQTTX にメッセージを送信すると、MQTTX 側でもメッセージが正しく受信されていることが確認できます。

mqttx.png

まとめ

ここまでで、Electron を使ってシンプルな MQTT デスクトップクライアントを作成し、クライアントと MQTT ブローカー間の接続、メッセージ送受信、サブスクライブ解除、切断のシナリオをシミュレートしました。完全なサンプルソースコードは MQTT Client Electron ページ からダウンロード可能です。また、他言語のデモ例も MQTT Client Example ページ でご覧いただけます。