忘備録-備忘録

技術的な備忘録

node-redを80番ポートで動作させる

2016-11-28 18:04:41 | raspberry ...
node-redはデフォルトで1880番ポートで待ち受けます。これをWeb標準の80番ポートで動作させるには、 ~/.node-red/setting.js を書き換えること(参考)で出来ますが、node-redをrootで動作させないといけません。スーパーユーザー以外で80番ポートを使用する方法がここに乗っています。

その方法は iptables のポートフォワーディング機能を利用することです。
最初にport forwardを有効にします。
/etc/sysctl.conf ファイル内の次の行を"0"から"1"に変更しリブートします。

net.ipv4.ip_forward = 1

次のコマンドでポートのフォワードを設定します。

$ sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 1880

node-redでローカルIPアドレスを取得する

2016-11-28 17:46:44 | raspberry ...
node-red上でローカルIPアドレスの値を取得する関数を作ってみました。

最初に ~/.node-red/setting.js の170行目くらいの functionGlobalContext の項目に必要な項目を追加します(コメントを外すだけです。)。
  1.     // Anything in this hash is globally available to all functions.
  2.     // It is accessed as context.global.
  3.     // eg:
  4.     // functionGlobalContext: { os:require('os') }
  5.     // can be accessed in a function block as:
  6.     // context.global.os
  7.     functionGlobalContext: {
  8.         os:require('os'),
  9.         // octalbonescript:require('octalbonescript'),
  10.         // jfive:require("johnny-five"),
  11.         // j5board:require("johnny-five").Board({repl:false})
  12.     },

次にコードを書きます。


-------------------------------------code-------------------------
[{"id":"98c4454e.0650c","type":"function","z":"78174f00.279c9","name":"IPアドレス取得(詳細)","func":"var os = context.global.os;\n\nvar ifacesObj = {}\nifacesObj.ipv4 = [];\nifacesObj.ipv6 = [];\nvar interfaces = os.networkInterfaces();\n\nfor (var dev in interfaces) {\n    interfaces[dev].forEach(function(details){\n        if (!details.internal){\n            switch(details.family){\n                case \"IPv4\":\n                    ifacesObj.ipv4.push({name:dev, address:details.address});\n                break;\n                case \"IPv6\":\n                    ifacesObj.ipv6.push({name:dev, address:details.address})\n                break;\n            }\n        }\n    });\n}\nmsg.payload = ifacesObj;\nreturn msg;","outputs":1,"noerr":0,"x":299.5,"y":371,"wires":[["d775a21.dbef86"]]},{"id":"d775a21.dbef86","type":"debug","z":"78174f00.279c9","name":"","active":true,"console":"false","complete":"false","x":589.5,"y":368,"wires":[]},{"id":"ce20cf3a.8685e8","type":"inject","z":"78174f00.279c9","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":91.5,"y":370,"wires":[["98c4454e.0650c","d0b13b58.8cbe3"]]},{"id":"d0b13b58.8cbe3","type":"function","z":"78174f00.279c9","name":"IPアドレス取得","func":"var os = context.global.os;\nvar ifaces = os.networkInterfaces();\nvar ipAddress;\n \nObject.keys(ifaces).forEach(function (ifname) {\n  ifaces[ifname].forEach(function (iface) {\n \n    if ('IPv4' !== iface.family || iface.internal !== false) {\n      // skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses\n      return;\n    }\n \n    console.log(ifname, iface.address);\n    // en0 192.168.1.NNN\n    ipAddress = iface.address;\n \n  });\n});\nmsg.payload = ipAddress;\nreturn msg;","outputs":1,"noerr":0,"x":277.5,"y":415,"wires":[["d775a21.dbef86"]]}]
-------------------------------------code-------------------------

参考URL
node.jsでローカルIPアドレスの取得
node.js local IP アドレスを取得したい

node-redでWebSocket通信を行う

2016-11-28 17:34:32 | raspberry ...
node-redを使用してWebSocket通信を行うサンプルを作ってみました。


慣れるまでは、?なところがありましたが、慣れてしまえば簡単に作れて便利です。

