ひとりぶろぐ

価値ある情報をユーザー視点で発信するブログ

2.0で面白くなったスマートウォッチPebbleを、JavaScriptゴリゴリでネット監視装置として使う

      2016/05/24

え?Pebbleってまだ続いてたの?

Kickstarter発のスマートウォッチとして話題になったPebble。

The Pebble iOS Smartwatch

とっくに時空の彼方に消え去った存在だと思っている人も多いかもしれませんが、開発陣はソフトウェアの地道なブラッシュアップを1年以上にわたり続けており、つい最近第二世代、2.0への移行が完了したばかり。

この2.0での変化、進化は、Pebbleがスマートウォッチのナンバーワンプラットフォームとしての地位を確立する上で、非常に意義の大きなものです。

洗練度が上がったSDK/ファームウェア2.0

2.0では、Pebble appstoreのオープンが大きなトピック。

Pebble Smartwatch App
カテゴリ: ライフスタイル
価格: 無料

IMG 2805

Pebble appstoreの利用が可能になったのはiOSが先になりましたが、Androidも追従。

Pebble
カテゴリ: ライフスタイル
Google Playで詳細を見る

NewImage

2.0世代での変化は、このPebble appstoreにフォーカスしたものであるといえます。

Getting Started with Pebble SDK 2.0

不特定多数が開発するPebble用アプリ/ウォッチフェースからPebbleのOSに相当する部分にアクセスしにくいようにして安全度を高めたり、メモリ管理の方法を改めたりといったようなことです。

結果として、スマートフォン用Pebbleアプリから、続々新作が登場するPebble用のアプリ/ウォッチフェースをどんどんダウンロードして、Pebbleで実行して楽しむ環境が現実のものとなっています。

IMG 2804

Pebble appstoreは、なかなかのユーザーエクスペリエンスを提供。

IMG 2808

このワクワク感といったらありません。iPhone OS 2.0でApp Storeがサービスインしたときの感動を覚えていますか?

Pebble appstoreには現在のところ決済手段がありませんから、(恐らく)全部フリーウェアで、ビジネスの場になっているわけではありません。

しかし、地道な努力を続け、市井の開発者を巻き込んでムーブメントを起こし、Pebbleの世界をここまでしっかりと構築したPebble開発陣は、ただ者ではないといえましょう。

(続きは[Read More]から)

Pebbleは実用的スマートウォッチ

Pebbleはスマートウォッチとしては小さく軽く、防水。

電池がよく持ち、昼間でも見える反射液晶、そしてスマートウォッチに重要なバイブレーターを搭載。

Pebble Watch

日用品の仲間入りをしうる使い勝手を実現している点において、ほかのどのスマートウォッチの追従も許しません。


日本語が表示できないが

Pebble OSは日本語表示をサポートしていません。

Can Pebble display notifications in other languages?

Pebble is currently only set up for English, but developers will be able to develop apps to support other languages. We are still looking into how various languages (and what versions – eg. simplified vs traditional Chinese) will display for basic notifications.

Pebble Support Center

アプリで補えない通知中のマルチバイト文字の表示方法は模索しているけれど、アプリ中のマルチバイト文字表示は開発者が頑張って実現しろっていうのがPebbleのスタンスみたいですね。

国際化は無理でも、アプリのローカライズならできる範囲かな。

Pebble 美咲フォント 日本語

表示できた方がいいに決まっているけれど、スマートウォッチのナンバーワンプラットフォームが日本語表示非対応なのだから、郷に従うしかありません。

この件で糾弾したい人はこちらへ。

UTF-8 support – Pebble Forums

僕は、日用品的な存在感を獲得する上でのトレードオフだと受け止めています。

注目しているPebble JavaScript Framework

javascript 14 03 14 18 55

要するにPebbleが今熱いということを言いたいわけですが、熱い2.0のフィーチャーの中でも、僕がとびきり気に入っているのがJavaScript Frameworkという仕組み。

PebbleKit JavaScript Framework for Pebble OS

この魅力を知ってもらおうと、今回のエントリを書きました。

PebbleはBluetoothでスマートフォンと連携します。

Pebble OS 2.0で追加されたJavaScript Frameworkは、Pebbleとスマートフォン用のPebbleアプリとの間のBluetooth通信のための仕組み。

