Raspberry PiにNode.jsをインストールして、Raspberry Piからの情報をWebSocketでリアルタイムにパソコンに提供できる環境を作ってみました。
Node.jsは、グーグルが開発したV8エンジン上で実行する環境で、サーバーサイドJavaScriptとも呼ばれ、サーバ側もJavaScriptで記述できるのが大きな特徴です。
WebSocketは、Socket.IOモジュールで実装されます。Socket.IOモジュールは、双方向通信用のプロトコルであるWebSocketを、ブラウザに依存せず、違いを吸収するためのモジュールです。
Node.jsのインストール
Raspberry Piは、以前はソースを落としてきてセルフビルドに2時間近く掛かっていたのですが、現在は下記のようにバイナリをインストールできるようになっています。今回はv0.10.24を使用します。
$ wget http://nodejs.org/dist/v0.10.24/node-v0.10.24-linux-arm-pi.tar.gz $ tar -zxvf node-v0.10.24-linux-arm-pi.tar.gz $ sudo mv node-v0.10.24-linux-arm-pi /usr/local/node
エディタで.bashrcファイルにNode.jsのパスを次のように追加し、sourceコマンドで再起動します。
$ sudo vi /home/pi/.bashrc // 「export PATH=/usr/local/node/bin:$PATH」を最終行に追加する $ source ~/.bashrc
ビルドが終了するとインストールできたか確認います。下記のように「v0.10.24」が表示されると成功です。
$ node -v v0.10.24
インストールが完了したら、お約束のHello Worldアプリケーションを作成します。適当なディレクトリに以下の内容のコードを「helloworld.js」として作成します。
helloworld.js
var sys = require('sys'); var http = require('http'); var server = http.createServer( function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.write('Hello World!!\n'); response.end(); } ).listen(8124); sys.log('Server running at http://127.0.0.1:8124/');
ターミナルから先ほど作成した「helloworld.js」を指定して、Node.jsを起動します。
$ node helloworld.js 20 Feb 12:05:06 – Server running at http://127.0.0.1:8124/
Webブラウザを起動し、「http://127.0.0.1:8124/」にアクセスすると、「Hello World!!」と表示されます。
Socket.IOモジュールのインストール
npm(node package manager)を利用してSocket.IOをインストールします。npmは、次のコマンドでインストールします。
$ sudo curl https://npmjs.org/install.sh | sudo sh
では実際に、次のコマンドでSocket.IOをインストールします。新規に作業用のフォルダ(ここではmotionとします)を作成し、ここでコマンドを実行して、Socket.IOをインストールします。package.jsonのワーニングがでますが、さしあたって無視します。
$ npm install socket.io
少し時間がかかります。
動作確認
サーバー側(app.js)
var app = require('http').createServer(handler) var io = require('socket.io').listen(app); var fs = require('fs'); app.listen(9999); function handler (req, res) { fs.readFile(__dirname + '/index.html', function (err, data) { if (err) { res.writeHead(500); return res.end('Error loading index.html'); } res.writeHead(200); res.end(data); }); } //接続イベントで io.sockets.on('connection', function (socket) { //ferret イベントで tobiを受信し、wootをackとしてクライアントに送信 socket.on('ferret', function (name, fn) { fn('TomoSoft'); }); });
クライアント側(index.html)
<script src="/socket.io/socket.io.js"></script> <script> var socket = io.connect('http://192.168.0.50:9999'); socket.on('connect', function () { //ferret イベントで tobiをサーバに送信 socket.emit('ferret', 'tobi', function (data) { console.log(data); // data will be 'TomoSoft' }); }); </script>
Raspberry Piから次のコマンドの実行で、WebSocket用サーバーを立てます。
$ node app.js
raspberry piと同一のLANに接続されたPCから、ブラウザを用いて以下のURLにアクセスします
http://192.168.11.4:9999/
Firefoxで確認する場合、ツール ⇒ WEB開発 ⇒ WEBコンソールでwebコンソールを表示すると、表示されたwebコンソールで、サーバから次のデータを転送されたことが確認できます。また、サーバ側は起動したままで、何も表示されません。
“TomoSoft”
今回の実行環境では、作成したクライアント側とサーバ側のソフトが同じディレクトリにあり、Socket.IOモジュールのフォルダ「node_modules」も同じディレクトリに作りました。作成した「motion」フォルダの直下の内容を次に示します。
drwxr-xr-x 3 pi pi 4096 Oct 26 13:27 . drwxrwxrwx 13 root root 4096 Oct 26 06:22 .. -rw-rw-rw- 1 pi pi 588 Oct 26 13:34 app.js -rw-rw-rw- 1 pi pi 333 Oct 26 13:30 index.html drwxr-xr-x 3 pi pi 4096 Oct 26 06:08 node_modules
エラーメッセージ/警告メッセージについて
「node app.js」を実行したときに、次のエラーメッセージが出ることがあります。
Error: Cannot find module ‘socket.io’
これは、 実行するディレクトリが誤っている場合に表示されます。example.js のファイルが存在するディレクトリで、「$ npm install socket.io」を実行する必要があります。
Node.jsで開発をしているときに予期せぬ終了があると、Node.jsを次に起動するときに次に警告メッセージが表示されることがあります。
warn – error raised: Error: listen EADDRINUSE
これはそのポートが既に使われてる場合に発生します。つまり、異常終了時ではNode.jsプロセスが生きている場合があります。生きている場合に、このメッセージが表示されます。Node.jsのプロセスが生きている場合は、psコマンド(とgrep)でプロセス名を調べて、killでプロセスを終わらせて、Node.jsを再実行すれば解決します。
$ ps aux | grep node pi 6335 0.8 3.5 36548 15684 pts/5 T 04:53 0:04 /usr/local/node/bin/node hello_node.js pi 10291 0.0 0.1 3552 856 pts/4 S+ 05:03 0:00 grep --color=auto node