diff --git a/platypush/backend/scard/__init__.py b/platypush/backend/scard/__init__.py new file mode 100644 index 0000000000..039eebfa16 --- /dev/null +++ b/platypush/backend/scard/__init__.py @@ -0,0 +1,76 @@ +import logging +import json + +from smartcard.CardType import AnyCardType, ATRCardType +from smartcard.CardRequest import CardRequest +from smartcard.util import toHexString + +from platypush.backend import Backend +from platypush.message.event.scard import SmartCardDetectedEvent + + +class ScardBackend(Backend): + """ + Generic backend to read smart cards and trigger SmartCardDetectedEvent + messages with the card ATR whenever a card is detected. It requires + pyscard https://pypi.org/project/pyscard/ + + Extend this backend to implement more advanced communication with + custom smart cards. + """ + + def __init__(self, atr=None, *args, **kwargs): + """ + Params: + atr -- If set, the backend will trigger events only for card(s) + with the specified ATR(s). It can be either an ATR string + (space-separated hex octects) or a list of ATR strings. + Default: none (any card will be detected) + """ + super().__init__(*args, **kwargs) + self.ATRs = [] + + if atr: + if isinstance(atr, str): + self.ATRs = [atr] + elif isinstance(atr, list): + self.ATRs = atr + else: + raise RuntimeError("Unsupported ATR: \"{}\" - type: {}, " + + "supported types: string, list".format( + atr, type(atr))) + + self.cardtype = ATRCardType( *[toBytes(atr) for atr in self.ATRs] ) + else: + self.cardtype = AnyCardType() + + + def run(self): + super().run() + + logging.info('Initialized smart card reader backend - ATR filter: {}'. + format(self.ATRs)) + + prev_atr = None + while not self.should_stop(): + try: + cardrequest = CardRequest(timeout=None, cardType=self.cardtype) + cardservice = cardrequest.waitforcard() + cardservice.connection.connect() + + reader = cardservice.connection.getReader() + atr = toHexString(cardservice.connection.getATR()) + + if atr != prev_atr: + logging.info('Smart card detected on reader {}, ATR: {}'. + format(reader, atr)) + + self.bus.post(SmartCardDetectedEvent(atr=atr, reader=reader)) + prev_atr = atr + except Exception as e: + logging.exception(e) + prev_atr = None + + +# vim:sw=4:ts=4:et: + diff --git a/platypush/message/event/scard.py b/platypush/message/event/scard.py new file mode 100644 index 0000000000..4bf1809dc9 --- /dev/null +++ b/platypush/message/event/scard.py @@ -0,0 +1,10 @@ +from platypush.message.event import Event + + +class SmartCardDetectedEvent(Event): + def __init__(self, atr, reader=None, *args, **kwargs): + super().__init__(atr=atr, reader=reader, *args, **kwargs) + + +# vim:sw=4:ts=4:et: +