GPS
Garmin
BLE
IoT
ConnectIQ
OriginalqnoteDay 13

ケイデンスが100を超えるとごほうびに猫の写真が表示されるサイコンを作る

はじめに

アドベントカレンダーのネタが見つからずギリギリまで悩んでいましたが、趣味をネタにすればスラスラ書けるかも?と言うことで、今回は大好きな自転車の趣味を絡めた話題です。ちなみにタイトルにあるサイコンは Garmin Edge を使用しますので若干ハードル高しです。

cadence-under.png

ケイデンスとは

ケイデンスとはペダルの回転数のことで1分間の回転数を表します。ケイデンス100はどのくらいかと言うと、(個人差はありますが)通常のギアで時速30〜35km/hくらいのスピードが出ます。

Garmin Edge とは

Garmin Edge は Garmin 社が販売する高級サイクルコンピューターです。センサーの精度や安定性も然ることながら、公式にSDKが配布されており自由にセンサー類を使ったアプリや計器などを開発し、配布することができるのも大きな特徴です。
毎日自転車に乗る私にとっては物欲センサーをかなり刺激される品物で、Qiitaのネタにもなるという事から Edge 520 を持っているにも関わらずフラッグシップモデルの Edge 1030 を酔った勢いでポチりました。
結構いい値段する割には、調べれば調べるほどこの記事のニッチである事に気付いてしまい、こんなの誰が見るんだと些かの不安もありますが、年末のカレンダー祭りに便乗して公開します。

IMG_0120.jpg

Garmin Edge のセンサー

Garmin Edge には標準で次のようなセンサーが内蔵、および、別売りでのセンサーキットを購入することで、計測可能になります。

  • GPS
  • 気圧高度計
  • 加速度計
  • 温度計
  • 心拍計
  • スピードセンサー
  • ケイデンスセンサー

今回はケイデンスセンサーの値を監視して画面に反映してみます。

Garmin Edge アプリを作るには?

Connect IQ という Garmin 社独自のプラットフォームを使用します。SDKも無料で手に入り、開発したアプリはストアにアップロードすることで世界中に公開されます。でも有料アプリについては記載が無かったので、App Store や Google Play のようにマネタイズするのは難しそうです。

開発言語は?

「Monkey C」という言語です。おそらく Qiita でもこの言語の記事は初じゃないでしょうか。
Cを名乗りつつも JAVA (Android) っぽくもありつつ、型推論があるなどLL言語の影響を受けているらしく、特にとっつきにくい部分はありませんでした。

ビルド環境

IDE は Eclipse のプラグインとして提供されています。
これがなんと、実機ビルドができません。シミュレータで試して、実際にストアにアップロード(公開)しなければ、実機での動作確認は出来ないようです。
なので今回はシミュレータ上でダミーのケイデンスを取得して試してみました。

SDK ダウンロード

下記URLからダウンロードしてください。

https://developer.garmin.com/connect-iq/sdk/

解凍したら任意のフォルダにまるっとコピーして下さい。公式ドキュメントにはPATHを通す必要があると書いてありますが、コマンドラインツールを使用しないのであれば不要です。

Eclipse ダウンロード

まだ持ってない方は下記からダウンロード。
http://www.eclipse.org/downloads/

Eclipse Connect IQ Plugin のインストール

Eclipse を起動してプラグインをインストールします。
メニュー > Help > Install New Software...からプラグインインストール画面を開きます。
Addボタンからリポジトリの追加ダイアログをクリックし、下記を入力し。

Name: 任意 (Garmin とか)
Location: https://developer.garmin.com/downloads/connect-iq/eclipse/

OKを押すと Connect IQ がリストに出てくるのでチェックボックスを有効にしてNextボタン...あとは画面通りで完了です。

Connect IQ SDK の設定

最初にダウンロードして任意のフォルダに展開したSDKのパスを Eclipse に教えます。
Eclipseの環境設定画面から Connect IQ のメニューを開き、ローカルの SDK のパスを入力しましょう。
preferences.png

デベロッパーキーの生成

Connect IQ のコンパイル時にアプリケーションに署名するためのデベロッパーキーというものが必要になります。公式ドキュメントでは openssl コマンドで生成していましたが、Eclipse上からの操作の方が簡単でオススメです。

Eclipseの環境設定画面から Connect IQ のメニューを開き、Complierメニューを選択。
Complier

Generateボタンをクリックし、任意のファイル名を入力したら「Finish」ボタンをクリックして完了。

