以前のエントリで、大須にある佐古前装備さん
で購入したカードリーダーFelica RC-S330
をRaspberryPi
から使用してみたという内容を書いていました。
結論から言えば、RaspberryPi
からはnfcpy
の使用はできず、libpafe
をインストールすれば、使用できるというような結果でした。
その後、python
のユーザープログラムからIDm
を取得してみたところ、IDm
の値の並び(エンディアン)が異なっていました。そこでlibpafe
を使用した場合でもnfcpy
のtagtool.py
と同じIDm
の値を取得する方法を調べてみました。
参考
状況の確認
まずは状況の確認になります。libpafe
のインストールを行ったときに同時にインストールされるfelica_dump
というコマンドを実行してみると、交通系のFelica
から多くの情報を取得することができます。すると以下の様な表示が行われます。
そして、nfcpy
をインストールしてtagtool.py
コマンドからIDm
を取得すると以下の様な表示が行われます。(注)RaspberryPi
から使用できないので、Ubuntu
からの実行結果を表示しています。
このときのIDm
の値は同じようです。
ですが、以下のような自作のプログラムを作成し、IDm
を取得してみると…
IDm.py
# -*- coding: utf-8 -*- from __future__ import print_function from ctypes import * FELICA_POLLING_ANY = 0xffff if __name__ == '__main__': libpafe = cdll.LoadLibrary("/usr/local/lib/libpafe.so") libpafe.pasori_open.restype = c_void_p pasori = libpafe.pasori_open() libpafe.pasori_init(pasori) libpafe.felica_polling.restype = c_void_p felica = libpafe.felica_polling(pasori, FELICA_POLLING_ANY, 0, 0) idm = c_ulonglong() #←16桁受けとる libpafe.felica_get_idm.restype = c_void_p libpafe.felica_get_idm(felica, byref(idm)) # IDm16進表記 print("%016X" % idm.value) #←16桁の16進数文字列の表示 # READMEより、felica_polling()使用後はfree()を使う必要あり libpafe.free(felica) libpafe.pasori_close(pasori)
実行結果は以下のようになってしまします。
tagtool.py
などから取得されるIDm
(自分の実験カード)では
0112から始まり8F06で終わる16桁の値になっているのですが、
自作プログラムで取得した値は
068Fから始まり1201で終わる16桁になっています。
つまり、エンディアン表記が異なっている状況になっています。メモリやバイナリファイルなどでは比較的エンディアンの違いに気をつけるようにはしていましたが、NFC
も同じようにエンディアン気をつける必要があるとは思っていませんでした。
そこで以下の情報を参考にソースを変更することにしました。
参考 16進文字列のリトルエンディアン化変換
具体的な内容としては
- 16進数文字列を2桁のバイト配列として変換
- 変換後の配列の順序を反転
- 再度文字列化する
配列化まで行えれば反転はpython
では容易な処理ですね。
IDm_le.py
# -*- coding: utf-8 -*- from __future__ import print_function from ctypes import * FELICA_POLLING_ANY = 0xffff if __name__ == '__main__': libpafe = cdll.LoadLibrary("/usr/local/lib/libpafe.so") libpafe.pasori_open.restype = c_void_p pasori = libpafe.pasori_open() libpafe.pasori_init(pasori) libpafe.felica_polling.restype = c_void_p felica = libpafe.felica_polling(pasori, FELICA_POLLING_ANY, 0, 0) idm = c_ulonglong() #←16桁を受けとる libpafe.felica_get_idm.restype = c_void_p libpafe.felica_get_idm(felica, byref(idm)) # IDmは16進表記(リトルエンディアン化処理も行う) # print("%016X" % idm.value) #←16桁の16進数文字列化 hex_be = "%016X" % idm.value bytes_be = bytes.fromhex(hex_be) bytes_le = bytes_be[::-1] idm_le = bytes_le.hex() print(idm_le) # READMEより、felica_polling()使用後はfree()を使う必要あり libpafe.free(felica) libpafe.pasori_close(pasori)
このプログラムを実行すると以下のようになります。
これでtagtool.py
と同じ実行結果になりました。
おわりに
久々にエンディアンを気をつける必要のあるコードを書いたような気がします。
個人的にはそこはビックエンディアンにしておいてよという気持ちでいっぱいですが致し方ないですね。
これでpython
からも容易にIDm
が取得できるようになったので、いろいろな自作の工作にも応用できそうです。