Intel EdsionでNode.jsのサーバを動かす

続いて、Node.js + expressでWebサーバを立ち上げてみます

パッケージマネージャの更新

Yoctoではapt-getとかではなく、opkgというパッケージマネージャを使うようです。これを最新にしておきます。 こちらを参考に

# cd /etc/opkg
# curl http://nonnoise.github.io/Edison/_sources/Edison/base-feeds.conf 
# curl http://nonnoise.github.io/Edison/_sources/Edison/intel-iotdk.conf 
# curl http://nonnoise.github.io/Edison/_sources/Edison/mraa-upm.conf

アップデートしておきます

# opkg update
# opkg upgrade

Node.jsの確認

とりあえずコマンド叩いてみましょう

# node
>
(^C again to quit)
>

間違いなくNode.jsが入ってます。バージョンは

# node -v
v0.10.28

そして、Nodeのパッケージマネージャであるnpmも入ってます

# npm

Usage: npm <command>

where <command> is one of:
    add-user, adduser, apihelp, author, bin, bugs, c, cache,
    completion, config, ddp, dedupe, deprecate, docs, edit,
    explore, faq, find, find-dupes, get, help, help-search,
    home, i, info, init, install, isntall, issues, la, link,
    list, ll, ln, login, ls, outdated, owner, pack, prefix,
    prune, publish, r, rb, rebuild, remove, repo, restart, rm,
    root, run-script, s, se, search, set, show, shrinkwrap,
    star, stars, start, stop, submodule, t, tag, test, tst, un,
    uninstall, unlink, unpublish, unstar, up, update, v,
    version, view, whoami

npm <cmd> -h     quick help on <cmd>
npm -l           display full usage info
npm faq          commonly asked questions
npm help <term>  search for help on <term>
npm help npm     involved overview

Specify configs in the ini-formatted file:
    /home/root/.npmrc
or on the command line via: npm <command> --key value
Config info can be viewed via: npm help config

npm@1.4.9 /usr/lib/node_modules/npm

expressのインストール

npmが入っているので、npmでexpressをグローバルインストールします。

# npm install -g express

expressコマンドを使いたいのですが、そのままではパスが通っていません。どこにインストールされたのか調べます

# find / -name express
/usr/lib/node_modules/iotkit-agent/node_modules/.bin/express
/usr/lib/node_modules/iotkit-agent/node_modules/express
/usr/lib/node_modules/iotkit-agent/node_modules/express/bin/express

どうやらグローバルインストールされたコマンドは.bin以下にシンボリックリンクが配置されるようなので、ここにパスを通します。ただしYoctoでは".bashrc"とか".bash_profile"ではなく、".profile"を読み込むようなので、ホームディレクトリに".profile"ファイルを作成して、そこにexportでパスを追加します。vimも無いようで、viエディタを使います。

# vi .profile

.profileにパスを追加します

export PATH=/usr/lib/node_modules/iotkit-agent/node_modules/.bin:$PATH

読み込み直します(rebootしてちゃんと読み込まれることを確認した方がいいでしょう)

# source .profile

パスを見てみます

# echo $PATH
/usr/lib/node_modules/iotkit-agent/node_modules/.bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

expressでNode.jsサーバを作成

ここまで出来たら、あとはカンタンです。expressでフレームワークを生成して、Nodeを起動するだけです。テンプレートエンジンはejsを使います。

# express -e server

   create : server
   create : server/package.json
   create : server/app.js
   create : server/public
   create : server/public/javascripts
   create : server/public/images
   create : server/public/stylesheets
   create : server/public/stylesheets/style.css
   create : server/routes
   create : server/routes/index.js
   create : server/routes/user.js
   create : server/views
   create : server/views/index.ejs

   install dependencies:
     $ cd server && npm install

   run the app:
     $ node app

# cd server && npm install

# node app.js

ifconfigで調べたEdisonのIPアドレスにポート3000でアクセスしてみましょう。

f:id:tomo_watanabe:20141031152141p:plain

というわけで、カンタンにWebサーバを起動させることができます。

たった1日で出来たWeb + Android + Arduinoのリアルタイム連携プロトタイピング

はじめに

今回のネタは、早稲田大学で行われているAndroidアプリ開発養成講座TechInstituteで、センサー回りの講座を受け持つことになり、Androidのセンサーを使った応用例として作成しました。

動作概要

Android

動作としては某L◯NEの「ふるふる」っぽい動作をAndroidでは行います。「加速度センサー」で、ある一定の加速度を超えたら、「GPSセンサー」で位置情報をサーバに送信します。Webサーバでは送信された位置情報をGoogleMapにマッピングします。

Arduino

Arduinoには何かセンサーを接続します。なんでもいいのですが、「照度センサー」とします。照度センサーにより、周囲が暗くなったらサーバに「暗くなった」ことを通知します。

Web

Webサーバは送られてきた位置情報のマッピングを行います。またブローカサーバがArduinoからのセンサー情報を、接続している全Android端末にPush配信を行います。

構成

ざっくりこんな感じです。

f:id:tomo_watanabe:20140820234129p:plain

もうちょっと詳しく書くと

f:id:tomo_watanabe:20140820234656p:plain

Androidアプリから、位置情報をMQTTプロトコルでブローカにpublishすることで、subscribeしているWebサーバがそれを受信して、GoogleMap上にマッピングします。Arduinoから「暗くなった」とブローカにpublishすると、Androidアプリでは事前にそのTopicをsubscribeしているようにしてあるので、Pushが飛んできます。※MQTTについてはこちらを参照

使っている技術は難しくありません。

  • Androidアプリ:加速度センサー、GPSセンサー、MQTTクライアント
  • Arduino:照度センサー、MQTTクライアント
  • MQTTブローカサーバ:mosquitto
  • Webサーバ:Node.js + WebSocket(Socket.IO) + MQTTライブラリ

それぞれの画面

Androidアプリ

スクリーンネームを入れて、スタートボタンを押して「振る」単純なアプリです。加速度センサーをチェックして、振れ幅が大きくなったら位置情報を送信します。

f:id:tomo_watanabe:20140820235916p:plain

Arduino

UIは無いです。Cdsセルで周囲の照度を測定して、一定値以下になったら「暗くなった」と通知します。

f:id:tomo_watanabe:20140821101028j:plain

AndroidにはPushで通知が飛んできます。

f:id:tomo_watanabe:20140821101840p:plain

Web

Node.jsでWebSocketを使用して、送信された位置情報とスクリーンネームマッピングします。

f:id:tomo_watanabe:20140821000241p:plain

作成の流れ

  1. Androidのセンサー応用例のデモを作ろう
  2. ふるふるっぽいのなら、加速度センサーとGPSセンサーでできそうだな(ここまで前日案)
  3. 位置情報を表示するMapが欲しいな。んじゃMQTTを使ってNode.jsで受けるか
  4. MQTTブローカサーバ立てる
  5. PyhtonでMQTTのPubSubのサンプルを作成して動作を確認
  6. Node.js + Socket.IOでGoogleMap表示部作成
  7. MQTTライブラリをNode.jsに組み込んで、ブローカをSubscribeするようにする
  8. PythonでMQTTのサンプルのPublishを作成して、ダミーの位置情報をブローカに送信するとNode.js上のGoogleMap上にマッピングできることを確認
  9. Androidアプリで加速度センサーとGPSを組み合わせてアプリを作る
  10. MQTTライブラリを送信用に組み込んで、8で作成したtopicフォーマットに沿って送信するようにする
  11. Andoridアプリをふるふるすると、無事GoogleMapに表示できた\(^o^)/
  12. Arduinoも講義で扱うし、ArduinoにもMQTTクライアントがあるからこれも繋げてみよう
  13. 題材で使用する照度センサーとArduino Ethernetを組み合わせてMQTTでブローカに投げるようにする
  14. Androidアプリの方にArduinoの通知を受け取れるように、MQTTブローカへのSubscribeを追加
  15. ほぼ完成\(^o^)/

ここまででほぼ1日8時間くらいの作業という感じでした(途中買い物行ったりしてので、出来たのは夜中近く)

参考情報(Topicの扱い)

  • Android

    • subscribe "PUBLIC/location/port/all/#"
    • publish "PUBLIC/location/state/hogefuga" ← hogefugaはスクリーンネームが入る
  • Node.js

    • subscribe "PUBLIC/location/state/#"
  • Arduino

    • publish "PUBLIC/location/port/all/push"

ArduinoのあたりのTopicの扱いが変だけど、最後取ってつけた関係上...

まとめ

ここに出てくる技術はひと通り経験したことがあるので、アイデアが出れば実装はさほど難しくありません。 だいたい1日の作業でこのくらいまでプロトタイピング実装できるんだなーと、あらためて今の技術の恩恵を感じました。逆に言えば、技術よりもアイデアの方が重要なのかも(こっちのが難しい)

さて、実装してみると色々展開できることが見えてきます。

MQTTなので上手くTopicのPublish/Subscribeのルールを決めてやることで

他にも

  • ボタンでの通知を時間間隔での通知にして、ジオフェンスを使った遊びや監視?
  • Arduino側をウェアラブルデバイスとしてアイデアを膨らますこともできそうです
  • Arduino側を様々な家電に置き換えて考えると、コントローラ&通知システム作れますね

