NFC通信での読み取り_Suicaの残高の読み取り

■スマホでSuica残高を読み取るコード。
前回タグの読み取りができたけど、実際のデータが返ってこなかった。ウェブで調べたコードを基に、Suica残高を表示させてみた。
データ自体は前回試した connect、transceive のメソッドで十分だった。パラメータの値として、Suicaのサービスコードとブロックコードを含めることでデータ取得ができた。

タグを読み取った後のコードは下の通り。Suicaのサービスコード0x090f、ブロック番号0x80はウェブで調べたもの(ここで0xは16進数を示す。0x090f は、090fの16進数のため、10進数で2319となる)。

            NfcF nf = NfcF.get(tag);
            int length = 64;
            ByteBuffer buff = ByteBuffer.allocate(length);
            byte byteLength = (byte) length;
            byte[] idm = nf.getTag().getId();
            byte[] read_wo_encryption_command = new byte[]{(byte) 0x06};
            // Suicaのサービスコード: 0x090f
            byte[] data = new byte[]{
                    (byte) 0x01,
                    (byte) 0x0f,
                    (byte) 0x09,
                    (byte) 0x01,
                    (byte) 0x80,
                    (byte) 0x00,
            };
            buff.put(byteLength).put(read_wo_encryption_command).put(idm).put(data);
            byte[] tranCmd = buff.array();
            byte[] result = new byte[255];

            TextView tv = findViewById(R.id.tv1);
            try {
                nf.connect();
                result = nf.transceive(tranCmd);

      (以下省略)

transceive の引数のフォーマット(長さ 1バイト、コマンドコード 1バイト、ID 8バイト、パラメータ 10バイト:1バイトは8ビット(0~255))と比べても、上の例は合致する。

パラメータ部分(上の例でのdata部分)は、おそらくサービス数(0x01)、サービスコード(0x090fを2つに分けたもの)、ブロック数(0x01)、ブロック位置(ブロック位置を2つに分けたもの)。1ブロックは16バイトとのことなので、0x80 (128、1ブロック)、0x100 (256、2ブロック)、0x180 (384、3ブロック) などから指定できるよう。0x180 とする場合、(byte) 0x80, (byte) 0x01 と指定する。

Suicaの場合、1ブロックの中に残高を含めた取引履歴が入っているそうで、2ブロック分のデータを取得した場合は、最新のものと1つ前のものが含まれていた。

実行してSuicaを読み取った結果が下のもの。読み取った結果もバイト表記となるので、それらを変換して表示させたもの。


今回、ウェブのコードを基にしたけど、Suicaの仕様など分からなかったらサービスコードとか何を使えばいいか分からなかっただろうなー。