PaSoRiを使ってみました


久しぶりのBlog更新です。
こんにちは。masuyamaです。

最近、勤怠管理システムを調査する機会があったのですが、製品を見るとカードでの打刻でFeliCaを使用する際にはどれもPaSoRiの購入が必要なことに気がつきました。
既製品を利用しているなら自分でも作れるのではと思い、早速買ってみました。

PaSoRiって?

PaSoRiとは、FeliCaのデータを読み書きするための非接触型カードリーダーです。
詳しくはこちらを参照してください。

購入したのはWindows用のUSB接続タイプでこちらの製品になります。
他にもBluetooth接続でiOS製品でつかえるものもあるようです。

IMG_20150716_135423

開発環境

FeliCaは開発用SDKが公開されています
製品を作る場合には有償となりますが、開発・評価用には無料版が提供されているので、こちらを使用します。

実装

それでは、VisualStudioを起動して早速アクセスするプログラムを書いてみたいと思います。

なんといってもまずは初期化です。こちらはサンプルに従い記述します。

	if (!initialize_library()) {
		MessageBoxA(NULL, (LPCSTR)"Can't initialize library.", (LPCSTR)"FeliCaReader", MB_OK);
		return -1;
	}

	if (!open_reader_writer_auto()) {
		MessageBoxA(NULL, (LPCSTR)"Can't open reader writer.", (LPCSTR)"FeliCaReader", MB_OK);
		return -1;
	}

次にPollingです。
FeliCaSDKでは、カードの情報がイベント等で通知されてくるのではなく、Pollingして情報を取りに行きます。
ダイアログアプリで作成していますので、Timerを設定して一定間隔でPollingするようにします

INT_PTR CALLBACK  DialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg){
	case WM_INITDIALOG:
		SetTimer(hWnd, 1, 1000, NULL);
		break;

	case WM_TIMER:
		Polling(hWnd);
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDOK:
			PostQuitMessage(0);
			break;
		case IDCANCEL:
			PostQuitMessage(0);
			break;
		}
		break;

	default:
		return DefWindowProc(hWnd, msg, wParam, lParam);
	}

	return 0L;
}

Polling部分

void Polling(HWND hWnd)
{
	structure_polling polling;
	unsigned char system_code[2] = { 0xff, 0xff };
	polling.system_code = system_code;
	polling.time_slot = 0x00;

	unsigned char number_of_cards = 0;

	structure_card_information card_information;
	unsigned char card_idm[8];
	unsigned char card_pmm[8];
	card_information.card_idm = card_idm;
	card_information.card_pmm = card_pmm;

	HWND edit;
	if (!polling_and_get_card_information(&polling, &number_of_cards, &card_information)) {
		edit = (HWND)GetDlgItem(hWnd, IDC_EDIT_IDM);
		SetWindowTextA(edit, "");
		edit = (HWND)GetDlgItem(hWnd, IDC_EDIT_PMM);
		SetWindowTextA(edit, "");
		return;
	}

	char buffer[sizeof(card_idm) * 4];
	sprint_vector(buffer, sizeof(buffer), card_idm, sizeof(card_idm));
	edit = (HWND)GetDlgItem(hWnd, IDC_EDIT_IDM);
	SetWindowTextA(edit, buffer);

	sprint_vector(buffer, sizeof(buffer), card_pmm, sizeof(card_pmm));
	edit = (HWND)GetDlgItem(hWnd, IDC_EDIT_PMM);
	SetWindowTextA(edit, buffer);
}

カード情報を取得して、IDm, PMmを表示しています。

	structure_polling polling;
	unsigned char system_code[2] = { 0xff, 0xff };
	polling.system_code = system_code;
	polling.time_slot = 0x00;

この部分で初期値を指定します。
system_code は事業者や目的毎に割り振られるコードです。
0xFFFF がワイルドカード(どのカードでも読み込む)扱いなので、それを指定します。

	if (!polling_and_get_card_information(&polling, &number_of_cards, &card_information)) {

これが実際にカードから情報を取得している部分です。
戻り値がfalseならばカードはないので表示を消しています。

IDm、PMmについてはこちらの資料で詳しく説明されています。
このIDmがカード固有の番号なので、これをユーザ情報とマッピングすれば個人の特定が可能となります。

動かしてみる

秘蔵のKitacaでためしてみました。

IMG_20150716_185636-2IMG_20150716_185641-2

この読み込みと各種サービスのAPIを組み合わせることでいろいろな仕組みが作れそうです。
Windows限定ですが。。。