ソースコードは公開してもいいのですが、なんせ1日で作ったレベルなのでちょっと...

要望があれば整理して公開できるようにするかもしれません。

Node.js + Socket.IO + pm2でデーモン化とクラスタリング

Socket.IOをpm2でクラスタリングするには、ちょっと工夫が必要だったのでメモ

forever

Node.jsのデーモン化といえばforeverです。しかしクラスタリングしようとすると、Node.jsのコードをクラスタリング対応で書かないといけないのでやや面倒だったりします。今回、foreverよりも高機能なpm2を使ってクラスタリングを試してみました。

pm2

pm2はforeverと同じようにNode.jsをデーモン化するツールですが、モニタ機能やクラスタリング機能などかなり高機能になっています。

pm2のインストール

pm2はグローバルでインストールします。

$ npm install -g pm2

対応するNode.jsのバージョンは古いと動かないかもしれません。今回はv0.10.20(on Mac)で動作確認しました。動かすNode.jsアプリはこちらのSocket.IOのサンプルアプリです。このコードだとSocket.IOのバージョンが古いようなので、一旦npm uninstall socket.ioして、再度npm install socket.ioで再インストールしました。

pm2を使ってクラスタリング

$ pm2 start app.js -i max

として起動するとプロセスがCPUコア数分だけ起動し、クラスタリングされます。簡単ですね。起動リストを表示させるには

$ pm2 list

f:id:tomo_watanabe:20140131120059p:plain

プロセスが4つ起動されているのがわかります。この時にブラウザでアクセスして確認します。

f:id:tomo_watanabe:20140131120326p:plain

片方がxhr-pollingになってたりしますね。これリロードするとwebsocketになったり、xhr-pollingになったりなんとも不安定になります。

ログを表示するには

$ pm2 logs

f:id:tomo_watanabe:20140131120712p:plain

ところどころに警告がでています。

warn  - client not handshaken client should reconnect

調べてみるとSocket.IOの接続に起因するものでSocket.IO or WebSocket を AmazonELB でバランスする検証にありました。

つまり、 Socket.IO は接続確立までに 2 回リクエストを投げるということです。 そしてこの最初の要求と、 WS の接続要求は、「同じインスタンス」にアクセスする必要があります。 二つの接続がバランスされて別々のサーバに行くと、ハンドシェイクがエラーになり、リトライが発生します。 たまたま二回同じサーバにいけば、接続が確立できるので、バランスするサーバが増えるほど成功確率が減 り、確立までの時間が長くなります。

redisの導入

解決策としてredisをセッションキーストアとして利用する、ということのようです。今更だけどSocket.ioについてまとめてみる

redisのPub/Subを利用して、各プロセス間でセッション共有をするということです。

このサイトの記事のとおりなのですが、ひと通りメモ

redisのインストールと起動

$ brew install redis
$ redis-server /usr/local/etc/redis.conf &
[1] 3234
$ [3234] 31 Jan 11:29:03.112 * Max number of open files set to 10032
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 2.8.1 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in stand alone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 3234
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

[3234] 31 Jan 11:29:03.113 # Server started, Redis version 2.8.1
[3234] 31 Jan 11:29:03.113 * The server is now ready to accept connections on port 6379

redisのpub/sub機能

redisにはpublisher/subscriberという機能があって、いずれかのプロセスが受けた通知をredisに設定することで、他のプロセスに通知を行い共有できるということです。この機能を使うことでクラスタリングされたプロセス間でセッションの共有を行えます。

サーバアプリの書き換え

app.jsを以下のように書き換えます

var app = express()
    , server = http.createServer(app)
    , redis = require('socket.io/lib/stores/redis')  // socket.ioにredisがある
    , redisConf = { host: '127.0.0.1', port: 6379 }
    , io = require('socket.io').listen(server);

// storeタイプをredisに変更
io.set('store', new redis({
    redisPub: redisConf,
    redisSub: redisConf,
    redisClient: redisConf
}));

pm2でクラスタリング

再びpm2でクラスタリングを試してみます。

$ pm2 start app.js -i max

この時のアクセスログを見ると警告が無くなり、かつ正常にクラスタリングされているようです\(^o^)/

f:id:tomo_watanabe:20140131120626p:plain

BeagleBone BlackのUbuntuにbonescriptをインストールする

デフォルトのAngstromではなく、Ubuntuの方にbonescript入れてやればいいよね?的な発想でインストール

Node.js v0.10.21でインストール

前々回にインストールしたv0.10.12でbonescriptをインストールしてみます

ubuntu@ubuntu-armhf:~$ npm install -g bonescript
npm http GET https://registry.npmjs.org/bonescript
npm http 304 https://registry.npmjs.org/bonescript

