RaspberryPiで交通系ICカードを読み取る(RC-S380の接続)

RaspberryPiで交通系ICカードを読み取る(RC-S380の接続)

以前、交通系ICカードの読み取りをWindows8.1&Androidにて行うというセッションをまどべんよっかいちさんでさせていただきましたが、 RaspberryPiでもできないかと思いやってみました。WindowsではC#を用いてAPIを呼び出しカード内のIDmの読み込みを行っていましたが、 RaspberryPiではpythonを使うことにします。pythonはなんとなく読める程度の知識しかないのでかなり不安はありますが何とかなるかなという軽い気持ちで。

f:id:ueponx:20160423194225j:plain

【参考】まどべんよっかいち資料(タイトルを気にしてはいけない)

www.slideshare.net

接続に使ったリーダー

使用したリーダは↓です。2000~3000円ぐらいで購入できると思いますが、中古市場で買えばもっと安く手に入ると思います。

RC-S380接続から認識まで

実は接続するとあっさり認識します。

接続前のlsusbの内容

~ $ lsusb
Bus 001 Device 006: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Bus 001 Device 005: ID 2019:1201 PLANEX
Bus 001 Device 004: ID 05e3:0608 Genesys Logic, Inc. USB-2.0 4-Port HUB
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. LAN9500 Ethernet 10/100 Adapter / SMSC9512/9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

接続後のlsusbの内容

~ $ lsusb
Bus 001 Device 007: ID 054c:06c3 Sony Corp.
Bus 001 Device 006: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Bus 001 Device 005: ID 2019:1201 PLANEX
Bus 001 Device 004: ID 05e3:0608 Genesys Logic, Inc. USB-2.0 4-Port HUB
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. LAN9500 Ethernet 10/100 Adapter / SMSC9512/9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Bus 001 Device 007: ID 054c:06c3 Sony Corp.が追加されているのがわかります。

ちなみにdmesgの結果は以下が追加されています。

(中略)
[  100.229467] usb 1-1.3: new full-speed USB device number 7 using dwc_otg
[  100.334131] usb 1-1.3: New USB device found, idVendor=054c, idProduct=06c3
[  100.334171] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=4
[  100.334191] usb 1-1.3: Product: RC-S380/P
[  100.334208] usb 1-1.3: Manufacturer: SONY
[  100.334223] usb 1-1.3: SerialNumber: ????????

(注)SerialNumberは伏せてあります。

デバイスの認識としてはこれで完了です。おめでとうございます。

設定の追加

このままでも使用することはできるのですが、一般ユーザはsudo経由でしか使用することができません。そこで、一般ユーザからでも使用可能なように以下のファイルを作成します。

~ $ sudo vim /etc/udev/rules.d/nfcdev.rules

ファイルの内容は以下になります。違うデバイスを使用するときにはidVendorとidProductの値を変更してください。

SUBSYSTEM=="usb", ACTION=="add", ATTRS{idVendor}=="054c", ATTRS{idProduct}=="06c3", GROUP="plugdev"

ファイルの編集が終了すると、ディレクトリは以下のようになります。

