1. Imagawayaki

    No comment

    Imagawayaki
Changes in body
Source | HTML | Preview
@@ -1,180 +1,180 @@
# PythonでSuicaの残高を取得する(libpafe使用)
* 手元に中古で買ったFelicaリーダのRC-S320があったので,Pythonを使って動かせないか試してみた.
* ちょっとした備忘録的なメモです.
* そのうちRaspberry piとかで何かと組み合わせてみる予定.
## 動作環境
* OS: LMDE 2 Betsy
* FeliCaリーダ: Sony RC-S320
* Pythonのバージョン: 2.7.9
## ライブラリ
* [nfcpy](http://nfcpy.readthedocs.io/en/latest/index.html)の存在を知ったが,RC-S320には対応していない.
* [libpafe](https://github.com/rfujita/libpafe)が対応していた.
* C言語のライブラリとして使える.
* Ruby上なら[libpafe-ruby](http://hito.music.coocan.jp/pasori/libpafe-ruby.html)が使える.
## 環境設定
1. libusbのインストール
* `$ sudo apt-get install libusb-dev`
2. GitHubからlibpafeをcloneする
* `$ git clone https://github.com/rfujita/libpafe.git`
3. コンパイル&インストール
```
$ cd libpafe
$ ./configure
$ make
$ sudo make install
```
4. 動作確認
```
$ cd libpafe
$ ./tests/pasori_test
PaSoRi (RC-S320)
firmware version 1.40
Echo test... success
EPROM test... success
RAM test... success
CPU test... success
Polling test... success
```
5. udevの設定
* 60-libpafe.rulesを作成
- `$ sudo vi /lib/udev/rules.d/60-libpafe.rules`
+ * `$ sudo vi /lib/udev/rules.d/60-libpafe.rules`
* 以下の内容を記述
```60-libpafe.rules
ACTION!="add", GOTO="pasori_rules_end"
SUBSYSTEM=="usb_device", GOTO="pasori_rules_start"
SUBSYSTEM!="usb", GOTO="pasori_rules_end"
LABEL="pasori_rules_start"
ATTRS{idVendor}=="054c", ATTRS{idProduct}=="01bb", MODE="0664", GROUP="plugdev"
ATTRS{idVendor}=="054c", ATTRS{idProduct}=="02e1", MODE="0664", GROUP="plugdev"
LABEL="pasori_rules_end"
```
* `$ sudo udevadm control --reload-rules`を実行
* `$ sudo reboot`で再起動する.
## ICカードのIDmを取得する
* ひとまずICカードのIDmを取得してみる.
[raspberrypiでFeliCaのIDmを読み取る(pasori RC-S320版)](http://qiita.com/t114/items/819a9cdfe90ea98dd4d3)
[Raspberry Pi + libpafe + Python + ctypesで、FeliCaのIDmを読む](http://thinkami.hatenablog.com/entry/2015/06/16/212600)
(ほぼこちらに載せられていたものを参考にしています)
```python:read_idm.py
# -*- coding: utf-8 -*-
from __future__ import print_function
from ctypes import *
# libpafe.hの77行目で定義
FELICA_POLLING_ANY = 0xffff
if __name__ == '__main__':
libpafe = cdll.LoadLibrary("/usr/local/lib/libpafe.so")
libpafe.pasori_open.restype = c_void_p
pasori = libpafe.pasori_open()
libpafe.pasori_init(pasori)
libpafe.felica_polling.restype = c_void_p
felica = libpafe.felica_polling(pasori, FELICA_POLLING_ANY, 0, 0)
idm = c_ulonglong()
libpafe.felica_get_idm.restype = c_void_p
libpafe.felica_get_idm(felica, byref(idm))
# IDmは16進表記
print("IDm:", "%016X" % idm.value)
# READMEより、felica_polling()使用後はfree()を使う
# なお、freeは自動的にライブラリに入っているもよう
libpafe.free(felica)
libpafe.pasori_close(pasori)
```
* libpafeはC言語用のライブラリだが,Pythonのctypesを使うことでC言語の関数がPython上で使えるようになる.
* felica_get_idmを使う.
* `int felica_get_idm(felica *f, uint8 *idm);`
* f : felica_pollingで取得したfelica型のポインタ
* idm : IDmを格納するためのポインタ
## Suicaの残高を取得する
* Suicaの残高を表示するのはどうやるか?
* ICカード内の情報を取ってきて,その中から残高の情報を拾ってくる必要がある
* Suicaのデータ構造まとめ: [suica - FeliCa Library Wiki - FeliCa Library - OSDN](https://ja.osdn.net/projects/felicalib/wiki/suica)
* 10-11のあたりのデータを取ってくれば良さそう.
* libpafeのfelica_readという関数で諸々の情報を取ってくることができるので,それを使う.
参考: [続けるブログ: ラズベリーパイがICカードの残高をしゃべるよ](http://continue-to-challenge.blogspot.jp/2014/11/ic.html)
* ↑こちらはC言語で書かれているため,ctypesを使ってPython上でfelica_readを呼び出せるように書き換える
* 引数が構造体のポインタを示していたりするので,あらかじめ定義して調整する
```python:read_balance.py
# -*- coding: utf-8 -*-
from __future__ import print_function
from ctypes import *
# libpafe.hの77行目で定義
FELICA_POLLING_ANY = 0xffff
# 構造体の代わりとなるクラスの定義
class felica_block_info(Structure):
_fields_ = [
("service", c_uint16),
("mode", c_uint8),
("block", c_uint16)
]
if __name__ == '__main__':
libpafe = cdll.LoadLibrary("/usr/local/lib/libpafe.so")
libpafe.pasori_open.restype = c_void_p
pasori = libpafe.pasori_open()
libpafe.pasori_init(pasori)
libpafe.felica_polling.restype = c_void_p
felica = libpafe.felica_polling(pasori, FELICA_POLLING_ANY, 0, 0)
# Cのint型配列の定義(長さ16)
int_array16 = c_uint8 * 16
# 応答データ
data = int_array16()
# サービスコードのリスト
info = felica_block_info(c_uint16(0x090f), c_uint8(0), c_uint16(0))
for i in range(0, 32):
c_i = c_int(i)
libpafe.felica_read(felica, byref(c_i), byref(info), byref(data))
if (data[1] > 0) or (data[2] > 0):
print("残高:", data[11] * 256 + data[10], "円")
break
libpafe.free(felica)
libpafe.pasori_close(pasori)
```
* 同じ構造になっているからか,ICOCAとtoicaでもちゃんと使えた.
## 参考
* [raspberrypiでFeliCaのIDmを読み取る(pasori RC-S320版)](http://qiita.com/t114/items/819a9cdfe90ea98dd4d3)
* [Raspberry Pi + libpafe + Python + ctypesで、FeliCaのIDmを読む](http://thinkami.hatenablog.com/entry/2015/06/16/212600)
* [suica - FeliCa Library Wiki - FeliCa Library - OSDN](https://ja.osdn.net/projects/felicalib/wiki/suica)
* [ラズベリーパイがICカードの残高をしゃべるよ](http://continue-to-challenge.blogspot.jp/2014/11/ic.html)
* [ctypes 〜pythonでCをイジる(Macで)〜 - カールヌードル](http://curlnoodle.hatenablog.com/entry/2013/12/30/221858)