> bonescript@0.2.3 preinstall /home/ubuntu/.nodebrew/node/v0.10.21/lib/node_modules/bonescript
> node-gyp clean || (exit 0); node-gyp configure build

make: Entering directory `/home/ubuntu/.nodebrew/node/v0.10.21/lib/node_modules/bonescript/build'
  CXX(target) Release/obj.target/misc/misc.o
../misc.cpp:1:0: warning: "BUILDING_NODE_EXTENSION" redefined [enabled by default]

<--中略-->

make: *** [Release/obj.target/misc/misc.o] Error 1
make: Leaving directory `/home/ubuntu/.nodebrew/node/v0.10.21/lib/node_modules/bonescript/build'
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/home/ubuntu/.nodebrew/node/v0.10.21/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:267:23)
gyp ERR! stack     at ChildProcess.EventEmitter.emit (events.js:98:17)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (child_process.js:789:12)
gyp ERR! System Linux 3.8.13-bone30
gyp ERR! command "node" "/home/ubuntu/.nodebrew/node/v0.10.21/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "configure" "build"
gyp ERR! cwd /home/ubuntu/.nodebrew/node/v0.10.21/lib/node_modules/bonescript
gyp ERR! node -v v0.10.21
gyp ERR! node-gyp -v v0.10.10
gyp ERR! not ok 
npm ERR! weird error 1
npm ERR! not ok code 0

おうふ・・・

bonescriptは対応Nodeバージョンがある

ググったところ、こんな情報を発見。Installing Ubuntu 13.10, Node.js, bonescript.js on BBB

I had to make some changes when installing node.js in order to get bonescript.js installed. Bonescript.js is only compatible with node.js v0.8 Github issue #53.

たしかにAngstromの場合v0.8.22でした。というわけで、v0.8.22をインストール。こういう時にnodebrewを使ってると便利ですね。

Node.js v0.8.22をインストール

ubuntu@ubuntu-armhf:~$ nodebrew install v0.8.22

-- ビルド約1時間--

ubuntu@ubuntu-armhf:~$ nodebrew ls
v0.8.22
v0.10.21

current: v0.10.21
ubuntu@ubuntu-armhf:~$ nodebrew use v0.8.22
use v0.8.22

あらためてbonescriptをインストール

ubuntu@ubuntu-armhf:~$ npm install -g bonescript

> serialport@1.0.6 install /home/ubuntu/.nodebrew/node/v0.8.22/lib/node_modules/bonescript/node_modules/serialport
> node-gyp rebuild

-- 中略 --
make: Entering directory `/home/ubuntu/.nodebrew/node/v0.8.22/lib/node_modules/bonescript/node_modules/serialport/build'
  CXX(target) Release/obj.target/serialport/src/serialport.o
  CXX(target) Release/obj.target/serialport/src/serialport_unix.o
  SOLINK_MODULE(target) Release/obj.target/serialport.node
  SOLINK_MODULE(target) Release/obj.target/serialport.node: Finished
  COPY Release/serialport.node
make: Leaving directory `/home/ubuntu/.nodebrew/node/v0.8.22/lib/node_modules/bonescript/node_modules/serialport/build'
bonescript@0.2.3 /home/ubuntu/.nodebrew/node/v0.8.22/lib/node_modules/bonescript
├── systemd@0.2.0
├── i2c@0.1.4 (bindings@1.1.1, repl@0.1.3, underscore@1.2.4, coffee-script@1.3.3)
├── winston@0.6.2 (cycle@1.0.3, stack-trace@0.0.7, eyes@0.1.8, colors@0.6.2, pkginfo@0.2.3, async@0.1.22, request@2.9.203)
├── express@3.1.0 (methods@0.0.1, fresh@0.1.0, cookie-signature@0.0.1, range-parser@0.0.4, debug@0.7.4, buffer-crc32@0.1.1, cookie@0.0.5, commander@0.6.1, mkdirp@0.3.3, send@0.1.0, connect@2.7.2)
├── socket.io@0.8.7 (policyfile@0.0.4, redis@0.6.7, socket.io-client@0.8.7)
└── serialport@1.0.6 (bindings@0.3.0, sf@0.1.3, async@0.1.18, optimist@0.3.7, node-gyp@0.6.2)

expressやらsocket.io, serialportなども同時にインストールされるようです。リストを取ってみます

