134 lines
4.9 KiB
Swift
Executable File
134 lines
4.9 KiB
Swift
Executable File
import Foundation
|
|
import CoreNFC
|
|
|
|
@available(iOS 13.0, *)
|
|
extension NFCISO7816APDU {
|
|
func toHexString() -> String {
|
|
let dataFieldInHex = (self.data ?? Data(_ : [])).hexEncodedString()
|
|
return String(format:"%02X %02X %02X %02X", self.instructionClass, self.instructionCode, self.p1Parameter, self.p2Parameter) + " " + dataFieldInHex + String(format:"%02X", self.expectedResponseLength) + " "
|
|
}
|
|
}
|
|
|
|
typealias CompletionHandler = (_ response:ApduResponse) -> Void
|
|
|
|
@available(iOS 13.0, *)
|
|
public class ApduRunner: NSObject, NFCTagReaderSessionDelegate {
|
|
public static let NFC_TAG_CONNECTED_EVENT:String = "nfcTagConnected"
|
|
|
|
var sessionEx: NFCTagReaderSession?
|
|
var callback: ApduCallback?
|
|
var nfcApi : UnifiedNfcApi?
|
|
|
|
func setApduCallback(callback : ApduCallback) {
|
|
self.callback = callback
|
|
}
|
|
|
|
func setUnifiedNfcApi(nfcApi : UnifiedNfcApi) {
|
|
self.nfcApi = nfcApi
|
|
}
|
|
|
|
func startScan() {
|
|
let langCode = Locale.current.languageCode ?? "en"
|
|
self.sessionEx = NFCTagReaderSession(pollingOption: [.iso14443, .iso18092], delegate: self)
|
|
self.sessionEx?.alertMessage = "scanMessage".localizeString(string: langCode)
|
|
self.sessionEx?.begin()
|
|
}
|
|
|
|
|
|
public func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
|
|
guard self.callback != nil else {
|
|
debugLog("NfcCallback is empty.")
|
|
return
|
|
}
|
|
guard self.sessionEx != nil else {
|
|
return
|
|
}
|
|
guard tags.count > 0 else {
|
|
debugLog("Nfc Tag???.")
|
|
return
|
|
}
|
|
guard let firstTag = tags.first else {
|
|
return
|
|
}
|
|
if case NFCTag.iso7816(_) = firstTag {
|
|
sessionEx?.connect(to: firstTag) { [self] (error: Error?) in
|
|
if let err = error {
|
|
debugLog("Error connecting to Nfc Tag" + err.localizedDescription)
|
|
return
|
|
}
|
|
debugLog("Nfc Tag is connected.")
|
|
if let callback = self.callback, let nfcApi = self.nfcApi {
|
|
callback.connected(unifiedNfcApi: nfcApi)
|
|
}
|
|
}
|
|
} else if case .feliCa(let feliCaTag) = firstTag {
|
|
sessionEx?.connect(to: firstTag) { [self] (error: Error?) in
|
|
if let err = error {
|
|
debugLog("Error connecting to Nfc Tag" + err.localizedDescription)
|
|
return
|
|
}
|
|
// felicaTag = feliCaTag
|
|
debugLog("Felica is connected.")
|
|
if let callback = self.callback, let nfcApi = self.nfcApi {
|
|
debugLog("Felica is connected 2.")
|
|
callback.felicaConnected(unifiedNfcApi: nfcApi, tag: feliCaTag)
|
|
}
|
|
// self.sendFelicaCommand(tag: feliCaTag, session: sessionEx!)
|
|
|
|
// let idm = feliCaTag.currentIDm.map { String(format: "%.2hhx", $0) }.joined()
|
|
// let hexString = "0F06" + idm + "010B30018000"
|
|
// print("hex: \(hexString)")
|
|
// if let apduData = hexString.hexToData() {
|
|
// feliCaTag.sendFeliCaCommand(commandPacket: apduData)
|
|
// }
|
|
|
|
// if (self.callback != nil){
|
|
// self.callback!.connected(felicaNfcApi: self.felicaNfcApi!)
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
func exchangeApdu(apduCommand: NFCISO7816APDU, completionHandler: @escaping CompletionHandler) {
|
|
guard let connectedTag = self.sessionEx?.connectedTag else {
|
|
debugLog("No connected NFC tag available")
|
|
return
|
|
}
|
|
if case let NFCTag.iso7816(nfcTag) = connectedTag {
|
|
nfcTag.sendCommand(apdu: apduCommand) { (response: Data, sw1: UInt8, sw2: UInt8, error: Error?)
|
|
in
|
|
let resp = ApduResponse()
|
|
debugLog("SW1-SW2: " + String(format: "%02X, %02X", sw1, sw2))
|
|
resp.setSw1(_sw1: sw1)
|
|
resp.setSw2(_sw2: sw2)
|
|
resp.setData(_data: response)
|
|
completionHandler(resp)
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
func invalidateSession() {
|
|
sessionEx?.invalidate()
|
|
}
|
|
|
|
func invalidateSession(msg : String) {
|
|
sessionEx?.invalidate(errorMessage: msg)
|
|
}
|
|
|
|
public func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
|
|
debugLog("Nfc session is active")
|
|
}
|
|
|
|
public func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
|
|
debugLog("Error happend: " + error.localizedDescription)
|
|
NotificationCenter.default.post(name: Notification.Name("stopTimer"), object: nil)
|
|
if ((sessionEx?.isReady) != nil){
|
|
self.invalidateSession(msg: error.localizedDescription)
|
|
}
|
|
}
|
|
|
|
|
|
}
|