search
LoginSignup
28

More than 5 years have passed since last update.

posted at

nfcpy で Apple Pay のエクスプレスカードを扱う

nfcpy を利用して Apple Pay の エクスプレスカード設定された Suica (以後エクスプレスカード)を扱おうとしたところ思いっきり躓いたので、ポイントを記事にしておきます。
導入方法や実際のデータの読み書きについてはわかりやすいまとめがあると思いますのでここでは記載しません。(参考リンクなどを参照してください)

環境

  • Raspberry Pi 3 Model B (Rasbian jessie 8.0)
  • Python 2.7.9
  • nfcpy 0.11.0
  • PaSoRi RC-S380

connect を使用した際の挙動

nfcpy を使用してデータの読み書きを行う際には nfc.ContactlessFrontend の connect メソッドを使用すると簡単に実装出来るようになっているのですが、これはエクスプレスカードでは正常に動作しません。

たとえば以下のようなコードの場合。

nfc_connect.py
import nfc


def on_startup(targets):
  for target in targets:
    # 0003(Suica)
    target.sensf_req = bytearray.fromhex("0000030000")
  return targets


def on_connect(tag):
  print tag


def main():
  clf = nfc.ContactlessFrontend('usb')
  # 212F(FeliCa)
  clf.connect(rdwr={'targets': ['212F'], 'on-startup': on_startup, 'on-connect': on_connect})
  clf.close()


if __name__ == '__main__':
  main()

スリープ状態の iPhone をリーダーにかざすと、iPhone 側の画面では Suica と読み取り完了のチェックマークが表示されますが、プログラム側ではほぼ常に何も起きません。(ごくたまに on_connect が呼び出されることがあります)
connect で on-discover (対象が見つかった時に呼び出される)を指定しても同様となります。
この事象はエクスプレスカードの場合でのみ発生するようで、Wallet アプリを起動してカード指定してかざした場合には発生しません。

sense を使用する

nfcpy では connect 以外にも検出に使用するメソッドが提供されています。
これらを使用することでエクスプレスカードでも正常に検出ができます。

nfc_sense.py
import binascii
import nfc


def main():
  clf = nfc.ContactlessFrontend('usb')
  # 212F(FeliCa)
  target_req = nfc.clf.RemoteTarget("212F")
  # 0003(Suica)
  target_req.sensf_req = bytearray.fromhex("0000030000")
  while True:
    target_res = clf.sense(target_req, iterations=10, interval=0.01)
    if target_res != None:
      print binascii.hexlify(target_res.sensf_res)
      tag = nfc.tag.tt3.Type3Tag(clf, target_res)
      tag.sys = 3
      print tag
      break
  clf.close()


if __name__ == '__main__':
    main()

sense は指定された対象を interval 間隔で iterations 回検索し、結果を返します。
見つかった場合は対象の RemoteTarget、見つからなかった場合は None を返しますので、None であれば再度検索をします。
RemoteTarget オブジェクトの sensf_res には見つかった対象の IDM/PMM/SYS がまとめて格納されていますので、これらのみが必要な場合はこれ以降は必要ありません。

ここからデータの読み書きをできるようにするには Tag オブジェクトが必要です。
この Tag オブジェクトは nfc.tag.tt3.Type3Tag(clf, target) として定義されているので clf と RemoteTarget から生成してあげればよい事になります。
ただしここで生成した Tag には SYS の情報が入っていないので、改めて Suica の 0x0003 を代入してあげます。

これで connect を使用した場合に on-connect の引数として渡される Tag と同等の処理が可能になります。

参考リンク

・nfcpy で複数の System Code を持つ NFC タグを扱う方法
http://uchan.hateblo.jp/entry/2016/11/18/190237
・FeliCaのPollingによるApplePayのWalletの動作
http://qiita.com/bellx2/items/fb081c4bdd822c8d36fd

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
28