先は長いけれどがんばる!
Preparing AppMessage
watchappでもwatchfaceでも、通信で用いる主なAPIは「AppMessage API」です。
「key」と「value」のセットを用いて、Pebbleとその親機となるスマートフォンとの間で送受信をすることができます。キーとバリューのセットというのは、「key:温度」&「value:29度」とか「key:天気」&「value:晴れ」という感じです。keyを指定して値をセットしたり取得したりできるのです。
1.メッセージやエラーを受け取るための、AppMessageのコールバック関数を作る。
2.コールバック関数をシステムに登録する。
3.AppMessageをオープンする。
オープンすると、メッセージが届くことで AppMessageInboxReceived コールバックが呼び出されるようになりますので、アプリはそれに応じた処理をすればよいと。
コールバック関数は使用される前に定義する必要があるので、init()より上に記載するのが良いでしょう。
static void inbox_received_callback(DictionaryIterator *iterator, void *context) { }
コールバック関数をあと3つ定義します。メッセージ消失の検出、送信エラーの検出、送信完了の検出です。
static void inbox_dropped_callback(AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_ERROR, "Message dropped!"); } static void outbox_failed_callback(DictionaryIterator *iterator, AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_ERROR, "Outbox send failed!"); } static void outbox_sent_callback(DictionaryIterator *iterator, void *context) { APP_LOG(APP_LOG_LEVEL_INFO, "Outbox send success!"); }
それぞれの処理が行われたことがわかるように、APP_LOG関数でログを出力するようにしています。
次に、init()の中で上記関数の登録を行います。
// Register callbacks app_message_register_inbox_received(inbox_received_callback); app_message_register_inbox_dropped(inbox_dropped_callback); app_message_register_outbox_failed(outbox_failed_callback); app_message_register_outbox_sent(outbox_sent_callback);
最後に、メッセージが届くように、AppMessage をオープンします。
// Open AppMessage app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());
メッセージの取りこぼしをしないために、順番として、オープン処理の前に必ず登録処理をしてください。
Pebble側の送受信の処理はこれで完了です。次に、実際に送受信される内容を決めます。
送信時のキーとなる値ですね。整数値で決めます。ここでは
「温度」を「KEY_TEMPERATURE」でプログラムとしての値は「0」
「天気」を「KEY_CONDITIONS」でプログラムとしての値は「1」
とします。
ソースファイルでは#defineで定義しとくといいです。
#define KEY_TEMPERATURE 0 #define KEY_CONDITIONS 1
定義が多い時は、enum使うのもいいっすよ、とのこと。
enum { KEY_TEMPERATURE = 0, KEY_CONDITIONS = 1 }
Preparing PebbleKit JS
次は PebbleKit JS の準備です。ここでは、天気情報を PebbleKit JSを通して取得するわけですが、そもそも、PebbleKit JSってナニモンじゃあ、という感じです。そこはまあ、実装しながら、理解していくことにします。
最初に「SOURCE FILES」で「ADD NEW」、FILE TYPEは「JavaScript file」を選択。名前は「weather.js」にして「CREATE」します。
PebbleKit JS SDKを使うための基本的なテンプレートがありまして、2つのイベントリスナーがあります。
・readyイベント
Pebbleでwatchapp/watchfaceが実行された後で、PebbleKit JSが準備OKになったときに発生。
・appmessageイベント
AppMessageがPebbleから親機スマートフォンに送られたときに発生。
テンプレートは下記のようになります。「weather.js」に貼り付けてセーブしといてください。
// Listen for when the watchface is opened Pebble.addEventListener('ready', function(e) { console.log('PebbleKit JS ready!'); } ); // Listen for when an AppMessage is received Pebble.addEventListener('appmessage', function(e) { console.log('AppMessage received!'); } );
ここまでで、いったん動作確認してみます。
起動完了したら「VIEW LOGS」でログ見てみてください。
うまくいってると「[PHONE] pebble-app.js:?: PebbleKit JS ready!」が出てると思います。
「DISMISS」押しちゃった場合は左メニュー「COMPILATION」の「VIEW APP LOGS」からログ見れます。
Cファイルからは「APP_LOG」、JSファイルからは「console.log()」でログ出力ができるのですね。
「表示準備」「Pebbleとスマートフォンのデータ送受信準備」ができましたので、実際に表示するための情報を取得する部分に入ります。
Getting Weather Information
OpenWeatherMap.org から天気情報を取得してWatchfaceに表示する手順は下記の通り。
1.スマートフォンからユーザの位置情報を取得
2.XMLHttpRequest オブジェクトを使ってOpenWeatherMap API を呼ぶ。このとき1.で取得した位置情報を渡す。
3.XMLHttpRequestの戻り値から取得した情報をPebbleに送り、Watchfaceに表示する。
最初に「SETTING」の「USES LOCATION」のチェックを入れて、位置情報が使用できるようにします。(「SAVE CHANGES」忘れずに!)
次に位置情報取得の処理をJSに追加します。パラメータとしてtimeoutにタイムアウト時間、maximumAgeにキャッシュ最大保存時間を指定します
function locationSuccess(pos) { // We will request the weather here } function locationError(err) { console.log('Error requesting location!'); } function getWeather() { navigator.geolocation.getCurrentPosition( locationSuccess, locationError, {timeout: 15000, maximumAge: 60000} ); } // Listen for when the watchface is opened Pebble.addEventListener('ready', function(e) { console.log('PebbleKit JS ready!'); // Get the initial weather getWeather(); }
位置情報取得でエラーが起きる可能性もあるのでその場合の処理も入ってますね。
「ready」イベントが起きると「getWeather()」が呼ばれ、さらに「getCurrentPosition()」が呼ばれます。
うまく位置取得できれば「locationSucess()」が呼ばれて位置情報が入っている「pos」が引数で送られてきます。
次に取得した「pos」を使って天気情報を取得します。
XMLHttpRequest を使って OpenWeatherMap.org から情報取得ですね。
最初にシンプルにリクエストするだけの関数を作りましょう。
locationSuccess();の前に書いておいてください。
var xhrRequest = function (url, type, callback) { var xhr = new XMLHttpRequest(); xhr.onload = function () { callback(this.responseText); }; xhr.open(type, url); xhr.send(); };
引数は、URL、type(GET または POST)、受信完了時のcallback関数です。
呼び出すURLは、OpenWeatherMapのAPI pageに仕様が載っています。「pos」の値で緯度/経度を指定して、下記のようになります
var url = 'http://api.openweathermap.org/data/2.5/weather?lat=' + pos.coords.latitude + '&lon=' + pos.coords.longitude;
typeはGETを使います。戻り値を処理するcallback関数も書いて、全体では下記のようになります。
function locationSuccess(pos) { // Construct URL var url = 'http://api.openweathermap.org/data/2.5/weather?lat=' + pos.coords.latitude + '&lon=' + pos.coords.longitude; // Send request to OpenWeatherMap xhrRequest(url, 'GET', function(responseText) { // responseText contains a JSON object with weather info var json = JSON.parse(responseText); // Temperature in Kelvin requires adjustment var temperature = Math.round(json.main.temp - 273.15); console.log('Temperature is ' + temperature); // Conditions var conditions = json.weather[0].main; console.log('Conditions are ' + conditions); } );
これで、位置情報が正しく取得されれば、
xhrRequestが呼ばれて、その戻りのJSONをパースすることで温度と天気を獲得することができます。全体では、どんな値が返ってきているかというと、
こういう感じです。これはロンドンの例ですね。
戻ってきた値から、下記情報を取得しています。
・main.temp →温度(ケルビンなのでセ氏に直す)
・weather[0].main →天気
その他、風速が知りたければ「wind.speed」を見ればいいですし、いろいろ情報が取れますね。実行してログ確認して、下記のように取得できてればOKです。
[PHONE] pebble-app.js:?: Temperature is 12 [PHONE] pebble-app.js:?: Conditions are Clouds
CloudPebbleでPCで動作させていると、正しい位置は取れないようなのですけども、そこはまあ、しょうがない…。
値が取れるようになったので、あとはこれをPebble側に渡して表示するのじゃあ!