1

I have two NFC reading devices: ACR12U and ACR1252U

I have a short script in python using pyscard to read the UIDs of NFC tags:

from smartcard.CardMonitoring import CardMonitor, CardObserver
from smartcard.util import toHexString
from smartcard.Exceptions import CardConnectionException

getuid = [0xFF, 0xCA, 0x00, 0x00, 0x00]

class transmitobserver(CardObserver):
    def update(self, observable, actions):
        (addedcards, removedcards) = actions
        for card in addedcards:
            card.connection = card.createConnection()
            try:
                card.connection.connect()
            except CardConnectionException:
                # print("Card was removed too fast!")
                return
            response, sw1, sw2 = card.connection.transmit(
                getuid)
            nfc_id = "{}".format(toHexString(response)).replace(" ", "").lower()
            return nfc_id

if __name__ == '__main__':
    cardmonitor = CardMonitor()
    cardobserver = transmitobserver()
    cardmonitor.addObserver(cardobserver)
    try:
        while True:
            pass
    except KeyboardInterrupt:
        pass

The ACR122U buzzes as soon as I an NFC card is in proximity. The ACR1252U buzzes when an NFC is in proximity and buzzes again when I remove it.

I would like to change this behaviour so they only buzz when I remove the card and the card has been read. I tested it out and the program fails if I remove a card too fast, but the reader still buzzes like it was a success.

This is the first time I am working with things like this so I tried some trial and error methods.

So I figured getuid = [0xFF, 0xCA, 0x00, 0x00, 0x00] is sending the reader a command to read the UID, which I was able to find in both of their manuals:

enter image description here

Now I thought I could use this to control the buzzer. In the manual for the ACR1252U I found this:

enter image description here

So I tried the following:

buzzer = [0xE0, 0x00, 0x00, 0x28, 0x01, 0xFF]
response = card.connection.transmit(buzzer)

But nothing is happening. There is a different instruction for the ACR122U, but same thing happens. Can anyone aid me what am I doing wrong?

EDIT:

I was able to come a little closer to the solution, however I still dont understand what is going on 100%.

I only have a ACR122U when I am writing this, so all testing is done with that one. from the manual I was able to get a bunch of APDUs and I found a code that emulates a card read without an actual card being touched to the device, so I can test it.

from smartcard.System import readers
from smartcard.CardConnection import CardConnection
from smartcard.scard import SCARD_SHARE_DIRECT

reader = readers()[0]
connection = reader.createConnection()
connection.connect(protocol=CardConnection.RAW_protocol, mode=SCARD_SHARE_DIRECT)
turn_off_red = [0xFF, 0x00, 0x40, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00]
r, sw1, sw2 = connection.transmit(turn_off_red)

Now I have this APDU: turn_off_red = [0xFF, 0x00, 0x40, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00]

Which turns of the red led according to the manual, and it works as well, but just for a few seconds. Even if I put a sleep(50) at the end of the code, the red LED only blinks for a second, than turns back.

I think the same thing is happening when I try to use configBuzzer = [0xFF, 0x00, 0x52, 0x00, 0x00]. It turn the buzzer off for a couple of seconds, but turns it back on afterwards.

Gábor Erdős
  • 3,599
  • 4
  • 24
  • 56

1 Answers1

1

Two pointers

1)All commands sent using Command APDU's have a standard Response APDU format of Result (If available - most do have a Result), SW1 and SW2

So you should use the code response, sw1, sw2 = card.connection.transmit(buzzer)

You should always check that SW1 = 90h and SW2 = 00h to confirm the command was successful (Other values will indicate an error, see the datasheet for more details of what the codes mean)

2)You say you want it to buzz when it successful read the card, but you don't check the SW1 and SW2 values for success when you read the UID.

3)The command buzzer = [0xE0, 0x00, 0x00, 0x28, 0x01, 0xFF] is to manually turn the buzzer on, great for when you manually want to indicate success after checking in the SW1 and SW2 values of the read but this command does not change the default buzzing behaviour of the reader.

On the ACR1252U configBuzzer = [0xE0, 0x00, 0x00, 0x21, 0x01, 0x67] should be the right bits to turn off buzzing on Card Insertion Events and Card Removal Events, which is what you described you wanted, so you can manually trigger the buzzer on success (Again check SW1 and SW2 for success)

Update for the ACR122U

configBuzzer = [0xFF, 0x00, 0x52, 0x00, 0x00]

then

response, sw1, sw2 = card.connection.transmit(configBuzzer)

This will not cause buzzer to not turn on during Tag detection (the ACR122U has less configuration options than the ACR1252U)

Andrew
  • 8,198
  • 2
  • 15
  • 35
  • Thanks a lot for the response! Sadly I only have an ACR122U at the ready, but I found the following in the manual to stop the buzzer: `stop_buzzer = [0xFF, 0x00, 0x52, 0x00, 0x00]`. In principle the SW2 should be 0 and it is, but SW1 should be 90 on success and 63 on error, but I get 144. I am a little bit lost – Gábor Erdős Feb 06 '22 at 09:55
  • Also I found that dec 144 == hex 90, which might indicate that it was successful, however the reader still makes a noise, so I think the buzzer is still not properly set. – Gábor Erdős Feb 06 '22 at 10:05
  • Also with further testing (adding a bunch of sleep() lines) that the buzzing happens before the APDU is transmitted, I also believe that the reader still dioes not understand my command as it still buzzes on the second time I put a card to the reader. – Gábor Erdős Feb 06 '22 at 10:19
  • I think you missed the point of point 3, the buzzer has some configuration options for it's default buzzer behaviour, you need to change these config options so it does not buzz when you don't want to and then you can directly cause the buzzer to buzz when you send it a "buzz" command. – Andrew Feb 06 '22 at 17:32
  • I think I got that part, I did some more digging, and was able to produce some results, however not the desired results. I updated my question with my findings. – Gábor Erdős Feb 06 '22 at 18:04