Kazzzさんが公開されている nfc-felica
http://code.google.com/p/nfc-felica/ をカスタマイズして入退場記録を表示してみました。
入退場記録のフォーマット
以下のサイトを参考にしました。
http://jennychan.web.fc2.com/format/suica.html#108F
カスタマイズ箇所
・入退場記録クラスをSuica.javaに追加
public static class Inout {
final byte[] data;
Context context;
/**
* コンストラクタ
* @param data データのバイト列(16バイト)をセット
* @param context androidコンテキストをセット
*/
public Inout(byte[] data, Context context) {
this.data = data;
this.context = context;
}
public String getConsoleType(){
switch(data[0]){
case (byte) 0x00:return "清算出場";
case (byte) 0x20:return "出場";
case (byte) 0x21:return "駅務機器出場";
case (byte) 0x40:return "定期出場";
case (byte) 0xA0:return "入場";
case (byte) 0xC0:return "定期入場";
}
return Byte.toString(data[0]);
}
/**
* 入場駅を取得します
* @return String バスの場合、序数0に会社名、1停留所名が戻ります
* 鉄道の場合、序数0に会社名、1に路線名、2に駅名が戻ります
*/
public String[] getEntranceStation() {
// if ( this.isByBus() ) {
// //バス利用の場合
// return getBusStop(Util.toInt(new byte[]{this.data[6], this.data[7]})
// , Util.toInt(new byte[]{this.data[8], this.data[9]}));
// } else {
//鉄道利用の場合
return getStation(0, this.data[2], this.data[3]);
// }
}
/**
* 地区コード、線区コード、駅順コードから駅名を取得します
* http://sourceforge.jp/projects/felicalib/wiki/suicaを参考にしています
* @param regionCode 地区コードをセット
* @param lineCode 線区コードをセット
* @param statioCode 駅順コードをセット
* @return 取得できた場合、序数0に会社名、1に路線名、2に駅名が戻ります
*/
private String[] getStation(int regionCode, int lineCode, int statioCode) {
int areaCode = regionCode & 0xff;
DBUtil util = new DBUtil(this.context);
try {
SQLiteDatabase db = util.openDataBase();
Cursor c = db.query(TABLE_STATIONCODE
, COLUMNS_STATIONCODE
, COLUMNS_STATIONCODE[0] + " = '" + areaCode + "' and "
+ COLUMNS_STATIONCODE[1] + " = '" + (lineCode & 0xff) + "' and "
+ COLUMNS_STATIONCODE[2] + " = '" + (statioCode & 0xff) + "'"
, null, null, null, COLUMN_ID);
return ( c.moveToFirst() )
? new String[]{ c.getString(3), c.getString(4), c.getString(5)}
: new String[]{"???", "???", "???"};
} catch (Exception e) {
e.printStackTrace();
return new String[]{"error", "error", "error"};
} finally {
util.close();
}
}
/**
* 処理日付(出場日付)を取得します
* @return byte[]
*/
public Date getProccessDate() {
int date = Util.toInt(new byte[]{this.data[6], this.data[7]});
int yy = date >> 9;
int mm = (date >> 5) & 0xf;
int dd = date & 0x1f;
int hh = Util.toInt(new byte[]{(byte) ((this.data[8]&0xf0) >> 4) }) * 10
+ Util.toInt(new byte[]{(byte) (this.data[8]&0x0f)});
int min = Util.toInt(new byte[]{(byte) ((this.data[9]&0xf0) >> 4) }) * 10
+ Util.toInt(new byte[]{(byte) (this.data[9]&0x0f)});
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, 2000 + yy);
c.set(Calendar.MONTH, mm-1);
c.set(Calendar.DAY_OF_MONTH, dd);
c.set(Calendar.HOUR_OF_DAY , hh);
c.set(Calendar.MINUTE, min);
return c.getTime();
}
@Override
public String toString() {
NumberFormat nf = NumberFormat.getCurrencyInstance();
nf.setMaximumFractionDigits(0);
SimpleDateFormat dfl = new SimpleDateFormat("yyyy/MM/dd HH:mm");
StringBuilder sb = new StringBuilder();
sb.append("入出場: " + this.getConsoleType() + "\n");
sb.append("日時: " + dfl.format(this.getProccessDate()) + "\n");
String[] entranceInfo = this.getEntranceStation();
sb.append(" 利用会社: " + entranceInfo[0]+ "\n");
sb.append(" 路線名: " + entranceInfo[1]+ "線\n");
sb.append(" 駅名: " + entranceInfo[2] + "\n");
return sb.toString();
}
}
・NFCFeliCaReader.javaの入退場記録ボタンを有効化
未解決事項
フォーマットは分かったのですが、以下の事項が未解決です。
・入出場、使用装置種別
→ 0byte目のデータですが、すべての値が判明していない
・地域コードがわからない
→ 路線コード(2byte目)&駅コード(3byte目)は判明しているが、
レコードの中に地域コードの値がない
・バス利用時は入退場に記録されるのか不明
→ こんどバスに乗ったときに履歴を除いてみます