通信のための仕組みがあるだけで、それを何に使うかは開発者に委ねられています。

JavaScript Framework対応アプリのインストール時に何が行われるか

JavaScript Framework対応アプリのインストール時に行われることが興味深いので、伝わりやすいよう図にしてみました。

Pebbleのアプリは、pbwという拡張子のファイルで流通します。

実体はzipファイルで、中にたくさんファイルが入っています。スマートフォン用のPebbleアプリを介してPebbleにインストールするわけですが、JavaScript Framework対応アプリの場合、スマートフォン側にはJavaScriptがインストールされます。

JavaScriptは、スマートフォン用のPebbleアプリが実行するわけです。

Pebble js framework 14 03 12 3

JavaScriptは、JavaScript Framework対応アプリと協調して動くよう、開発者が自由に書くことができるものです。

開発者が、スマートフォン側の動作、Pebble側のアプリの動作の両方の指揮を取れるわけです。

ポイントは、Bluetoothを使うアプリなので、iOSにおいても制限時間なしのバックグラウンド動作が許されていることです。

JavaScriptを自由にインストールでき、バックグラウンドで動かし続けられるのです。これだけでご飯3杯ぐらいいける。

JavaScript Framework対応アプリの動作

スマートフォン用Pebbleアプリ側にインストールされたJavaScriptと、Pebble側にインストールされたJavaScript Framework対応アプリとは、AppMessage APIを使って通信します。

ボタン押下に応じて、あるいはPebble用アプリからの任意のタイミングで、あるいは定期的な呼び出しで、スマートフォン用Pebbleアプリ側にインストールされたJavaScriptを実行し、必要に応じてフィードバックを得ることができます。

スマートフォン用Pebbleアプリ側にインストールされたJavaScriptの側から、Pebble用アプリ側を突っつくこともできます。

ここで注目したいのが、スマートフォン用Pebbleアプリ側にインストールされたJavaScriptが、スマートフォンの通信機能と、JavaScriptのXMLHttpRequestを使って、Web上の情報を取得したり、Webに情報を送信できることです。

pebble-js-framework 14 03 12 15 32

それをBluetoothを介してPebbleに受送信できるので、WebアクセスするPebble用のアプリが作れるというわけです。

2.0になって登場した、天気予報を表示するウォッチフェースは、この仕組みを利用しています。

IMG 2809

JavaScriptだけで開発できるSimply.jsの登場

JavaScript Framework対応アプリを作るためには、Pebble側のアプリをC言語で、スマートフォン用Pebbleアプリ側で動作するものをJavaScriptで書かなければなりません。

ところが、JavaScriptを書くだけでユーザー側で動作を自由にコントロールできるカスタマイザブルなPebble用アプリ、Simply.jsが登場して、状況が大きく変わりました。

Simply.jsは、ほかのアプリ同様、Pebble appstoreからインストールできます。

IMG 2810

Simply.jsの詳細は、オフィシャルページから得ることができます。

Simply.js

Simply.jsはgithub上で開発されていて、オープンソースのプロジェクトです。

Meiguro/simplyjs | GitHub

Pebble用のアプリをクラウド上の開発環境で開発できるWebサービス、CloudPebbleが、Simply.jsにも対応しました。

CloudPebble

Simply.jsの起動と仕組みの把握

とりあえずSimply.jsをPebble appstoreからPebbleにインストールし、起動。

Pebble screenshot 2014 03 12 00 28 29

すると、こんな画面になります。

Pebble screenshot 2014 03 12 00 27 40

本体右サイド、ボタンの上、中央、下を押すと、それに応じて画面が変化します。Pebbleを装着したまま腕をブルンと振ると、加速度センサーからの入力によって画面が変化します。

これだけでは何の役にも立ちませんから、カスタマイズすることにします。

Pebble screenshot 2014 03 12 00 28 02

Pebble用のウォッチフェース、アプリの設定は、スマートフォン用のアプリから変更できます(設定項目がないものもある)。MY PEBBLEからたどり……。

IMG 2811

Simply.jsを見つけたら、「SETTINGS」ボタンをタップ。

IMG 2812

