nfcpyでお手軽NFC開発[1/2]

nfcpyでお手軽NFC開発[1/2]


こんにちは,プログラマの保坂です。

NFCに対応したAndroid端末が増え,NFCを活用したアプリや製品も徐々に増えてきました。近年では,Bluetooth製品とAndroid端末のペアリングにNFCを使ったりする例や,NFCタグにURLを書き込んで「スマートポスター」として使ったりする例があります。

ところで,SuicaやEdyなどの電子マネーは,SonyのFeliCaという規格を利用したサービスで,このFeliCaもNFCの仲間です。なので,非暗号化領域に限れば,NFCリーダーによるFeliCaカードの読み書きが可能です。ここでは,どこのご家庭にもある(?)NFCリーダー(RC-S370)を使って,Suicaの利用履歴を読み出すスクリプトをPythonで実装してみたいと思います。

今回の記事では,更新を2回に分けて,Suicaの利用履歴を読み出すスクリプトを実装するまでの流れを紹介します。前編となる今回の更新では,PythonからNFCリーダーを制御するライブラリの導入までを解説していきます。

NFCとは

環境導入に入る前に,NFCという技術について簡単に紹介します。

NFCは「Near Field Communication」の略称で,広義では10cm程度の距離で通信する近距離無線通信の技術全般を,狭義ではNXP社とSony社が中心となって策定した近距離無線通信の国際標準「ISO/IEC 18092」のことを指します。ここでは,狭義のNFCを中心に紹介します。

NFCの規格の中にはおおまかに分けてNFC-A,NFC-B,NFC-Fという3つの区分があります。NFC-Aは非接触ICカードの国際標準「ISO/IEC 14443」のType-Aを取り込んだもので,同様にNFC-BはISO/IEC 14443のType-Bを取り込んだものです。NFC-Fは「JIS X 6319-4」として日本国内で標準化されていた規格で,これまでFeliCaと呼ばれていたものです。

NFC-A規格のカードとしては「Taspo」,NFC-B規格のカードとしては運転免許証や住基ネットカード,NFC-F規格のカードとしては「Suica」や「PASMO」などがあります。海外ではNFC-AやNFC-Bが多く使われているようですが,日本国内ではNFC-F規格のカードやサービスが広く普及しています。

NFC対応機器でできることは大きく分けて3種類あります。

1つ目はリーダー・ライター機能です。この機能を使うと,NFCチップが埋め込まれているカード・タグをNFC対応機器にかざして,カード・タグに記録されているデータを読み込んだり,あるいは書き込んだりできます。

2つ目はP2P通信機能です。この機能を使うと,NFC対応機器同士でデータを無線でやりとりすることができます。一昔前のケータイにあった赤外線通信のようなもの,と言うと少し分かりやすいでしょうか。NFC対応のAndroid端末では,この機能を活用してURLなどのデータを互いに送受信することができます。

3つ目はカードエミュレーション機能です。この機能を使うと,NFCチップが埋め込まれたカードをNFC対応機器でエミュレートすることができます。簡単に言えば,端末がカードのふりをします。「おサイフケータイ」などのサービスは,端末のカードエミュレーション機能によって実現されています。

実際には,これら3つの機能をいつでも自由に使えるというわけではなく,データ保護・暗号化のための特殊なハードウェアが必要なケースや,あるいは制御用のAPIが公開されておらず,端末キャリアやプラットフォーム運営者とのライセンス契約が別途必要なケースもあります。

この記事では,nfcpyで提供されているリーダー・ライター機能を使って,最終的にはSuicaカードから利用履歴を読み出すところまでを解説したいと思います。

環境の導入

今回は,NFCリーダーの制御にnfcpyというPython用のライブラリを使用します。この節では,このnfcpyのサンプルコードを動かすまでの流れを順を追って紹介します。

実行環境としては,OS Xがインストールされていて,brew・python・pipなどのコマンドが導入されているマシンを前提としています。WindowsやLinux系のOSを使用する場合も,導入するライブラリの構成は特に変わりありませんので,インストールのコマンドなどを適宜読み替えていただければと思います。

nfcpyのダウンロード

まず最初に,nfcpyのスクリプト郡をリポジトリからダウンロードします。bzrコマンドは予めbrewなどでインストールしておいてください。ちなみに,bzrはバージョン管理システムBazzarのコマンドラインツールです。

$ bzr branch lp:nfcpy
Not checking SSL certificate for xmlrpc.launchpad.net
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".
Branched 173 revisions.

libusbのインストール

nfcpyを動かす前に,いくつかライブラリのインストールが必要です。まず,libusbというUSB通信用の汎用ライブラリを導入します。brew環境であれば,次のようにしてインストール可能です。

$ brew install libusb
$ brew install libusb-compat

pyusbのインストール

pythonからlibusbを使うためのモジュールをインストールします。

$ sudo pip install pyusb
Downloading/unpacking pyusb
Could not find a version that satisfies the requirement pyusb (from versions: 1.0.0a2, 1.0.0a2, 1.0.0a3, 1.0.0a3)
Cleaning up...
No distributions matching the version for pyusb
Storing complete log in /Users/hosaka/Library/Logs/pip.log

pyusbはプレビューバージョンなので,v1.4以降のpipではオプション無しでインストールできません。--preオプションを付けて再度やってみましょう。

$ sudo pip install --pre pyusb
Downloading/unpacking pyusb
Downloading pyusb-1.0.0a3.tar.gz (40kB): 40kB downloaded
Running setup.py egg_info for package pyusb

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

Successfully installed pyusb
Cleaning up...

インストールができました。

サンプルスクリプトの実行

Getting Startedを参考に,サンプルスクリプトを実行してみます。

$ cd nfcpy
$ python examples/tagtool.py show
[nfc.clf] searching for reader with path 'usb'
[nfc.clf] no reader found at 'usb'
[main] no contactless reader found

「contactless reader」というのは,非接触ICカードリーダーのことです。マシンにNFCリーダーが接続されていないと,このような表示になります。改めて,マシンにRC-S370を接続して試してみます。

$ python examples/tagtool.py show
[nfc.clf] searching for reader with path 'usb'
[nfc.clf] using Sony RC-S370/P at usb:250:007
[main] touch a tag

上記のような文字列が出力され,実行が止まります。ここでSuicaカードをリーダーにタッチしてみましょう。

Type3Tag IDm=01010310870f6c31 PMm=100b4b428485d0ff SYS=0003

Suicaカードに記録されているカードIDなどのデータを取得できました!

ここまでで,PythonからNFCリーダーを制御するまでの準備が整いました。後編では,実際にSuicaの利用履歴を読み出すスクリプトを実装していきます。

後編はこちらです。