MQTTことはじめ


## 環境

* Broker
	* [ActiveMQ Apollo](http://activemq.apache.org/apollo/) 1.7.1
* Client
	* Node.js v0.12.2
		* [mqtt-connection](https://github.com/mqttjs/mqtt-connection)

## Brokerの環境構築

インストールする。

```bash
$ brew install apollo
```

Brokerのインスタンスを作成する。

```bash
$ /usr/local/Cellar/apollo/1.7.1/bin/apollo create /usr/local/var/apollo
```

とりあえず、`launchctl`を使わず起動する。

```bash
$ /usr/local/var/apollo/bin/apollo-broker run

    _____                .__  .__
   /  _  \ ______   ____ |  | |  |   ____
  /  /_\  \\____ \ /  _ \|  | |  |  /  _ \
 /    |    \  |_> >  <_> )  |_|  |_(  <_> )
 \____|__  /   __/ \____/|____/____/\____/
         \/|__|  Apache Apollo (1.7.1)


Loading configuration file '/usr/local/var/apollo/etc/apollo.xml'.
INFO  | OS     : Mac OS X 10.10.3
INFO  | JVM    : Java HotSpot(TM) 64-Bit Server VM 1.7.0_79 (Oracle Corporation)
INFO  | Apollo : 1.7.1 (at: /usr/local/Cellar/apollo/1.7.1/libexec)
INFO  | OS is restricting the open file limit to: 6250
WARN  | Please increase the process file limit using 'ulimit -n 18500' or configure lower connection limits on the broker connectors.
INFO  | Starting store: leveldb store at /usr/local/var/apollo/data
INFO  | Accepting connections at: tcp://0.0.0.0:61613
INFO  | Accepting connections at: tls://0.0.0.0:61614
INFO  | Accepting connections at: ws://0.0.0.0:61623/
INFO  | Accepting connections at: wss://0.0.0.0:61624/
INFO  | Administration interface available at: https://127.0.0.1:61681/
INFO  | Administration interface available at: http://127.0.0.1:61680/
```

起動すると、[connector](http://activemq.apache.org/apollo/documentation/user-manual.html#Connectors)と呼ばれる、クライアントからの接続を待ち受けるための、４つのポートがオープンするようだ。クライアントは、TCP/TLS/WS/WSSで接続することが可能なようだ。
また、それとは別に、管理者用のWebインタフェース用の口も開くので、ブラウザからアクセス可能である。
MQTTクライアントから接続する場合も、ブラウザから接続する場合も、共にユーザー名・パスワードを設定してあげる必要がある。初期値は、`admin`/`password`である。

## クライアントの実装

### 利用するライブラリの選定について

クライアントの実装は、`mqtt-connection`を使う。最初、[MQTT.js](https://github.com/mqttjs/MQTT.js)を使っていたが、deprecatedなAPIがちらほらある(ログにWARNINGが出力される)のでやめた。マニュアルを見てみると、３つのコンポーネントに分割されたとのこと。

>v1.0.0 improves the overall architecture of the project, which is now splitted in three components: MQTT.js keeps the Client, mqtt-connection includes the barebone Connection code for server-side usage, and mqtt-packet includes the protocol parser and generator. 

README.mdの「Important notes for existing users」より引用。

### プロジェクトを作成する

```bash
$ mkdir mqtt-pubsub-cli
$ cd mqtt-pubsub-cli/
$ npm init
```

今回は、CLIとして作成する予定なので、一応`bin`と`preferGlobal `を`package.json`に定義しておく。(定義しなくても、動作上は問題ない。)

作成された`package.json`は、こんな感じ。

```json
{
  "name": "mqtt-pubsub-cli",
  "version": "0.0.1",
  "description": "MQTT PubSub Playground",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "bin": "index.js",
  "preferGlobal": true,
  "keywords": [
    "mqtt"
  ],
  "author": "toshiyuki.hina@gmail.com",
  "license": "MIT"
}
```

### 依存パッケージのインストール

`mqtt-connection`と[yargs](https://www.npmjs.com/package/yargs)をインストールする。`yargs`は、コマンドパラメータの構築のためのライブラリ。

```bash
$ npm install --save mqtt-connection yargs
npm WARN package.json mqtt-pubsub-cli@0.0.1 No repository field.
npm WARN package.json mqtt-pubsub-cli@0.0.1 No README data
npm WARN package.json mqtt-pubsub-cli@0.0.1 No bin file found at index.js
yargs@3.8.0 node_modules/yargs
├── decamelize@1.0.0
├── camelcase@1.0.2
├── window-size@0.1.0
└── cliui@2.1.0 (wordwrap@0.0.2, right-align@0.1.1, center-align@0.1.1)

mqtt-connection@2.1.1 node_modules/mqtt-connection
├── inherits@2.0.1
├── through2@0.6.5 (xtend@4.0.0, readable-stream@1.0.33)
├── reduplexer@1.1.0 (readable-stream@1.0.33)
└── mqtt-packet@3.2.0 (bl@0.9.4)
```

### 接続してみる

まずはTCPで接続してみる。

```javascript:index.js
'use strict';

var net = require('net'),
    mqttConn = require('mqtt-connection'),
    stream = net.createConnection('61613', 'localhost'), // (1)
    conn = mqttConn(stream);

conn.connect({
  protocolId: 'MQIsdp', // (2)
  protocolVersion: 3,
  clientId: 'foo',      // (3)
  username: 'admin',    // (4)
  password: 'password'  // (5)
});

conn.on('connack', function(packet) {
  if (packet.returnCode) {
    console.error('Failed to connect.');
    return;
  }
  console.log('Connected!');
});

conn.on('error', function(err) {
  console.error(err);
});
```

上記コードを実行した結果は以下。正常に接続できると、`connack`イベントが通知され"Connected!"が出力される。

```bash
$ node index.js
Connected!
```

簡単にプログラムの説明をする。

- (1) TCPで接続するので、第１引数には`61613`を渡す。
- (2) これはマニュアル通りに指定している。
- (3) `clientId`には、とりあえず固定文字列を渡しているが、一意な識別子を渡すようにしなければならない。後でコマンドパラメータで渡せるようにする。
- (4)/(5) `username`と`password`には、brokerに接続するためのユーザー名とパスワードを設定しなければならない。初期値を変更していなければ、`admin`/`password`を指定すれば良い。