~ $ ls /etc/udev/rules.d/* -l
-rw-r--r-- 1 root root 114  318 17:45 /etc/udev/rules.d/40-scratch.rules
-rw-r--r-- 1 root root 506  114 03:44 /etc/udev/rules.d/99-com.rules
-rw-r--r-- 1 root root 117  422 20:58 /etc/udev/rules.d/nfcdev.rules

python側の設定

pythonのものはRaspbianにすでにインストールされているので、実行時に読み込むモジュール類のインストールを行うことになります。NFC関連のモジュールはnfcpyを使用します。

【参考】http://nfcpy.readthedocs.org/en/latest/topics/get-started.html

ネットをみるとbzrで設定することが多いようなのですが、あまり詳しくないので行き当たりばったりで設定をチャレンジして見ました。事前にpython-usbをインストールし、サイトからnfcpyモジュールのソースをwgetして展開をします。

~ $ sudo apt-get install python-usb
(途中経過は略)
~ $ wget https://launchpad.net/nfcpy/0.11/0.11.0/+download/nfcpy-0.11.0.tar.gz
(途中経過は略)
~ $ tar xvzf nfcpy-0.11.0.tar.gz
(途中経過は略)

展開したディレクトリに移動し、その中のexampleディレクトリにあるtagtool.pyを実行します。

~/nfcpy-0.11.0 $ ls
HISTORY.rst  LICENSE  README.rst  docs  examples  nfc  setup.py  tests  tools
~/nfcpy-0.11.0 $ cd examples/
~/nfcpy-0.11.0/examples $ ls
__init__.py              llcp-dta-iut.py      phdc-test-manager.py
beam.py                  llcp-dta-test.py     rfstate.py
cli.py                   llcp-test-client.py  sense.py
handover-test-client.py  llcp-test-server.py  snep-test-client.py
handover-test-server.py  ndeftool.py          snep-test-server.py
listen.py                phdc-test-agent.py   tagtool.py
~/nfcpy-0.11.0/examples $ sudo python tagtool.py

これでうまくいくのかなと思ったのですが…以下のような表示がでます。

~/nfcpy-0.11.0/examples $ sudo python tagtool.py
Traceback (most recent call last):
  File "tagtool.py", line 37, in <module>
    from cli import CommandLineInterface
  File "/home/pi/nfcpy-0.11.0/examples/cli.py", line 35, in <module>
    import nfc
  File "/home/pi/nfcpy-0.11.0/nfc/__init__.py", line 28, in <module>
    from clf import ContactlessFrontend
  File "/home/pi/nfcpy-0.11.0/nfc/clf/__init__.py", line 35, in <module>
    from . import device
  File "/home/pi/nfcpy-0.11.0/nfc/clf/device.py", line 39, in <module>
    from . import transport
  File "/home/pi/nfcpy-0.11.0/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'

最後の一文をみると「usb1というモジュールをpipをつかってインストールしてね」ってことらしいです。インストールしてみます。(pytonに詳しくないのでかなり手さぐりです)

~/nfcpy-0.11.0/examples $ sudo pip install libusb1
Downloading/unpacking libusb1
  Downloading libusb1-1.5.0.tar.gz (45kB): 45kB downloaded
  Running setup.py (path:/tmp/pip-build-HsYzk_/libusb1/setup.py) egg_info for package libusb1

Installing collected packages: libusb1
  Running setup.py install for libusb1

Successfully installed libusb1
Cleaning up...
~/nfcpy-0.11.0/examples $

無事にインストールできたみたいです。では気を取り直して実行してみます。

~/nfcpy-0.11.0/examples $ sudo python tagtool.py
[nfc.clf] searching for reader on path usb
[nfc.clf] using SONY RC-S380/P NFC Port-100 v1.11 at usb:001:007
** waiting for a tag **
Type3Tag 'FeliCa Standard (RC-SA00/1)' ID=??????????????? PMM=???????????????? SYS=????
~/nfcpy-0.11.0/examples $

実行すると読み込み待ち状態になるのでFelicaカードを読み込んでみるとIDなどが表示されます。 無事に動作したようです。(値が?になっていますが伏せているだけで実際には値が表示されます)

もう、動作したのですが折角なのでpythonプログラムから動作するところまでやってみます。このあたりは公式サイトに使い方が乗っているのですが、自分のやり方ではbzrを使ってなかったのではまってしまいましたので、念のための記述になります。

コマンドラインインタプリタを起動します。

~/nfcpy-0.11.0/examples $ python
Python 2.7.9 (default, Mar  8 2015, 00:52:26)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.

通常であれば、import nfcだけでよいのですが、自分のやった方法ではnfcモジュールが読み込めないエラーが発生します。そこで、先ほどのtagtool.pyをのぞいてみたところ、importをする前にパスにnfcpyのモジュールパスをインストールしていることがわかりました。sys.path.insert処理がそれにあたります。

そこでimport nfcを行う前に

>>> import sys
>>> sys.path.insert(1, '/home/pi/nfcpy-0.11.0')

を行うことにします。'/home/pi/nfcpy-0.11.0'の部分を自分の作業したPathに変更してください。

【実行例】

>>> import sys
>>> sys.path.insert(1, '/home/pi/nfcpy-0.11.0')
>>> import nfc
>>> clf = nfc.ContactlessFrontend('usb')
>>> print(clf)
SONY RC-S380/P on usb:001:005
>>> def connected(tag): print(tag); return False
...
>>> clf.connect(rdwr={'on-connect': connected})
Type3Tag 'FeliCa Standard (RC-S???)' ID=???????????????? PMM=???????????????? SYS=????
<nfc.tag.tt3_sony.FelicaStandard object at 0x????????>
>>> clf.close()

これで読み込みができました。

公式サイトの設定例と違うことをしたのではまってしまいましたが、そのままやればもう少し楽ができたのかもしれません。今後はpythonにも触れていこうと思います。

【参考】

http://nfcpy.readthedocs.org/en/latest/index.html

/* -----codeの行番号----- */