注意
この記事は nfcpy
が Python2
にしか対応していなかった頃に実装した記録です。
現在、 nfcpy
は Python3
に対応しています。
環境変数について
私は環境変数を使う形で書いたのですが、一般ユーザーで環境変数を設定した後
raspbian では sudo すると環境変数がリセットされてしまうので、
sudo 時に環境変数を引き継ぐようにするか sudo 無しで使えるようにする必要がありました。
sudo
無しでRC-S380を使える様にする
参考: Suicaでセサミを解錠 ( with ラズパイ)
参考: 交通系電子マネーカードを 黒PaSori RC-S380 + Raspberry Pi + python で
> lsusb
> sudo sh -c 'echo SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"054c\", ATTRS{idProduct}==\"06c3\", GROUP=\"plugdev\" >> /etc/udev/rules.d/nfcdev.rules'
> sudo udevadm control --reload-rules
> sudo reboot
ATTRS{idVendor}==\"XXXX\", ATTRS{idProduct}==\"YYYY\"
の部分は使っているカードリーダーによって固定の値です。
Sony の PaSori RC-S380 なら上記のコピペで平気なはずです。
参考: USBのベンダーIDとプロダクトIDの話
違うリーダーの場合 lsusb
の値を参照しましょう。
sudo 時に環境変数を引き継ぐようにする場合
こちらの記事を参考にしました
参考: sudo時に環境変数PATHが引き継がれない時の対策
上記記事では PATH
に限定していますが、 PATH 以外の環境変数を引き継ぎたい場合も visudo
で同様にできます
root になってから visudo
を実施します
$ su -
# visudo
env_reset
と secure_path
をコメントアウト(先頭に #
を足)します
そして、次の一行を追加します
Defaults env_keep += "<引き継ぎたい環境変数>"
と env_keep
に加えることで引き継がせることが出来ます。
実装
これらの記事を参考にしました
参考: Suicaでセサミを解錠 ( with ラズパイ)
参考: PaSoRiでNFCタグとFeliCaを読み込んで出力
参考: Raspberry PiにNFCリーダを接続してSuicaを読み取る
環境変数から情報を取る
Python の話です。
Felica における IDm や NFC の UID 、APIのAuthTokenといった秘匿しておきたい情報についてはコード上に載せず、
環境変数から取ってくるようにしました。
os.environ.get()
コマンドで取得出来ます
API
必要なAPIコールはそれぞれ関数として定義しておきます
操作
def control_sesame(device_id, command):
url_control = "{0}/sesame/{1}".format(api_endpoint, device_id)
head_control = {"Authorization": auth_token,
"Content-Type": "application/json"}
payload_control = {"command": command}
response_control = requests.post(
url_control, headers=head_control, data=json.dumps(payload_control))
return response_control
結果確認
def check_sesame_task(task_id):
url_check = "{0}/action-result?task_id={1}".format(api_endpoint, task_id)
head_check = {"Authorization": auth_token}
response_check = requests.get(url_check, headers=head_check)
return response_check
解錠
def unlock_sesame(device_id, card_id):
response_control = control_sesame(device_id, "unlock")
if response_control == None and not hasattr(response_control, "_content"):
return False
# print vars(response_control)
response_control_content = json.loads(response_control._content)
task_id = response_control_content["task_id"]
print "task_id = {0}".format(task_id)
time.sleep(7.0)
response_check = check_sesame_task(task_id)
if response_check == None and not hasattr(response_check, "_content"):
return False
response_check_content = json.loads(response_check._content)
# print response_check_content
if response_check_content["status"] == "processing":
print "processing"
pass
if response_check_content["status"] == "terminated":
result = response_check_content["successful"]
print "[{0}] card_id: {1} device_id: {2} unlock: {3}".format(datetime.now().strftime("%Y/%m/%d %H:%M:%S"), card_id, device_id, "successful" if result else "failed")
return
メイン
if __name__ == "__main__":
# NFC接続リクエストのための準備
target_req_nfc = nfc.clf.RemoteTarget("106A")
# Suica接続リクエストのための準備
target_req_felica = nfc.clf.RemoteTarget("212F")
print "Waiting for NFC..."
while True:
# USBに接続されたNFCリーダに接続してインスタンス化
clf = nfc.ContactlessFrontend("usb")
# NFC待ち受け開始
# clf.sense( [リモートターゲット], [検索回数], [検索の間隔] )
target_res = clf.sense(target_req_nfc, target_req_felica, iterations=int(
TIME_cycle//TIME_interval) + 1, interval=TIME_interval)
if target_res != None:
print target_res
print vars(target_res)
if not hasattr(target_res, "_brty_send"):
continue
brty = target_res._brty_send
if brty == "106A":
tag = nfc.tag.activate_tt2(clf, target_res)
elif brty == "212F":
tag = nfc.tag.activate_tt3(clf, target_res)
else:
continue
print tag
if tag != None:
print vars(tag)
print tag.type
# Felica
if hasattr(tag, "type") and tag.type == "Type3Tag":
tag.sys = 3
idm = binascii.hexlify(tag.idm)
print "Felica detected. idm = {0}".format(idm)
if idm in key_idms:
unlock_sesame(device_id, idm)
# NFC
else:
if not hasattr(tag, "_nfcid"):
print "Error: tag doesn't have nfcid"
continue
uid = binascii.hexlify(tag._nfcid)
print "NFC detected. uid = {0}".format(uid)
if uid in key_uids:
unlock_sesame(device_id, uid)
# 共通
print "sleep {0} seconds".format(str(TIME_wait))
time.sleep(TIME_wait)
clf.close()
if brty == "106A":
tag = nfc.tag.activate_tt2(clf, target_res)
elif brty == "212F":
tag = nfc.tag.activate_tt3(clf, target_res)
の部分ですが、Windowsで行っていた際、 nfc.tag.activate(clf, target_res)
でどちらも対応できましたが、
raspbian だとそれぞれTypeを指定しないと動きませんでした。
コード全体は GitHub に置いてあります