Edited at

PaSoRiを使ってpythonでNFCタグを読み書きする

More than 1 year has passed since last update.


概要

USB接続のNFC/FelicaリーダーライタであるSONYのPaSoRi(RC-S380)を使って、Mac上のpythonから、安価なNFCタグ(NTAG)を読み書きする方法をまとめます。

基本は nfcpy で一発です。

試していませんが、Raspberry Piでも同じ方法で使える模様。

(追記)Raspbian でも、インストール手順としては、sudo apt-get install python-pip; sudo pip install nfcpy だけで OK でした。

ただし、一般権限で usb にアクセスするためには、Raspberry Pi に nfcpy をインストールする手順 - 2016年3月 私家版の後半に書かれた手順が必要です。


環境セットアップ手順


前提

brew の python 2.7 を用いています。システム側の python でもできるはずですが、openssl のバージョンがどうなっているのか微妙なところですので、うまく動かなかったら試行錯誤してください。


nfcpy

bzr で nfcpy を持ってくる手順が紹介されていることが多いですが、pip で一発です。

> brew install libusb

> pip install nfcpy


openssl 関連でハマったら

python の REPL で import nfc と打って問題なくロードできれば良いですが、openssl に含まれる libcrypto のロードに失敗するケースがあります。

>>> import nfc

(中略)
AttributeError: dlsym(0x7fbc82c404a0, EC_KEY_set_public_key_affine_coordinates): symbol not found

対策として、brew で新しい openssl をインストールして link すれば OK と書いてある記事が多いのですが、

> brew link openssl --force

Warning: Refusing to link: openssl

と言われて link できません。

/usr/local/opt/openssl/lib 以下に最新の libcrypto.1.0.0.dylib がインストールされていますので、ここをダイナミックリンクライブラリのロードパスに指定すればとりあえず動きます。正しい対処方法はどうすればいいのか……。

export DYLD_LIBRARY_PATH=/usr/local/opt/openssl/lib:$DYLD_LIBRARY_PATH


NFC タグの読み書き


nfcpy の公式サンプル

公式のget-startedを読むか、examples にあるサンプルを見れば、だいたい使い方はわかります。サンプル単体でコマンドとしても使えます(使い方

例えば、以下のコマンドで NFC タグの情報を表示できます。

> python tagtool.py show

YouTube 動画を開くデータを NTAG に書き込むには以下の通り。

> python ndeftool.py make smartposter -t PPAP https://youtu.be/0E00Zuayv9Q | python tagtool.py load -


自力で書く

nfcpy を使って自力で必要な処理を書く場合は以下のようなコードとなります。

import nfc

import nfc.ndef

def startup(targets):
print "waiting for new NFC tags..."
return targets

def connected(tag):
if not tag.ndef or not tag.ndef.is_writeable:
print("not a writeable nfc tag")
return False
print("old message:")
print(tag.ndef.message.pretty())

smartposter = nfc.ndef.SmartPosterRecord("https://youtu.be/0E00Zuayv9Q")
smartposter.title = "PPAP"
new_message = nfc.ndef.Message(smartposter)

if len(str(new_message)) > tag.ndef.capacity:
print "too long message"
return True

if tag.ndef.message == new_message:
print "already same record"
return True

tag.ndef.message = new_message
print("new message:")
print(tag.ndef.message.pretty())

return True

def released(tag):
print("released:")
if tag.ndef:
print(tag.ndef.message.pretty())

clf = nfc.ContactlessFrontend('usb')
print(clf)
if clf:
while clf.connect(rdwr={
'on-startup': startup,
'on-connect': connected,
'on-release': released,
}):
pass

Ctrl-C で止めるまで、ひたすら NFC タグを YouTube 動画を開くものに書き換えます。


参考URL

nfcpy で複数の System Code を持つ NFC タグを扱う方法

Raspberry Pi に nfcpy をインストールする手順 - 2016年3月 私家版