ここに、Simply.jsの動作を決めるJavaScriptのURLの入力欄があります。デフォルトでは「http://meiguro.com/simplyjs/demo.js」となっているので、Webブラウザから見てみることにします。

IMG 2813

さきほどSimply.js上で見た「This is a demo. Press buttons or tap the watch!」も、スクリプト上の記述として見えます。これを書き換えれば、Simply.jsの動作をカスタマイズできるわけですね。

console.log('Simply.js demo!');

simply.on('singleClick', function(e) {
  console.log(util2.format('single clicked $button!', e));
  simply.subtitle('Pressed ' + e.button + '!');
});

simply.on('longClick', function(e) {
  console.log(util2.format('long clicked $button!', e));
  simply.vibe();
  simply.scrollable(e.button !== 'select');
});

simply.on('accelTap', function(e) {
  console.log(util2.format('tapped accel axis $axis $direction!', e));
  simply.subtitle('Tapped ' + (e.direction > 0 ? '+' : '-') + e.axis + '!');
});

simply.setText({
  title: 'Simply Demo!',
  body: 'This is a demo. Press buttons or tap the watch!',
}, true);

改造して自分用のスクリプトを作成

しかし、人様のサイトのファイルはいじれないので、自分の裁量下にあるWebサーバに置いて改造することにします。

Dropboxが手軽でいいでしょう。DropboxのPublicディレクトリに置き、公開リンクを得る。

simplyjs 14 03 14 19 31

公開リンクを、Simply.jsの設定画面にペースト。これで、Simply.jsがDropbox上に置いたJavaScriptを読み込んで動くようになります。

IMG 2815 3

サンプルのスクリプトを改造して作ったのが以下のものです。

$status = {
	usdjpy: "xx.xx",
	subscribers: "xxx",
	loadAverage: "xxx",
	okutamaAmeras: "x.x",
	hachiojiAmeras: "x.x",
	fuchuAmeras: "x.x",
	setagayaAmeras: "x.x"
};

function updateSubtitle() {
	var fmt = "JPY: $usdjpy\nSCR: $subscribers\nAVG: $loadAverage";
	simply.subtitle(util2.format(fmt, $status));
}

function updateBody() {
	var fmt = "AME: O:$okutamaAmeras / H:$hachiojiAmeras / F:$fuchuAmeras / S:$setagayaAmeras";
	simply.body(util2.format(fmt, $status));
}

function zeroFill(num, fill) {
	var padd = "0000000000";
	return (padd + num).slice(-fill);
}

// A.日付と時刻
function timeText() {
	var now = new Date();
	var n = {
		month: zeroFill(now.getMonth()+1, 2),
		date: zeroFill(now.getDate(), 2),
		hours: zeroFill(now.getHours(), 2),
		minutes: zeroFill(now.getMinutes(), 2)
	}
	return util2.format("$month/$date - $hours:$minutes", n);
}

function ameras(area, prop) {
	ajax({ url: 'http://agora.ex.nii.ac.jp/digital-typhoon/ameras/' + area + '/' }, function(data) {
		$status[prop] = data.match(/\n1時間降水量<\/th>\n(.*?)<\/td>/)[1];
		updateBody();
	});
}

/*
load_average.php


*/

$tasks = {
	loadAverage: function() {
		ajax({ url: 'http://hitoriblog.com/pebble/load_average.php' }, function(data) {
			$status.loadAverage = data;
			updateSubtitle();
		});
	},
	/*
	usdjpy: function() {
		// B.ドル円相場
		ajax({ url: 'http://api.aoikujira.com/kawase/json/usd', type: 'json' }, function(data) {
			$status.usdjpy = Number(data['JPY']).toFixed(2);
			updateSubtitle();
		});
	},
	*/
	usdjpy: function() {
		// B.ドル円相場
		ajax({ url: 'http://stocks.finance.yahoo.co.jp/stocks/detail/?code=usdjpy%3Dx' }, function(data) {
			$status.usdjpy = Number(data.match(/(.*?)<\/td>/)[1]).toFixed(2);
			updateSubtitle();
		});
	},
	subscribers: function() {
		// C.Feedly購読者数
		var feed = 'http://hitoriblog.com/?feed=rss2';
		ajax({ url: 'http://cloud.feedly.com/v3/feeds/feed%2F' + encodeURIComponent(feed), type: 'json' }, function(data) {
			$status.subscribers = data['subscribers'];
			updateSubtitle();
		});
	},
	okutamaAmeras: function() {
		// E.奥多摩の直近1時間の降水量
		ameras('44046', 'okutamaAmeras');
	},
	hachiojiAmeras: function() {
		// E.八王子の直近1時間の降水量
		ameras('44112', 'hachiojiAmeras');
	},
	fuchuAmeras: function() {
		// E.府中の直近1時間の降水量
		ameras('44116', 'fuchuAmeras');
	},
	setagayaAmeras: function() {
		// E.世田谷の直近1時間の降水量
		ameras('44126', 'setagayaAmeras');
	}
}

