こんにちは、のすけです。
最近は毎週朝に、カフェでもくもく作業しています。
そんなもくもくの成果を一つ書いておきます。
NodeでLEDを遠隔チカチカさせる(仮想編)
やってみたいじゃないですか。遠隔チカチカ。
最近はクラウドのIoTサービスなんかもあって便利なんですが、その前に自分でサーバを作ってやってみないことには IoTサービスの便利さを体感できないと思います。
というわけで、最近はまっているNodeを利用してサクッとサーバを立てて、それからLEDチカチカへ移りたいと思います。 チカチカさせるマイコンとしては、Rasberry pi2を利用します。
POSTデータを受け取るサーバ作成
まず、POSTデータを受け取るサーバプログラムはこちら
var http = require('http'); var querystring = require('querystring'); var util = require('util'); var fs = require('fs'); var form = fs.readFileSync('./public/form.html'); http.createServer(function (req, res){ if(req.method === 'GET'){ res.writeHead(200,{'Content-Type': 'text/html'}); res.end(form); } if(req.method='POST'){ var postData = ''; req.setEncoding('utf8'); req.on('data',function (chunk){ // per request postData += chunk; }).on('end',function(){ // response data var respose_data = ''; // end request if(!postData){ res.end(); return; } // if postData is empty. var postDataObject = querystring.parse(postData); console.log('user posted following data:' + postData); console.log(postDataObject.userinput1); respose_data += 'your poted data is:\n' + util.inspect(postDataObject)+'\n'; res.end(respose_data,"utf8"); }); } }).listen(8080);
基本的なサーバ機能を提供するhttp
、クエリストリングをいい感じに読んでくれるquerystring
、POSTデータを簡単に文字列に変えることができるutil
、ファイルを読み込めるfs
のライブラリを使っています。
form用のHTMLは別ファイル./public/form.html
に置いておいて。それをfs
で読み込みます。
<form method="post"> <input type="text" name="userinput1"><br><br> <input type="text" name="userinput2"><br><br> <input type="submit"> </form>
単純にHTMLでform作ってmethodをpostにします。 input要素を2つくらいとsubmitをつけただけ。
サーバの方に戻ります。 req.methodがGETの時はform.htmlを表示させ、POSTの時は処理を挟みます。
req.setEncoding('utf8'); を入れているのは近年のブラウザはutf8で処理しているのですが、これの設定入れないと違うエンコーディングで読んだりして文字化ける可能性があるそうです。
req.on('data',function (chunk){ // per request postData += chunk; }
リクエストのデータは複数回に分かれて細切れに飛んできます。dataイベントが複数回発生しますので、これを結合して一つのデータにしています。
on('end',function()
データの受信が終わったらendイベントが発生するため、ここから主処理を開始できます。
querystring.parse
でpostDataを扱いやすいようにオブジェクトに変換しています。
util.inspect(postDataObject)
でオブジェクトを文字列に変換しています。
res.end(respose_data,"utf8");
ではレスポンスに文字列response_data
を返却しています。ここでエンコーディングタイプutf8
を指定しないと、日本語を返した場合にブラウザがどんなエンコーディングタイプで読めば良いかわからないため文字化けします。
LED点灯できるコマンド実行できるようにする
nodeではコンソールで実行するようなコマンドを発行することができます。
具体的にはrequire('child_process').exec
を利用します。
var exec = require('child_process').exec, cmd; cmd_ledon = 'echo "LED ON!!"'; cmd_ledoff = 'echo "LED OFF!!"'; led_onoff = function(cmd) { return exec(cmd, {timeout: 1000}, function(error, stdout, stderr) { console.log('stdout: '+(stdout||'none')); // 標準出力 console.log('stderr: '+(stderr||'none')); // 標準エラー出力 if(error !== null) { console.log('exec error: '+error); } // errorの時 else{ console.log('exec: '+cmd); } // errorなしの時 } ) }; led_onoff(cmd_ledon); led_onoff(cmd_ledoff);
最後の2行でLED点灯、LED消灯を実行しています。led_onoff
関数を作成し、そこにコマンドを渡してあげると実行してくれます。
今回は(仮想編)ですので実際にLEDを点灯するコマンドではなくecho "LED ON!!"
とecho "LED OFF!!
でLEDが点灯、消灯したということにします。
上記プログラムを合体して、POSTデータによってLEDの点灯、消灯を切り替える
var http = require('http'); var querystring = require('querystring'); var util = require('util'); var fs = require('fs'); var form = fs.readFileSync('./public/form.html'); var exec = require('child_process').exec, cmd; cmd_ledon = 'echo "LED ON!!"'; cmd_ledoff = 'echo "LED OFF!!"'; led_onoff = function(cmd) { return exec(cmd, {timeout: 1000}, function(error, stdout, stderr) { console.log('stdout: '+(stdout||'none')); // 標準出力 console.log('stderr: '+(stderr||'none')); // 標準エラー出力 if(error !== null) { console.log('exec error: '+error); } // errorの時 else{ console.log('exec: '+cmd); } // errorなしの時 } ) }; http.createServer(function (req, res){ if(req.method === 'GET'){ res.writeHead(200,{'Content-Type': 'text/html'}); res.end(form); } if(req.method='POST'){ var postData = ''; req.setEncoding('utf8'); req.on('data',function (chunk){ // per request postData += chunk; }).on('end',function(){ // response data var respose_data = ''; // end request if(!postData){ res.end(); return; } // if postData is empty. var postDataObject = querystring.parse(postData); console.log('user posted following data:' + postData); console.log(postDataObject.userinput1); respose_data += 'your poted data is:\n' + util.inspect(postDataObject)+'\n'; if(postDataObject.userinput1 == '1'){ led_onoff(cmd_ledon); respose_data += 'LEDが点灯しました !!'; } // if userinput1で1がPOSTされたならledon if(postDataObject.userinput1 == '2'){ led_onoff(cmd_ledoff); respose_data += 'LEDが消灯しました!!'; } // if userinput1で2がPOSTされたならledoff res.end(respose_data,"utf8"); }); } }).listen(8080);
LEDの点灯、消灯はpostDataObject.userinput1
のみを見て判断しています。
1がPOSTされれば点灯、2がPOSTされれば消灯です。それ以外ならPOSTされた値が表示されるだけです。なお、postDataObject.userinput2
は何も意味がありません。飾りです。
やってみる
まず、formに1を入力して送信すると・・・
LEDが点灯!!と表示され、コンソールを見てみると
次に、formに2を入力して送信すると・・・
LEDが消灯!!と表示され、コンソールを見てみると
実際にコマンドが発行されているのが確認出来ました。これでLEDを点灯させる準備が出来たとこになります。
まとめ
Nodeを利用してPOSTデータを受け取り、送信されるデータに従ってLEDを点灯・消灯させることが出来ました。
今回は仮想的にやりましたので、次回はRasberry pi上にNodeサーバを立ち上げて実際に遠隔からLEDをチカチカ制御してみたいと思います。
ではまた!