ラズパイと繋げてSuicaを読み取る時に使ったFeliCaカードリーダー PaSoRi(RC-S380)をね、分解してみました。中のFeliCaリーダーモジュールだけ取り出せたらもっとコンパクトになってラズパイに組み込みやすくなったりするかもじゃん。

※当たり前ですがおすすめはしません。やるなら絶対に自己責任でお願いします。

 

必要なもの

  • PaSoRi RC-S380
  • ちょうどいいサイズのドライバー

 

分解します

まず裏返して滑り止めシールを取ります。

2016-03-14 12.20.25

 

ドライバーでネジを取ります。

2016-03-14 12.20.56

 

前後にズラしながらカバーを開けます。若干力使います。持った時の軽さで予想はついてたけど思った以上に中はスカスカです。

2016-03-14 12.22.24

 

モジュールを天板から剥がします。両面テープで張り付いていただけでした。

2016-03-14 12.23.19

 

中身です

こんな感じになっています。

2016-03-14 20.42.26

 

反対側

2016-03-14 20.42.48

 

もちろんこのままUSBでラズパイとつないで使えます。

2016-03-14 20.46.35

 

前回の続きです。前回はRaspberry PiとPaSoRiを繋げてSuicaのIDmを取得しました。今回はSuicaの履歴を読み取ります。

 

Felicaの「ブロック」について

FeliCaには暗号化された領域と暗号化されていない領域があります。われわれ一般ピーポーが勝手にアクセスできるのは暗号化されていない領域だけです。

Suicaでは暗号化されていない領域に直近20件の履歴が記録されています。各履歴レコードは「ブロック」と呼ばれ、1ブロック=1履歴です。この暗号化されていない領域からブロックを読み取る命令を「Read Without Encryption」といいます。(詳細はSonyのFelicaカード ユーザーズマニュアルをご覧ください)

 

Pythonでブロックを読み取る

前回使用したPython用NFCライブラリ「nfcpy」を今回も使用します。まず最初にソースコード全体をお見せします。

<説明>

7行目で nfcpy をダウンロードしたディレクトリを指定してパスに追加しています。そして8行目でimportしています。

10行目で宣言している service_code = 0x090f はSuica内の乗降履歴情報のサービスコードです。これはこういうものだと覚えておきましょう。

26行目でPaSoRiとの接続を開始して、on-connect で12行目〜の connected が呼ばれます。

17行目でサービスコード(0x090f)を read_without_encryption メソッドに渡すためのServiceCodeクラスインスタンスに変換しています。

18行目は読み込むブロックの番号を指定するのですが、今回は0番(1ブロック目)を指定しています。

そして19行目でRead Without Encryptionコマンドを発行し、結果を表示しています。

実行結果はこんな感じ。

$ sudo python felica.py 
Type3Tag 'FeliCa Standard (RC-S???)' ID=011203123412A30B PMM=100B4B428485D0FF SYS=0003
block: c8460000206b4cc049f907120007e000

現状では読み取ったブロックを16進数文字列で表示しているだけなので、これを更にパースしてあげる必要があります。

 

ブロックをパースする