/*
 奥多摩 http://agora.ex.nii.ac.jp/digital-typhoon/ameras/44046/
 八王子 http://agora.ex.nii.ac.jp/digital-typhoon/ameras/44112/
 府中 http://agora.ex.nii.ac.jp/digital-typhoon/ameras/44116/
 世田谷 http://agora.ex.nii.ac.jp/digital-typhoon/ameras/44126/
*/

function refresh() {
	simply.title(timeText());
	for (var task in $tasks) {
		$tasks[task]();
	}
	updateSubtitle();
	updateBody();
}

// イベントハンドラ

simply.on('singleClick', function(e) {
	simply.vibe();
	refresh();
});

simply.on('accelTap', function(e) {
	simply.vibe();
	refresh();
});

// エントリポイント

simply.begin = function() {
	try {
		console.log('Simply.js start!');
		simply.fullscreen(true);
		refresh();
		setInterval(refresh, 60000);
	} catch (e) {
		console.log(e);
		simply.body(e);
	}
};

これを動かすと、以下のような画面が表示されます。Simply.jsはテキスト表示しかできませんから、いささか見てくれが悪いですが、JavaScriptでかき集めてきたWeb上の情報をパッチワークのようにして構成してみました。

simplyjs 14 03 14 19 46

これをsetIntervalで1分に1回更新しています。自分の欲しい情報を自由に集めてきて、Pebble上に表示。たまりません! 本体右側のボタンのいずれかを押したり、手をブルンと振ったりしても更新されるようにしてあります。

これは、まるでOS X用のGeekToolのようですね。

Tynsoe projects

非常に面白げではないでしょうか。

これに飽き足らなければ、C言語を使ってPebbleアプリを作ってしまう手も、もちろん残されています。

Simply.js用スクリプト開発手法とデバッグ

Simply.js用のスクリプトは、JavaScriptなのでWebブラウザで開発できます。

GitHubからチェックアウトしてきたものを使うのが便利でしょう。「simplyjs/src/js」にSimply.jsで使うJavaScriptがあるので、これをhtmlにincludeします。

simplyjs 14 03 14 20 31










Webページから必要な情報を抜き出す部分は、こんな感じでWebブラウザで開発ができます。

実機でのデバッグにはデバッガが使えませんが、デバッグプリントはPebble SDKの標準コマンドであるpebbleコマンドでできます。

Pebble SDKをインストール。OS Xなら、XcodeがインストールしてあればHomebrewよろしくワンライナーでセットアップ完了です。

Getting Started with Pebble SDK 2.0

Pebbleとペアリングしているスマートフォンと開発機を同一ネットワークに置き、環境変数「PEBBLE_PHONE」に、スマートフォンのIPアドレスを設定。

export PEBBLE_PHONE=192.168.1.100

スマートフォン側のPebbleアプリのDEVELOPERモードをオンにします。

IMG 2816 3

これで、「開発機→Wi-Fi→スマートフォンのPebbleアプリ→Bluetooth→Pebble」という経路ができます。

あとは、pebbleコマンドをlogsオプションを付けて実行すると、Androidのadbコマンドのlogcat同様の状態になります。

Simply.js用のJavaScriptでconsole.logを実行すると、ここのログに流れてきます。

pebble logs

非常に僕好みの作りですよ。というわけで、Pebbleマジオススメ。

 - Android, iOS, iPad, iPhone, JavaScript, Pebble, ガジェット