【C++】PaSoRi RC-S380と標準ライブラリでICカードを読み込みたい
こんにちは。mugiHaLです。
唐突に出退勤アプリが作りたくなったので、VisualStudioで遊んでいます。
調べた内容の覚え書きです。
はじめに
IDE:Microsoft Visual Studio Community 2019
言語:C++
使用デバイス:SONY PaSoRi RC-S380/P
まず、言語の選定理由は、PC/SCライブラリを使用するためです。
SONYの開発ライブラリが10万円くらいするらしくって(無償のLite版もありますが)、無料で出来るならそれで良いじゃんと。
最終的には、Windowsデスクトップアプリケーションを作成したいので、C#を使用したいのですが、ライブラリが標準で用意されているC++にしました。デスクトップアプリはMFCで作ろうか・・・。
C#だとDLLのインポートが必要なので諦めました。調べればC#の実装も出てきますがそんなやる気ありません。
それから、ICカードリーダーの選定ですが、ISO14443準拠なら何でもよくて、非接触だけで良いので、近所のビックカメラに売っていたのは以下の2つ。
・RC-S380
・ACR1251CL
無難にPaSoRiにしておきました。
余談ですが、ICカードリーダーって開発用途しか無いと思っていましたが、市販のICカードリーダーにはSuicaの残高確認ソフトとか、確定申告にも使えるみたいで需要があるみたいですね。知らない世界でした。
実装について
最終的な仕様・設計は以下のようにしたいです。
使用機器:
・ICカードリーダー(RC-S380)
・ICカード(Amazonで10枚2000円くらいで売ってた)
・Windows10 PC(Windows7でも動くと思う。XPとかもう考えなくていいでしょ。)
ファイル:
・実行ファイル(.exe)
・利用者リスト(.dat)・・・カードIDと社員情報を紐付けする
・出退勤情報(.csv)・・・出退勤の情報を書き出す
考慮する点:
・紛失した場合・・・新規カードを使用する。ユーザと紐づいたIDの書き換え。
・打刻忘れ・・・その日最初のタッチで出勤、2回目で退勤など。メニューから出勤のみ退勤のみ設定。
・管理者権限・・・好きな時間に。悪用してはいけない。
・基準となる時間・・・インターネットにつなげてTCPで取得したいけど、個人情報アプリなのでスタンドアローンにしたい・・・。基準から相対時間で計算する?
アルゴリズム:
① ICカードリーダーと接続する。
② ICカードリーダーの状態を監視する。
②-1 ICカードを検知したらカードのIDを取得する。
③ ICカードリーダーと切断する。
ソースコード
インクルード
#include <winscard.h>
接続
LONG lResult; SCARDCONTEXT scardtext; // 接続 lResult = SCardEstablishContext( SCARD_SCOPE_USER, NULL, NULL, &scardtext );
カードリーダーの監視
LONG lResult; // カードリーダーを列挙する LPTSTR lpszReaderName; DWORD dwAutoAllocate = SCARD_AUTOALLOCATE; lResult = SCardListReaders( scardtext, SCARD_ALL_READERS, (LPTSTR)&lpszReaderName, &dwAutoAllocate); //カードリーダーの状態の取得する(カードが存在するか) SCARD_READERSTATE readerState; readerState.szReader = lpszReaderName; // リーダー名を設定する readerState.dwCurrentState = SCARD_STATE_UNAWARE; // 初期状態を設定する // リーダーの状態を知る lResult = SCardGetStatusChange(scardtext, 0, &readerState, 1); // カードセットしていない場合 if (readerState.dwEventState & SCARD_STATE_EMPTY){ while (1) { readerState.dwCurrentState = readerState.dwEventState; // カードセット待ち lResult = SCardGetStatusChange(scardtext, INFINITE, &readerState, 1); if (readerState.dwEventState & SCARD_STATE_PRESENT) //カードセット else if (readerState.dwEventState & SCARD_STATE_UNAVAILABLE) //カードリーダ切断 } } //カードリーダー名領域を開放する lResult = SCardFreeMemory(scardtext, lpszReaderName);
切断
LONG lResult;
// 切断
lResult = SCardReleaseContext(scardtext);
最後に
仕事が終わっておうちに帰ってソースコードなんて見たくないですね。元気があるときにチャレンジします。
実家で使わせてみたいと思いましたが、うちは従業員いないから意味ないんですよね・・・。
どうでもよいことですが、初めて目次使ってみました。手動でリンクさせるのかと思いきや簡単でした。
それでは!