【ev3dev】nodejsでインテリジェントブロックのボタン押下状態を判定するプログラムを実装

## はじめに
EV3で動くLinux環境ev3devを使って開発します。この記事は、EV3にev3devをインストールし、SSH接続できている状態であることを前提にしています。
環境構築ができていない方はこちらの記事を参考にしてください。
>
[mindstorm-EV3をLinuxで制御しよう! ev3dev OSのインストールととSSH接続](http://qiita.com/murotani/items/46f905bec33b1673c41a)

## つくるもの
ev3devのインテリジェントブロックのボタンの押下状態を取得するライブラリをJavaScript(nodejs)で実装します。ev3devのnodejsライブラリには[ev3-lang-js](https://github.com/WasabiFan/ev3dev-lang-js)がありますが、インテリジェントブロックのボタン押下状態取得まではサポートされていないようです。

>
[nodejsでmindstrom-EV3を制御するev3dev-lang-js入門](http://qiita.com/murotani/items/86921723020e4a537ed5)

## プログラム
ボタンの押下状態はデバイスファイル/dev/input/by-path/platform-gpio-keys.0-eventに流れてくるバイナリーデータから判定することができます。
デバイスファイルを監視し、押下状態の変化を判定するイベント関数を作成しましょう。
button.jsとして次のプログラムを保存します。

```js:button.js
const fs = require("fs");
const util = require('util');
const events = require('events');
const keysEventsFile = '/dev/input/by-path/platform-gpio-keys.0-event';

var readButton = function(){
    events.EventEmitter.call(this);
}

util.inherits(readButton, events.EventEmitter);

readButton.prototype.read = function(){
        var self = this;
        fs.open(keysEventsFile, "r", function(error, fd) {
                if (error) {
                        self.emit('error', error);
                        console.log(error);
                }
                var buffer = new Buffer(16);
                fs.read(fd, buffer, 0, buffer.length, null, function(error, bytesRead, buffer) {
                        var code = buffer.readUInt16LE(10);
                        var value = buffer.readUInt32LE(12);
                        self.emit('data', code, value);
                        self.read();
                });
        });
}


var reader = new readButton();

reader.on('data',function(code,value){
        console.log("code : " + code + "," + "value : " + value);
});

reader.read();
```

## プログラム実行
プログラムを実行させインテリジェントブロックのボタンを押すとボタンコード(code)と押下状態(value)が出力されます。

```
$ nodejs button.js
code : 103,value : 0
code : 108,value : 0
code : 108,value : 1
code : 106,value : 0
code : 106,value : 1
code : 105,value : 0
code : 105,value : 1
```

![スクリーンショット 2017-02-09 20.59.39.png](https://qiita-image-store.s3.amazonaws.com/0/149019/63e81db9-2cd7-1209-1af4-5255e6121702.png)

codeの数字はそれぞれ上図のボタンに対応しています
>
UP = 103;
DOWN = 108;
LEFT = 105;
RIGHT = 106;
ENTER = 28;
ESCAPE = 14;

イベントはボタンを押した時と離した時に発生します。valueの値によって状態を判定できます。
>
0 = 押した時
1 = 離した時

##　プログラム解説

### イベント定義
デバイスファイルを開いてバイト列を読み込んでint型に変換しています。変数codeに押されたボタンの状態、変数valueに押下状態を記憶し、dataイベントを発火させます。さらに関数内で自身を呼び出すことで連続的に処理を続けます。

```js
readButton.prototype.read = function(){
        var self = this;
        fs.open(keysEventsFile, "r", function(error, fd) {
                if (error) {
                        self.emit('error', error);
                        console.log(error);
                }
                var buffer = new Buffer(16);
                fs.read(fd, buffer, 0, buffer.length, null, function(error, bytesRead, buffer) {
                        var code = buffer.readUInt16LE(10);
                        var value = buffer.readUInt32LE(12);
                        //dataイベントを定義
                        self.emit('data', code, value);
                        self.read();
                });
        });
}
```

### イベント呼び出し
dataイベントを呼び出している部分です。変数code,valueを標準出力させます。

```js
var reader = new readButton();

reader.on('data',function(code,value){
        console.log("code : " + code + "," + "value : " + value);
});

reader.read();
```

##　まとめ
インテリジェントブロックのボタン押下状態判定プログラムのミニマムなプログラムを説明しました。
ev3devを使ったプログラミングの幅がさらに広がりそうです。