如何使用VB.net中的ACR122U阅读器和PCSC库读取标签(例如Mifare Classic)的UID

问题描述 投票:0回答:1

是的,我有以下代码,使用 PCSC-sharp Iso7816 库可以正常工作:

Imports PCSC
Imports PCSC.Iso7816
Imports PCSC.Utils
Imports System


Public Class TapMembershipCard

    Dim MembershipCardUID As String

    Sub ReadCard() Handles ReadCardBtn.Click
        Using context = New SCardContext()
            context.Establish(SCardScope.System)

            Dim readerNames = context.GetReaders()
            Dim sc As PCSC.SCardError

            Dim readerName = readerNames.FirstOrDefault()
            If readerName Is Nothing Then
                Return
            End If

            Using rfidReader = New SCardReader(context)
                sc = rfidReader.Connect(readerName, SCardShareMode.Shared, SCardProtocol.Any)
                If sc <> SCardError.Success Then
                    'THIS IS USUALLY WHERE THE PROGRAM WILL GET TO IF NO CARD HAS BEEN PRESENTED
                    Return
                End If

                PresentCard.Visibility = Visibility.Hidden

                Dim apdu = New CommandApdu(IsoCase.Case2Short, rfidReader.ActiveProtocol) With {
                    .CLA = &HFF,
                    .Instruction = InstructionCode.GetData,
                    .P1 = &H0,
                    .P2 = &H0,
                    .Le = 7
                }

                sc = rfidReader.BeginTransaction()
                If sc <> SCardError.Success Then
                    Console.WriteLine("Could not begin transaction.")
                    Return
                End If

                Console.WriteLine("Retrieving the UID .... ")

                Dim receivePci = New SCardPCI() ' IO returned protocol control information.
                Dim sendPci = SCardPCI.GetPci(rfidReader.ActiveProtocol)

                Dim receiveBuffer = New Byte(255) {}
                Dim command = apdu.ToArray()

                sc = rfidReader.Transmit(sendPci, command, receivePci, receiveBuffer)
                If sc <> SCardError.Success Then
                    Console.WriteLine("Error: " & SCardHelper.StringifyError(sc))
                End If

                Dim responseApdu = New ResponseApdu(receiveBuffer, IsoCase.Case2Short, rfidReader.ActiveProtocol)
                Console.Write("SW1: {0:X2}, SW2: {1:X2}" & vbCrLf & "Uid: {2}", responseApdu.SW1, responseApdu.SW2, If(responseApdu.HasData, BitConverter.ToString(responseApdu.GetData()), "No uid received"))

                rfidReader.EndTransaction(SCardReaderDisposition.Leave)
                rfidReader.Disconnect(SCardReaderDisposition.Reset)

                MembershipCardUID = BitConverter.ToString(responseApdu.GetData())
            End Using
        End Using
    End Sub
End Class

但理想情况下,我希望拥有它,以便它不断检查卡片是否存在,而不必在卡片出现后单击按钮。另外,可以以任何方式简化吗?我觉得光是读取 UID 就已经有很多代码了。

我愿意使用任何与 VB.net 兼容的库或框架,并且如果愿意的话,我也很高兴用 C# 编写任何想法。 仅供参考,我正在使用 .NET 8.0 WPF 应用程序。 读写器为ACR122U读写器

我尝试简单地使用递归或在此 IF 语句中再次调用子函数:

sc = rfidReader.Connect(readerName, SCardShareMode.Shared, SCardProtocol.Any)
If sc <> SCardError.Success Then
    'THIS IS USUALLY WHERE THE PROGRAM WILL GET TO IF NO CARD HAS BEEN PRESENTED
    Return
End If

问题在于,没有任何视觉元素加载/一切都会冻结,同时它不断迭代,直到出现卡片。

理想情况下,我希望能够有一些代码来检测何时出示卡,然后发送 ADPU 命令来检索 UID。

vb.net nfc acr122
1个回答
0
投票

我最终使用了 ACR122U 库 这是文档:Github + 网站。它似乎没有维护,但非常有帮助。这是我最终使用的代码(它绝不是完美的,它是一项正在进行的工作。我刚刚设法完成以下工作):

Imports System
Imports PCSC
Imports PCSC.Iso7816
Imports PCSC.Monitoring


Public Class TapMembershipCard

    Private maxReadWriteLength As Integer = 50
    Private blockSize As Integer = 4
    Private startBlock As Integer = 4
    Private readbackDelayMilliseconds As Integer = 100
    Private cardReaderNames As String() = Nothing
    Private cardContext As ISCardContext = Nothing
    Private buzzerSet As Boolean = False
    Private buzzerOnOff As Boolean = False

    Public Event CardInserted As CardInsertedHandler
    Public Delegate Sub CardInsertedHandler(reader As ICardReader)

    Public Event CardRemoved As CardRemovedHandler
    Public Delegate Sub CardRemovedHandler()


    Public Sub Init()
        buzzerOnOff = True
        maxReadWriteLength = 16
        blockSize = 16
        startBlock = 0
        readbackDelayMilliseconds = 10

        cardContext = ContextFactory.Instance.Establish(SCardScope.System)

        cardReaderNames = cardContext.GetReaders()

        Dim monitor = MonitorFactory.Instance.Create(SCardScope.System)
        AddHandler monitor.CardInserted, AddressOf Monitor_CardInserted
        AddHandler monitor.CardRemoved, AddressOf Monitor_CardRemoved
        monitor.Start(cardReaderNames)
    End Sub

    Private Sub Monitor_CardInserted(sender As Object, e As CardStatusEventArgs)
        Dim reader As ICardReader = Nothing

        Try
            reader = cardContext.ConnectReader(cardReaderNames(0), SCardShareMode.Shared, SCardProtocol.Any)
        Catch
        End Try

        If reader IsNot Nothing Then
            If Not buzzerSet Then
                buzzerSet = True
                SetBuzzer(reader, buzzerOnOff)
            End If

            RaiseEvent CardInserted(reader)
            GetUID(reader)

            Try
                reader.Disconnect(SCardReaderDisposition.Leave)
            Catch
            End Try
        End If
    End Sub

    Public Sub SetBuzzer(reader As ICardReader, [on] As Boolean)
        Dim ret As Byte() = New Byte(1) {}

        reader.Transmit(New Byte() {&HFF, &H0, &H52, If([on], &HFF, &H0), &H0}, ret)
    End Sub


    Private Sub Monitor_CardRemoved(sender As Object, e As CardStatusEventArgs)
        RaiseEvent CardRemoved()
    End Sub

    Public Sub GetUID(reader As ICardReader)
        Dim uid As Byte() = New Byte(9) {}

        reader.Transmit(New Byte() {&HFF, &HCA, &H0, &H0, &H0}, uid)

        Array.Resize(uid, 7)
    End Sub
End Class
© www.soinside.com 2019 - 2024. All rights reserved.