Node-RED で WebSocket を使った HTTP server push (1) ブラウザ表示更新

## 目標
サーバからのきっかけでブラウザの表示を更新する

## 知識材料 
- [Push技術(Wikipedia)](https://ja.wikipedia.org/wiki/Push%E6%8A%80%E8%A1%93)
- [Node-RED(Node-RED 日本ユーザ会)](https://nodered.jp/)

## 利用環境
- [IBM Cloud ライト・アカウント(無料)](https://www.ibm.com/cloud-computing/jp/ja/lite-account/)
- [IBM Cloud Node-RED (v0.19.4)](https://console.bluemix.net/catalog/starters/node-red-starter)
(IBM Cloud の特別なノードは使用していないので、npm でインストールした Node-RED でも大丈夫です)

## 前提条件
Node-RED でフローが作成できる

## 今回のゴール
サーバきっかけで、任意の文字列をブラウザに表示させる。

# 実践
Node-RED のフローと、ブラウザで表示する HTML と作る。 
## Node-RED フロー
![flow](https://dl.dropboxusercontent.com/s/22d1kweux1sigaw/181119-01.png)

### 使用ノード
#### [input] inject
ブラウザに表示したい文字列を `Payload` に入力する。
![inject Setting](https://dl.dropboxusercontent.com/s/ohxngvl1ncef8cr/181119-02.png)
#### [output] websocket
クライアントとなるブラウザ側が接続する URL を `path` に入力する。
![output websocket Setting](https://dl.dropboxusercontent.com/s/alpygs0rlfyy2k5/181119-03.png)

# ブラウザで表示するHTML
[参考(MDN:WebSocket クライアントアプリケーションの記述)](https://developer.mozilla.org/ja/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications)

`url` 変数を、`[output] websocket の path` で入力したURLと合わせる

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>WebSocket 試す１</title>
</head>
<body style="color: #000000; background-color: #ffffff; font-size: 100%">
  <script type="text/javascript">
    // 接続先URI
    var uri = "ws://" + "your.host.name" + "/testws"; // ← [output] websocket の path に合わせる
    // WebSocketオブジェクト
    var webSocket = null;

    // 接続
    function open() {
        if (webSocket == null) {
            // 初期化
            webSocket = new WebSocket(uri);
            // イベントハンドラ
            webSocket.onopen = (ev) =>
              {
                console.log("Connect..");
              };

            webSocket.onmessage = (ev) =>
              {
                if (ev && ev.data) {
                    console.log(ev.data);
                    var d = document.getElementById("targetDiv");
                    d.innerHTML = ev.data;
                }
              };

            webSocket.onclose = (ev) => {
                console.log("disconnect(" + ev.code + ")");
                webSocket = null;
              };

            webSocket.onerror = (ev) =>
              {
                  console.log("Error " + ev);
              };;
        }
    }
    open();
  </script>
  <div id="targetDiv" style="width:300px;height:300px;border:solid 1px;"></div>
</body>
</html>
```

## 実行と結果
#### ブラウザ初期表示
ブラウザで index.html を開く
![ブラウザ初期表示](https://dl.dropboxusercontent.com/s/w5b4ddg4m196ewo/181119-04.png)

index.html と Node-RED が正しく動作している場合、Node-RED の [websocket]ノードの下に、接続されているクライアントの数が表示される。
![websocket connected](https://dl.dropboxusercontent.com/s/qznnbn4ot7irp0l/181119-05.png)

#### サーバきっかけで Push
Node-RED の inject ノード を実行する。
![inject 実行](https://dl.dropboxusercontent.com/s/0pow4v43qn4kthg/181119-06.png)
ブラウザで表示している矩形の中に、`[input] inject の Payload` に入力した文字列が表示される。
![ブラウザ最終結果](https://dl.dropboxusercontent.com/s/gjjghylfdyyesnv/181119-07.png)

## まとめ
プッシュ型のメッセージを使ったプロダクトで実際に使おうとすると考えければならないことが多々あるかと思うが、プロトタイプを作る際にはお気軽に試せると感じた。

IoT をやってみたくて取り組んでいるので、デバイスの状態やセンサーの値をプッシュしたり、ブラウザからデバイスを制御する部分を試していきたい。