はじめに
Node-RED を起動すると以下のようなメッセージが出ます。
Nov 13:59:48 - [info] Settings file : /home/amnt/cfgrjp/node-red/settings.js
Nov 13:59:48 - [info] User directory : /home/amnt/.node-red
Nov 13:59:48 - [info] Flows file : /home/amnt/.node-red/flows_vanadium.json
Nov 13:59:48 - [info] Server now running at http://127.0.0.1:1880/
情報メッセージ[info]に、setting.js ファイルを読み取っていると出ています。このファイルでは Node-RED の Debug タブに出力されるメッセージの長さを規定する debugMaxLength (デフォルト値 1000) などがあります。Node-RED を Web サーバーにするヒントがここに隠されています。以下の行がコメントアウトされていますね。
//httpStatic: '/home/nol/node-red-dashboard/'
Node.js で express を利用している開発者も多いと思われますが、静的コンテンツを利用する場合には
app.use(express.static(path.join(__dirname, 'public')));
などのように指定していることを覚えていると思います。Node-REDを動作させるアプリケーション red.js を開くと、次の行が見つかります。
app.use("/",express.static(settings.httpStatic));
つまりは、Node-RED を簡易WEBサーバーにすることができるということです。
Node-RED を簡易WEBサーバーにするための変更
Node-REDを簡易WEBサーバーにするには、httpStatic と httpAdminRoot の設定のコメントをはずします。ここでは、コンテンツディレクトリとして 'public'、Node-RED 本体は '/red' でアクセスできるように設定してみました。
$ diff settings.js.original settings.js
64c64
< //httpAdminRoot: '/admin',
---
> httpAdminRoot: '/red',
84c84
< //httpStatic: '/home/nol/node-red-dashboard/',
---
> httpStatic: 'public',
public にしたのは、'npm install node-red' を実行したときにすでに存在しているのですね。見てみると、まさに使ってくれといわんばかりの bootstrap / jquery などが存在します。
$ ls public/vendor/
ace bootstrap font-awesome jquery vendor.css vendor.js
簡単に動作確認
まずは簡単に動作確認するため、簡単な html ファイルを public に放り込みます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset=utf-8>
<title>title</title>
</head>
<body>
<h1>これはヘッダー</h1>
<p>
ここはパラグラフです
</p>
</body>
</html>
Node-REDを起動し、確認してみます。
$ node red.js
Browser は 1880 ポートを指定します。
ついでに、/red も開いてみます。
簡易WEBサーバーになっているようです。ここでおや?どこか Bluemixなんかで見たことがある!と思われた方もいるかもしれません。実は、Bluemix の Node-Red テンプレートは最初からそのように工夫されていたのですね。Bluemixの場合、bluemix-setting.js ファイルが該当しますが、開くと以下のような行が見つかるはずです。
// Move the admin UI
httpAdminRoot: '/red',
// Serve up the welcome page
httpStatic: path.join(__dirname,"public"),
Bluemix の場合は、今回紹介しているものとはパラメータ内容が異なりますが、効果は同じです。
これだけではつまらないので、少しカスタマイズ
せっかく Node-RED が動作しているので少しカスタマイズしてみます。せっかく bootstrap / jQuery が入っているのでそれを活用しない手はないですね。
Node-RED のフローとしては以下のフローを作成してみました。
Twitterで 'Bluemix' というメッセージを検索し、検索結果の msg.tweet を msg.payload に変換した後、websocketでブラウザーに通知します(ブロードキャスト)。
index.html は Websocket からの通知を受けてメッセージを表示しています。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- Bootstrap core CSS -->
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<H1> みんなのBluemixつぶやき </H1>
<div id="twitter"> </div>
</div>
<script src='vendor/vendor.js'></script>
<script>
var tweet;
var tweets = [];
var wsUri = "ws://vanadium:1880/ws/twitter";
var ws = new WebSocket(wsUri);
ws.onmessage = function(evt) {
tweet = JSON.parse(evt.data);
tweets.unshift({text: tweet.text, profile_image: tweet.user.profile_image_url, name: tweet.user.name});
var tbl = '<table class="table table-striped">';
for (var i in tweets) {
tbl = tbl + '<tr>';
tbl = tbl + '<td>' + tweets[i].name + ' <img src=' + tweets[i].profile_image + '>' + '</td>';
tbl = tbl + '<td>' + tweets[i].text + '</td>';
tbl = tbl + '</tr>';
}
tbl = tbl + '</table>';
document.getElementById("twitter").innerHTML = tbl;
};
</script>
</body>
</html>
動作させると一応出てますね(メッセージを出すためにつぶやきましたが(笑))。
おまけ
今回の内容は PaaS 勉強会 の内容を少し加工しています。勉強会では、Twitterのメッセージはローカルで実行しましたが、Node-RED がリモートにあるので動かないユーザーがいました。そこで、次回への教訓として、今度は Node-RED 本体に任せようと思い、資料を修正しているのですが、どうせなので Qiita にも投稿しようかなと思ったしだいです。なお、今回がはじめての投稿です。今後ともよろしくお願いいたします。