Mosquitto(MQTT)を動かしてみた

MQTTとは

MQTT(MQ Telemetry Transport : MQはMessage Queuing?)というプロトコルで、TCP/IP層で動作するWebSocketっぽいもの(ザックリ)。詳しくはそこはかとなく書くよん。を見てもらった方が分かりやすいです。簡単に言えば、M2Mでの使用を考えた軽量なメッセージプロトコルという感じです。Mosquittoはブローカの実装で使用します。

2013年のカンファレンスでは、2011年当時の「Beluga」(現Facebook Messenger)に使われているという発表があったようです

MQTTのブローカとクライアントの動作確認の構成

今回下記のような構成でMQTTの動作確認を行いました。

  • ブローカ(サーバ):Mosquitto
  • クライアント:Paho Python版クライアント

f:id:tomo_watanabe:20140418232239p:plain

Mosquittoにsub.pyで接続し、pub.pyによってpublishされるとsub.py側に出力されることを確認します。

Mosquitto(ブローカ)のインストール

パッケージからインストール

Ubuntuでは基本的にはパッケージインストールができるので

$ sudo apt-get install mosquitto

以上でインストールと起動まで完了します。停止・再起動はserviceコマンドで行えます。

ソースからコンパイルする場合

開発環境のインストール

$ sudo apt-get install gcc make g++ libssl-dev libc-ares-dev

Mosquittoのダウンロードページからソースを落として展開し、makeしてインストールします。

$ wget http://mosquitto.org/files/source/mosquitto-1.3.1.tar.gz
$ tar -xvzf http://mosquitto.org/files/source/mosquitto-1.3.1.tar.gz
$ cd mosquitto-1.3.1
$ make
$ sudo make install

環境設定ファイルを設定します。

$ sudo cp /etc/mosquitto/mosquitto.conf.example /etc/mosquitto/mosquitto.conf

デフォルトでMQTTは1883ポートを使用します。必要に応じてサーバのポートを開放します。

起動します。

※引数なしの起動方法では前述のconfファイルは使われず、デフォルトで起動します。-cオプションでファイルを指定する必要がありますが、何も修正していなければ動作はデフォルトとなります。

$ mosquitto
1397719018: mosquitto version 1.3.1 (build date 2014-04-17 15:13:13+0900) starting
1397719018: Using default config.
1397719018: Opening ipv4 listen socket on port 1883.
1397719018: Opening ipv6 listen socket on port 1883.

この場合、サーバがIPv4/6両対応なので、ポートそれぞれでリッスンしている状態になります。

PahoクライアントでPub/Subを実行する

Pahoの下の方に各言語用のダウンロードリンクがありますので、そこからcloneしてきて利用するのがいいのと思います。今回はPythonクライアントのexampleを少し修正してsub.pyとpub.pyを作成しました。

paho MQTT pythonライブラリのインストール

$ sudo pip install paho-mqtt

sub.pyの実行

詳しい解説は後回しにしてまずは実行してみましょう。まずは待ち受けのsub.pyを実行しておきます。

コードはsub.pyにあります。

起動して、ブローカサーバに接続するとこのようなメッセージになります。

$ python sub.py
rc: 0
Subscribed: 1 (0,)

ブローカサーバへの接続が失敗した場合こんなメッセージが出ます。

Traceback (most recent call last):
  File "sub.py", line 60, in <module>
    mqttc.connect("HOST", 1883, 60)
  File "/Library/Python/2.7/site-packages/paho/mqtt/client.py", line 588, in connect
    return self.reconnect()
  File "/Library/Python/2.7/site-packages/paho/mqtt/client.py", line 710, in reconnect
    self._sock = socket.create_connection((self._host, self._port), source_address=(self._bind_address, 0))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 571, in create_connection
    raise err
socket.error: [Errno 61] Connection refused

接続に成功していればブローカサーバ(Mosquitto)の方では以下のようなメッセージが表示されているはずです

