IBM Bluemix で IoT (3) - Androidのセンサ値をモニタする

[前回](http://qiita.com/f_nishio/items/33b4922ccf705d74b002)までは、python版のpaho-mqttライブラリを使ってきたが、[paho](http://www.eclipse.org/paho/)にはAndroid版もあるので、Androidのセンサ値をモニタするプロトタイプを作ってみる。
プロトタイプのコードは github [fnishio/mqtt-sample](https://github.com/fnishio/mqtt-sample)のSensorSampleを参照。

Androidセンサ値のモニタ
========================

- Android側
    - Lightセンサーの値をMQTT eventとして定期的にpublishする。
- サービス側
    - センサー値のeventをWebSocketに出力する。
    - ブラウザからWebSocketに接続してセンサー値をモニタリングする。


Android側
--------------

### MQTT Brokerにつなぐ
Android版のpahoライブラリを使ってMQTT Brokerに接続する。

```java:MyMqttClient.java
MyMqttClient(Context context) {
    mClient = new MqttAndroidClient(context, MyMqttConfig.ENDPOINT_URL, MyMqttConfig.CLIENT_ID);
}

public void connect() {
    MqttConnectOptions options = new MqttConnectOptions();
    options.setUserName(MyMqttConfig.USER);
    options.setPassword(MyMqttConfig.PASSWORD.toCharArray());
    try {
        mClient.connect(options, null, new IMqttActionListener() {
            @Override
            public void onSuccess(IMqttToken mqttToken) {
              // ...
            }

            @Override
            public void onFailure(IMqttToken arg0, Throwable arg1) {
              // ...
            }
        });
    } catch (MqttSecurityException e) {
        // do nothing.
    } catch (MqttException e) {
        // do nothing.
    }
}
```

### Event Publish
SensorEventListenerのonSensorChanged()でセンサー値を監視してトピック`iot-2/evt/sensor/fmt/json`にpublishする。

```java:SensorActivity.java
@Override
public final void onSensorChanged(SensorEvent event) {
    float value = event.values[0];
    mClient.publish("sensor", "light", value);
}
```

サービス側
------------
サービス側は、2つのフローを実装する。

(1) センサー値のイベントをWebSocketに送信するフロー
![websocket.png](https://qiita-image-store.s3.amazonaws.com/0/88598/56dcb948-ae38-3462-f872-20598f7f75de.png)

(2) WebSocketの値を監視するWebページをブラウザに送るフロー
![monitor_page.png](https://qiita-image-store.s3.amazonaws.com/0/88598/bc0ab625-c013-f21e-cfed-6d308b97d1f5.png)

### Event Subscirbe
MQTT Deviceから送信されるトピック`iot-2/evt/sensor/fmt/json`の
センサー値イベントを
受け取って、WebSocket に送信するデータに整形する。

![ws_format.png](https://qiita-image-store.s3.amazonaws.com/0/88598/db38e23e-8b99-8b85-1fb7-34c8dfb502cb.png)

WebSocket `/ws/sensor`にデータを送る。
![ws_out.png](https://qiita-image-store.s3.amazonaws.com/0/88598/40627b34-cbc6-2293-2d71-6dc9b5c5fffb.png)

### Monitoring
`/sensor`にHTTP GETされたら以下のhtmlをブラウザに返す。htmlの処理内容は、WebSocket `/ws/sensor`につないでセンサ値を取得し、ブラウザ上のセンサー値表示を更新する。
このテンプレートをNode-REDのSensor Valueノードに設定する。

```html:monitor_template.html
<head>
  <title>Sensor</title>
  <script type="text/javascript">
  var wsUri = "ws://{{req.headers.host}}/ws/sensor";
  var ws = new WebSocket(wsUri);

  ws.onmessage = function(ev) {
    var payload = JSON.parse(ev.data);
    var device = document.getElementById('device');
    device.textContent = payload.deviceId;
    var sensor = document.getElementById('sensor');
    sensor.textContent = payload.light;
  }
  </script>
</head>

<body>
    <div>Sensor Monitor:</div>
    <div>
      Id: <span id="device">xxx</span>
      Value:<span id="sensor">00</span>
    </div>
</body>
```

実行
----
Android上でアプリを実行するとLightセンサーの値を定期的にpublishする。
ブラウザから``http://[server address]/sensor``にアクセスすると、publishされているセンサ値をモニタすることができる。
![monitor_html.png](https://qiita-image-store.s3.amazonaws.com/0/88598/148f2452-a27d-6611-ae88-305135ee4893.png)