ubuntu@ubuntu-armhf:~$ npm list -g
/home/ubuntu/.nodebrew/node/v0.8.22/lib
├─┬ bonescript@0.2.3
│ ├─┬ express@3.1.0
│ │ ├── buffer-crc32@0.1.1
│ │ ├── commander@0.6.1
│ │ ├─┬ connect@2.7.2
│ │ │ ├── bytes@0.1.0
│ │ │ ├── formidable@1.0.11
│ │ │ ├── pause@0.0.1
│ │ │ └── qs@0.5.1
│ │ ├── cookie@0.0.5
│ │ ├── cookie-signature@0.0.1
│ │ ├── debug@0.7.4
│ │ ├── fresh@0.1.0
│ │ ├── methods@0.0.1
│ │ ├── mkdirp@0.3.3
│ │ ├── range-parser@0.0.4
│ │ └─┬ send@0.1.0
│ │   └── mime@1.2.6
│ ├─┬ i2c@0.1.4
│ │ ├── bindings@1.1.1
│ │ ├── coffee-script@1.3.3
│ │ ├── repl@0.1.3
│ │ └── underscore@1.2.4
│ ├─┬ serialport@1.0.6
│ │ ├── async@0.1.18
│ │ ├── bindings@0.3.0
│ │ ├─┬ node-gyp@0.6.2
│ │ │ ├─┬ fstream@0.1.25
│ │ │ │ ├── graceful-fs@2.0.1
│ │ │ │ └── inherits@2.0.1
│ │ │ ├─┬ glob@3.2.7
│ │ │ │ └── inherits@2.0.1
│ │ │ ├── graceful-fs@1.2.3
│ │ │ ├─┬ minimatch@0.2.14
│ │ │ │ ├── lru-cache@2.5.0
│ │ │ │ └── sigmund@1.0.0
│ │ │ ├── mkdirp@0.3.5
│ │ │ ├─┬ nopt@2.1.2
│ │ │ │ └── abbrev@1.0.4
│ │ │ ├─┬ npmlog@0.0.6
│ │ │ │ └── ansi@0.2.1
│ │ │ ├── osenv@0.0.3
│ │ │ ├── request@2.9.203
│ │ │ ├── rimraf@2.2.5
│ │ │ ├── semver@1.1.4
│ │ │ ├─┬ tar@0.1.19
│ │ │ │ ├── block-stream@0.0.7
│ │ │ │ └── inherits@2.0.1
│ │ │ └── which@1.0.5
│ │ ├─┬ optimist@0.3.7
│ │ │ └── wordwrap@0.0.2
│ │ └── sf@0.1.3
│ ├─┬ socket.io@0.8.7
│ │ ├── policyfile@0.0.4
│ │ ├── redis@0.6.7
│ │ └─┬ socket.io-client@0.8.7
│ │   ├── uglify-js@1.0.6
│ │   ├── websocket-client@1.0.0
│ │   └── xmlhttprequest@1.2.2
│ ├── systemd@0.2.0
│ └─┬ winston@0.6.2
│   ├── async@0.1.22
│   ├── colors@0.6.2
│   ├── cycle@1.0.3
│   ├── eyes@0.1.8
│   ├── pkginfo@0.2.3
│   ├── request@2.9.203
│   └── stack-trace@0.0.7
└─┬ npm@1.2.14
  ├── abbrev@1.0.4
  ├── ansi@0.1.2
  ├── archy@0.0.2
  ├── block-stream@0.0.6
  ├── chmodr@0.1.0
  ├── chownr@0.0.1
  ├── fstream@0.1.22
  ├─┬ fstream-npm@0.1.3
  │ └── fstream-ignore@0.0.6
  ├── glob@3.1.21
  ├── graceful-fs@1.2.0
  ├── inherits@1.0.0
  ├── ini@1.1.0
  ├─┬ init-package-json@0.0.6
  │ └── promzard@0.2.0
  ├── lockfile@0.3.0
  ├── lru-cache@2.2.2
  ├─┬ minimatch@0.2.11
  │ └── sigmund@1.0.0
  ├── mkdirp@0.3.5
  ├── node-gyp@0.8.5
  ├── nopt@2.1.1
  ├─┬ npm-registry-client@0.2.18
  │ └── couch-login@0.1.15
  ├─┬ npmconf@0.0.23
  │ └─┬ config-chain@1.1.5
  │   └── proto-list@1.2.2
  ├── npmlog@0.0.2
  ├── once@1.1.1
  ├── opener@1.3.0
  ├── osenv@0.0.3
  ├─┬ read@1.0.4
  │ └── mute-stream@0.0.3
  ├── read-installed@0.1.1
  ├── read-package-json@0.2.2
  ├── request@2.9.203
  ├── retry@0.6.0
  ├── rimraf@2.1.4
  ├── semver@1.1.4
  ├── slide@1.1.3
  ├── tar@0.1.16
  ├── uid-number@0.0.3
  └── which@1.0.5

これでUbuntuでもbonescriptを使ったNodeアプリが書ける・・・はず>たぶん次回

