forked from platypush/platypush
Added an `add_dependencies` plugin to the Sphinx build process that parses the manifest files of the scanned backends and plugins and automatically generates the documentation for the required dependencies and triggered events. This means that those dependencies are no longer required to be listed in the docstring of the class itself. Also in this commit: - Black/LINT for some integrations that hadn't been touched in a long time. - Deleted some leftovers from previous refactors (deprecated `backend.mqtt`, `backend.zwave.mqtt`, `backend.http.request.rss`). - Deleted deprecated `inotify` backend - replaced by `file.monitor` (see #289).
87 lines
2.8 KiB
Python
87 lines
2.8 KiB
Python
from platypush.backend import Backend
|
|
from platypush.message.event.scard import SmartCardDetectedEvent, SmartCardRemovedEvent
|
|
|
|
|
|
class ScardBackend(Backend):
|
|
"""
|
|
Generic backend to read smart cards and NFC tags and trigger an event
|
|
whenever a device is detected.
|
|
|
|
Extend this backend to implement more advanced communication with custom
|
|
smart cards.
|
|
"""
|
|
|
|
def __init__(self, atr=None, *args, **kwargs):
|
|
"""
|
|
:param 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).
|
|
"""
|
|
|
|
from smartcard.CardType import AnyCardType, ATRCardType
|
|
|
|
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(
|
|
f"Unsupported ATR: \"{atr}\" - type: {type(atr)}, "
|
|
+ "supported types: string, list"
|
|
)
|
|
|
|
self.cardtype = ATRCardType(*[self._to_bytes(atr) for atr in self.ATRs])
|
|
else:
|
|
self.cardtype = AnyCardType()
|
|
|
|
@staticmethod
|
|
def _to_bytes(data) -> bytes:
|
|
if isinstance(data, str):
|
|
data = data.encode()
|
|
return data
|
|
|
|
def run(self):
|
|
from smartcard.CardRequest import CardRequest
|
|
from smartcard.Exceptions import NoCardException, CardConnectionException
|
|
from smartcard.util import toHexString
|
|
|
|
super().run()
|
|
|
|
self.logger.info(
|
|
'Initialized smart card reader backend - ATR filter: {}'.format(self.ATRs)
|
|
)
|
|
|
|
prev_atr = None
|
|
reader = 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:
|
|
self.logger.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:
|
|
if isinstance(e, (NoCardException, CardConnectionException)):
|
|
self.bus.post(SmartCardRemovedEvent(atr=prev_atr, reader=reader))
|
|
else:
|
|
self.logger.exception(e)
|
|
|
|
prev_atr = None
|
|
|
|
|
|
# vim:sw=4:ts=4:et:
|