はじめに
最近になって Raspberry Pi を使い始めました。
Raspberry Pi とサーバで通信するのに MQTT プロトコルを使うことにしました。
また、Raspberry Pi 、サーバともに Node.js で書きたいと思いました。
MQTT とは
MQTT とは、IoT や M2M のためのメッセージ転送プロトコルです。
多数のデバイスの間で短いメッセージを頻繁に送受信することを想定しています。
プロトコルヘッダが小さく、通信量、CPU 負荷、電力消費などを抑えることができます。
メッセージの送信側を、Publisher (発行者) と呼びます。
メッセージの受信側は、Subscriber (購読者) です。Subscriber は Publisher に対してメッセージの購読を予め希望します。
このとき Publisher と Subscriber は直接通信でなく、それぞれ Broker (仲介者) に接続します。Publisher と Subscriber はクライアント、Broker はサーバに位置づけられます。
Publisher と Subscriber は1対1だけでなく、容易に1対多、多対多に対応できます。
Publisher が発行するメッセージは、トピックをつけて送信します。Subcriber は、トピックを指定して購読を希望します。
MQTT.js を使う
MQTT.js は、MQTT クライアントのためのライブラリです。Node.js およびブラウザの JavaScript で使用できます。
公式 https://www.npmjs.com/package/mqtt
まず Node.js で使用してみます。
- Node.js 8.1.4
- mqtt.js 2.9.2
ワークスペースを作る
インストールする
$ npm install mqtt
Publisher の実装
var mqtt = require('mqtt');
var client = mqtt.connect('mqtt://mosquitto.org');
client.on('connect', function(){
console.log('publisher.connected.');
});
setInterval(function(){
var message = Date.now().toString()/
client.publish('topic0', message);
console.log('publisher.publish:', message);
}, 1000);
まず、mqtt.connect()
で、インスタンスを生成すると同時にサーバ (Broker) に接続します。
サーバ (Broker) は、既存のサービス (mqtt://mosquitto.org) を利用させて貰います。
続いて、client.publish()
で、サーバ (Broker) にメッセージ送信します。このときトピックを指定します。
ここでは setInterval() を使ってループしています。Ctrl+C で終了させて下さい。
Subscriber の実装
var mqtt = require('mqtt');
var client = mqtt.connect('mqtt://mosquitto.org');
client.on('connect', function(){
console.log('subscriber.connected.');
});
client.subscribe('topic0', function(err, granted){
console.log('subscriber.subscribed.');
});
client.on('message', function(topic, message){
console.log('subscriber.on.message', 'topic:', topic, 'message:', message.toString());
});
まず、mqtt.connect()
で、インスタンスを生成すると同時にサーバ (Broker) に接続します。
サーバ (Broker) は、既存のサービス (mqtt://mosquitto.org) を利用させて貰います。
続いて、client.subscribe()
で、サーバ (Broker) に購読を希望します。このときトピックを指定します。前述の Publisher の実装と合わせて下さい。
サーバ (Broker) からメッセージが届くと client.on('messege',
で受信できます。
実行する
$ node publisher.js
$ node subscriber.js
Mosca を使う
Mosca は、MQTT broker のためのライブラリです。Node.js で使用できます。
- Node.js 8.1.4
- Mosca 2.5.2
ワークスペースを作る
インストールする
$ npm install mosca
Broker の実装
var mosca = require('mosca');
var server = new mosca.Server({
port: 1883,
});
server.on('ready', function(){
console.log('Server is ready.');
});
まず、new mosca.Server()
でインスタンス生成します。
port
は任意です。
これで、Publisher からメッセージを受信し、Subscriber にメッセージを転送できるようになっています。
server.on('clientConnected', function(client){
console.log('broker.on.connected.', 'client:', client.id);
});
server.on('clientDisconnected', function(client){
console.log('broker.on.disconnected.', 'client:', client.id);
});
server.on('subscribed', function(topic, client){
console.log('broker.on.subscribed.', 'client:', client.id, 'topic:', topic);
});
server.on('unsubscribed', function(topic, client){
console.log('broker.on.unsubscribed.', 'client:', client.id);
});
server.on('published', function(packet, client){
if (/\/new\//.test(packet.topic)){
return;
}
if (/\/disconnect\//.test(packet.topic)){
return;
}
console.log('broker.on.published.', 'client:', client.id);
});
Publisher および Subscriber が接続すると server.on('clientConnected',
で確認できます。なくても構いません。
Subscriber が購読希望すると server.on('subscribed',
で確認できます。なくても構いません。
Publiser がメッセージ送信すると server.on('published',
で確認できます。なくても構いません。Publisher や Subscriber が接続したときも発火するようです。なので packet.topic
を確認します。
Publisher の実装
前述のコードを若干変更します。
var client = mqtt.connect({
host: 'localhost',
port: 1883,
clientId: 'mqtt.publisher',
});
host
および port
は、前述の Broker の実装に合わせて下さい。
clientId
は、指定しなければ自動でセットされます。ここでは確認のため指定しています。
Subscriber の実装
前述のコードを若干変更します。
var client = mqtt.connect({
host: 'localhost',
port: 1883,
clientId: 'mqtt.subscriber',
});
host
および port
は、前述の Broker の実装に合わせて下さい。
clientId
は、指定しなければ自動でセットされます。ここでは確認のため指定しています。
実行する
$ node publisher.js
$ node subscriber.js
$ node broker.js
MQTT クライアントをブラウザで動かす
MQTT.js を使う
MQTT.js は、MQTT クライアントのためのライブラリで、Node.js およびブラウザの JavaScript で使用できます。
ブラウザで動くプログラムを作ってみます。
インストールする
今回は CDN を利用します。
https://unpkg.com/mqtt/dist/mqtt.min.js
Publisher の実装
<html>
<head>
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
</head>
<body>
<script>
var client = mqtt.connect({
host: 'localhost',
port: 3000,
clientId: 'http.publisher'
});
</script>
<div id='buttonPublish' v-on:click='doPublish'>[発行する]</div>
<script>
new Vue({
el: '#buttonPublish',
methods: {
doPublish: function(){
client.publish('topic0', Date.now().toString());
}
}
});
</script>
</body>
</html>
mqtt.connect()
で、インスタンスを生成すると同時にサーバ (Broker) に接続します。
host
および port
は、後述する Broker の実装に合わせて下さい。
clientId
は、指定しなければ自動でセットされます。ここでは確認のため指定しています。
client.publish()
で、サーバ (Broker) にメッセージ送信します。このときトピックを指定します。
ボタン押下時の処理は Vue.js を使っています。別のフレームワークでも構いません。
Subscriber の実装
<html>
<head>
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
</head>
<body>
<script>
var client = mqtt.connect({
host: 'localhost',
port: 3000,
clientId: 'http.subscriber'
});
client.subscribe('topic0');
var data = {};
data.messages = [];
client.on('message', function(topic, payload){
var message = String.fromCharCode.apply(null, payload);
console.log(message);
data.messages.push(message);
});
</script>
<ul id='listMessage'>
<li v-for='message in messages'>
{{ message }}
</li>
</ul>
<script>
new Vue({
el: '#listMessage',
data: data
});
</script>
</body>
</html>
mqtt.connect()
で、インスタンスを生成すると同時にサーバ (Broker) に接続します。
host
および port
は、後述する Broker の実装に合わせて下さい。
clientId
は、指定しなければ自動でセットされます。ここでは確認のため指定しています。
client.subscribe()
で、サーバ (Broker) に購読を希望します。このときトピックを指定します。前述の Publisher の実装と合わせて下さい。
サーバ (Broker) からメッセージが届くと client.on('messege',
で受信できます。
受信結果を表示する処理は Vue.js を使っています。別のフレームワークでも構いません。
実行する
publisher.html
および subscriber.html
をブラウザで開きます。
サーバをブラウザの MQTT クライアントに対応させる
Mosca を使う
Mosca は、MQTT broker のためのライブラリで、Node.js で使用できます。
Broker の実装
前述のコードを利用します。以下のコードを追加します。
var http = require('http');
var httpServer = http.createServer();
server.attachHttpServer(httpServer);
httpServer.listen(3000);
server
は、従来の MQTT サーバのインスタンスです。attachHttpServer()
で HTTP サーバのインスタンス httpServer
と結びつけます。
httpServer.listen()
で指定するポート番号は、前述のクライアントの実装に合わせて下さい。
実行する
$ node publisher.js
$ node subscriber.js
$ node broker.js
ブラウザの Publisher でメッセージ送信すると、ブラウザの Subscriber でメッセージ受信します。同時に Node.js の Subscriber でも従来通りメッセージ受信します。
Node.js の Publisher で送信されたメッセージも、ブラウザの Subscriber および Node.js の Subscriber で受信され表示されます。