Electron と MQTT.js SDK を使用したデプロイメントへの接続
本記事では、Electron プロジェクトでの MQTT の使用方法を主に紹介し、シンプルな MQTT デスクトップクライアントの作成、およびクライアントと MQTT ブローカー間の接続、サブスクライブ、サブスクライブ解除、メッセージ送受信などの機能を実装する方法を解説します。
前提条件
Electron アプリケーションを EMQX Cloud に接続する前に、以下の前提条件を完了していることを確認してください。
- MQTT ブローカーのデプロイ
- Electron アプリケーションの作成
MQTT ブローカーのデプロイ
アプリケーションをEMQX Cloudに接続するには、デプロイメントを作成して設定する必要があります。
サーバレスデプロイメント
EMQX Cloudコンソールでサーバレスデプロイメントを作成します。
デプロイメントが作成されて稼働したら、デプロイメントの概要ページに移動し、以下を含むMQTT接続情報を確認します。
ブローカーアドレス
ポート番号(サーバレスではTLSポートのみ対応)
サーバレスデプロイメントはTLS接続が必須です。概要ページからCA証明書をダウンロードし、TLS用のポート
8883を使用してください。デプロイメントのアクセス制御 -> クライアント認証で、デフォルト認証(ユーザー名/パスワード)を設定します。
詳細はサーバレスポートガイドを参照してください。
Dedicated Flex または BYOC デプロイメント
EMQX CloudコンソールでDedicated FlexまたはBYOCのデプロイメントを作成できます。
作成後、デプロイメントの概要ページに移動し、以下を含むMQTT接続情報を取得します。
ブローカーアドレス
MQTTおよびWebSocket用のTCPおよびTLSポート番号(TCPおよびTLS接続の両方に対応)
デプロイメントのアクセス制御 -> クライアント認証で、デフォルト認証(ユーザー名/パスワード)を設定します。
詳細なポート設定については、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)によって提供されます。開発者はフラグの追加、アイコンのカスタマイズ、実行ファイルの名前変更や編集を自由に行えます。
新規プロジェクトの構築方法は多数ありますが、以下にいくつかの簡単な例を示します。
手動で作成する場合、プロジェクトディレクトリで以下を実行します。
shellcd your-project npm init npm i -D electron@latestまた、プロジェクト構築手順については以下のドキュメントも参照してください。
公式テンプレートプロジェクト
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 startReact.jsを使って開発可能なテンプレートプロジェクトelectron-react-boilerplateによる高速開発。住所: https://github.com/electron-react-boilerplate/electron-react-boilerplate
shellgit clone --depth 1 --single-branch https://github.com/electron-react-boilerplate/electron-react-boilerplate.git your-project-name cd your-project-name yarnVue.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 プロジェクトテンプレートを使用してプロジェクトを初期化し、例示プロジェクトを迅速に構築します。
依存関係のインストール
コマンドラインから以下を実行してインストールします。
npm install mqtt --save依存関係のインストール後、デバッグ用にコンソールを開きたい場合は、main.js のコードを修正し、win.webContents.openDevTools() のコメントアウトを解除してください。
// DevTools を開く
mainWindow.webContents.openDevTools()この場合、ローカルにインストールした MQTT.js モジュールは、フロントエンドビルダーでフロントエンドページをパッケージ化しない限り、renderer.js に直接読み込むことはできません。ビルドツールを使う方法のほかに、以下の2つの方法があります。
webPreferencesのnodeIntegrationを true に設定する。このプロパティがあると、webview内で Node 統合が有効になり、requireやprocessといった Node API を使って低レベルのシステムリソースにアクセス可能です。Node 統合はデフォルトで無効です。javascriptconst mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, preload: path.join(__dirname, 'preload.js'), }, })preload.jsで MQTT.js モジュールをインポートする。Node 統合が無効でも、このスクリプトはすべての Node API にアクセス可能です。ただし、このスクリプトの実行が完了すると、Node 経由で注入されたグローバルオブジェクトは削除されます。MQTT.js モジュールをメインプロセスでインポートし接続する。Electron では、
ipcMainとipcRendererモジュールを使い、開発者定義の「チャネル」を介してプロセス間通信を行います。これらのチャネルは任意の名前を付けられ、双方向に通信可能です。使用例は IPC チュートリアル を参照してください。
接続
より直感的に説明するため、例の主要な接続コードは renderer.js ファイルに記述します。セキュリティを考慮し、インストールした MQTT モジュールは Node.js API の require メソッドを使い、preload.js ファイルで読み込みます(上記方法2)。また、この方法でグローバルの window オブジェクトに注入します。
注意: Context isolation (contextIsolation) は Electron 12 以降デフォルトで有効です。preload スクリプトはレンダラーに付随する
windowグローバルを共有しますが、contextIsolationにより preload スクリプトから直接windowに変数をアタッチできません。
そのため、webPreferences に contextIsolation: false を設定して無効化します。
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: false, // バージョン 12.0.0 以上はデフォルトで有効
}
})これにより、renderer.js で読み込んだモジュールに直接アクセス可能になります。
- MQTT モジュールのインポート例
// preload.js
const mqtt = require('mqtt')
window.mqtt = mqttTCP ポートで接続
クライアント ID、ユーザー名、パスワードを以下のコードで設定します。クライアント ID は一意である必要があります。
const clientId = 'emqx_vue3_' + Math.random().toString(16).substring(2, 8)
const username = 'emqx_test'
const password = 'emqx_test'以下のコードでクライアントと MQTT ブローカー間の接続を確立します。
const client = mqtt.connect('mqtt://broker.emqx.io:1883', {
clientId,
username,
password,
// ...その他のオプション
})TCP セキュアポートで接続
TLS/SSL 暗号化が有効な場合、接続のパラメーターオプションは TCP ポート接続時と同様です。プロトコルを mqtts に変更し、正しいポート番号を指定するだけで構いません。
以下のコードでクライアントと MQTT ブローカー間の接続を確立します。
const client = mqtt.connect('mqtts://broker.emqx.io:8883', {
clientId,
username,
password,
// ...その他のオプション
})WebSocket ポートで接続
MQTT の WebSocket は接続パスとして /path を統一的に使用し、接続時に指定する必要があります。EMQX ブローカーは /mqtt をパスとして使用しています。
そのため、WebSocket 接続時はポート番号の変更とプロトコルを ws に切り替えるだけでなく、/mqtt パスも追加する必要があります。
以下のコードでクライアントと MQTT ブローカー間の接続を確立します。
const client = mqtt.connect('ws://broker.emqx.io:8083/mqtt', {
clientId,
username,
password,
// ...その他のオプション
})WebSocket セキュアポートで接続
TLS/SSL 暗号化が有効な場合、接続のパラメーターオプションは WebSocket ポート接続時と同様です。プロトコルを wss に変更し、正しいポート番号を指定するだけで構いません。
以下のコードでクライアントと MQTT ブローカー間の接続を確立します。
const client = mqtt.connect('wss://broker.emqx.io:8084/mqtt', {
clientId,
username,
password,
// ...その他のオプション
})サブスクライブとパブリッシュ
トピックのサブスクライブ
サブスクライブするトピックと対応する QoS レベル(任意)を設定し、MQTT.js の subscribe メソッドを呼び出してサブスクライブ操作を行います。
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
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
function onSend() {
if (client.connected) {
const { topic, qos, payload } = publisher
client.publish(topic.value, payload.value, {
qos: parseInt(qos.value, 10),
retain: false,
})
}
}メッセージの受信
// 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
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 からクライアントにメッセージを送信すると、メッセージが正しく受信されていることが確認できます。

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

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