1397719236: New connection from 2001:3e0:0:*:*:*:*on port 1883.
1397719236: New client connected from 2001:3e0:0:*:*:*:* as paho/E917914937EA634F0F (c1, k60).

一部"*"でマスクしています。

pub.pyの実行

次にpub.pyを実行して、メッセージを送信します。

コードはpub.pyにあります。

コンソールをもう一つ開いてpub.pyを実行すると直ぐに終了します。

$ python pub.py
1

sub.pyの出力の方を見てみると、1行メッセージが追加されていると思います。

rc: 0
Subscribed: 1 (0,)
message 0 Hello MQTT!

pub.pyを実行することにより、subscribeしていたsub.pyの方にメッセージ送信が行われたことがわかります。

解説

sub.pyの方から見ていきます。(以下抜粋)

# メッセージを受信した時に呼ばれる。
def on_message(mqttc, obj, msg):
    print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))

# 接続先のブローカを設定する
mqttc.connect("HOST NAME", 1883, 60)
# "message"というtopicをsubscribeする
mqttc.subscribe("message", 0)

sub.pyは起動すると"message"というtopicが来るまで待機状態になります。pub.pyを実行して。メッセージを受信すると、topicとqosとpayloadを表示します。今の場合は

  • topic : message
  • qos: 0
  • payload : Hello MQTT!

pub.pyの方はこれだけですね。

publish.single("message", "Hello MQTT!", hostname="HOST NAME")

"message"というtopicに"Hello MQTT!"を送信しています。qosは省略されていますが、デフォルトが0になっています。今回は簡単にするためにtopcを"message"としましたが、これを"$SYS/#"のようにワイルドカードで指定したり、"paho/test/single"のようにすることもできます。この指定の仕方はMQTTの仕様のようで、これを利用して各々のM2M機器がsubscribeする対象を設定できるようになっています。

まとめ

MQTTを実動作させるテストを行いました。MQTTの実装はLinuxMacだけでなく、mbedやArduinoAndroidなどにもありますし、様々な言語での実装もあります。またNode.jsでWebSocketと組み合わせてブラウザへの出力もできます(この辺は後日)僕はこのM2M用途としてのMQTTはよく知らなかったのですが、実際使用してみると結構いろいろなことが出来そうな気がします。プロトコルはシンプルだし、QoSの概念が導入されているのも面白い点です。

BeagleBone Blackにcloud9をインストールする

UbuntuをインストールしたBeagleBone Blackにcloud9 IDEをインストールしてみます。

cloud9 IDEとは

BeagleBone Blackに標準インストールのAngstrom上にプリインストールされている、Node.jsを利用したブラウザIDE環境です。今回はUbuntuに入れ替えてあるので、ここにcloud9 IEDを追加でインストールします。

cloud9 IDEのインストール

cloud9 IDEはgitihubに公開されていますので、これをインストールすれば動くはずです。

Requirements:

  • NodeJS >= 0.6.16
  • NPM >= 1.1.16
  • libxml2-dev

となっていますが、すでにNode.jsは0.8.22をnodebrewを使ってインストール済みで、同時にNPMもインストールされているので、libxml2-devをインストールします。

$ sudo apt-get install libxml2-dev

次にcloud9をインストールします

$ git clone https://github.com/ajaxorg/cloud9.git
$ cd cloud9
$ npm install

cloud9 IDEの起動

cloud9はデフォルトで起動すると、localhostからしかアクセスできないので、外部からブラウザ経由でアクセスするためには。以下のように起動します。

