Skip to content

Commit 1d6dec3

Browse files
authored
Merge pull request #37 from dunkmann00/listen-for-passive-target
Add support to 'listen' for tags
2 parents 50de551 + 02c0630 commit 1d6dec3

File tree

2 files changed

+123
-8
lines changed

2 files changed

+123
-8
lines changed

adafruit_pn532/adafruit_pn532.py

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,19 @@ def call_function(
295295
for a response and return a bytearray of response bytes, or None if no
296296
response is available within the timeout.
297297
"""
298+
if not self.send_command(command, params=params, timeout=timeout):
299+
return None
300+
return self.process_response(
301+
command, response_length=response_length, timeout=timeout
302+
)
303+
304+
def send_command(
305+
self, command, params=[], timeout=1
306+
): # pylint: disable=dangerous-default-value
307+
"""Send specified command to the PN532 and wait for an acknowledgment.
308+
Will wait up to timeout seconds for the acknowlegment and return True.
309+
If no acknowlegment is received, False is returned.
310+
"""
298311
# Build frame data with command and parameters.
299312
data = bytearray(2 + len(params))
300313
data[0] = _HOSTTOPN532
@@ -306,12 +319,21 @@ def call_function(
306319
self._write_frame(data)
307320
except OSError:
308321
self._wakeup()
309-
return None
322+
return False
310323
if not self._wait_ready(timeout):
311-
return None
324+
return False
312325
# Verify ACK response and wait to be ready for function response.
313326
if not _ACK == self._read_data(len(_ACK)):
314327
raise RuntimeError("Did not receive expected ACK from PN532!")
328+
return True
329+
330+
def process_response(self, command, response_length=0, timeout=1):
331+
"""Process the response from the PN532 and expect up to response_length
332+
bytes back in a response. Note that less than the expected bytes might
333+
be returned! Will wait up to timeout seconds for a response and return
334+
a bytearray of response bytes, or None if no response is available
335+
within the timeout.
336+
"""
315337
if not self._wait_ready(timeout):
316338
return None
317339
# Read response bytes.
@@ -348,15 +370,41 @@ def read_passive_target(self, card_baud=_MIFARE_ISO14443A, timeout=1):
348370
otherwise a bytearray with the UID of the found card is returned.
349371
"""
350372
# Send passive read command for 1 card. Expect at most a 7 byte UUID.
373+
response = self.listen_for_passive_target(card_baud=card_baud, timeout=timeout)
374+
# If no response is available return None to indicate no card is present.
375+
if not response:
376+
return None
377+
return self.get_passive_target(timeout=timeout)
378+
379+
def listen_for_passive_target(self, card_baud=_MIFARE_ISO14443A, timeout=1):
380+
"""Send command to PN532 to begin listening for a Mifare card. This
381+
returns True if the command was received succesfully. Note, this does
382+
not also return the UID of a card! `get_passive_target` must be called
383+
to read the UID when a card is found. If just looking to see if a card
384+
is currently present use `read_passive_target` instead.
385+
"""
386+
# Send passive read command for 1 card. Expect at most a 7 byte UUID.
351387
try:
352-
response = self.call_function(
353-
_COMMAND_INLISTPASSIVETARGET,
354-
params=[0x01, card_baud],
355-
response_length=19,
356-
timeout=timeout,
388+
response = self.send_command(
389+
_COMMAND_INLISTPASSIVETARGET, params=[0x01, card_baud], timeout=timeout
357390
)
358391
except BusyError:
359-
return None # no card found!
392+
return False # _COMMAND_INLISTPASSIVETARGET failed
393+
return response
394+
395+
def get_passive_target(self, timeout=1):
396+
"""Will wait up to timeout seconds and return None if no card is found,
397+
otherwise a bytearray with the UID of the found card is returned.
398+
`listen_for_passive_target` must have been called first in order to put
399+
the PN532 into a listening mode.
400+
401+
It can be useful to use this when using the IRQ pin. Use the IRQ pin to
402+
detect when a card is present and then call this function to read the
403+
card's UID. This reduces the amount of time spend checking for a card.
404+
"""
405+
response = self.process_response(
406+
_COMMAND_INLISTPASSIVETARGET, response_length=19, timeout=timeout
407+
)
360408
# If no response is available return None to indicate no card is present.
361409
if response is None:
362410
return None

examples/pn532_simplelisten.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""
2+
This example shows connecting to the PN532 with I2C (requires clock
3+
stretching support), SPI, or UART. SPI is best, it uses the most pins but
4+
is the most reliable and universally supported. In this example, we also connect
5+
IRQ and poll that pin for a card. We don't try to read the card until we know
6+
there is one present. After initialization, try waving various 13.56MHz RFID
7+
cards over it!
8+
"""
9+
10+
import time
11+
import board
12+
import busio
13+
from digitalio import DigitalInOut
14+
15+
#
16+
# NOTE: pick the import that matches the interface being used
17+
#
18+
from adafruit_pn532.i2c import PN532_I2C
19+
20+
# from adafruit_pn532.spi import PN532_SPI
21+
# from adafruit_pn532.uart import PN532_UART
22+
23+
# I2C connection:
24+
i2c = busio.I2C(board.SCL, board.SDA)
25+
26+
# Non-hardware
27+
# pn532 = PN532_I2C(i2c, debug=False)
28+
29+
# With I2C, we recommend connecting RSTPD_N (reset) to a digital pin for manual
30+
# harware reset
31+
reset_pin = DigitalInOut(board.D6)
32+
# On Raspberry Pi, you must also connect a pin to P32 "H_Request" for hardware
33+
# wakeup! this means we don't need to do the I2C clock-stretch thing
34+
req_pin = DigitalInOut(board.D12)
35+
# Using the IRQ pin allows us to determine when a card is present by checking
36+
# to see if the pin is pulled low.
37+
irq_pin = DigitalInOut(board.D10)
38+
pn532 = PN532_I2C(i2c, debug=False, reset=reset_pin, req=req_pin, irq=irq_pin)
39+
40+
# SPI connection:
41+
# spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
42+
# cs_pin = DigitalInOut(board.D5)
43+
# pn532 = PN532_SPI(spi, cs_pin, debug=False)
44+
45+
# UART connection
46+
# uart = busio.UART(board.TX, board.RX, baudrate=115200, timeout=100)
47+
# pn532 = PN532_UART(uart, debug=False)
48+
49+
ic, ver, rev, support = pn532.firmware_version
50+
print("Found PN532 with firmware version: {0}.{1}".format(ver, rev))
51+
52+
# Configure PN532 to communicate with MiFare cards
53+
pn532.SAM_configuration()
54+
55+
# Start listening for a card
56+
pn532.listen_for_passive_target()
57+
print("Waiting for RFID/NFC card...")
58+
while True:
59+
# Check if a card is available to read
60+
if irq_pin.value == 0:
61+
uid = pn532.get_passive_target()
62+
print("Found card with UID:", [hex(i) for i in uid])
63+
# Start listening for a card again
64+
pn532.listen_for_passive_target()
65+
else:
66+
print(".", end="")
67+
time.sleep(0.1)

0 commit comments

Comments
 (0)