TI SensorTagのボタンとGUIの暗黒面 "SendKeys" とを組み合わせてプレゼンリモコンをつくる

まずは[これを見みやがれ](https://www.youtube.com/watch?v=mJvXfdE6IH4)です (30秒動画)

[![TI sensotTagをプレゼン用クリッカーに仕立て上げる (simpleKeyのみ) ](http://img.youtube.com/vi/mJvXfdE6IH4/0.jpg)](https://www.youtube.com/watch?v=mJvXfdE6IH4)

本当は[こんな感じのX'mas](http://www.mana-cat.com/entry/SORACOM-Xmas-tree)をやりたかったお。。。

GUIスクリプティングで面倒なのがAPI操作。Officeやブラウザを操作しようとすると、COM等のAPIを叩く必要がありますが、正直めんどうです
しかし、GUIには "SendKeys"系のダークフォースがあります。即ち「キーを押したことにする」仕組みです

今回はおなじみ TI SensorTagのボタンをキー入力に割り当てて、プレゼン用リモコンに仕立ててみます

環境
----

- Ubuntu 15.10
- Node.js 5.3.0

コード
------

```javascript:run.js
/*
 * Presentation Clicker by TI SensorTag
 * @ma2shita
 * License: MIT
 *
 * Usage:
 * $ npm install sensortag
 * # node run.js
 */
var myUUID = process.env["TI_UUID"] || "5c313ebfec2a";

var execSync = require('child_process').execSync;
function xdotool(keyscan) {
	var c = 'xdotool search --onlyvisible --class libreoffice windowfocus key "' + keyscan + '"';
	console.log(c);
	try {
		var r = "" + execSync(c);
	} catch(e) {
		//Nothing Todo
	}
}

function key_event(keyscan) {
	xdotool(keyscan);
}

function ti_simple_key(tag) {
	tag.notifySimpleKey(function() {
		console.info("READY!: notifySimpleKey");
		tag.on("simpleKeyChange", function(left, right) { /* run per pushed button */
			 if (!left &&  right) { key_event("Right"); }
			 if ( left && !right) { key_event("Left"); }
		});
	});
}

/* MAIN */
var SensorTag = require('sensortag');
console.info(">> STOP: Ctrl+C or SensorTag power off");
console.info("start");
console.info("waiting for connect from " + myUUID);
SensorTag.discoverByUuid(myUUID, function(sensorTag) {
	console.info("FOUND!: connect and setup ... (waiting 5~10 seconds)");
	sensorTag.connectAndSetup(function() {
		sensorTag.readDeviceName(function(error, deviceName) {
			console.info("connect: " + deviceName);
			ti_simple_key(sensorTag);
		});
	});
	/* In case of SensorTag PowerOff or out of range when fired `onDisconnect` */
	sensorTag.on("disconnect", function() {
		sensorTag.disableAccelerometer(function(e){});
		console.info("disconnect and exit");
		process.exit(0);
	});
});
```

### 解説 ###

TI sensorTag の simpleKey のイベントから child_process で xdotool を起動してるだけです

えーっと、node.js成分が足りず、asyncとか使えません。cb地獄をお楽しみください

### 実行 ###

```
$ npm install sensortag
$ sudo node run.js
```

改造ポイント
------------

### 各OSへのポーティング ###

- Ubuntu(Linux): `xdotool` を使いましょう
- OS X(Mac): `osascript` を使いましょう。具体的な使い方は[こちらが詳しい](https://dodastrand.wordpress.com/2013/10/24/key-code-left-arrow/)です
- Windows: Windows Host Scriptingの [`SendKeys` メソッド](https://msdn.microsoft.com/ja-jp/library/cc364423.aspx)を使うことになります。cscript.exe はインライン実行のオプションがないのでファイルに保存したものを実行するなり、工夫してください

### 加速度センサーを使ってみる ###

振ると "Escape" の押下が発火する機能を入れてみます
[こんな感じで動きます](https://www.youtube.com/watch?v=Oyw2I6PMRJo) (30秒動画)

[![TI sensotTagをプレゼン用クリッカーに仕立て上げる (振るとEscape) ](http://img.youtube.com/vi/Oyw2I6PMRJo/0.jpg)](https://www.youtube.com/watch?v=Oyw2I6PMRJo)

#### コード ####

```diff
--- run.js	2015-12-24 13:22:56.416042611 +0900
+++ run_w_accel.js	2015-12-24 13:22:35.079839374 +0900
@@ -34,6 +34,27 @@
 	});
 }
 
+function ti_accelerometer(tag) {
+	var borderOverCounter = 0;
+	var accelerometerPeriod = 300; // ms
+	tag.enableAccelerometer(function(e) {
+		tag.setAccelerometerPeriod(accelerometerPeriod, function(e) {
+			tag.notifyAccelerometer(function(e){
+				console.info("READY!: notifyAccelerometer");
+				tag.on('accelerometerChange', function(x, y, z) {
+					var max = Math.max(Math.abs(x), Math.abs(y), Math.abs(z));
+					if (max > 7.0) {
+						borderOverCounter++;
+					} else {
+						borderOverCounter = 0; // reset
+					}
+					if (borderOverCounter > 1) { key_event("Escape"); }
+				});
+			});
+		});
+	});
+}
+
 /* MAIN */
 var SensorTag = require('sensortag');
 console.info(">> STOP: Ctrl+C or SensorTag power off");
@@ -45,6 +66,7 @@
 		sensorTag.readDeviceName(function(error, deviceName) {
 			console.info("connect: " + deviceName);
 			ti_simple_key(sensorTag);
+			ti_accelerometer(sensorTag);
 		});
 	});
 	/* In case of SensorTag PowerOff or out of range when fired `onDisconnect` */
```

あとがき
--------

よい年末を！