BeagleBone BlackのAngstrom Linuxに入ってるNode.jsについて

ちょっとだけ調べてみました。

Nodeのバージョン

root@beaglebone:~# node -v
v0.8.22

Node Package Managerも入っているようです

root@beaglebone:~# npm

Usage: npm <command>

where <command> is one of:
    add-user, adduser, apihelp, author, bin, bugs, c, cache,
    completion, config, ddp, dedupe, deprecate, docs, edit,
    explore, faq, find, find-dupes, get, help, help-search,
    home, i, info, init, install, isntall, issues, la, link,
    list, ll, ln, login, ls, outdated, owner, pack, prefix,
    prune, publish, r, rb, rebuild, remove, restart, rm, root,
    run-script, s, se, search, set, show, shrinkwrap, star,
    stars, start, stop, submodule, tag, test, tst, un,
    uninstall, unlink, unpublish, unstar, up, update, version,
    view, whoami

npm <cmd> -h     quick help on <cmd>
npm -l           display full usage info
npm faq          commonly asked questions
npm help <term>  search for help on <term>
npm help npm     involved overview

Specify configs in the ini-formatted file:
    /home/root/.npmrc
or on the command line via: npm <command> --key value
Config info can be viewed via: npm help config

npm@1.2.14 /usr/lib/node_modules/npm

Nodeのパッケージを調べてみる

root@beaglebone:~# npm list -g
/usr/lib
├─┬ bonescript@0.2.2
│ ├─┬ express@3.1.0
│ │ ├── buffer-crc32@0.1.1
│ │ ├── commander@0.6.1
│ │ ├─┬ connect@2.7.2
│ │ │ ├── bytes@0.1.0
│ │ │ ├── formidable@1.0.11
│ │ │ ├── pause@0.0.1
│ │ │ └── qs@0.5.1
│ │ ├── cookie@0.0.5
│ │ ├── cookie-signature@0.0.1
│ │ ├── debug@0.7.2
│ │ ├── fresh@0.1.0
│ │ ├── methods@0.0.1
│ │ ├── mkdirp@0.3.3
│ │ ├── range-parser@0.0.4
│ │ └─┬ send@0.1.0
│ │   └── mime@1.2.6
│ ├── UNMET DEPENDENCY serialport 0.7.5
│ ├─┬ socket.io@0.8.7
│ │ ├── policyfile@0.0.4
│ │ ├── redis@0.6.7
│ │ └─┬ socket.io-client@0.8.7
│ │   ├── uglify-js@1.0.6
│ │   ├── websocket-client@1.0.0
│ │   └── xmlhttprequest@1.2.2
│ ├── systemd@0.2.0
│ └─┬ winston@0.6.2
│   ├── async@0.1.22
│   ├── colors@0.6.0-1
│   ├── cycle@1.0.2
│   ├── eyes@0.1.8
│   ├── pkginfo@0.2.3
│   ├── request@2.9.203
│   └── stack-trace@0.0.6
└─┬ npm@1.2.14
  ├── abbrev@1.0.4
  ├── ansi@0.1.2
  ├── archy@0.0.2
  ├── block-stream@0.0.6
  ├── chmodr@0.1.0
  ├── chownr@0.0.1
  ├── fstream@0.1.22
  ├─┬ fstream-npm@0.1.3
  │ └── fstream-ignore@0.0.6
  ├── glob@3.1.21
  ├── graceful-fs@1.2.0
  ├── inherits@1.0.0
  ├── ini@1.1.0
  ├─┬ init-package-json@0.0.6
  │ └── promzard@0.2.0
  ├── lockfile@0.3.0
  ├── lru-cache@2.2.2
  ├─┬ minimatch@0.2.11
  │ └── sigmund@1.0.0
  ├── mkdirp@0.3.5
  ├── node-gyp@0.8.5
  ├── nopt@2.1.1
  ├─┬ npm-registry-client@0.2.18
  │ └── couch-login@0.1.15
  ├─┬ npmconf@0.0.23
  │ └─┬ config-chain@1.1.5
  │   └── proto-list@1.2.2
  ├── npmlog@0.0.2
  ├── once@1.1.1
  ├── opener@1.3.0
  ├── osenv@0.0.3
  ├─┬ read@1.0.4
  │ └── mute-stream@0.0.3
  ├── read-installed@0.1.1
  ├── read-package-json@0.2.2
  ├── request@2.9.203
  ├── retry@0.6.0
  ├── rimraf@2.1.4
  ├── semver@1.1.4
  ├── slide@1.1.3
  ├── tar@0.1.16
  ├── uid-number@0.0.3
  └── which@1.0.5

npm ERR! missing: serialport@0.7.5, required by bonescript@0.2.2
npm ERR! not ok code 0

