More nfc changes #370

Merged
blacklight merged 3 commits from 299-nfc-backend-migration into master 2024-02-27 22:35:43 +01:00
5 changed files with 28 additions and 114 deletions

View File

@ -15,7 +15,6 @@ Backends
platypush/backend/music.spotify.rst
platypush/backend/nodered.rst
platypush/backend/redis.rst
platypush/backend/scard.rst
platypush/backend/sensor.ir.zeroborg.rst
platypush/backend/sensor.leap.rst
platypush/backend/stt.deepspeech.rst

View File

@ -1,6 +0,0 @@
``scard``
===========================
.. automodule:: platypush.backend.scard
:members:

View File

@ -1,87 +0,0 @@
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:

View File

@ -1,17 +0,0 @@
manifest:
events:
platypush.message.event.scard.SmartCardDetectedEvent: when a smart card is detected
platypush.message.event.scard.SmartCardRemovedEvent: when a smart card is removed
install:
apk:
- py3-pyscard
apt:
- python3-pyscard
dnf:
- python-pyscard
pacman:
- python-pyscard
pip:
- pyscard
package: platypush.backend.scard
type: backend

View File

@ -7,7 +7,7 @@ from platypush.message.event.nfc import (
NFCDeviceConnectedEvent,
NFCDeviceDisconnectedEvent,
)
from platypush.plugins import RunnablePlugin
from platypush.plugins import RunnablePlugin, action
class NfcPlugin(RunnablePlugin):
@ -21,7 +21,7 @@ class NfcPlugin(RunnablePlugin):
"""
def __init__(self, device='usb', *args, **kwargs):
def __init__(self, device='usb', **kwargs):
"""
:param device: Address or ID of the device to be opened. Examples:
@ -29,7 +29,7 @@ class NfcPlugin(RunnablePlugin):
* ``usb:003`` opens the first available device on bus 3
* ``usb`` opens the first available USB device (default)
"""
super().__init__(*args, **kwargs)
super().__init__(**kwargs)
self.device_id = device
self._clf = None
@ -229,6 +229,31 @@ class NfcPlugin(RunnablePlugin):
return callback
@action
def status(self):
"""
Get information about the NFC reader status.
Example output:
.. code-block:: json
{
"display_name": "ACS ACR122U PN532v1.6 at usb:001:017",
"path": "usb:001:017",
"product_name": "ACR122U",
"vendor_name": "ACS"
}
"""
assert self._clf and self._clf.device, 'NFC reader not initialized'
return {
'display_name': str(self._clf.device),
'path': self._clf.device.path,
'product_name': self._clf.device.product_name,
'vendor_name': self._clf.device.vendor_name,
}
def main(self):
fail_wait = 5
max_fail_wait = 60