こんにちは、のすけです。

最近は毎週朝に、カフェでもくもく作業しています。

そんなもくもくの成果を一つ書いておきます。

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で読み込みます。
f:id:hollywis:20160218085231p:plain

<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を入力して送信すると・・・

f:id:hollywis:20160218093731p:plain

f:id:hollywis:20160218093738p:plain

LEDが点灯!!と表示され、コンソールを見てみると

f:id:hollywis:20160218094140p:plain

次に、formに2を入力して送信すると・・・

f:id:hollywis:20160218093549p:plain

f:id:hollywis:20160218093557p:plain

LEDが消灯!!と表示され、コンソールを見てみると

f:id:hollywis:20160218094205p:plain

実際にコマンドが発行されているのが確認出来ました。これでLEDを点灯させる準備が出来たとこになります。

まとめ

Nodeを利用してPOSTデータを受け取り、送信されるデータに従ってLEDを点灯・消灯させることが出来ました。

今回は仮想的にやりましたので、次回はRasberry pi上にNodeサーバを立ち上げて実際に遠隔からLEDをチカチカ制御してみたいと思います。

ではまた!

Receive the latest news in your email
Table of content
Related articles