👋
I-O DataのNFCリーダライタ ぴタッチ(USB-NFC3)にMac上のUnityでNFCカードのUIDを読み取る
1. 概要
以下の記事の続き。接続するところまでできたので、カードの情報を読み取る。
2. 環境
- USB-NFC3(ぴタッチ) | ICカードリーダー | IODATA アイ・オー・データ機器
- MacBook Pro (16-inch, 2019) / macOS Big Sur
- Unity 2021.3.16.f1
3. 方法
3.1 タッチしたかどうかを判定する
以下を参考にした。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PCSC;
using PCSC.Monitoring;
public class SimpleRead : MonoBehaviour
{
string readerName;
ISCardMonitor monitor;
void Start()
{
var contextFactory = ContextFactory.Instance;
using (var context = contextFactory.Establish(SCardScope.System)) {
Debug.Log("Currently connected readers: ");
var readerNames = context.GetReaders();
foreach (var readerName in readerNames) {
Debug.Log("\t" + readerName);
}
readerName = readerNames[0];
}
var monitorFactory = MonitorFactory.Instance;
monitor = monitorFactory.Create(SCardScope.System);
// connect events here..
monitor.StatusChanged += (sender, args) =>
Debug.Log($"New state: {args.NewState}");
monitor.Start(readerName);
}
void OnApplicationQuit()
{
monitor.Cancel();
monitor.Dispose();
}
実行するとこんな感じ。NFCカードを検出するとNew state: Present
、カードが離れるとNew state: Empty
が表示される。
monitor.Cancel();
とmonitor.Dispose();
がないと終了後にフリーズすることがある気がする。
3.2 タッチされたカードの情報を取得する
以下の記事を参考にしました。
上記の記事でもPCSC-Sharpのサンプルを参考にしてあったので、カードを検出した後の挙動は基本的にはこちらのサンプルをベースにしました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PCSC;
using PCSC.Monitoring;
using PCSC.Iso7816;
using System; // BitConverterを使う
public class ReadCardInfo : MonoBehaviour
{
string readerName;
ISCardMonitor monitor;
void Start()
{
var contextFactory = ContextFactory.Instance;
// using (var context = contextFactory.Establish(SCardScope.System)) {
using (var context = contextFactory.Establish(SCardScope.System)) {
Debug.Log("Currently connected readers: ");
var readerNames = context.GetReaders();
foreach (var readerName in readerNames) {
Debug.Log("\t" + readerName);
}
readerName = readerNames[0];
}
var monitorFactory = MonitorFactory.Instance;
// var monitor = monitorFactory.Create(SCardScope.System);
monitor = monitorFactory.Create(SCardScope.System);
// connect events here..
monitor.StatusChanged += (sender, args) => {
Debug.Log($"New state: {args.NewState}");
if( args.NewState == SCRState.Present)
{
ReadData();
}
};
monitor.Start(readerName);
}
// read data
private void ReadData() {
using (var context = ContextFactory.Instance.Establish(SCardScope.System)) {
using (var rfidReader = context.ConnectReader(readerName, SCardShareMode.Shared, SCardProtocol.Any)) {
var apdu = new CommandApdu(IsoCase.Case2Short, rfidReader.Protocol) {
CLA = 0xFF,
Instruction = InstructionCode.GetData,
P1 = 0x00,
P2 = 0x00,
Le = 0 // We don't know the ID tag size
};
using (rfidReader.Transaction(SCardReaderDisposition.Leave)) {
Console.WriteLine("Retrieving the UID .... ");
var sendPci = SCardPCI.GetPci(rfidReader.Protocol);
var receivePci = new SCardPCI(); // IO returned protocol control information.
var receiveBuffer = new byte[256];
var command = apdu.ToArray();
var bytesReceived = rfidReader.Transmit(
sendPci, // Protocol Control Information (T0, T1 or Raw)
command, // command APDU
command.Length,
receivePci, // returning Protocol Control Information
receiveBuffer,
receiveBuffer.Length); // data buffer
var responseApdu =
new ResponseApdu(receiveBuffer, bytesReceived, IsoCase.Case2Short, rfidReader.Protocol);
Debug.Log(string.Format("SW1: {0:X2}, SW2: {1:X2}\nUid: {2}",
responseApdu.SW1,
responseApdu.SW2,
responseApdu.HasData ? BitConverter.ToString(responseApdu.GetData()) : "No uid received"));
}
}
}
}
void OnApplicationQuit()
{
monitor.Cancel();
monitor.Dispose();
}
}
全然理解していないが、とりあえずカードのUIDが読み取れた。
Discussion