$ bin/cloud9.sh -l 0.0.0.0
make: Nothing to be done for `worker'.
Linux ARM
connect plugin start
Connect server listening at http://0.0.0.0:3131
IDE SERVER PLUGIN:  auth
IDE SERVER PLUGIN:  git
IDE SERVER PLUGIN:  gittools
IDE SERVER PLUGIN:  hg
IDE SERVER PLUGIN:  npm
IDE SERVER PLUGIN:  filelist
IDE SERVER PLUGIN:  search
IDE SERVER PLUGIN:  revisions
IDE SERVER PLUGIN:  settings
IDE SERVER PLUGIN:  shell
IDE SERVER PLUGIN:  state
IDE SERVER PLUGIN:  watcher
IDE SERVER PLUGIN:  node-runtime
IDE SERVER PLUGIN:  npm-runtime
IDE SERVER PLUGIN:  python-runtime
IDE SERVER PLUGIN:  apache-runtime
IDE SERVER PLUGIN:  ruby-runtime
IDE SERVER PLUGIN:  php-runtime
Started '/home/ubuntu/cloud9/configs/default'!
IDE server initialized. Listening on 0.0.0.0:3131

ポートは3131で起動していますので、BeagleBone BlackのIPアドレスを調べてアクセスしてみましょう。

f:id:tomo_watanabe:20131228220414p:plain

LEDの点灯・消灯サンプル

clou9が起動したら、サンプルアプリを動かしてみましょう。「New File」で新規ファイルを作成します。led.jsとかファイル名を付けておきます。下記はBoneScriptを使って、LEDを制御するプログラムです。

/**
 * LED点灯、2秒後に消灯
 */
var b = require('bonescript');

// LEDの設定
b.pinMode('USR0', b.OUTPUT);
b.pinMode('USR1', b.OUTPUT);
b.pinMode('USR2', b.OUTPUT);
b.pinMode('USR3', b.OUTPUT);

// LEDをONに
b.digitalWrite('USR0', b.HIGH);
b.digitalWrite('USR1', b.HIGH);
b.digitalWrite('USR2', b.HIGH);
b.digitalWrite('USR3', b.HIGH);

// 2秒後にLEDをOFFに
setTimeout(function() {
    b.digitalWrite('USR0', b.LOW);
    b.digitalWrite('USR1', b.LOW);
    b.digitalWrite('USR2', b.LOW);
    b.digitalWrite('USR3', b.LOW);
}, 2000);

実行してみます。

Running Node Process
Your code is running at 'http://0.0.0.0:21479'.
Important: in your scripts, use 'process.env.PORT' as port and '0.0.0.0' as host.
fs.js:338
  return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
                ^
Error: EACCES, permission denied '/sys/class/leds/beaglebone:green:usr0/trigger'
    at Object.fs.openSync (fs.js:338:18)
    at Object.fs.writeFileSync (fs.js:756:15)
    at Object.f.pinMode (/home/ubuntu/cloud9/node_modules/bonescript/index.js:132:20)
    at Object. (/home/ubuntu/cloud9/myScript/led1.js:7:3)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)
    at process.startup.processNextTick.process._tickCallback (node.js:245:9)

どうやら、LEDへのアクセス権が無いということで怒られてしまいました....cloud9をroot権限で実行してやらないと、デバイスへのアクセスは出来ないようです。

$ sudo bin/cloud9.sh 
make: Nothing to be done for `worker'.
Linux ARM
bin/cloud9.sh: 18: bin/cloud9.sh: node: not found

今度はnodeが無いと怒られてしまいました。nodebrewをubuntuユーザでインストールしたため、rootユーザにnodeがインストールされていません。これを回避するには

  • rootでnodeをインストール
  • rootでcloud9を起動し、ubuntuユーザのnodeパスを指定

のどちらかを選択することになりますが、今回はnodeがすでにインストールされているので後者の方法で起動します。cloud.shを下記のように書き換えます。

Linux*arm*)  echo "Linux ARM"
    /home/ubuntu/.nodebrew/current/bin/node server.js "$@" -a x-www-browser
    ;;

BeagleBone Blackは"Linux ARM"なので、ここの部分をnodebrewのcurrentのnodeが起動するように修正します。これでもう一度起動して、先ほどのプログラムを実行します。

