Last active
March 20, 2019 09:57
-
-
Save paralleltree/d14153bdf2891878070c4f23833ed1f3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'optparse' | |
require 'pasori' | |
require_relative 'suica' | |
parser = OptionParser.new | |
args = {} | |
parser.on('--idm') { |v| args[:mode] = :idm } | |
parser.on('--balance') { |v| args[:mode] = :balance } | |
parser.on('--gate-history') { |v| args[:mode] = :gate_history } | |
parser.on('--purchase-history') { |v| args[:mode] = :purchase_history } | |
parser.on('-v', '--verbose') { |v| args[:verbose] = true } | |
parser.parse!(ARGV) | |
unless args[:mode] | |
warn 'No options supplied. Exiting.' | |
exit 1 | |
end | |
Pasori.open do |p| | |
warn 'Waiting for a card...' if args[:verbose] | |
begin | |
p.felica_polling(Felica::POLLING_SUICA) do |f| | |
warn "Reading..." if args[:verbose] | |
suica = Suica.new(f) | |
case args[:mode] | |
when :idm | |
puts sprintf("%016X", suica.idm) | |
when :balance | |
puts suica.balance | |
when :gate_history | |
suica.gate_history.reverse.each do |h| | |
puts "#{h[:time].strftime("%FT%R")} #{h[:gate_type]} #{h[:line_code]} #{h[:station_code]}" | |
end | |
when :purchase_history | |
suica.purchase_history.reverse.each do |h| | |
vendor = Suica::VendorType[h[:vendor_type]] | |
event = Suica::EventType[h[:event_type]] | |
puts "#{h[:serial_number]} #{h[:date]} #{format("%4d", h[:balance])} #{event} #{vendor}" | |
end | |
end | |
end | |
break | |
rescue PasoriError | |
sleep 1 | |
end while true | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'date' | |
require 'pasori' | |
class Suica | |
def initialize(felica) | |
@felica = felica | |
end | |
def fetch(service, mode = 0) | |
[].tap do |arr| | |
@felica.foreach(service) { |l| arr << l } | |
end | |
end | |
def idm | |
@felica.idm.unpack('Q>').first | |
end | |
def balance | |
@felica.read(0x008B, 0).unpack('NNCnvCn')[4] | |
end | |
def purchase_history | |
fetch(Felica::SERVICE_SUICA_HISTORY).map do |l| | |
d = l.unpack('CCCCnCCCCvCvC') | |
{ | |
vendor_type: d[0], | |
event_type: d[1], | |
entered_with_pass: d[3] == 3, | |
exited_with_pass: d[3] == 4, | |
origin_line_code: d[5], | |
origin_station_code: d[6], | |
dest_line_code: d[7], | |
dest_station_code: d[8], | |
date: Date.new((d[4] >> 9) + 2000, (d[4] >> 5) & 0b1111, d[4] & 0b11111), | |
balance: d[9], | |
serial_number: d[11], | |
special: d[12] | |
} | |
end | |
end | |
def gate_history | |
fetch(Felica::SERVICE_SUICA_IN_OUT).map do |l| | |
d = l.unpack('CCCCnnnvvn') | |
{ | |
gate_type: d[0], | |
line_code: d[2], | |
station_code: d[3], | |
time: Time.new((d[5] >> 9) + 2000, (d[5] >> 5) & 0x0f, d[5] & 0x1f, (d[6] >> 8).to_s(16).to_i, (d[6] & 0xff).to_s(16).to_i, 0), | |
extra: d[7] | |
} | |
end | |
end | |
VendorType = { | |
0x03 => '精算機', | |
0x05 => '車載端末', | |
0x07 => '券売機', | |
0x08 => '券売機', | |
0x09 => '入金機', | |
0x12 => '券売機', | |
0x14 => '券売機等', | |
0x15 => '券売機等', | |
0x16 => '改札機', | |
0x17 => '簡易改札機', | |
0x18 => '窓口端末', | |
0x19 => '窓口端末', | |
0x1A => '改札端末', | |
0x1B => '携帯電話', | |
0x1C => '乗継精算機', | |
0x1D => '連絡改札機', | |
0x1F => '簡易入金機', | |
0x23 => '新幹線改札機', | |
0x46 => 'VIEW ALTTE', | |
0x48 => 'VIEW ALTTE', | |
0xC7 => '物販端末', | |
0xC8 => '自販機', | |
} | |
EventType = { | |
0x01 => '改札出場', | |
0x02 => 'チャージ', | |
0x03 => '磁気券購入', | |
0x04 => '精算', | |
0x05 => '入場精算', | |
0x06 => '改札窓口処理', | |
0x07 => '新規発行', | |
0x08 => '窓口控除', | |
0x0d => 'バス', | |
0x0f => 'バス', | |
0x11 => '再発行処理', | |
0x13 => '支払(新幹線利用)', | |
0x14 => '入場時オートチャージ', | |
0x15 => '出場時オートチャージ', | |
0x1f => 'バスチャージ', | |
0x23 => 'バス路面電車企画券購入', | |
0x46 => '物販', | |
0x48 => '特典チャージ', | |
0x49 => 'レジ入金', | |
0x4a => '物販取消', | |
0x4b => '入場物販', | |
0xc6 => '現金併用物販', | |
0xcb => '入場現金併用物販', | |
0x84 => '他社精算', | |
0x85 => '他社入場精算', | |
} | |
GateType = { | |
0x20 => '出場', | |
0x40 => '出場(定期)', | |
0xa0 => '入場', | |
0xc0 => '入場(定期)', | |
0x00 => '清算', | |
} | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment