MQTT.js でブラウザから MQTTブローカ に Pub/Sub する

# はじめに

またもや、MQTTシリーズ行きますよ。今回は、`MQTT.js` [^1] で `Mosquitto™` [^2] の テストサーバ（ブローカ）に接続するの巻

[^1]: [GitHub](https://github.com/mqttjs/MQTT.js)
[^2]: [`test.mosquitto.org`](https://test.mosquitto.org/)

# サンプルコード

これでとりあえず動く。ブラウザのコンソールに `{"name": "sensor1", "temp": 10}` が表示されるはず。 `floor1/room1`  [^3] にある `sensor1` が 温度を送信している感じにしてみた

[^3]: MQTT の トピックは `/` で階層をつくるのが一般的

```html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>MQTT</title>
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
</head>

<body>

<script>
let client = mqtt.connect('wss://test.mosquitto.org:8081');
let topic = "floor1/room1"
let metric = '{"name": "sensor1", "temp": 10}'

client.subscribe(topic);
client.publish(topic, metric);

client.on('message', function (topic, message) { // message is Buffer
  console.log(message.toString());
});

client.end();
</script>

</body>

</html>
```

* ブラウザからMQTT投げる場合は、いきなりTCPソケットを張ることはできないので、`MQTT over WebSocket` を使うのが一般的で、今回もそれ
* そのため、プロトコル指定を意識して `wss://test.mosquitto.org:8081` として接続

# センサーっぽく、定期的に `pub` する

定期的にデータを送信するように変更

```html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>MQTT DASH</title>
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
</head>

<body>

<script>
let client = mqtt.connect('wss://test.mosquitto.org:8081');
let topic = "floor1/room1"

client.subscribe(topic);

pubLoop = setInterval(() => {
  const time = Date.now().toString();
  const temp = Math.floor( Math.random() * 11 );
  let metric = '{"time":' + time + ', "name": "sensor1", "temp":' + temp + '}'
  client.publish(topic, metric);
}, 1000);

client.on('message', function (topic, message) { // message is Buffer
  console.log(message.toString());
});

setTimeout(function() { clearInterval( pubLoop ); }, 10000); // stop after 10sec

</script> 

</body>

</html>
```

コンソール出力。まあ、それっぽくなってきたかな

```json:console.log
{"time":1588127649527, "name": "sensor1", "temp":6}
{"time":1588127650532, "name": "sensor1", "temp":4}
{"time":1588127651530, "name": "sensor1", "temp":6}
{"time":1588127652529, "name": "sensor1", "temp":1}
{"time":1588127653531, "name": "sensor1", "temp":3}
{"time":1588127654530, "name": "sensor1", "temp":8}
{"time":1588127655528, "name": "sensor1", "temp":10}
{"time":1588127656529, "name": "sensor1", "temp":10}
{"time":1588127657530, "name": "sensor1", "temp":4}
```

# `Pub` / `Sub` を分けた方がわかりやすいかも

こういう風に pub / sub のインスタンスをわけた方がわかりやすいかも

```javascript:two-instances.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>MQTT DASH</title>
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
</head>

<body>

<script>

let pub = mqtt.connect('wss://test.mosquitto.org:8081');
let sub = mqtt.connect('wss://test.mosquitto.org:8081');
let topic = "floor1/room1"


sub.subscribe(topic);

pubLoop = setInterval(() => {
  const time = Date.now().toString();
  const amp = Math.floor( Math.random() * 11 );
  const tem = Math.floor( Math.random() * 11 );
  const hum = Math.floor( Math.random() * 11 );
  let metric = '{"time":' + time + ', "name": "sensor1", "amp":' + amp + ', "temp":' + tem + ', "hum":' + hum + '}'
  pub.publish(topic, metric);
  console.log("pub: " + metric);
}, 1000);

sub.on('message', function (topic, message) { // message is Buffer
  console.log("sub: " + message.toString());
});

setTimeout(function() {
  clearInterval( pubLoop );
  pub.end();
  sub.end();
}, 10000); // stop after 10sec

</script> 
</body>
</html>
```

# 参考にしたサイト

* [Node.jsでMQTTブローカーを立てて、ブラウザから確認する](https://qiita.com/n0bisuke/items/629799710d5834e98b93)
* [ブラウザでもMQTTでメッセージングしたい！](https://lealog.hateblo.jp/entry/2015/07/24/205838)
* [WebSocket connection to "ws://test.mosquitto.org/" failed: Error during WebSocket handshake: Unexpected response code: 200 #628](https://github.com/mqttjs/MQTT.js/issues/628#issuecomment-345412483)

# シリーズ

- [DockerとMosquitto™でMQTTに触れる](https://qiita.com/narutaro/items/e48def9dca38036f01f9)
- [MQTTを調べている](https://qiita.com/narutaro/items/1837e392ef3255c9d6b2)
- [MQTTの通信を可視化する - shiftr.io](https://qiita.com/narutaro/items/5a9102f4a2e29e4525db)
- [Azure IoT Hub に Mosquitto™ から MQTT なげてみる](https://qiita.com/narutaro/items/1a16ff1321f5044afaf0)
- [MQTT.js でブラウザから MQTTブローカ に Pub/Sub する](https://qiita.com/narutaro/items/2819ce79eb82a87357eb)