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