Pebble WatchFace開発

年末にPebble WatchFaceを作ってみたので、その備忘録。

  • Pebbleとは?
    • 所謂スマートウォッチ
    • スマホBlueToothでつながる
    • 表示はモノクロe-paper(e-inkではないらしい)ので7日位バッテリーが持つ(自分の実測では5日)
    • ボタンが4つついてるので、これを操作してスマホ側アプリと連携してなんかすることもできる

詳細はこの辺を見て。
公式: Pebble Smartwatch | Smartwatch for iPhone & Android
まとめ: スマートウォッチ「Pebble」まとめ - NAVER まとめ
分解: Pebble Teardown - iFixit
いろんなWatchFace: http://www.mypebblefaces.com/


ここから開発について。

開発関連情報

とにかくここ、こまったらここを見る。
Develop for Pebble

開発環境

自分のPCに環境を作ってもいいですが、Web上でコーディング&コンパイルスマホへのインストールまでできるサイトがあったので、今回はCloudPebbleで開発します。
ちなみにWindowsは今のところ非対応らしい。ただ、Windowsで開発するにせよ、CloudPebbleで開発するにせよ、SDKのアーカイブにサンプルコードが含まれているので、ダウンロードしておいた方が幸せになれます。

SDK

Pebble SDK 1.X系と2.0系があってAPI名とか多分他にもなんかが違う。今から古いのを使うのもなんなんで、2.0を使います。

WatchFace?WatchApp?

WatchFaceはPebbleのボタンを使わないもの、WatchAppはボタンを使えるもの。
BlueTooth通信の有無ではないらしい。

PebbleKit?

iOS, Androidで動くスマホ側のアプリの開発キットらしい。今回は使わないので未調査。

サンプルWatchFace

今回、作ったのは砂時計。ざっくりとした仕様は

  • 1時間で砂が流れ切る
  • 上側と下側の砂の量は、時間と対応付けて表示を変える
  • 砂が流れるアニメーションをつける
  • 砂が流れ切ったら砂時計が1回転する
  • Pebbleを振ると下側の砂が平らになる
// アプリの開始時に実行
static void do_init(void) {
	//割り込みハンドラの登録、リソースの確保、初期化とか
}

// アプリの終了時に実行
static void do_deinit(void) {
	//リソースの開放とか
}

int main(void) {
	do_init();
	app_event_loop(); // おまじない
	do_deinit();
}

…詳細を書こうと思ったけど、
Develop for Pebbleの'Getting Started', 'Pebble Developer Guide'と拙作のソースを見てもらった方が早いなぁ、と思ったり。
きたないけどソースはzinziroge/sandglass_watchface · GitHubに置いてあります。
他にもGithubhttp:// http://www.mypebblefaces.com/でソースが公開されているものもあるのでそれを参考にするのが手っ取り早いと思います。

これで終わるのもあれなのではまったところだけ箇条書き。

時間割り込みの登録

秒、分、時、日、月、年が変わるタイミングで呼ばれるハンドラが登録できるのだが、例えば1秒毎、1時間毎に割り込みをかけようとして以下のように2つハンドラを登録したら1秒毎の割り込みが実施されず。

tick_timer_service_subscribe(SECOND_UNIT, &handle_second_tick);
tick_timer_service_subscribe(HOUR_UNIT, &handle_hour_tick);

正解は、これ。

tick_timer_service_subscribe(SECOND_UNIT|HOUR_UNIT, &handle_tick_timer);

で、ハンドラ側で割り込み要因を判別して処理を分ける。

void handle_tick_timer(struct tm *tick_time, TimeUnits units_changed) {
	if( units_changes | SECOND_UNIT) {
		// 1秒毎に実施する処理
	}
	if( units_changes | HOUR_UNIT )
		// 1時間毎に実施する処理
	}
}
2pixel以上の太い線が描けない

graphics_draw_line() という線を引くAPIがあるが、太さを指定できない(つまり1pixel)。
水平線や垂直線なら graphics_fill_rect() で実現できる。でも、斜め線が描けない。
PebbleにはDrawing Pathsという一筆書きで線を描いて、内部を塗りつぶすこともできるデータ型がある。
これを使って太さと傾きに応じて太線の4頂点の座標を計算すれば、gpath_draw_filled()で描ける。
ちなみにsin,cos,atan2はテーブルで持っていてそれをAPIで参照できるので、上の座標計算もダイナミックにできます。

1つ作ってみての感想

WatchFaceぐらいの規模だと環境作る方がめんどいから、クラウドで開発できるのすごくいいと思う。
エディタもメモ帳レベルだけじゃなくて, vim-like, emacs-likeが選べるのでどっちか使える人には便利。
CloudPebbleは楽チンですばらしいのだが、唯一こまるのがスクリーンショットが撮れないこと(Linux環境だと撮れる(らしい))。
CloudPebble blog | What're we up to?(開発者Blog)を見ると最優先事項だと認識しているらしいので実装されると大変うれしい。

Android で画像処理

OpenCV も使ったり、画像取り扱いの基本

  • OpenCV library を使うために前準備

libs に OpenCV-2.4.7-android-sdk\sdk\java\bin\opencv library - 2.4.7.jar をDrag&Drop
f:id:zinziroge:20131223174100p:plain

OpenCV Managerの呼出
Activityの実行直前に非同期に呼び出す(onResume()で呼び出すのはなんでだろう。onStart(), onCreate()じゃだめ?)
https://groups.google.com/forum/#!topic/android-opencv/LIixgr-iYSs
http://corkboard.ivory.ne.jp/?p=17

  • setContentView()

XMLのレイアウトファイルを使う方法と実行時にViewを作る方法がある
http://www.javadrive.jp/android/activity/index4.html
http://allabout.co.jp/gm/gc/80740/

