(Felica/Mifare/NFC チャレンジシリーズ) その他の記事はこちら 「Felica/Mifare/NFC でいろいろ実験」
https://qiita.com/nanbuwks/items/1f416d6e45a87250ee0a
「RaspberryPiでPN532 NFC RFID module で Felica 学生カードを読む」
https://qiita.com/nanbuwks/items/3858283873e968316a2d
では、FCF Student カードに入っている学生証の学籍番号を読んでみました。
しかしながらちょっとスッキリしないです。
tag.dump() # why need?
を入れないと学籍番号をうまく読まなかったり、ライブラリで何のコマンドを PN532 に送信しているのかよくわからなかったりします。
さて、
「libnfc で pn53x-tamashell を使ってみる」
https://qiita.com/nanbuwks/items/d2c47f6b24ec07f48dee
において、PN532とローレベルのやり取りを行いました。これで PN532 や カードに渡すコマンドは把握できたので、直接 PN532 とやり取りするプログラムを作ってみました。
環境
- PN532 NFC RFID module
- 電解コンデンサ追加加工済
- cf., 「NFC モジュールの動作安定性を改善する」
- https://qiita.com/nanbuwks/items/a9217ba2e8f206b899b1
- Raspberry Pi Model B+ V1.2
- Raspberry Pi OS Lite armhf-2020-12-04
- Python 3.7.3
通信インターフェースは シリアル接続を使い、以下の記事のように設定しています。
「Raspberry Pi で nfcpy + PN532 NFC RFID module」
https://qiita.com/nanbuwks/items/e14d8fdd6f863d5b68fe
Pythonプログラム
import serial
import time
def makepredata(payload):
predata=bytearray([0x00,0x00,0xFF])
predata.append(len(payload))
predata.append(256-(len(payload)))
return(predata)
def makepostdata(payload):
sum=0
for i in range(len(payload)):
sum=sum+payload[i]
postdata=bytearray([256-(sum % 256)])
postdata.append(0x00)
return(postdata)
# ペイロードにプレデータ、ポストデータを追加しPN532へ送信する
def senddata(payload):
predata=makepredata(payload)
postdata=makepostdata(payload)
alldata=predata+payload+postdata
ser.write(alldata)
# PN532からの返事を受信する
def getreturn():
result=bytearray([])
while 1:
time.sleep(0.01)
result = result + ser.read_all()
if len(result)<4:
continue
if ( 0x00==result[0] and 0xFF==result[1] and result[2]==256-result[3] ):
if len(result)<result[2]+6:
continue
else:
result=result[1:]
continue
break
# print(result.hex())
if 0xd5==result[4] and 0x00==result[-1] :
# 返事のチェックサムを照合
sum=0
for i in result[4:-2]:
sum=sum+i
if (256-(sum%256))==result[-2]:
return(result)
else:
return(bytearray([]))
else:
return(bytearray([]))
ser = serial.Serial("/dev/ttyAMA0", 115200)
# FeliCa Poll
payload=bytearray([0xD4])+bytearray([0x4A,0x01,0x01,0x00,0xFE,0x00,0x01,0x00])
senddata(payload)
#print("send:",senddata.hex())
result=getreturn()
#print(result.hex())
# get Idm
Idm=result[10:18]
print("Idm:",Idm.hex())
# FeliCa read
payload=bytearray([0xD4])+bytearray([0x40,0x01,0x14,0x06])+Idm+bytearray([0x01,0x8B,0x1A,0x03,0x80,0x00,0x80,0x02,0x80,0x03])
senddata(payload)
#print("send:",senddata.hex())
result=getreturn()
#print(result.hex())
print()
print("block 8000:",result[21:36].hex())
print("block 8002:",result[37:52].hex())
print("block 8003:",result[53:68].hex())
print()
print("block 8000:",bytes(result[21:36]))
print("block 8002:",bytes(result[37:52]))
print("block 8003:",bytes(result[53:68]))
ser.close()
実行結果
Idm: 010106016702a515
block 8000: 313233343536373839303100003131
block 8002: 363031303039383736353433323130
block 8003: 303232303333313939393939393939
block 8000: b'12345678901\x00\x0011'
block 8002: b'601009876543210'
block 8003: b'022033199999999'
読めました
他の環境
今回は、Raspberry Pi とシリアル接続で行いました。
しかしながらPCやWindowsなどでも、ポート指定などの若干の変更で動くハズ。
また、SPI や I2C 対応も難しくないでしょう。