以下を参考に Suica のデータを具体的に解析してみましょう。
最初の1バイトが 0x1B だとクレジット入金、0x07 or 0x08だと入金、0x46だとサンクスチャージの入金で、0x16が自動改札乗降、0xC7が購買のようです。5バイト目から2バイトが日付で、先頭から7ビットが年、4ビットが月、残り5ビットが日のようです。(ここが面倒でしたね。パズルみたい)7バイト目からの2バイトが入った駅、続く2バイトが出た駅がコードで入っています。駅のコードは、路線コード/駅コードの組合わせで、有志によるデータベースが公開されています。IC SFCard Fan DB Srevice このソフトではコードからの変換はしていません。12バイト目から2バイトが残金(リトルエンディアン)です。
160100020e98e376e37d2e2200008000
を例として詳しく見ていくと以下のようになります。
16 |
010002 |
0e98 |
e376 |
e37d |
2e22 |
00008000 |
1 | 2-4 | 5,6 | 7,8 | 9,10 | 11,12 | 13-16 |
- 1 バイト(タイプ)
-
1b
クレジット入金07
,08
入金46
サンクスチャージ入金16
自動改札乗降c7
購買
- 2-4 バイト
- 不明。私の場合、すべて
010002
になっている。 - 5,6 バイト(日付)
-
0e98
を2進数表記にすると0000 1110 1001 1000
年(7bit)/月(4bit)/日(5bit) なので
0000111 0100 11000
となりこれを10進数にして7 4 24
年に2000を足すことで 2007年4月24日 という日付が求められる。
- 7,8 バイト(入場駅)
-
前半1バイトが 線区コード で後半1バイトが 駅順コード と言うらしい。
これは、IC SFCard Fan のページで調べられる。SOAP による Web Service も公開されているのでこれを利用するとよさそう。
- 9,10 バイト(出場駅)
- 同上
- 11,12 バイト(残額)
- リトルエンディアン(
2e22
)らしいのでビッグエンディアン(222e
)に変換して10進数にすると 8750円 となる。 - 13-16 バイト(連番?)
- 15バイト目が 1 or 2 づつインクリメントしていることが確認できるが、それが意味するところは分からない。
これを Ruby で実装すると以下のような感じになります。
def Pasori.parse_suica_raw_value data d = "%016b" % data[8, 4].hex { :type => data[0, 2], :date => Time.local(d[0, 7].to_i(2) + 2000, d[7, 4].to_i(2), d[11, 5].to_i(2)), :in => data[12, 4], :out => data[16, 4], :yen => data[20, 2].hex + (data[22, 2].hex << 8), } end
こちらで作成したプログラムに上記関数を適用します。
dump_suica_2.rb
require 'pasori' Pasori.felica_raw_values Pasori::POLLING_SUICA, Pasori::SERVICE_SUICA, true do |data| d = Pasori.parse_suica_raw_value data str = sprintf "%s %s %s %s %5s", d[:type], d[:date].strftime('%Y/%m/%d'), d[:in], d[:out], d[:yen] puts str end
実行結果(dump_suica.rb)
% ruby dump_suica.rb 160100020e9bf101f20c661c00008e00 160100020e9bf102c5026a1d00008c00 160100020e9be37de532781e00008a00 160100020e9ae532e37d361f00008800 160100020e9ae37de532f41f00008600 160100020e99e532e37db22000008400 160100020e99e37de532702100008200 160100020e98e376e37d2e2200008000 1d0100020e98f102f104a62200007e00 160100020e98c502f102502300007c00 160100020e98f102c5025e2400007a00 160100020e98e37de5326c2500007800 160100020e97e355e37d2a2600007600 160100020e97e43ee3552a2600007400 160100020e97e355e43ee82600007200 160100020e97e37de37a062700007000 160100020e9625020102a62700006e00 160100020e9501022502462800006c00 160100020e95e37de37ae62800006a00 1b023f000e9500000000862900006800
実行結果(dump_suica_2.rb)
% ruby dump_suica_2.rb 16 2007/04/27 f101 f20c 7270 16 2007/04/27 f102 c502 7530 16 2007/04/27 e37d e532 7800 16 2007/04/26 e532 e37d 7990 16 2007/04/26 e37d e532 8180 16 2007/04/25 e532 e37d 8370 16 2007/04/25 e37d e532 8560 16 2007/04/24 e376 e37d 8750 1d 2007/04/24 f102 f104 8870 16 2007/04/24 c502 f102 9040 16 2007/04/24 f102 c502 9310 16 2007/04/24 e37d e532 9580 16 2007/04/23 e355 e37d 9770 16 2007/04/23 e43e e355 9770 16 2007/04/23 e355 e43e 9960 16 2007/04/23 e37d e37a 9990 16 2007/04/22 2502 0102 10150 16 2007/04/21 0102 2502 10310 16 2007/04/21 e37d e37a 10470 1b 2007/04/21 0000 0000 10630
こちらで実行したものと同じような結果を得ることができるようになりました。あとは何とか駅名を日本語表示にしてみたいものです。
2 comments:
hermes
kevin durant shoes
goyard
kd 12 shoes
kd 11 shoes
louboutin shoes
yeezy supply
balenciaga
vans
kyrie 5 spongebob
this contentdirectory find more infoofficial statement this websitearticle
Post a Comment