Android 開発環境整備

Windowsで開発環境を整えて、
実機デバッグ、OpenCVが使えるようになるまで。

Android Studioでやろうと思ったけど、今回は挫折。
Eclipse + ADT Plugin のセットにしたアーカイブ。
http://developer.android.com/sdk/index.html

ADTに含まれるので不要

  • USBドライバー

手持ちのAndroidスマホがSHARP製なので。
https://sh-dev.sharp.co.jp/android/modules/driver/
http://www.adakoda.com/android/000242.html
http://developer.android.com/tools/device.html
http://d.hatena.ne.jp/wize03/20130113/1358069204

http://www.kosaic.jp/wordpress/2012/12/opencv-for-android-2-4-3-2-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/
http://answers.opencv.org/question/14546/how-to-work-with-opencv4android-in-android-studio/
http://blog.bbtune.com/archives/1372/compiler-compliance-level-1-5-%E2%86%92-1-6-the-project-was-not-built-since-its-build-path-is-incomplete

  • Android NDK(Native Development Kit)

CとかC++で開発するために必要らしい。特に使う予定はないが、OpenCVのサンプルのいくつかをコンパイルするために必要。
http://developer.android.com/tools/sdk/ndk/index.html

Kindle Paperwhite を買いました

Kindle Paperwhite 3G

Kindle Paperwhite 3G

を買って、2週間くらい使っての感想。
3G版を買いました。Amazon.comで買った Kindle4 も持ってるのでそれとも比較してみます。

いいところ

  1. 喫茶店で本が買える
  2. バックライトがいい

1つ目は、わざわざ外で本を買うことなんてないからwifi版でもいいやと思ってたけど、
喫茶店とかで本をその場で買えるのは結構新鮮でした。
2つ目は、寝床に入って本を読むのにバックライトがなかなかよいです。

いまいちなところ

  1. 電池の持ちはKindle4より悪い
  2. wifi接続でないとメールを取得できない

1つ目の電池の持ちが悪いのは、3Gの待ち受けとバックライトの性だと思うのまぁしょうがないかな。無線を切る機能はあるけど、3Gだけ切れるようにもして欲しかった。
2つ目は自分の調査不足。3GはAmazonで書籍を買うためにしか使えないらしい。
ブラウザがつながらないのは知っていたけどメールも駄目なのね。
スマホで見つけて面白いページをその場でmobiに変換して、kindleに送って見れるかと思ったけど、できませんでした。
Amazonにすれば、何にもお金が落ちてこないから当たり前なのか。

でも、おおむね満足。
#漫画が危険w。手軽すぎて、読み終わったらついつい次の巻も購入してしまう。

Raspberry Pi でRuby

まずは、rvm(Ruby Version Manager)を下記を参考にしてインストール。
RVM
Linux で rvm を用いて Ruby をインストール

curl -L https://get.rvm.io | bash -s stable --ruby

対応するバイナリがないのでソースから自動的にコンパイルしてくれる。が、小一時間かかる。
次にrubygemsをupdate。

gem install rubygems-update

openssl ライブラリがないとかなんとか怒られるので、

sudo aptitude install libopenssl-ruby1.9.1

でいいかなぁと思ったけど駄目だった。ググる

rvm pkg install openssl
rvm pkg install readline

が必要らしい。そんで、rubyをreinstallしろと言われるので素直に従う。

rvm reinstall all --force

で、rubyをソースからコンパイルするので小一時間待つ。
やっとこさrvmのインストール完了。こんな感じ。

pi@raspberrypi ~ $ rvm list

rvm rubies

=* ruby-1.9.3-p374 [ armv6l ]

# => - current
# =* - current && default
#  * - default

次にGPIOをたたくためのライブラリをインストールする。
RPi Low-level peripheralsを見るとRubyでRaspberryのGPIOをたたくには、WiringPiPi Piper の二つがあるらしい。
Pi Piperはイベントドリブン型。
RaspberryのGPIOをラジオのボリューム調整とチャンネル選択に使うので、今回はPi Piperの方がよさげなので、こちらをインストールする。

gem install pi_piper

まずは、ここまで。

Raspberry Pi でらじる

radikoは聴けるようになったので、NHKのらじるも聴けるようにする。
録音スクリプトはこれをベースに使用させていたただきました。
録音はできるのだが、ノイズがはげしくて音がとぎれとぎれになってしまう。
また、何回か試してみるとらじるにつながらないこともある。
同じスクリプトをUbuntuで動かすとこの問題は発生しないので、Raspberry側の問題らしい。

どうやって、解析すればいいのやら。
rtmpdump に

--verbose|-V            Verbose command output.
--debug|-z              Debug level command output.

のオプションがあるのでログを出してみたけど、読み解けないorz。

RaspBerry Pi で無線LAN その2

なんか無線LANがつながらなくなって復旧するまで。
いろいろ調べたけど結局は、
電源ケーブルが断線気味でhaltせずに電源が落ちたことでファイルが壊れた?。
実際何回かfsckしてるし。

で、

/etc/network/if-pre-up.d/wpasupplicant
/etc/network/if-up.d/wpasupplicant

がいなくなってた。
ので、シンボリックリンクを張って

pi@raspberrypi ~ $ sudo ln -s /etc/wpa_supplicant/ifupdown.sh /etc/network/if-pre-up.d/wpasupplicant
pi@raspberrypi ~ $ sudo ln -s /etc/wpa_supplicant/ifupdown.sh /etc/network/if-up.d/wpasupplicant
pi@raspberrypi ~ $ sudo ifup wlan0

でAPに再びつながるようになった。

...てか他にも壊れてんじゃない? ((((;゜Д゜)))