凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

node-xbee を使って JavaScript で XBee から温度取得してみた

はじめに

XBeeZigBee 規格で通信を行なってくれる小型の無線通信モジュールです。前回(boost::asio::serial_port で ZigBee と会話してみた - 凹みTips)は C++ZigBee を扱いましたが、今回は Node.js での値の取得をやってみたいと思います。

出来るようになること

  • JavaScript から部屋の温度を無線で取得

環境 / 構成

  • Mac OS X 10.8.2 or Ubuntu 10.04
  • Node.js 0.9.2
  • XBee × 2個
  • SparkFun ZigBee Explorer
  • 温度センサ(LM61)などなど



node-serialport の導入

Node.js 用のアドオンとして node-xbee が公開されていますので、これを使います。

Readme を読んでみると、node-serialport を利用してシリアル通信を行うようです。一つ注意しなくてはならないのは、node-serialport の最新版では動かず、0.7.3 を用いる点です。

npm install serialport@0.7.3
npm install xbee

ただ、0.7.3 の古い node-serialport では、ネイティブモジュールの作成に node-waf を用いており、node-waf は最新の Node.js(0.9.2@2012/10/15現在)では取り除かれてしまいました。そこで node-waf で書いている部分を node-gyp 用に書き換えます。モジュールのディレクトリは以下になります。

$ cd node_modules/serialport

まず、node-gyp 用に binding.gyp を作ります。

serialport_native/binding.gyp
{
	'targets': [
		{
			'target_name'    : 'serialport_native',
			'sources'        : [ 'serialport_native.cc' ],
		},
	],
}

次に、C++ソースコードにも1行追加します。

serialport_native/serialport_native.cc(362行目から)
  extern "C" void
  init (Handle<Object> target) 
  {
    HandleScope scope;
    SerialPort::Initialize(target);
  }
  
  NODE_MODULE(serialport_native, init); // <-- ここを追記  
}

一個上の階層に上がり、serialport.js の中で Node.js v0.9.x から廃止になった IOWatcher の行を取り除きます。

serialport.js(12行目)
// var IOWatcher   = process.binding('io_watcher').IOWatcher; <-- コメントアウト

最後に Makefile を書き換えます。

Makefile
setup :
	cd serialport_native;node-gyp configure build;cd ..; # <-- node-waf から node-gyp に
	cp serialport_native/build/Debug/serialport_native.node . # 環境に合わせて Release から Debug に

で、Make すれば OK です。

$ make

温度を取得

node-xbee は node-serialport のアドオン的な位置づけで書かれています。AT コマンドの IS で 1 秒おきに XBee からデータを受け取って温度を表示するコードは以下のようになります。

temp.js
var SerialPort = require("serialport").SerialPort
  , xbee       = require("xbee")
;

var serial_xbee = new SerialPort("/dev/tty.usbserial-A501DG57", {
	parser: xbee.packetParser()
});

serial_xbee.on("data", function(data) {
	// console.log('xbee data received:', data); <-- これで何が入っているか見れます
	var ain3hi  = data.bytes[19];
	var ain3lo  = data.bytes[20];
	var voltage = 1.2 * (ain3hi * 0x0100 + ain3lo) / 0x03ff;
	var temperature = (voltage - 0.6) * 100;
	console.log(temperature);
});

var atc = new xbee.RemoteATCommand();
atc.setCommand('IS');
atc.destination64 = [0x00,0x13,0xa2,0x00,0x40,0x89,0x9d,0x84]; // XBee のアドレス
atc.destination16 = [0xff,0xfe];

setInterval(function() {
	serial_xbee.write( atc.getBytes() );
}, 1000);
実行
$ node temp
27.859237536656888
27.74193548387097
(以下略)

SerialPort は Ubuntu なら「/dev/ttyUSB0」、Windows なら「COM3」といった形になります(数字は変わります)。Mac の場合は以下のサイトから FTDI のドライバをインストールする必要があります。

温度計算の部分については、 LM 61 という温度センサを用いて温度を測定したのでその電圧 - 温度変換式に準拠した形になっています。

おわりに

これにこの間作成した iRemocon の Node.js モジュール(node-iRemocon つくった - 凹みTips)を組み合わせれば、指定した温度にエアコンを設定してくれる部屋が簡単にできます!
node-xbee の Readme の文みたいな世界にまで出来ると楽しくなりそうですね。

node-xbee の序文(引用)
frontdoor.on("open", function() {
  if (alarm.state == "on") {
    alarm.sound();
    hounds.release();
  } else {
    lights.switchOn();
    voice.speak("Welcome home");
  }
});