-----------------------------code--------------------------
[{"id":"c18f94af.d97d18","type":"http in","z":"78174f00.279c9","name":"","url":"/wstest","method":"get","swaggerDoc":"","x":121,"y":87,"wires":[["342be234.95c17e"]]},{"id":"342be234.95c17e","type":"template","z":"78174f00.279c9","name":"Webページ雛形","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<HTML xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"ja\">\n    <HEAD>\n        <META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"> \n        <META name=\"viewport\" content=\"width=240px,initial-scale=1,user-scalable=yes\">\n        <TITLE>Web sockt sample</TITLE>\n    </HEAD>\n    <BODY>\n        PROXYごしだとwebSocktの接続が切れます。\n        <FORM name='form1'>\n            <TABLE border='0' width='240px'>\n                <TR>\n                    <TD>HOST</TD>\n                    <TD id='hostname'><INPUT type='text' name='fhostname'></TD>\n                </TR>\n                <TR>\n                    <TD>SYSMSG</TD>\n                    <TD id='output'><INPUT type='text' name='foutput'></TD>\n                </TR>\n                <TR>\n                    <TD>RECEIVE</TD>\n                    <TD id='rcvmsg'><INPUT type='text' name='frcvmsg'></TD>\n                </TR>\n                <TR>\n                    <TD colspan='2' align='center'>\n                        <INPUT type='button' value='READ' onClick='refTemp()'>\n                    </TD>\n                </TR>\n            </TABLE>\n            \n            <TABLE  border='0' width='240px'>\n                <TR>\n                    <TD id='dig' colspan='3' align='center'>\n                        <LABEL>OFF</LABEL>\n                        <input id='radbtn0' type='radio' name='DIG' value='0' checked='checked' onchange='changeDIG(this.value)'>\n                        <input id='radbtn1'type='radio' name='DIG' value='1' onchange='changeDIG(this.value)'>\n                        <LABEL>ON</LABEL>\n                    </TD>\n                </TR>\n                <TR>\n                    <TD align='right'><LABEL>0</LABEL></TD>\n                    <TD align='center'>\n                        <input id='slider' type='range' name='num' min='0' max='100' step='5' value='50' onchange='changeValue(this.value)'>\n                    </TD>\n                    <TD align='left'><LABEL>100</LABEL></TD>\n                </TR>\n                <TR colspan='3'>\n                    <TD colspan='3' align='center'>\n                        <INPUT type='button' value='RELOAD' onClick='refScreen()'>\n                    </TD>\n                </TR>\n            </TABLE>        \n        </FORM>\n    </BODY>\n\n    <SCRIPT type = 'text/javascript'>\n    \tvar ws;\n\n    \tfunction changeValue(value) {\n    \t\tvar m;\n    \t\tvar n;\n    \t\tm = ('00'+value).substr(-3);\n    \t\tn = m;\n    \t\tm = 'A:'+ m;\n    \t\tws.send(m);\n    \t}\n    \n    \tfunction changeDIG(value) {\n    \t\tvar m;\n    \t\tm = 'D:'+value;\n    \t\tws.send(m);\n    \t}\n    \n    \tfunction refTemp() {\n    \t\tvar m;\n    \t\tm = 'T:0';\n    \t\tws.send(m);\n    \t}\n    \n    \tfunction refScreen() {\n    \t\tvar m;\n    \t\tm = 'R:0';\n    \t\tws.send(m);\n    \t}\n    \n    \t(function() {\n    \t\thadr = location.host;\n    \t\tslidval = document.getElementById('slider');\n    \t\tledval0 = document.getElementById('radbtn0');\n    \t\tledval1 = document.getElementById('radbtn1');\n    \t\tws= new WebSocket('ws://'+hadr+'/ws/io');\n\n    \t\tdocument.form1.fhostname.value = hadr;   //form内に表示\n    \n    \t\tws.onmessage = function(e) {\n    \t\t    document.form1.frcvmsg.value = (e.data).toString();   //form内に表示\n                var rcvobj = JSON.parse(e.data);\n                slidval.value = rcvobj.A;\n                if (rcvobj.D == 0) {\n    \t\t\t    ledval0.checked = 'checked';\n    \t\t\t} else {\n    \t\t\t\tledval1.checked = 'checked';\n    \t\t\t}\n    \t\t\tif(rcvobj.R==1) {\n    \t\t\t    location.reload(true);\n    \t\t\t}\n    \t\t};\n            ws.onopen = function () {\n    \t\t\tdocument.form1.foutput.value = 'connect: ' + hadr; //form内に表示\n         \t\tvar m; //初期値をサーバから取得\n        \t\tm = 'T:0';\n    \t    \tws.send(m);\n   \t\t    };\n    \t\tws.onclose = function (e) {\n    \t\t\tdocument.form1.foutput.value = 'disconnect'+e.code + '-' + e.type + '-' + + e.reason;  //form内に表示\n    \t\t};\n    \t\t\n    \t\tws.onerror = function (e) {\n              document.form1.frcvmsg.value = 'error ' + e.message;\n            };\n\n    \n    \t}() );\n    </script>\n\n</HTML>\n","x":306,"y":88,"wires":[["73ed63fc.f6132c"]]},{"id":"73ed63fc.f6132c","type":"http response","z":"78174f00.279c9","name":"","x":516,"y":89,"wires":[]},{"id":"5975bdc5.3039f4","type":"websocket out","z":"78174f00.279c9","name":"","server":"fc1dd35d.2ba3b","client":"","x":521,"y":158,"wires":[]},{"id":"13992052.defd2","type":"websocket in","z":"78174f00.279c9","name":"","server":"fc1dd35d.2ba3b","client":"","x":105,"y":156,"wires":[["212218fe.d858d8"]]},{"id":"212218fe.d858d8","type":"function","z":"78174f00.279c9","name":"データ処理及び配信","func":"// context.set('変数名',値); グローバル変数の設定\n// var val = context.get('変数名')||0;グローバル変数の読み込み\n// ||0; の部分は初期化指定 \n// 変数が設定されていない場合内は0に初期化\n\n//プロパティの追加\n//静的変数のように使用できる\n//注意: 外部からの参照も可能\nif (typeof this.old_r === 'undefined') {\n    this.old_r = 0;\n}\n\nvar m = (msg.payload).toString();\nvar n = m.split(':');\n//var old_r = context.get('oldreload')||0;\nvar old_r = this.old_r;\n\nif(n[0] == 'D') {\n    context.set('digdat',parseInt(n[1],10));\n}\nif(n[0] == 'A') {\n    context.set('anadat',parseInt(n[1],10));\n}\nif(n[0] == 'R') { //リロード\n    context.set('reload',1);\n}\nif(n[0] == 'T') {\n}\nvar d = context.get('digdat')||0;\nvar a = context.get('anadat')||0;\nvar r = context.get('reload')||0;\nif((old_r==1) && (r==1)) {\n    context.set('reload',0);\n    r = 0;\n}\nmsg.payload = '{\"D\":' +  d + ',\"A\":' + a + ',\"R\":' + r +'}'; //JSON形式でデータを送信\nold_r = r; //繰り返しリロードしないように\n//context.set('oldreload',old_r);\nthis.old_r = old_r;\n\ndelete msg._session; //ブロードキャストする\n//msg._msgid = \"\";\nreturn msg;\n\n","outputs":1,"noerr":0,"x":298,"y":158,"wires":[["5975bdc5.3039f4","2cb20b90.d81a54"]]},{"id":"2cb20b90.d81a54","type":"debug","z":"78174f00.279c9","name":"","active":false,"console":"false","complete":"payload","x":521,"y":235,"wires":[]},{"id":"fc1dd35d.2ba3b","type":"websocket-listener","z":"","path":"/ws/io","wholemsg":"false"}]
-----------------------------code--------------------------

参考図書
ブラウザでお絵描きI/O!Node-REDで極楽コンピュータ・プログラミング (インターフェースSPECIAL) CQ出版