ふむふむ、bonescriptはもちろん、express, socket.io, serialportなどがグローバルインストールされていました。ということは、AngstromのままでもNode.jsでプログラム書いて動かして遊ぶのもいいですね

BeagleBone BlackにNode.jsをインストールする2(セルフビルド)

前回のおさらい

見事にビルドに失敗・・・ググってみたら、傘のお肉はどこにあるの?知り合いの@iwata_nのブログに引っ掛かったw

つまりは

./configure --without-snapshot

が必要ということなので、nodebrewのソースを修正して対応します。

nodebrew本体のコード(~./nodebrew/nodebrew)の「sub _cmd_install」にあるConfigureに--without-snapshotを追加します

system qq[
    cd "$src_dir/$target_name" &&
    ./configure --without-snapshot --prefix="$self->{node_dir}/$version" &&
    make &&
    make install
];

これでもう一度インストールしてみます。一旦さっきのバージョンをuninstallしておいてから再度インストール。

ubuntu@ubuntu-armhf:~$ nodebrew uninstall v0.10.21
v0.10.21 uninstalled
ubuntu@ubuntu-armhf:~$ nodebrew ls
not installed

current: none
ubuntu@ubuntu-armhf:~$ nodebrew install v0.10.21
fetch: http://nodejs.org/dist/v0.10.21/node-v0.10.21.tar.gz
######################################################################## 100.0%
{ 'target_defaults': { 'cflags': [],
                       'default_configuration': 'Release',
                       'defines': [],
                       'include_dirs': [],
                       'libraries': []},
  'variables': { 'arm_fpu': 'vfpv3',
                 'arm_neon': 0,
                 'armv7': 1,
                 'clang': 0,
                 'gcc_version': 46,
                 'host_arch': 'arm',
                 'node_install_npm': 'true',
                 'node_prefix': '/home/ubuntu/.nodebrew/node/v0.10.21',
                 'node_shared_cares': 'false',
                 'node_shared_http_parser': 'false',
                 'node_shared_libuv': 'false',
                 'node_shared_openssl': 'false',
                 'node_shared_v8': 'false',
                 'node_shared_zlib': 'false',
                 'node_tag': '',
                 'node_unsafe_optimizations': 0,
                 'node_use_dtrace': 'false',
                 'node_use_etw': 'false',
                 'node_use_openssl': 'true',
                 'node_use_perfctr': 'false',
                 'node_use_systemtap': 'false',
                 'python': '/usr/bin/python',
                 'target_arch': 'arm',
                 'v8_enable_gdbjit': 0,
                 'v8_no_strict_aliasing': 1,
                 'v8_use_arm_eabi_hardfloat': 'true',
                 'v8_use_snapshot': 'false'}}

「'v8_use_snapshot': 'false'」になっています。失敗した時のログを見てみると

fetch: http://nodejs.org/dist/v0.10.21/node-v0.10.21.tar.gz
######################################################################## 100.0%
{ 'target_defaults': { 'cflags': [],
                       'default_configuration': 'Release',
                       'defines': [],
                       'include_dirs': [],
                       'libraries': []},
  'variables': { 'arm_fpu': 'vfpv3',
                 'arm_neon': 0,
                 'armv7': 1,
                 'clang': 0,
                 'gcc_version': 46,
                 'host_arch': 'arm',
                 'node_install_npm': 'true',
                 'node_prefix': '/home/ubuntu/.nodebrew/node/v0.10.21',
                 'node_shared_cares': 'false',
                 'node_shared_http_parser': 'false',
                 'node_shared_libuv': 'false',
                 'node_shared_openssl': 'false',
                 'node_shared_v8': 'false',
                 'node_shared_zlib': 'false',
                 'node_tag': '',
                 'node_unsafe_optimizations': 0,
                 'node_use_dtrace': 'false',
                 'node_use_etw': 'false',
                 'node_use_openssl': 'true',
                 'node_use_perfctr': 'false',
                 'node_use_systemtap': 'false',
                 'python': '/usr/bin/python',
                 'target_arch': 'arm',
                 'v8_enable_gdbjit': 0,
                 'v8_no_strict_aliasing': 1,
                 'v8_use_arm_eabi_hardfloat': 'true',
                 'v8_use_snapshot': 'true'}}

こちらはtrueになっていました。

さてまたしても1時間経過・・・ビルド完了

symlinking ../lib/node_modules/npm/bin/npm-cli.js -> /home/ubuntu/.nodebrew/node/v0.10.21/bin/npm
updating shebang of /home/ubuntu/.nodebrew/node/v0.10.21/bin/npm to /home/ubuntu/.nodebrew/node/v0.10.21/bin/node
ubuntu@ubuntu-armhf:~$ nodebrew ls
v0.10.21

