MESHのカスタムタグで時間を計測してGoogle スプレッドシートにデータをアップロードする

# はじめに

この記事では、スマートフォンやタブレットに無線で接続したセンサなどを入力としてイベント間の時間を計測し、その結果をGoogle スプレッドシートにデータをアップロードする方法を紹介します。Google スプレッドシート以外の「部品」としてはMESHとIFTTTを用います。

[MESH](https://meshprj.com/jp/)は、ソニー株式会社のMESHプロジェクトがつくった、リアルなブロックである「MESHタグ」とスマートフォンやタブレット用のアプリ「MESHアプリ」からなるDIYキットです。LED、ボタン、人感、動き、明るさ、温度・湿度、GPIOなどのMESHタグをMESHアプリでつなぐことで、プログラミングや電子工作の知識がなくとも、誰でも簡単につくり始めることができます。MESHタグ以外にも、スマートフォンやタブレット上のカメラやスピーカを利用できるソフトウェアタグや、スマート電球「[Hue](http://www2.meethue.com/ja-jp/)」などのハードウェアデバイスに対応したタグも利用できます。さらに、SDKを用いて「カスタムタグ」をつくることで独自の機能を拡張することも可能です。

[IFTTT](https://ifttt.com/)（イフト）は、IFTTT Inc.が運営するウェブサービスです。TwitterやFacebook、Instagramをはじめとするさまざまなウェブサービスに加えて、スマートロックやネットワーク対応リモコン、コミュニケーションロボットなどのデバイスをサポートしており、さらに自家製のデバイスを接続するための仕組みをサポートしています。ウェブサイト上でアカウントの登録を済ませることで無料で利用でき、iOSまたはAndroidが動作するスマートフォンアプリが提供されています。IFTTTでは、トリガとアクションの単位をサービスと呼び、自家製デバイスは[Maker Webhooksサービス](https://ifttt.com/maker_webhooks)を利用してウェブリクエストで通信します。今回は、この仕組みを利用してIFTTTとMESHアプリと接続し、IFTTT経由でGoogle スプレッドシートにデータをアップロードします。

MESHとIFTTTを組み合わせ、MESHタグ→MESHアプリ（＋カスタムタグ）→IFTTT→Google スプレッドシートと順に接続することで、MESHタグで発生したイベント間の時間を計測してGoogle スプレッドシートにデータをアップロードするための一連の流れをつくることができます。

# 準備

MESHのSDKを使用するには[ウェブサイト](https://meshprj.com/sdk/)での登録が必要です。メールアドレスとパスワードを入力してSDKに登録するとドキュメントやチュートリアルにアクセスできますので、そちらを参照して準備を行ってください。

# 実装

## カスタムタグの構成

MESHのカスタムタグは1つ以上のFunctionを持ちます。それぞれのFunctionが持つ属性には、Functionの名前である「Function name」（表示名）、他のタグと接続する入出力の「Connector」（コネクタ）、パラメータを設定画面から入力できるようにする「Property」（プロパティ）、ソースコードを記述する「Code」（コード）の4つがあります。

![スクリーンショット 2017-03-23 13.14.29.png](https://qiita-image-store.s3.amazonaws.com/0/92577/6391b102-cead-1873-1f3b-edf7b3388793.png)

## Functionの各属性の設定と実装

以下、順に設定していきます。まず、ConnectorとしてStart（スタート）、Lap（ラップ）、Stop（ストップ）の3つの入力と、IFTTTへの接続が終わった時に（必要であれば）次にタグに知らせるための1つの出力を用意します。

![スクリーンショット 2017-03-23 8.04.28.png](https://qiita-image-store.s3.amazonaws.com/0/92577/1b073332-b394-aea9-edb2-21b77957f4ba.png)

次に、PropertyとしてIFTTTのMaker Webhooksサービスで必要となるeventとkeyの2つを用意します。これにより、カスタムタグの詳細画面からユーザがパラメータを設定できるようになります。

![スクリーンショット 2017-03-23 9.31.12.png](https://qiita-image-store.s3.amazonaws.com/0/92577/e9397f54-55f1-01fc-8e5c-5352e91ab258.png)

最後に、Codeにソースコードを記述します。Functionのメソッドには、初期化時に呼ばれる`Initialize`、入力コネクタからメッセージを受け取った際に呼ばれる`Received`、Function実行時に呼ばれる`Execute`、`Execute`メソッドが完了して出力コネクタから次のタグにメッセージを送信する際に呼ばれる`Result`の4つがあり、カスタムタグの編集画面ではそれぞれ別のタブに記述するようになっています。今回必要なのはResultを除く3つですので、それぞれのタブに以下のようなコードを記入します。

```js:Initialize
// 何番目のコネクタで受け取ったかを示す変数
var inputIndex = -1;

// スタート時刻
var startTime = 0;

// ラップ時刻
var lapTime = 0;
```

```js:Receive
if (index == 0) {
	// 1番目のコネクタ（Start）で受け取った
	inputIndex = 0;
} else if (index == 1) {
	// 2番目のコネクタ（Lap）で受け取った
	inputIndex = 1;
} else if (index == 2) {
	// 3番目のコネクタ（Stop）で受け取った
	inputIndex = 2;
}
```

```js:Execute
// プロパティからeventとkeyを取得してMaker Webhooksサービス用のURLを生成
var apiURL = "https://maker.ifttt.com/trigger/" + properties.event + "/with/key/" + properties.key;

if (inputIndex == 0) {
	// 1番目のコネクタ（Start）で受け取ったら
	// スタートした時刻を記録
	startTime = Date.now();

	// この時点では出力しないためメソッドの戻り値にresultType: "pause"をセット
	return {
		resultType: "pause"
	}
} else if (inputIndex == 1) {
	// 2番目のコネクタ（Lap）で受け取ったら
	// ラップした時刻を記録
	lapTime = Date.now();

	// この時点では出力しないためメソッドの戻り値にresultType: "pause"をセット
	return {
		resultType: "pause"
	}
} else if (inputIndex == 2) {
	// 3番目のコネクタ（Stop）で受け取ったら
	// ストップした時刻を記録
	var endTime = Date.now();

	// スタートからラップまで、ラップからストップまでの経過時間を計算
	// 単位はミリ秒なので1000で除算した後に四捨五入して秒に変換
	var fromStartToLap = Math.round((lapTime - startTime) / 1000);
	var fromLapToStop = Math.round((endTime - lapTime) / 1000);

	// 2つの経過時間をそれぞれvalue1とvalue2にセット
	var data = {
		"value1": fromStartToLap,
		"value2": fromLapToStop
	};

	ajax({
		url: apiURL,
		data: data,
		type: "post",
		timeout: 5000,
		success: function(contents) {
			// コールバックされた時点でcontinueする
			callbackSuccess({
				resultType: "continue",
			});
		},
		error: function(request, errorMessage) {
			log("[ERROR] " + errorMessage);

			// コールバックされた時点でcontinueする
			callbackSuccess({
				resultType: "continue",
			});
		}
	});

	// Ajaxは非同期通信のため、メソッドの戻り値にresultType: "pause"を指定して応答を待つ
	return {
		resultType: "pause"
	};
}
```

以上でカスタムタグの設定と実装は完了ですので、編集画面上でSaveを実行します。これにより、MESHアプリからカスタムタグを追加できるようになります。

## MESHアプリ上のレシピ

MESHアプリでは作成したカスタムタグをレシピに配置し、IFTTTのevent（以下の説明では`MESH`）とkeyを入力し、カスタムタグの入力にMESHタグを接続します。この例では、Start、Lap、Stopの全てにボタンタグを接続していますが、実際には利用場面に合わせて適切なタグと組み合わせます。

![IMG_0062.PNG](https://qiita-image-store.s3.amazonaws.com/0/92577/3f299868-19a1-0ad3-fac1-eead2a7c84ec.png)

## IFTTT

IFTTTでは、トリガーにMaker Webhooksサービス、アクションにGoogleドライブを指定します。eventはMESHアプリ上でStop Watchタグに入力したものと同じものを指定します。Formatted rowの初期状態は`{{OccurredAt}} ||| {{EventName}} ||| {{Value1}} |||{{Value2}} ||| {{Value3}}`になっています。この例では、この中から`EventName`と`Value3`を省略して設定しています。

![FireShot Capture 114 - If maker Event _MESH_, then add row t_ - https___ifttt.com_applets_51487550.png](https://qiita-image-store.s3.amazonaws.com/0/92577/46f2e05a-2c35-d95c-4ce2-f302c403062c.png)

以上でMESHアプリとIFTTTの双方で設定が完了しました。この状態でStop Watchタグの3つの入力コネクタをStart、Lap、Stopの順でトリガーするとIFTTTに対して`MESH`というイベントが送信され、Google スプレッドシートにタイムスタンプと2つの値が新しい行として追加されると思います。

# おわりに

今回は、StartからLapまでとLapからStopまでという2つの経過時間を計測するストップウォッチをつくりました。用途によってはLapは不要かもしれません。また、一般的なストップウォッチでは計測時間をリセットするためのResetが入力としてあった方がいいかもしれません。ここで紹介した基本形から発展させればそうしたバリエーションをつくるのは簡単だと思いますので、ぜひ挑戦してみてください。