Darren
Darren

Reputation: 10398

CoreNFC writing to iCode Slix2 tag doesn't seem stable

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

Answers (1)

J W
J W

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

Related Questions