Rubotoを使い、Androidで「長野市バス共通ICカード KURURU(くるる)」の履歴を読んでみた

第44回NSEG勉強会に行った時に「長野市バス共通ICカード KURURU(くるる)」を手に入れました。
FeliCaということなので 以前作ったアプリ に機能を追加して読めるかどうかを試してみたところ、読むことができました。

環境

RubotoとJavaのバージョンが上がっていたので、それに合わせて手元でもバージョンを上げてみました。バージョンの上げ方やその時のの不具合は前回まとめた通りです。

Platform JDK ant Ruby ruboto jruby-jars Device API level
Windows7 x64 1.7.0_45 1.9.1 RubyInstaller 1.9.3-p448 0.15.0 1.7.6 Nexus7 2012 android-17

くるるのフォーマット

フォーマットについては以下を参考にしました。くるるからは利用履歴と残高の2種類のデータが取れるようですが、今回は利用履歴を使いました。
KURURU 履歴フォーマット | あたがわの日記


なお、上記で想像と書かれている「場所・種別・会社・割引」については、手元のくるるだけでは情報が足りず特定することができませんでした。とりあえず想像の文字列を入れておきましたが、2進数のコードも併せて表示しておきます。
また、システムコードは「0x8D3F」、利用履歴を取る際のサービスコードは「0x000F」でした。



FeliCaの解析について

自力での解析も検討しましたが、さすがに手間がかかり過ぎると考え、以下のアプリ(Android_NFC_FelicaEdit)をインストールして使いました。システムコードやサービスコードも表示されるため、非常にありがたいです。なお、手元のNexus7(2012)は Android4.3 でしたが、問題なく動作しました。


ちなみに、くるるや他のFeliCaなどを見る限り、「循環RO」と出ているところが履歴データっぽいようです。


また、カード型のEdyには複数のシステムコードがありますが、android.nfc.TagのgetIdメソッドでは一つしか取れないため、「nfc-felica」ライブラリの FeliCaTagクラスのgetSystemCodeListを使って全件を取得することにしました。



JRubyまわり

Javaのクラスのprotectedフィールドにアクセスする

目的に応じて、「field_reader」「field_writer」「field_accessor」を使えば良いようです。
CallingJavaFromJRuby · jruby/jruby Wiki · GitHub


なお、「declared_field」と「set_value」を使えば同じようなことができるようですが、今回「set_value」でうまく値をセットできなかったため、使用しませんでした。
JRubyでJavaのクラスをいじり倒す。 - red5server @ ウィキ - アットウィキ



Rubyまわり

Rubyで商と余りを同時に取得する

instance method Numeric#divmod (Ruby 1.9.3)



ソースコード

今回の対応で、SuicaEdy・くるる、いずれかのカードをかざせば、自動的に判別してそれらの残額が表示されるようになりました。
GitHub - thinkAmi/RubotoFelicaRead: RubotoでEdyやSuicaの履歴を読むアプリ



スクリーンショット

NSEG勉強会当日に、くるるを使った流れは以下の通りです。

  1. くるるを新規購入(2,000円、うちデポジットが500円)
  2. 長野駅東口から文化会館入口まで、長電バスに乗車(170円)
  3. 信大工学部前から長野バスターミナルまで、アルピコバスに乗車(170円) *1
  4. 駅前のアルピコバス事務所で、入金(1,000円)


アプリを使うと以下のようなイメージで読むことができました。

*1:本当は長野駅まで乗車する予定が、バスターミナルという言葉に反応してしまい、誤って下車...