Merge pull request #37 from dunkmann00/listen-for-passive-target

Add support to 'listen' for tags
This commit is contained in:
Limor "Ladyada" Fried 2020-08-19 11:31:49 -04:00 committed by GitHub
commit 1d6dec350a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 123 additions and 8 deletions

View file

@ -295,6 +295,19 @@ class PN532:
for a response and return a bytearray of response bytes, or None if no
response is available within the timeout.
"""
if not self.send_command(command, params=params, timeout=timeout):
return None
return self.process_response(
command, response_length=response_length, timeout=timeout
)
def send_command(
self, command, params=[], timeout=1
): # pylint: disable=dangerous-default-value
"""Send specified command to the PN532 and wait for an acknowledgment.
Will wait up to timeout seconds for the acknowlegment and return True.
If no acknowlegment is received, False is returned.
"""
# Build frame data with command and parameters.
data = bytearray(2 + len(params))
data[0] = _HOSTTOPN532
@ -306,12 +319,21 @@ class PN532:
self._write_frame(data)
except OSError:
self._wakeup()
return None
return False
if not self._wait_ready(timeout):
return None
return False
# Verify ACK response and wait to be ready for function response.
if not _ACK == self._read_data(len(_ACK)):
raise RuntimeError("Did not receive expected ACK from PN532!")
return True
def process_response(self, command, response_length=0, timeout=1):
"""Process the response from the PN532 and expect up to response_length
bytes back in a response. Note that less than the expected bytes might
be returned! Will wait up to timeout seconds for a response and return
a bytearray of response bytes, or None if no response is available
within the timeout.
"""
if not self._wait_ready(timeout):
return None
# Read response bytes.
@ -348,15 +370,41 @@ class PN532:
otherwise a bytearray with the UID of the found card is returned.
"""
# Send passive read command for 1 card. Expect at most a 7 byte UUID.
response = self.listen_for_passive_target(card_baud=card_baud, timeout=timeout)
# If no response is available return None to indicate no card is present.
if not response:
return None
return self.get_passive_target(timeout=timeout)
def listen_for_passive_target(self, card_baud=_MIFARE_ISO14443A, timeout=1):
"""Send command to PN532 to begin listening for a Mifare card. This
returns True if the command was received succesfully. Note, this does
not also return the UID of a card! `get_passive_target` must be called
to read the UID when a card is found. If just looking to see if a card
is currently present use `read_passive_target` instead.
"""
# Send passive read command for 1 card. Expect at most a 7 byte UUID.
try:
response = self.call_function(
_COMMAND_INLISTPASSIVETARGET,
params=[0x01, card_baud],
response_length=19,
timeout=timeout,
response = self.send_command(
_COMMAND_INLISTPASSIVETARGET, params=[0x01, card_baud], timeout=timeout
)
except BusyError:
return None # no card found!
return False # _COMMAND_INLISTPASSIVETARGET failed
return response
def get_passive_target(self, timeout=1):
"""Will wait up to timeout seconds and return None if no card is found,
otherwise a bytearray with the UID of the found card is returned.
`listen_for_passive_target` must have been called first in order to put
the PN532 into a listening mode.
It can be useful to use this when using the IRQ pin. Use the IRQ pin to
detect when a card is present and then call this function to read the
card's UID. This reduces the amount of time spend checking for a card.
"""
response = self.process_response(
_COMMAND_INLISTPASSIVETARGET, response_length=19, timeout=timeout
)
# If no response is available return None to indicate no card is present.
if response is None:
return None

View file

@ -0,0 +1,67 @@
"""
This example shows connecting to the PN532 with I2C (requires clock
stretching support), SPI, or UART. SPI is best, it uses the most pins but
is the most reliable and universally supported. In this example, we also connect
IRQ and poll that pin for a card. We don't try to read the card until we know
there is one present. After initialization, try waving various 13.56MHz RFID
cards over it!
"""
import time
import board
import busio
from digitalio import DigitalInOut
#
# NOTE: pick the import that matches the interface being used
#
from adafruit_pn532.i2c import PN532_I2C
# from adafruit_pn532.spi import PN532_SPI
# from adafruit_pn532.uart import PN532_UART
# I2C connection:
i2c = busio.I2C(board.SCL, board.SDA)
# Non-hardware
# pn532 = PN532_I2C(i2c, debug=False)
# With I2C, we recommend connecting RSTPD_N (reset) to a digital pin for manual
# harware reset
reset_pin = DigitalInOut(board.D6)
# On Raspberry Pi, you must also connect a pin to P32 "H_Request" for hardware
# wakeup! this means we don't need to do the I2C clock-stretch thing
req_pin = DigitalInOut(board.D12)
# Using the IRQ pin allows us to determine when a card is present by checking
# to see if the pin is pulled low.
irq_pin = DigitalInOut(board.D10)
pn532 = PN532_I2C(i2c, debug=False, reset=reset_pin, req=req_pin, irq=irq_pin)
# SPI connection:
# spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
# cs_pin = DigitalInOut(board.D5)
# pn532 = PN532_SPI(spi, cs_pin, debug=False)
# UART connection
# uart = busio.UART(board.TX, board.RX, baudrate=115200, timeout=100)
# pn532 = PN532_UART(uart, debug=False)
ic, ver, rev, support = pn532.firmware_version
print("Found PN532 with firmware version: {0}.{1}".format(ver, rev))
# Configure PN532 to communicate with MiFare cards
pn532.SAM_configuration()
# Start listening for a card
pn532.listen_for_passive_target()
print("Waiting for RFID/NFC card...")
while True:
# Check if a card is available to read
if irq_pin.value == 0:
uid = pn532.get_passive_target()
print("Found card with UID:", [hex(i) for i in uid])
# Start listening for a card again
pn532.listen_for_passive_target()
else:
print(".", end="")
time.sleep(0.1)