Search code examples
python-3.xsmartcarduidacr122pyscard

How to reset this code after detecting a smartcard without terminating it, thus continues to listen for other smartcards?


I have a code running and successfully printing the ATR, UID, and status, however, the program ends after detecting and printing the UID. How do I make my code reset after detecting and wait for the removal and insertion of a different card (or same card)

I've tried using while loops, but that causes the program to print the ATR, UID, and status many time and when the card is removed the programm terminates with an error.

from smartcard.CardRequest import CardRequest
from smartcard.Exceptions import CardRequestTimeoutException
from smartcard.CardType import AnyCardType
from smartcard import util

WAIT_FOR_SECONDS = 60

# respond to the insertion of any type of smart card
card_type = AnyCardType()

# create the request. Wait for up to x seconds for a card to be attached
request = CardRequest(timeout=WAIT_FOR_SECONDS, cardType=card_type)

# listen for the card
service = None
try:
    service = request.waitforcard()
except CardRequestTimeoutException:
    print("ERROR: No card detected")
    exit(-1)

# when a card is attached, open a connection
conn = service.connection
conn.connect()

# get and print the ATR and UID of the card
get_uid = util.toBytes("FF CA 00 00 00")
print("ATR = {}".format(util.toHexString(conn.getATR())))
data, sw1, sw2 = conn.transmit(get_uid)
uid = util.toHexString(data)
status = util.toHexString([sw1, sw2])
print("UID = {}\tstatus = {}".format(uid, status))

The fix it tried (This keeps printing and when I remove the card it terminates(solved)):

from smartcard.CardRequest import CardRequest
from smartcard.Exceptions import CardRequestTimeoutException
from smartcard.CardType import AnyCardType
from smartcard import util

WAIT_FOR_SECONDS = 60
# respond to the insertion of any type of smart card
card_type = AnyCardType()

# create the request. Wait for up to x seconds for a card to be attached
request = CardRequest(timeout=WAIT_FOR_SECONDS, cardType=card_type)

while True:
    # listen for the card
    service = None
    try:
        service = request.waitforcard()
    except CardRequestTimeoutException:
        print("ERROR: No card detected")
        # could add "exit(-1)" to make code terminate

    # when a card is attached, open a connection
    try:
        conn = service.connection
        conn.connect()

        # get the ATR and UID of the card
        get_uid = util.toBytes("FF CA 00 00 00")
        data, sw1, sw2 = conn.transmit(get_uid)
        uid = util.toHexString(data)
        status = util.toHexString([sw1, sw2])


        # print the ATR and UID of the card
        print("ATR = {}".format(util.toHexString(conn.getATR())))
        print("UID = {}\tstatus = {}".format(uid, status))
    except:
        print("no connection")

The problem is I can't figure out how to create a loop where it prints once. After printing the UID it waits for card to be removed and another to be inputed and the cycle resets.

Edit: I managed to make the code reset, however, I can't figure out how to make the program print once rather than keep printing. Any suggestions?

I expect the code to print once after smartcard is present and then when the smartcard is removed, resets and listens to the smartcard again.


Solution

  • This will do that but it will make the UI unclickable since it's still running in the background.

    # respond to the insertion of any type of smart card
    card_type = AnyCardType()
    
    # create the request. Wait for up to x seconds for a card to be attached
    request = CardRequest(timeout=0, cardType=card_type)
    hasopened = False
    
    while True:
        # listen for the card
        service = None
        try:
            service = request.waitforcard()
        except CardRequestTimeoutException:
            print("ERROR: No card detected")
            ui.lineEdit_2.setText('NO CARD DETECTED')
            ui.lineEdit_2.setStyleSheet("background-color: #e4e0e0;\n" "color: #000000;")
            ui.label_5.setStyleSheet("background-color: #ff0000")
    
        # could add "exit(-1)" to make code terminate
    
        # when a card is attached, open a connection
        try:
            conn = service.connection
            conn.connect()
    
            # get the ATR and UID of the card
            get_uid = util.toBytes("FF CA 00 00 00")
            data, sw1, sw2 = conn.transmit(get_uid)
            uid = util.toHexString(data)
            status = util.toHexString([sw1, sw2])
    
            # print the ATR and UID of the card
            if conn and not hasopened:
                print("ATR = {}".format(util.toHexString(conn.getATR())))
                print("UID = {}\tstatus = {}".format(uid, status))
                ui.lineEdit_2.setText(uid)
                ui.lineEdit_2.setStyleSheet("background-color: #e4e0e0;\n" "color: #000000;")
                ui.label_5.setStyleSheet("background-color: #86dc3d")
    
                hasopened=True
        except:
            print("no connection")