Reputation: 10398
I am using CoreNFC
on iOS
to flash some iCode Slix2 NFC tags.
The problem I have is that sometimes i'll get successfully through my writes, but the majority of the time I get either of these errors:
Error Domain=NFCError Code=100 "Tag connection lost" UserInfo={NSLocalizedDescription=Tag connection lost}
Error Domain=NFCError Code=102 "Tag response error" UserInfo={NSLocalizedDescription=Tag response error, ISO15693TagResponseErrorCode=15}
Error Domain=NFCError Code=401 "Stack Error" UserInfo={NSLocalizedDescription=Stack Error, NSUnderlyingError=0x3017960d0 {Error Domain=nfcd Code=21 "writeNdefData:toTag:nLengthOptimization:error::403" UserInfo={Line=403, NSLocalizedDescription=Connection Closed, NSDebugDescription=writeNdefData:toTag:nLengthOptimization:error::403, Method=writeNdefData:toTag:nLengthOptimization:error:}}}
As an example of one of my writes, it's to completely erase the tag.
func erase(tag: NFCISO15693Tag) async throws {
print("🏷️", "ERASING TAG")
alertMessage = "ERASING TAG..."
let sysInfo = try await getSystemInfo(from: tag)
let totalBlocks = sysInfo.totalBlocks - 1
let blockSize = sysInfo.blockSize
var blockNumber: UInt8 = 0
func writeNextBlock() async throws {
if blockNumber < totalBlocks {
alertMessage = "ERASING TAG \(blockNumber)/\(totalBlocks)"
let blankData = Data(repeating: 0x00, count: blockSize)
try await write(data: blankData, to: tag, at: blockNumber)
// Move to the next block
blockNumber += 1
try await writeNextBlock()
} else {
// All blocks have been erased
alertMessage = "Tag erased successfully!"
}
}
// Start writing to the first block
try await writeNextBlock()
}
func write(data: Data, to tag: NFCISO15693Tag, at block: UInt8) async throws {
print("🏷️", "Writing data:", data, data.hexEncodedString(.upperCase), "at block:", block)
try await tag.writeSingleBlock(requestFlags: [.highDataRate], blockNumber: block, dataBlock: data)
}
@MainActor
private func eraseTag() {
session = NFCTagReaderSession(pollingOption: [.iso15693], delegate: self, queue: nil)
session?.alertMessage = "Hold your iPhone near a new NFC tag."
session?.begin()
}
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
guard tags.count == 1 else {
session.invalidate(errorMessage: "Can not write to more than one tag.")
return
}
let currentTag = tags.first!
guard case .iso15693(let iso15693Tag) = currentTag else {
session.invalidate(errorMessage: "Tag is not iso15693")
return
}
Task {
do {
try await session.connect(to: currentTag)
print("Connected: ========\(currentTag.isAvailable)========")
try await session.erase(tag: iso15693Tag)
session.invalidate()
} catch {
print("❗️", error)
session.invalidate(errorMessage: error.localizedDescription)
}
}
}
A lot of the time this won't get half way through writing the 79 blocks of the tag, but occasionally it will succeed.
I get the error sometimes when reading too, however if I use the NFC Tools app it manages to read the chip a lot more than my app can. Is there some additional parameters or setup I need? Or perhaps I have a threading issue?
How can I find what ISO15693TagResponseErrorCode=15
means?
Upvotes: 1
Views: 269
Reputation: 924
As for the meaning of ISO15693TagResponseErrorCode=15
func handleNFCError(_ error: NSError) {
if let errorCode = error.userInfo[NFCISO15693TagResponseErrorKey] as? NSNumber {
print("NFC Tag Command Error: \(errorCode)")
// // According to the ISO 15693-3 specification, the errorCode can be decoded here to understand the error.
} else {
print("Other NFC error: \(error.localizedDescription)")
}
}
You can try lowering the writing frequency, although I don’t know if it will help.
func erase(tag: NFCISO15693Tag) async throws {
print("🏷️", "ERASING TAG")
alertMessage = "ERASING TAG..."
let sysInfo = try await getSystemInfo(from: tag)
let totalBlocks = sysInfo.totalBlocks - 1
let blockSize = sysInfo.blockSize
var blockNumber: UInt8 = 0
func writeNextBlock() async throws {
if blockNumber <= totalBlocks {
alertMessage = "ERASING TAG \(blockNumber)/\(totalBlocks)"
let blankData = Data(repeating: 0x00, count: blockSize)
do {
try await write(data: blankData, to: tag, at: blockNumber)
try await Task.sleep(nanoseconds: 100_000_000)
blockNumber += 1
try await writeNextBlock()
} catch {
print("Write error: \(error), retrying...")
try await Task.sleep(nanoseconds: 500_000_000)
try await writeNextBlock()
}
} else {
alertMessage = "Tag erased successfully!"
}
}
try await writeNextBlock()
}
Upvotes: 0