Python
Mac
NFC
nfcpy

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月 私家版