Reputation: 11
I'm working on an app that uses Core NFC to detect NFC cards, and everything is working fine with other cards such as MIFARE or ISO 14443 tags. However, I'm having trouble detecting the Vigik badge specifically. I've registered the AID for the Vigik badge correctly in my app's Entitlements.plist, but when I scan the badge, it doesn’t get detected, even though other cards are working as expected.
Here are some details about my implementation:
//
// ViewController.swift
// testNFCCOre
//
// Created by mind on 12/11/24.
//
import UIKit
import CoreNFC
class ViewController: UIViewController, NFCTagReaderSessionDelegate {
var nfcSession: NFCReaderSession?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func onTapScan(_ sender: Any) {
startScanning()
}
func startScanning() {
guard NFCTagReaderSession.readingAvailable else {
print("NFC is not supported on this device.")
return
}
// Create a session for raw tag reading
nfcSession = NFCTagReaderSession(pollingOption: [.iso14443,.iso18092,.iso15693], delegate: self, queue: DispatchQueue.main)
// Begin the session
nfcSession?.begin()
}
// Called when the session becomes active
func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
print("NFC session is active.")
// You can inform the user that the NFC reader is active or show a message
}
// Called when the session is invalidated (e.g., user cancels or an error occurs)
func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
if let error = error as? NFCReaderError {
switch error.code {
case .readerSessionInvalidationErrorUserCanceled:
print("User canceled the session.")
case .readerSessionInvalidationErrorSessionTimeout:
print("Session timed out.")
case .readerSessionInvalidationErrorSystemIsBusy:
print("System is busy. Please try again.")
default:
print("Session invalidated with error: \(error.localizedDescription)")
}
} else {
print("Session invalidated with error: \(error.localizedDescription)")
}
}
// Called when the session detects NFC tags
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
let tag = tags.first!
session.connect(to: tag) { error in
if let error = error {
print("Connection failed: \(error.localizedDescription)")
return
}
print("Tag connected successfully!")
// Continue processing the tag depending on its type
for tag in tags {
switch tag {
case .miFare(let mifareTag):
print("MIFARE tag detected: \(mifareTag)")
self.handleMifareTag(mifareTag)
case .feliCa(let feliCaTag):
print("FeliCa tag detected: \(feliCaTag)")
self.handleFeliCaTag(feliCaTag)
case .iso7816(let iso7816Tag):
print("ISO 7816 tag detected: \(iso7816Tag)")
let aidData = Data([
0xA0, 0x00, 0x00, 0x00, 0x86, 0x32, 0x05, 0x49,
0x47, 0x49, 0x4B, 0xAE, 0x5F, 0x33
])
// Create APDU SELECT command
let command = NFCISO7816APDU(
instructionClass: 0x00,
instructionCode: 0xA4,
p1Parameter: 0x04,
p2Parameter: 0x00,
data: aidData,
expectedResponseLength: -1
)
// Send the APDU command
iso7816Tag.sendCommand(apdu: command) { response, sw1, sw2, error in
if let error = error {
print("Error sending APDU: \(error.localizedDescription)")
return
}
// Parse the response
print("Response: \(response)")
print("Status words: SW1=\(sw1), SW2=\(sw2)")
// Process specific application template if needed
if sw1 == 0x90 && sw2 == 0x00 {
print("Application selected successfully!")
} else {
print("Application selection failed with status words \(sw1), \(sw2)")
}
}
self.handleIso7816Tag(iso7816Tag)
case .iso15693(let nfcATag):
print("ISO 15693 tag detected: \(nfcATag)")
self.handleNfcATag(nfcATag)
default:
print("Unknown tag type detected.")
}
}
session.invalidate()
}
}
// Handle MIFARE tag
func handleMifareTag(_ mifareTag: NFCMiFareTag) {
// Process MIFARE tag data
print("MIFARE UID: \(mifareTag.identifier)")
}
// Handle FeliCa tag
func handleFeliCaTag(_ feliCaTag: NFCFeliCaTag) {
// Print available information from NFCFeliCaTag
print("FeliCa tag detected.")
}
// Handle ISO 7816 tag (smart cards)
func handleIso7816Tag(_ iso7816Tag: NFCISO7816Tag) {
// Process ISO 7816 tag data
print("Tag Identifier: \(iso7816Tag.identifier.hexString())")
let hexString = "4a6f686e" // Hex for "John"
if let decodedText = hexStringToText(hexString: iso7816Tag.identifier.hexString()) {
print("Decoded text: \(decodedText)") // Outputs: John
}
print("Application Data: \(String(describing: iso7816Tag.applicationData))")
print("Historical Bytes: \(String(describing: iso7816Tag.historicalBytes))")
if let historicalBytes = iso7816Tag.historicalBytes {
let hexString = historicalBytes.map { String(format: "%02hhx", $0) }.joined()
print("Historical Bytes as Hex: \(hexString)")
}
print("Selected AID: \(iso7816Tag.initialSelectedAID)")
}
// Handle NFC-A tag
func handleNfcATag(_ nfcATag: NFCISO15693Tag) {
// Process NFC-A tag data
print("NFC-A UID: \(nfcATag.identifier)")
}
// Convert Hex String to Text
func hexStringToText(hexString: String) -> String? {
var hex = hexString
var data = Data()
while hex.count > 0 {
let c = hex.prefix(2)
hex = String(hex.dropFirst(2))
if let byte = UInt8(c, radix: 16) {
data.append(byte)
}
}
return String(data: data, encoding: .utf8)
}
}
// Convert Data to Hex String
extension Data {
func hexString() -> String {
return self.map { String(format: "%02hhx", $0) }.joined()
}
func hexStringToData(hexString: String) -> Data? {
var data = Data()
// Ensure the hex string is in valid form (even length)
let cleanedHexString = hexString.replacingOccurrences(of: " ", with: "").uppercased()
// Process every pair of characters (each byte)
var startIndex = cleanedHexString.startIndex
while startIndex < cleanedHexString.endIndex {
let endIndex = cleanedHexString.index(startIndex, offsetBy: 2)
let hexPair = String(cleanedHexString[startIndex..<endIndex])
if let byte = UInt8(hexPair, radix: 16) {
data.append(byte)
} else {
print("Invalid hex pair: \(hexPair)")
return nil
}
startIndex = endIndex
}
return data
}
}
Upvotes: 1
Views: 78