$ sudo bin/cloud9.sh -l 0.0.0.0
make: Nothing to be done for `worker'.
Linux ARM
connect plugin start
Connect server listening at http://0.0.0.0:3131
IDE SERVER PLUGIN:  auth
IDE SERVER PLUGIN:  git
IDE SERVER PLUGIN:  gittools
IDE SERVER PLUGIN:  hg
IDE SERVER PLUGIN:  npm
IDE SERVER PLUGIN:  filelist
IDE SERVER PLUGIN:  search
IDE SERVER PLUGIN:  revisions
IDE SERVER PLUGIN:  settings
IDE SERVER PLUGIN:  shell
IDE SERVER PLUGIN:  state
IDE SERVER PLUGIN:  watcher
IDE SERVER PLUGIN:  node-runtime
IDE SERVER PLUGIN:  npm-runtime
IDE SERVER PLUGIN:  python-runtime
IDE SERVER PLUGIN:  apache-runtime
IDE SERVER PLUGIN:  ruby-runtime
IDE SERVER PLUGIN:  php-runtime
Started '/home/ubuntu/cloud9/configs/default'!
IDE server initialized. Listening on 0.0.0.0:3131

今度はLEDが一斉に点灯して、2秒後に消灯するように動くはずです。

おわりに

BoneScriptは簡単にLEDやGPIOを制御できる便利なライブラリです。以前BoneScriptのライブラリ構成を調べましたが、socket.ioやserialportも入ってると思ったのですが、これらはBoneScript配下で使用されるようで、自分で意識して扱う場合には別途インストールする必要があるようです。

cloud9 IDEはBeagelBone Black上でGPIO制御などの動作確認やプロトタイピングにはいいのですが、実際にNode.jsサーバを動かすといった場合には、いつものようexpressなどを使うのが良いと思われます。おそらくBoneScriptはそのまま使えるので、上手く利用できるでしょう。

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

続く

BeagleBone BlackにUbuntu12.04をインストールする

作業の備忘録として記録しています。Raspberry Piを触っていれば、ほぼ同じような手順ですが・・・ (本当はIntel Galileoで遊ぶつもりが発売が年明けに延びたので、こっちをやっつけることに...)

追記 この方法では、SDカードからのブート時に「ボタン」を押す必要がありますが、きんねこさんが押さなくても起動するように、解決してくれました。 armhf.comで配布しているUbuntuイメージはボタン押さないと起動できない件 解決方法は最後に追記しました

BeagleBone Blackの購入

たまたま寄った秋月電子に最新版のRev A6が売ってたので購入¥4,980

f:id:tomo_watanabe:20131215153638j:plain

UbuntuをSDカードに書き込む

ホストマシンはMacintoshです。まずはBeagleBone Black用のUbuntuイメージをダウンロードします。今回はLTS版のPrecidse 12.04を使います

ダウンロードしたら解凍します。

$ xz -d ubuntu-precise-12.04.3-armhf-3.8.13-bone30.img.xz

解凍して出来たイメージをSDカードに書き込みます。使用するmicroSDは2GB以上のclass10が良いでしょう。ddコマンドで書きこめばいいのですが、Raspberry Piで使用した「RPi-sd card builder」などを使うと楽になります。

Ubuntuから起動

LANケーブルを接続しておき、SDカードを本体に差し込み起動しますが、そのままでは起動しないので、Bootボタンを押しながら電源を入れます。LEDが点滅し始めたら離しても大丈夫のようです(離すまでの時間が曖昧・・・)無事起動していればsshでログインできるはずです。

f:id:tomo_watanabe:20131215163844p:plain

$ ssh ubuntu@192.168.0.6 <— BeagleBone Blackのアドレス
ubuntu@192.168.0.6's password: 
Welcome to Ubuntu 12.04.3 LTS (GNU/Linux 3.8.13-bone30 armv7l)

 * Documentation:  https://help.ubuntu.com/

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

ubuntu@ubuntu-armhf:~$

パーティションの拡張

今回は4GBのSDカードを使ったのですが、そのままではブートイメージのサイズ上2GBしか使用できないので、パーティションの拡張を行います。電子工作マスターへの歩みを参考にfdiskで拡張します

ubuntu@ubuntu-armhf:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs          1.8G  244M  1.5G  15% /
/dev/root       1.8G  244M  1.5G  15% /
devtmpfs        248M  4.0K  248M   1% /dev
none             50M  224K   50M   1% /run
none            5.0M     0  5.0M   0% /run/lock
none            248M     0  248M   0% /run/shm
/dev/mmcblk0p1 1004K  480K  524K  48% /boot/uboot

今はまだサイズが1.8GBになってますので、fdiskで拡張します

ubuntu@ubuntu-armhf:~$ sudo fdisk /dev/mmcblk0
ommand (m for help): p

Disk /dev/mmcblk0: 4023 MB, 4023386112 bytes
4 heads, 16 sectors/track, 122784 cylinders, total 7858176 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x80008000

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1   *        2048        4095        1024    1  FAT12
/dev/mmcblk0p2            4096     3751935     1873920   83  Linux

Command (m for help): d
Partition number (1-4): 2

Command (m for help): p

Disk /dev/mmcblk0: 4023 MB, 4023386112 bytes
4 heads, 16 sectors/track, 122784 cylinders, total 7858176 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x80008000

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1   *        2048        4095        1024    1  FAT12

Command (m for help): n
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p): p
Partition number (1-4, default 2): 
Using default value 2
First sector (4096-7858175, default 4096): 
Using default value 4096
Last sector, +sectors or +size{K,M,G} (4096-7858175, default 7858175): 
Using default value 7858175

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.

ここまで来たら、先のBootボタンを押しながらリブートします

ubuntu@ubuntu-armhf:~$ sudo reboot

起動したら再びsshで接続してログイン後、resizeコマンドを叩きます

ubuntu@ubuntu-armhf:~$ sudo fdisk /dev/mmcblk0

Command (m for help): p

Disk /dev/mmcblk0: 4023 MB, 4023386112 bytes
4 heads, 16 sectors/track, 122784 cylinders, total 7858176 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x80008000

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1   *        2048        4095        1024    1  FAT12
/dev/mmcblk0p2            4096     7858175     3927040   83  Linux

Command (m for help): q           

ubuntu@ubuntu-armhf:~$ sudo resize2fs /dev/mmcblk0p2   
resize2fs 1.42 (29-Nov-2011)
Filesystem at /dev/mmcblk0p2 is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
The filesystem on /dev/mmcblk0p2 is now 981760 blocks long.

ubuntu@ubuntu-armhf:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs          3.7G  246M  3.3G   7% /
/dev/root       3.7G  246M  3.3G   7% /
devtmpfs        248M  4.0K  248M   1% /dev
none             50M  224K   50M   1% /run
none            5.0M     0  5.0M   0% /run/lock
none            248M     0  248M   0% /run/shm
/dev/mmcblk0p1 1004K  480K  524K  48% /boot/uboot
ubuntu@ubuntu-armhf:~$ 

これで領域が3.7GBに拡張されました

ボタンを押さなくてもSDカードブートするように修正

前述のように、きんねこさんがSDカードブートするように解決してくれました。 調査内容はエントリ上部のリンクを参照してください。ここでは修正部分だけ追記します。

nEnv.txtに2行追加します

# cd /boot/uboot
# vim nEnv.txt

mmcpart=2
bootfile=zImage  <---- 追加
optargs=fixrtc
uenvcmd=i2c mw 0x24 1 0x3e; kd=0; if test $mmcdev -eq 1; then mmc dev 0; if mmc
rescan; then kd=1; fi; mmc dev 1; fi; setenv mmcroot /dev/mmcblk${kd}p${mmcpart} ro
loadfdt=load mmc ${mmcdev}:${mmcpart} ${fdtaddr} ${bootdir}/dtbs/${fdtfile}
loadimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${bootdir}/${bootfile}
mmcboot=echo Booting from mmc ...; run mmcargs; bootz ${kloadaddr} - ${fdtaddr}  <---- 追加

これで保存して、一度シャットダウンして再度電源を入れればSDから自動起動するようになります\(^o^)/