current: none
ubuntu@ubuntu-armhf:~$ nodebrew use v0.10.21
use v0.10.21
ubuntu@ubuntu-armhf:~$ node
>

というわけで、無事Node.jsが起動できるようになりました。

BeagleBone BlackにNode.jsをインストールする(セルフビルド)

いつものようにNode.jsをインストールします。今回はnvmではなくnodebrewを使い、セルフビルドにてインストールします。

BeagleBone Black用のNode.js

ビルドするのが面倒な方はこちらにインストールバイナリがありますので、こちらを使ったほうが楽チンです。その場合はnodebrewは必要ありません。このリンク先のNode.jsのバージョンはv0.10.21なので、同じバージョンをnodebrewでセルフビルドでインストールします

ビルド環境のインストール

ubuntu@ubuntu-armhf:~$ sudo apt-get install curl build-essential libssl-dev

nodebrewのインストール

nodebrewに関してはBlock Rockin’ Codesに記事があるのでご参考に。nodebrewのサイトはこちらです。サイトにあるように下記コマンドでインストールできます。なおnodebrewをインストールするとnpm(Node Package Manager)も同時にインストールされます。

ubuntu@ubuntu-armhf:~$ curl -L git.io/nodebrew | perl - setup
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 18651  100 18651    0     0  18947      0 --:--:-- --:--:-- --:--:-- 18947
fetching nodebrew...
install nodebrew in $HOME/.nodebrew

========================================
Add path:

export PATH=$HOME/.nodebrew/current/bin:$PATH
========================================

インストールしたら、上記パスをvimなどで.bashrcに追加して、sourceコマンドで読み込みなおしておきます

ubuntu@ubuntu-armhf:~$ vim .bashrc
ubuntu@ubuntu-armhf:~$ source .bashrc 

nodebrew ls-remoteで使えるNode.jsのバージョンが取得できます

ubuntu@ubuntu-armhf:~$ nodebrew ls-remote
-- 省略--
v0.9.0    v0.9.1    v0.9.2    v0.9.3    v0.9.4    v0.9.5    v0.9.6    v0.9.7
v0.9.8    v0.9.9    v0.9.10   v0.9.11   v0.9.12   

v0.10.0   v0.10.1   v0.10.2   v0.10.3   v0.10.4   v0.10.5   v0.10.6   v0.10.7
v0.10.8   v0.10.9   v0.10.10  v0.10.11  v0.10.12  v0.10.13  v0.10.14  v0.10.15
v0.10.16  v0.10.17  v0.10.18  v0.10.19  v0.10.20  v0.10.21  v0.10.22  v0.10.23


v0.11.0   v0.11.1   v0.11.2   v0.11.3   v0.11.4   v0.11.5   v0.11.6   v0.11.7
v0.11.8   v0.11.9   

nodebrewにはバイナリのインストール機能がありますので、試しにv0.10.21をインストールしようとすると、サポートしてないよ!ってエラーが出てしまいます。

ubuntu@ubuntu-armhf:~$ nodebrew install-binary v0.10.21
Error: Linux armv7l is not supported. at /home/ubuntu/.nodebrew/current/bin/nodebrew line 585.

Node.jsのセルフビルドでのインストール

というわけで、セルフビルドでインストールします (ちなみに以下、失敗します...ちゃんと動くようにビルドするにはコチラへ)

ubuntu@ubuntu-armhf:~$ nodebrew install v0.10.21

セルフビルドは約1時間・・・(class2のSDカードだったのでclass10だともっと速いと思われ)

installing /home/ubuntu/.nodebrew/node/v0.10.21/lib/node_modules/npm/lib/utils/completion/installed-shallow.js
installing /home/ubuntu/.nodebrew/node/v0.10.21/lib/node_modules/npm/lib/utils/completion/file-completion.js
symlinking ../lib/node_modules/npm/bin/npm-cli.js -> /home/ubuntu/.nodebrew/node/v0.10.21/bin/npm
updating shebang of /home/ubuntu/.nodebrew/node/v0.10.21/bin/npm to /home/ubuntu/.nodebrew/node/v0.10.21/bin/node

ちゃんとインストールされたか確認

ubuntu@ubuntu-armhf:~$ nodebrew ls
v0.10.21

current: none

v0.10.21を使用するように指定

ubuntu@ubuntu-armhf:~$ nodebrew use v0.10.21
use v0.10.21
ubuntu@ubuntu-armhf:~$ 

さて、ではnodeを起動してみます

ubuntu@ubuntu-armhf:~$ node 
Segmentation fault

_人人人人人人人人人人人_
> Segmentation fault <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄

...orz

続く