ここでは詳細についての説明はしませんが、ブロック内の何バイト目が何を意味するかというのは有志により解析されています。(suica – FeliCa Library Wiki – FeliCa Library – OSDN

これにしたがってパースする処理を追加したのがm2wasabiさんがGithub(https://github.com/m2wasabi/nfcpy-suica-sample)で公開している以下のコードです。駅コードから駅名を表示するために StationCode.csv というCSVファイルを同じディレクトリに置いています。

 

このスクリプトを実行すると以下のような結果が表示されます。

$ sudo python suica_read.py 
Type3Tag 'FeliCa Standard (RC-S???)' ID=011203123412A30B PMM=100B4B428485D0FF SYS=0003
=== 00 ===
端末種: 自販機
処理: 物販
日付: 16-03-11
入線区: None-None
入駅順: None
出線区: None-None
出駅順: None
残高: 4615
BIN: 
c8 46 00 00 20 6b 4c c0 49 f9 07 12 00 07 e0 00 
=== 01 ===
端末種: None
処理: 物販
日付: 16-03-10
入線区: None-None
入駅順: None
出線区: None-None
出駅順: None
残高: 5015
BIN: 
c7 46 00 00 20 6a b7 45 df e9 97 13 00 07 df 00 
=== 02 ===
端末種: 改札機
処理: 運賃支払
日付: 16-03-10
入線区: 東日本旅客鉄道-東海道本
入駅順: 浜松町
出線区: 東日本旅客鉄道-山手
出駅順: 池袋
残高: 5632
BIN: 
16 01 00 02 20 6a 01 04 25 0f 00 16 00 07 de 00 
  :

 

日付や駅名等が表示されましたね。

続き:Raspberry Pi 入門 5日目 – Raspberry PiのSDカードのバックアップを作成する(Mac OS Xの場合)

 

 

 

参考記事:

ラズパイにFeliCaカードリーダーを繋げてSuicaのIDmという識別子を読み取ってみます。ラズパイにSSHでログインしている状態から始めます。言語はPythonを使用します。

FeliCaカードリーダーはPaSoRi RC-S380を使用します。BluetoothではなくUSBで接続するタイプのやつです。

 

Raspberry Pi と PaSoRi を接続する

下図のようにラズパイのUSBポートにPaSoRiを接続します。

2016-03-07 12.05.12

 

この状態で lsusb コマンドを叩くとラズパイに接続されている機器の情報を見ることが出来ます。

$ lsusb
Bus 001 Device 004: ID 054c:06c3 Sony Corp. 
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

PaSoRiはSony製なので、Sony Corp. と表示されます。今回は一番上に表示されています。

 

PythonでSuicaのIDmを読み取る

PythonでNFCデバイスを制御するためのnfcpyというライブラリがあるので、今回はこれを使用します。

PythonはVer.2.7系のものがラズパイに初めから入っているので別途インストールする必要はありません。ということでnfcpyのインストールを行います。基本的に公式サイトの手順通りにコマンドを実行すれば問題ありません。

 

まずはbzrコマンドをインストールします。bzrはバージョン管理システムBazzarのコマンドラインツールです。

$ sudo apt-get install bzr
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下の追加パッケージがインストールされます:
  python-bzrlib python-configobj python-crypto python-gpgme python-httplib2 python-keyring python-launchpadlib python-lazr.restfulclient python-lazr.uri python-oauth python-secretstorage python-simplejson python-wadllib python-zope.interface
提案パッケージ:
  bzr-doc bzrtools python-bzrlib.tests python-bzrlib-dbg python-kerberos python-paramiko python-pycurl python-configobj-doc python-crypto-dbg python-crypto-doc gir1.2-gnomekeyring-1.0 python-fs python-gdata python-kde4 python-keyczar python-testresources gnome-keyring
  python-secretstorage-doc
以下のパッケージが新たにインストールされます:
  bzr python-bzrlib python-configobj python-crypto python-gpgme python-httplib2 python-keyring python-launchpadlib python-lazr.restfulclient python-lazr.uri python-oauth python-secretstorage python-simplejson python-wadllib python-zope.interface
アップグレード: 0 個、新規インストール: 15 個、削除: 0 個、保留: 0 個。
2,366 kB のアーカイブを取得する必要があります。
この操作後に追加で 13.1 MB のディスク容量が消費されます。
続行しますか? [Y/n] y
取得:1 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-configobj all 5.0.6-1 [35.3 kB]
取得:2 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-bzrlib armhf 2.6.0+bzr6595-6 [1,579 kB]
取得:3 http://mirrordirector.raspbian.org/raspbian/ jessie/main bzr all 2.6.0+bzr6595-6 [53.9 kB]                                                                                                                                                                               
取得:4 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-crypto armhf 2.6.1-5 [248 kB]                                                                                                                                                                            
取得:5 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-gpgme armhf 0.3-1 [20.4 kB]                                                                                                                                                                              
取得:6 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-httplib2 all 0.9+dfsg-2 [39.0 kB]                                                                                                                                                                        
取得:7 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-keyring all 4.0-1 [56.9 kB]                                                                                                                                                                              
取得:8 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-lazr.uri all 1.0.3-2 [13.7 kB]                                                                                                                                                                           
取得:9 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-simplejson armhf 3.6.5-1 [65.0 kB]                                                                                                                                                                       
取得:10 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-wadllib all 1.3.2-2 [34.3 kB]                                                                                                                                                                           
取得:11 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-zope.interface armhf 4.1.1-3.1 [84.1 kB]                                                                                                                                                                
取得:12 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-oauth all 1.0.1-4 [12.8 kB]                                                                                                                                                                             
取得:13 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-lazr.restfulclient all 0.13.3-1 [59.6 kB]                                                                                                                                                               
取得:14 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-launchpadlib all 1.10.2+ds-2 [51.6 kB]                                                                                                                                                                  
取得:15 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-secretstorage all 2.1.1-1 [12.9 kB]                                                                                                                                                                     
2,366 kB を 40秒 で取得しました (58.8 kB/s)                                                                                                                                                                                                                                     
以前に未選択のパッケージ python-configobj を選択しています。
(データベースを読み込んでいます ... 現在 126040 個のファイルとディレクトリがインストールされています。)
.../python-configobj_5.0.6-1_all.deb を展開する準備をしています ...
python-configobj (5.0.6-1) を展開しています...
以前に未選択のパッケージ python-bzrlib を選択しています。
.../python-bzrlib_2.6.0+bzr6595-6_armhf.deb を展開する準備をしています ...
python-bzrlib (2.6.0+bzr6595-6) を展開しています...
以前に未選択のパッケージ bzr を選択しています。
.../bzr_2.6.0+bzr6595-6_all.deb を展開する準備をしています ...
bzr (2.6.0+bzr6595-6) を展開しています...
以前に未選択のパッケージ python-crypto を選択しています。
.../python-crypto_2.6.1-5_armhf.deb を展開する準備をしています ...
python-crypto (2.6.1-5) を展開しています...
以前に未選択のパッケージ python-gpgme を選択しています。
.../python-gpgme_0.3-1_armhf.deb を展開する準備をしています ...
python-gpgme (0.3-1) を展開しています...
以前に未選択のパッケージ python-httplib2 を選択しています。
.../python-httplib2_0.9+dfsg-2_all.deb を展開する準備をしています ...
python-httplib2 (0.9+dfsg-2) を展開しています...
以前に未選択のパッケージ python-keyring を選択しています。
.../python-keyring_4.0-1_all.deb を展開する準備をしています ...
python-keyring (4.0-1) を展開しています...
以前に未選択のパッケージ python-lazr.uri を選択しています。
.../python-lazr.uri_1.0.3-2_all.deb を展開する準備をしています ...
python-lazr.uri (1.0.3-2) を展開しています...
以前に未選択のパッケージ python-simplejson を選択しています。
.../python-simplejson_3.6.5-1_armhf.deb を展開する準備をしています ...
python-simplejson (3.6.5-1) を展開しています...
以前に未選択のパッケージ python-wadllib を選択しています。
.../python-wadllib_1.3.2-2_all.deb を展開する準備をしています ...
python-wadllib (1.3.2-2) を展開しています...
以前に未選択のパッケージ python-zope.interface を選択しています。
.../python-zope.interface_4.1.1-3.1_armhf.deb を展開する準備をしています ...
python-zope.interface (4.1.1-3.1) を展開しています...
以前に未選択のパッケージ python-oauth を選択しています。
.../python-oauth_1.0.1-4_all.deb を展開する準備をしています ...
python-oauth (1.0.1-4) を展開しています...
以前に未選択のパッケージ python-lazr.restfulclient を選択しています。
.../python-lazr.restfulclient_0.13.3-1_all.deb を展開する準備をしています ...
python-lazr.restfulclient (0.13.3-1) を展開しています...
以前に未選択のパッケージ python-launchpadlib を選択しています。
.../python-launchpadlib_1.10.2+ds-2_all.deb を展開する準備をしています ...
python-launchpadlib (1.10.2+ds-2) を展開しています...
以前に未選択のパッケージ python-secretstorage を選択しています。
.../python-secretstorage_2.1.1-1_all.deb を展開する準備をしています ...
python-secretstorage (2.1.1-1) を展開しています...
man-db (2.7.0.2-5) のトリガを処理しています ...
python-configobj (5.0.6-1) を設定しています ...
python-bzrlib (2.6.0+bzr6595-6) を設定しています ...
bzr (2.6.0+bzr6595-6) を設定しています ...
python-crypto (2.6.1-5) を設定しています ...
python-gpgme (0.3-1) を設定しています ...
python-httplib2 (0.9+dfsg-2) を設定しています ...
python-keyring (4.0-1) を設定しています ...
python-lazr.uri (1.0.3-2) を設定しています ...
python-simplejson (3.6.5-1) を設定しています ...
python-wadllib (1.3.2-2) を設定しています ...
python-zope.interface (4.1.1-3.1) を設定しています ...
python-oauth (1.0.1-4) を設定しています ...
python-lazr.restfulclient (0.13.3-1) を設定しています ...
python-launchpadlib (1.10.2+ds-2) を設定しています ...
python-secretstorage (2.1.1-1) を設定しています ...

 

次にnfcpyのスクリプトをリポジトリからダウンロードします。

$ sudo bzr branch lp:nfcpy
You have not informed bzr of your Launchpad ID, and you must do this to
write to Launchpad or access private data.  See "bzr help launchpad-login".
273個のリビジョンをブランチしました。

$ ls -l
合計 4
drwxr-sr-x 8 root staff 4096  3月  7 12:51 nfcpy

 

次にPython用のUBS接続ライブラリをインストールします。

$ sudo apt-get install python-usb
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下のパッケージが新たにインストールされます:
  python-usb
アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 0 個。
17.7 kB のアーカイブを取得する必要があります。
この操作後に追加で 132 kB のディスク容量が消費されます。
取得:1 http://mirrordirector.raspbian.org/raspbian/ jessie/main python-usb armhf 0.4.3-1 [17.7 kB]
17.7 kB を 34秒 で取得しました (513 B/s)
以前に未選択のパッケージ python-usb を選択しています。
(データベースを読み込んでいます ... 現在 127249 個のファイルとディレクトリがインストールされています。)
.../python-usb_0.4.3-1_armhf.deb を展開する準備をしています ...
python-usb (0.4.3-1) を展開しています...
python-usb (0.4.3-1) を設定しています ...

以上で必要なもののインストールは完了です。

 

nfcpyの中にexamplesというサンプルコードがあるのでこれを実行してみます。PaSoRiにSuicaを乗せた状態で実行して下さい。

$ cd nfcpy/
$ sudo python examples/tagtool.py show
Traceback (most recent call last):
  File "examples/tagtool.py", line 37, in <module>
    from cli import CommandLineInterface
  File "/usr/local/src/nfcpy/examples/cli.py", line 27, in <module>
    import nfc
  File "/usr/local/src/nfcpy/nfc/__init__.py", line 28, in <module>
    from clf import ContactlessFrontend
  File "/usr/local/src/nfcpy/nfc/clf/__init__.py", line 35, in <module>
    from . import device
  File "/usr/local/src/nfcpy/nfc/clf/device.py", line 39, in <module>
    from . import transport
  File "/usr/local/src/nfcpy/nfc/clf/transport.py", line 34, in <module>
    raise ImportError("missing usb1 module, try 'pip install libusb1'")
ImportError: missing usb1 module, try 'pip install libusb1'

なんかエラーになりました。libusb1をインストールしろと言われているのでとりあえずインストールしました。

$ sudo pip install libusb1
Downloading/unpacking libusb1
  Downloading libusb1-1.4.1.tar.gz (43kB): 43kB downloaded
  Running setup.py (path:/tmp/pip-build-_bzOpK/libusb1/setup.py) egg_info for package libusb1
    
Installing collected packages: libusb1
  Running setup.py install for libusb1
    
Successfully installed libusb1
Cleaning up...

で、もう一回サンプルコードを実行してみます。

$ sudo python examples/tagtool.py show
[nfc.clf] searching for reader on path usb
[nfc.clf] using SONY RC-S380/P NFC Port-100 v1.11 at usb:001:004
** waiting for a tag **
Type3Tag 'FeliCa Standard (RC-S???)' ID=01140114BC13B824 PMM=100B4B428485D0FF SYS=0003

出ました!ID=xxxxというのがSuicaのIDmという識別子です。PMMが製造番号だったかな?Type3TagというのがFeliCaのことです。SYS=0003はNFCのシステムコードでSuicaは0003を使用しています。

他にはSAPICAという札幌のカードでは865Eを使用していたりします。

 

ということで、今回はSuicaのIDmを読み取ることが出来たので、次回は履歴を読み取ってみようと思います!

続き:Raspberry Pi 入門 4日目 – Suicaの履歴を読み取る