1. はじめに
node-redで、簡単な掲示板を作ってみます。厳密には、node-redというよりもhtmlのテクニックの方がメインです。
2. フロー全体
利用するノードはたったこれだけです。初期化が2つで、httpに関係するノードは全部で5つです。
最終的なフローはこちらです。試して見たい方は、コピペしてみてください。
フロー.json
[
{
"id": "a5f3251e.9214f",
"type": "http in",
"z": "65f2617e.1211a8",
"name": "",
"url": "/bbs",
"method": "post",
"upload": false,
"swaggerDoc": "",
"x": 140,
"y": 140,
"wires": [
[
"2bb7d440.d44c3c",
"794c41ad.05fbd8"
]
]
},
{
"id": "4b2d6b44.44dba4",
"type": "http in",
"z": "65f2617e.1211a8",
"name": "",
"url": "/bbs",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 140,
"y": 100,
"wires": [
[
"ac35ae63.4b0348"
]
]
},
{
"id": "a2781f59.0baae8",
"type": "http response",
"z": "65f2617e.1211a8",
"name": "",
"statusCode": "",
"headers": {},
"x": 650,
"y": 100,
"wires": []
},
{
"id": "794c41ad.05fbd8",
"type": "debug",
"z": "65f2617e.1211a8",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 410,
"y": 200,
"wires": []
},
{
"id": "43e7eb10.6d8044",
"type": "function",
"z": "65f2617e.1211a8",
"name": "set global",
"func": "messlogs='';\nglobal.set('messlogs',messlogs);\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 300,
"y": 40,
"wires": [
[]
]
},
{
"id": "179520ef.4f6a8f",
"type": "inject",
"z": "65f2617e.1211a8",
"name": "init",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 150,
"y": 40,
"wires": [
[
"43e7eb10.6d8044"
]
]
},
{
"id": "ac35ae63.4b0348",
"type": "function",
"z": "65f2617e.1211a8",
"name": "make a response",
"func": "msgBody01=\"<form action=\\\"bbs\\\" method=\\\"post\\\"><input type=\\\"textarea\\\" name=\\\"myarg01\\\" value=\\\"タイトル\\\"><BR><textarea rows=\\\"10\\\" cols=\\\"50\\\" name=\\\"myarg02\\\" >メッセージ</textarea><BR><input type=\\\"submit\\\" value=\\\"送信\\\"></form>\"\n\nmesslogs = global.get('messlogs');\n\nmsg.payload = msgBody01 + messlogs;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 490,
"y": 100,
"wires": [
[
"a2781f59.0baae8",
"794c41ad.05fbd8"
]
]
},
{
"id": "2bb7d440.d44c3c",
"type": "function",
"z": "65f2617e.1211a8",
"name": "get posted",
"func": "var mydate = new Date();\n\nmesslogs = '';\nmesslogs += 'datetime:\\n';\nmesslogs += mydate.getFullYear();\n// ref to http://www.digitra.net/2016/02/javascript.html\nmesslogs += (\"0\"+(mydate.getMonth() + 1)).slice(-2);\nmesslogs += (\"0\"+mydate.getDate() ).slice(-2);\nmesslogs += '_';\nmesslogs += (\"0\"+mydate.getHours()).slice(-2);\nmesslogs += (\"0\"+mydate.getMinutes()).slice(-2);\nmesslogs += (\"0\"+mydate.getSeconds()).slice(-2);\nmesslogs += '<BR>\\n';\nmesslogs += 'title:\\n';\nmesslogs += msg.req.body.myarg01;\nmesslogs += '<BR>\\n';\nmesslogs += 'messege:<BR>\\n';\nmesslogs += msg.req.body.myarg02;\nmesslogs += '<BR>\\n';\nmesslogs += '<BR>\\n';\nmesslogs +=global.get('messlogs');\nglobal.set('messlogs',messlogs);\n//msg.messlogs=messlogs;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 310,
"y": 140,
"wires": [
[
"ac35ae63.4b0348"
]
]
}
]
3. 解説
3.1. 初期化部分
起動時にglobal変数を定義するために、初回だけ起動するinjectionノードを設置します。必要な設定は、下にあるチェックを入れるだけです。
その後ろに、functionノードを配置し、接続します。
コードの紙はたったこれだけです。messlogsという変数をglobalとして定義し、他のfunctionノードでも使えるようにしておきます。
messlogs='';
global.set('messlogs',messlogs);
return msg;
3.2. http get部分
ブラウザでURLを叩いた際に、応答する処理部分です。
まずは、http-inノードを設置します。この設定では、メソッドをget
に、URLは、今回は/bbs
にします。
この後ろに、ブラウザに表示するためのhtml記述のページを作ります。
msgBody01が、入力フォーム部分です。
messlogsは、グローバル変数に入っている文字列を格納するローカル変数です。
msgBody01の後ろにmesslogsを挿入して、payloadに入れます。
msgBody01の内容が、post側のフローと一致しないと動きません。
post側へのURLは、bbs
にしてます。よって、post処理側のhttp-inノードにもURLがbbs
にする必要があります。(getと同じURLにしていますが、別の名前にしてもOKです。その場合は、post側もそれに変更してください)
タイトルを入れるフォームのname
をmyarg01
に、メッセージのname
をmyarg02
にしていますので、これもpost側と一致させておく必要があります。
msgBody01="<form action=\"bbs\" method=\"post\"><input type=\"textarea\" name=\"myarg01\" value=\"タイトル\"><BR><textarea rows=\"10\" cols=\"50\" name=\"myarg02\" >メッセージ</textarea><BR><input type=\"submit\" value=\"送信\"></form>"
messlogs = global.get('messlogs');
msg.payload = msgBody01 + messlogs;
return msg;
3.3. http post部分
http post側は、webブラウザに表示されているページの送信ボタンを押した際に、接続される処理部分です。
メソッドは、post
にして、ファイルのアップロードは無しにし、URLは、web用htmlで記載したものと同じ/bbs
にします。
その後ろに、postで受信した情報を展開するために、functionノードを設置します。
行う処理は、日時、タイトル、メッセージの抽出と変数格納を行い、その後ろに、過去の記録を追加し、最後にglobal変数に保存します。(変数名がローカルとグローバルとで、ややこしいと思う場合は、ローカルを別の変数名にすると判り易くなると思います)
postで受信した値は、msg.req.body.NAME
に格納されます。NAMEは、web用htmlで記載したものと同じ myarg01
とmyarg02
になります。
var mydate = new Date();
messlogs = '';
messlogs += 'datetime:\n';
messlogs += mydate.getFullYear();
messlogs += ("0"+(mydate.getMonth() + 1)).slice(-2);
messlogs += ("0"+mydate.getDate() ).slice(-2);
messlogs += '_';
messlogs += ("0"+mydate.getHours()).slice(-2);
messlogs += ("0"+mydate.getMinutes()).slice(-2);
messlogs += ("0"+mydate.getSeconds()).slice(-2);
messlogs += '<BR>\n';
messlogs += 'title:\n';
messlogs += msg.req.body.myarg01;
messlogs += '<BR>\n';
messlogs += 'messege:<BR>\n';
messlogs += msg.req.body.myarg02;
messlogs += '<BR>\n';
messlogs += '<BR>\n';
messlogs +=global.get('messlogs');
global.set('messlogs',messlogs);
return msg;
日付けは、Date()で取得した現在日時ですが、そのオブジェクトのままですので、年月日時刻をそれぞれ抽出します。注意点としては、月は0始まりなので1を加えます。また、1桁の時と2桁の時とで文字の長さが異なるので、常に2桁にする処理を加えました。
2桁にする処理は下記を参考にしました。(「javascript date 0埋め」で検索するとヒットします)
4. 動作確認
node-redの動いているサーバ(ラズパイなど)のIPアドレスとポート番号の後ろに設定した/bbs をつけるとアクセスできます。
(例: http:192.168.1.2:1880/bbs )
タイトルとメッセージを記載し、送信ボタンを押すと、下にその内容が記録されます。なお、ファイルには保存していませんので、再起動したりデプロイし直すと内容は消えます。
5. おわりに
居室で記載したメモを別の部屋で見たい時、LAN内にBBSみたいなのがあると良いと思い、作ってみました。例えば、IoTでnode-redを稼働させているラズパイはあるけど、新たにwebサーバを立ち上げるのは面倒という時に重宝するように思います。
今回、メッセージ部に改行があっても表示には反映されないようになっていますが、変換処理をfunctionノードに追加するのもありかもしれません。