Generate

準備は以上です。

プロジェクトの作成

では早速アプリを作ってみましょう。
Fileメニュー > New の項目に「Connect IQ Project」という項目が追加されているのでクリックしてウィザードを開きます。プロジェクト名は適当に入力し、次へ進みます。

Garmin Edge 上で動作するアプリは2種類あり、サイコン上の計測値欄に表示する DataField タイプと、画面全体に表示する Widget タイプがあります。今回は Widget タイプのアプリを作成します。

Close the Project Type: Widget
App Version: 0.0.1
Choose the Minimum SDK Version: 1.2.x

次に実際に動作するデバイスの選択です。Connect IQ は実はサイコンだけでなくGPSウォッチなど他のスポーツのデバイスにも対応していますが、サイコンは Edge シリーズのみですので、Edge の名称があるデバイスを全部選択しておきましょう。

devices

次に、このアプリで取得する情報に対するパーミッションを設定します。今回はケイデンスセンサーの値を取得するので、一番下にある Sensor にチェックを入れて下さい。

permissions.png

最後に「Finish」ボタンをクリックしてプロジェクトウィザードを完了します。

プロジェクト構成

プロジェクトを作成したら Explorer には下図のようなツリーが表示されているかと思います。なんとなく Android ぽいのは気のせいですかね。とりあえずはリソース以下に画像やらレイアウトのXMLを書いて、source の下には Monkey C のコードを書く、というのはわかります。

project.png

Connect IQ アプリでは、source/[プロジェクト名]App.mc のファイルがアプリの管理クラスで、source/[プロジェクト名]View.mc が画面の管理クラスを担当するようです。

センサー値の取得

センサー値の取得はセンサーの有効化とコールバックメソッドの設定が必要です。
CadenceCatView.mc のコンストラクタ initialize() メソッドに下記のように定義しときましょ。

    function initialize() {
        View.initialize();
        Snsr.setEnabledSensors( [Snsr.SENSOR_BIKECADENCE] ); // <= 追加
        Snsr.enableSensorEvents( method(:onSnsr) );      // <= 追加
    }

コールバックメソッドの中ではセンサー情報が引数で渡されるので、直接ケイデンスの値を取得できます。ここではあとでUIにアップデートするためにアプリケーションストレージに値を保存しています。

    function onSnsr(sensor_info)
    {
        var cadence = sensor_info.cadence;
        Application.Storage.setValue("cadence", cadence);
        Ui.requestUpdate();
    }

ちなみに渡される sensor_info は、Sensor.Info オブジェクトで、ケイデンス以外には下記の値が定義されています。

// The Sensor.Info class contains all information necessary for the Sensor.
// It can be passed on the update or it can be retrieved on demand.
class Info
{
    var speed;          // Speed in meters per second
    var cadence;        // Cadence in revolutions per minute
    var heartRate;      // HR in beats per minute
    var temperature;    // Temperature in degrees Centigrade
    var altitude;       // Altitude in meters
    var pressure;       // Pressure in Pa
    var heading;        // Heading in Radians
}

後はこのケイデンス値を見て、しきい値の判定をし、画面を切り替えるだけです。View の更新は onUpdate() メソッドの中に記述します。

    // Update the view
    function onUpdate(dc) {
        // Call the parent onUpdate function to redraw the layout
        View.onUpdate(dc);

        // アプリケーションストレージからケイデンス値を取得
        var cadence = Application.Storage.getValue("cadence");
        if (cadence == null) {
            cadence = 0;
        }
        // ケイデンス値が100以下なら値を表示するだけ。
        if (cadence < 100) {
            dc.drawText(40, 110, Gfx.FONT_LARGE, cadence + " rpm", Gfx.TEXT_JUSTIFY_LEFT);
        }
        // それ以上ならご褒美写真を表示
        else {
            var image = Ui.loadResource( Rez.Drawables.gohoubi );
            dc.drawBitmap(-10, 50, image);
        }
    }

これをシミュレータで実行するとこうなります。

cadences.png

こんなの表示されちゃったら走るのが楽しくなっちゃいますね!

まとめ

思っていたよりも Monkey C という言語に違和感なく入れました。センサーAPIも豊富にあり、スマホアプリとはまた違ったアプリが実現できそうです。あとは実機ビルドとマネタイズがあればもっと開発者が増えて良いアプリが増えてくるでしょうね。今後のSDKのアップデートに期待です。