Ran black, updated to pylint 2.x

This commit is contained in:
dherrada 2020-03-16 16:00:49 -04:00
parent d9b547eb5f
commit 129e02d563
10 changed files with 354 additions and 300 deletions

View file

@ -40,7 +40,7 @@ jobs:
source actions-ci/install.sh source actions-ci/install.sh
- name: Pip install pylint, black, & Sphinx - name: Pip install pylint, black, & Sphinx
run: | run: |
pip install --force-reinstall pylint==1.9.2 black==19.10b0 Sphinx sphinx-rtd-theme pip install --force-reinstall pylint black==19.10b0 Sphinx sphinx-rtd-theme
- name: Library version - name: Library version
run: git describe --dirty --always --tags run: git describe --dirty --always --tags
- name: PyLint - name: PyLint

View file

@ -55,114 +55,114 @@ __version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
# pylint: disable=bad-whitespace # pylint: disable=bad-whitespace
_PREAMBLE = const(0x00) _PREAMBLE = const(0x00)
_STARTCODE1 = const(0x00) _STARTCODE1 = const(0x00)
_STARTCODE2 = const(0xFF) _STARTCODE2 = const(0xFF)
_POSTAMBLE = const(0x00) _POSTAMBLE = const(0x00)
_HOSTTOPN532 = const(0xD4) _HOSTTOPN532 = const(0xD4)
_PN532TOHOST = const(0xD5) _PN532TOHOST = const(0xD5)
# PN532 Commands # PN532 Commands
_COMMAND_DIAGNOSE = const(0x00) _COMMAND_DIAGNOSE = const(0x00)
_COMMAND_GETFIRMWAREVERSION = const(0x02) _COMMAND_GETFIRMWAREVERSION = const(0x02)
_COMMAND_GETGENERALSTATUS = const(0x04) _COMMAND_GETGENERALSTATUS = const(0x04)
_COMMAND_READREGISTER = const(0x06) _COMMAND_READREGISTER = const(0x06)
_COMMAND_WRITEREGISTER = const(0x08) _COMMAND_WRITEREGISTER = const(0x08)
_COMMAND_READGPIO = const(0x0C) _COMMAND_READGPIO = const(0x0C)
_COMMAND_WRITEGPIO = const(0x0E) _COMMAND_WRITEGPIO = const(0x0E)
_COMMAND_SETSERIALBAUDRATE = const(0x10) _COMMAND_SETSERIALBAUDRATE = const(0x10)
_COMMAND_SETPARAMETERS = const(0x12) _COMMAND_SETPARAMETERS = const(0x12)
_COMMAND_SAMCONFIGURATION = const(0x14) _COMMAND_SAMCONFIGURATION = const(0x14)
_COMMAND_POWERDOWN = const(0x16) _COMMAND_POWERDOWN = const(0x16)
_COMMAND_RFCONFIGURATION = const(0x32) _COMMAND_RFCONFIGURATION = const(0x32)
_COMMAND_RFREGULATIONTEST = const(0x58) _COMMAND_RFREGULATIONTEST = const(0x58)
_COMMAND_INJUMPFORDEP = const(0x56) _COMMAND_INJUMPFORDEP = const(0x56)
_COMMAND_INJUMPFORPSL = const(0x46) _COMMAND_INJUMPFORPSL = const(0x46)
_COMMAND_INLISTPASSIVETARGET = const(0x4A) _COMMAND_INLISTPASSIVETARGET = const(0x4A)
_COMMAND_INATR = const(0x50) _COMMAND_INATR = const(0x50)
_COMMAND_INPSL = const(0x4E) _COMMAND_INPSL = const(0x4E)
_COMMAND_INDATAEXCHANGE = const(0x40) _COMMAND_INDATAEXCHANGE = const(0x40)
_COMMAND_INCOMMUNICATETHRU = const(0x42) _COMMAND_INCOMMUNICATETHRU = const(0x42)
_COMMAND_INDESELECT = const(0x44) _COMMAND_INDESELECT = const(0x44)
_COMMAND_INRELEASE = const(0x52) _COMMAND_INRELEASE = const(0x52)
_COMMAND_INSELECT = const(0x54) _COMMAND_INSELECT = const(0x54)
_COMMAND_INAUTOPOLL = const(0x60) _COMMAND_INAUTOPOLL = const(0x60)
_COMMAND_TGINITASTARGET = const(0x8C) _COMMAND_TGINITASTARGET = const(0x8C)
_COMMAND_TGSETGENERALBYTES = const(0x92) _COMMAND_TGSETGENERALBYTES = const(0x92)
_COMMAND_TGGETDATA = const(0x86) _COMMAND_TGGETDATA = const(0x86)
_COMMAND_TGSETDATA = const(0x8E) _COMMAND_TGSETDATA = const(0x8E)
_COMMAND_TGSETMETADATA = const(0x94) _COMMAND_TGSETMETADATA = const(0x94)
_COMMAND_TGGETINITIATORCOMMAND = const(0x88) _COMMAND_TGGETINITIATORCOMMAND = const(0x88)
_COMMAND_TGRESPONSETOINITIATOR = const(0x90) _COMMAND_TGRESPONSETOINITIATOR = const(0x90)
_COMMAND_TGGETTARGETSTATUS = const(0x8A) _COMMAND_TGGETTARGETSTATUS = const(0x8A)
_RESPONSE_INDATAEXCHANGE = const(0x41) _RESPONSE_INDATAEXCHANGE = const(0x41)
_RESPONSE_INLISTPASSIVETARGET = const(0x4B) _RESPONSE_INLISTPASSIVETARGET = const(0x4B)
_WAKEUP = const(0x55) _WAKEUP = const(0x55)
_MIFARE_ISO14443A = const(0x00) _MIFARE_ISO14443A = const(0x00)
# Mifare Commands # Mifare Commands
MIFARE_CMD_AUTH_A = const(0x60) MIFARE_CMD_AUTH_A = const(0x60)
MIFARE_CMD_AUTH_B = const(0x61) MIFARE_CMD_AUTH_B = const(0x61)
MIFARE_CMD_READ = const(0x30) MIFARE_CMD_READ = const(0x30)
MIFARE_CMD_WRITE = const(0xA0) MIFARE_CMD_WRITE = const(0xA0)
MIFARE_CMD_TRANSFER = const(0xB0) MIFARE_CMD_TRANSFER = const(0xB0)
MIFARE_CMD_DECREMENT = const(0xC0) MIFARE_CMD_DECREMENT = const(0xC0)
MIFARE_CMD_INCREMENT = const(0xC1) MIFARE_CMD_INCREMENT = const(0xC1)
MIFARE_CMD_STORE = const(0xC2) MIFARE_CMD_STORE = const(0xC2)
MIFARE_ULTRALIGHT_CMD_WRITE = const(0xA2) MIFARE_ULTRALIGHT_CMD_WRITE = const(0xA2)
# Prefixes for NDEF Records (to identify record type) # Prefixes for NDEF Records (to identify record type)
NDEF_URIPREFIX_NONE = const(0x00) NDEF_URIPREFIX_NONE = const(0x00)
NDEF_URIPREFIX_HTTP_WWWDOT = const(0x01) NDEF_URIPREFIX_HTTP_WWWDOT = const(0x01)
NDEF_URIPREFIX_HTTPS_WWWDOT = const(0x02) NDEF_URIPREFIX_HTTPS_WWWDOT = const(0x02)
NDEF_URIPREFIX_HTTP = const(0x03) NDEF_URIPREFIX_HTTP = const(0x03)
NDEF_URIPREFIX_HTTPS = const(0x04) NDEF_URIPREFIX_HTTPS = const(0x04)
NDEF_URIPREFIX_TEL = const(0x05) NDEF_URIPREFIX_TEL = const(0x05)
NDEF_URIPREFIX_MAILTO = const(0x06) NDEF_URIPREFIX_MAILTO = const(0x06)
NDEF_URIPREFIX_FTP_ANONAT = const(0x07) NDEF_URIPREFIX_FTP_ANONAT = const(0x07)
NDEF_URIPREFIX_FTP_FTPDOT = const(0x08) NDEF_URIPREFIX_FTP_FTPDOT = const(0x08)
NDEF_URIPREFIX_FTPS = const(0x09) NDEF_URIPREFIX_FTPS = const(0x09)
NDEF_URIPREFIX_SFTP = const(0x0A) NDEF_URIPREFIX_SFTP = const(0x0A)
NDEF_URIPREFIX_SMB = const(0x0B) NDEF_URIPREFIX_SMB = const(0x0B)
NDEF_URIPREFIX_NFS = const(0x0C) NDEF_URIPREFIX_NFS = const(0x0C)
NDEF_URIPREFIX_FTP = const(0x0D) NDEF_URIPREFIX_FTP = const(0x0D)
NDEF_URIPREFIX_DAV = const(0x0E) NDEF_URIPREFIX_DAV = const(0x0E)
NDEF_URIPREFIX_NEWS = const(0x0F) NDEF_URIPREFIX_NEWS = const(0x0F)
NDEF_URIPREFIX_TELNET = const(0x10) NDEF_URIPREFIX_TELNET = const(0x10)
NDEF_URIPREFIX_IMAP = const(0x11) NDEF_URIPREFIX_IMAP = const(0x11)
NDEF_URIPREFIX_RTSP = const(0x12) NDEF_URIPREFIX_RTSP = const(0x12)
NDEF_URIPREFIX_URN = const(0x13) NDEF_URIPREFIX_URN = const(0x13)
NDEF_URIPREFIX_POP = const(0x14) NDEF_URIPREFIX_POP = const(0x14)
NDEF_URIPREFIX_SIP = const(0x15) NDEF_URIPREFIX_SIP = const(0x15)
NDEF_URIPREFIX_SIPS = const(0x16) NDEF_URIPREFIX_SIPS = const(0x16)
NDEF_URIPREFIX_TFTP = const(0x17) NDEF_URIPREFIX_TFTP = const(0x17)
NDEF_URIPREFIX_BTSPP = const(0x18) NDEF_URIPREFIX_BTSPP = const(0x18)
NDEF_URIPREFIX_BTL2CAP = const(0x19) NDEF_URIPREFIX_BTL2CAP = const(0x19)
NDEF_URIPREFIX_BTGOEP = const(0x1A) NDEF_URIPREFIX_BTGOEP = const(0x1A)
NDEF_URIPREFIX_TCPOBEX = const(0x1B) NDEF_URIPREFIX_TCPOBEX = const(0x1B)
NDEF_URIPREFIX_IRDAOBEX = const(0x1C) NDEF_URIPREFIX_IRDAOBEX = const(0x1C)
NDEF_URIPREFIX_FILE = const(0x1D) NDEF_URIPREFIX_FILE = const(0x1D)
NDEF_URIPREFIX_URN_EPC_ID = const(0x1E) NDEF_URIPREFIX_URN_EPC_ID = const(0x1E)
NDEF_URIPREFIX_URN_EPC_TAG = const(0x1F) NDEF_URIPREFIX_URN_EPC_TAG = const(0x1F)
NDEF_URIPREFIX_URN_EPC_PAT = const(0x20) NDEF_URIPREFIX_URN_EPC_PAT = const(0x20)
NDEF_URIPREFIX_URN_EPC_RAW = const(0x21) NDEF_URIPREFIX_URN_EPC_RAW = const(0x21)
NDEF_URIPREFIX_URN_EPC = const(0x22) NDEF_URIPREFIX_URN_EPC = const(0x22)
NDEF_URIPREFIX_URN_NFC = const(0x23) NDEF_URIPREFIX_URN_NFC = const(0x23)
_GPIO_VALIDATIONBIT = const(0x80) _GPIO_VALIDATIONBIT = const(0x80)
_GPIO_P30 = const(0) _GPIO_P30 = const(0)
_GPIO_P31 = const(1) _GPIO_P31 = const(1)
_GPIO_P32 = const(2) _GPIO_P32 = const(2)
_GPIO_P33 = const(3) _GPIO_P33 = const(3)
_GPIO_P34 = const(4) _GPIO_P34 = const(4)
_GPIO_P35 = const(5) _GPIO_P35 = const(5)
_ACK = b'\x00\x00\xFF\x00\xFF\x00' _ACK = b"\x00\x00\xFF\x00\xFF\x00"
_FRAME_START = b'\x00\x00\xFF' _FRAME_START = b"\x00\x00\xFF"
# pylint: enable=bad-whitespace # pylint: enable=bad-whitespace
@ -179,7 +179,6 @@ def _reset(pin):
class BusyError(Exception): class BusyError(Exception):
"""Base class for exceptions in this module.""" """Base class for exceptions in this module."""
pass
class PN532: class PN532:
@ -196,7 +195,7 @@ class PN532:
try: try:
self._wakeup() self._wakeup()
self.get_firmware_version() # first time often fails, try 2ce self.get_firmware_version() # first time often fails, try 2ce
return return
except (BusyError, RuntimeError): except (BusyError, RuntimeError):
pass pass
@ -223,7 +222,9 @@ class PN532:
def _write_frame(self, data): def _write_frame(self, data):
"""Write a frame to the PN532 with the specified data bytearray.""" """Write a frame to the PN532 with the specified data bytearray."""
assert data is not None and 1 < len(data) < 255, 'Data must be array of 1 to 255 bytes.' assert (
data is not None and 1 < len(data) < 255
), "Data must be array of 1 to 255 bytes."
# Build frame to send as: # Build frame to send as:
# - Preamble (0x00) # - Preamble (0x00)
# - Start code (0x00, 0xFF) # - Start code (0x00, 0xFF)
@ -233,7 +234,7 @@ class PN532:
# - Checksum # - Checksum
# - Postamble (0x00) # - Postamble (0x00)
length = len(data) length = len(data)
frame = bytearray(length+8) frame = bytearray(length + 8)
frame[0] = _PREAMBLE frame[0] = _PREAMBLE
frame[1] = _STARTCODE1 frame[1] = _STARTCODE1
frame[2] = _STARTCODE2 frame[2] = _STARTCODE2
@ -246,7 +247,7 @@ class PN532:
frame[-1] = _POSTAMBLE frame[-1] = _POSTAMBLE
# Send frame. # Send frame.
if self.debug: if self.debug:
print('Write frame: ', [hex(i) for i in frame]) print("Write frame: ", [hex(i) for i in frame])
self._write_data(bytes(frame)) self._write_data(bytes(frame))
def _read_frame(self, length): def _read_frame(self, length):
@ -256,33 +257,37 @@ class PN532:
might be returned! might be returned!
""" """
# Read frame with expected length of data. # Read frame with expected length of data.
response = self._read_data(length+8) response = self._read_data(length + 8)
if self.debug: if self.debug:
print('Read frame:', [hex(i) for i in response]) print("Read frame:", [hex(i) for i in response])
# Swallow all the 0x00 values that preceed 0xFF. # Swallow all the 0x00 values that preceed 0xFF.
offset = 0 offset = 0
while response[offset] == 0x00: while response[offset] == 0x00:
offset += 1 offset += 1
if offset >= len(response): if offset >= len(response):
raise RuntimeError('Response frame preamble does not contain 0x00FF!') raise RuntimeError("Response frame preamble does not contain 0x00FF!")
if response[offset] != 0xFF: if response[offset] != 0xFF:
raise RuntimeError('Response frame preamble does not contain 0x00FF!') raise RuntimeError("Response frame preamble does not contain 0x00FF!")
offset += 1 offset += 1
if offset >= len(response): if offset >= len(response):
raise RuntimeError('Response contains no data!') raise RuntimeError("Response contains no data!")
# Check length & length checksum match. # Check length & length checksum match.
frame_len = response[offset] frame_len = response[offset]
if (frame_len + response[offset+1]) & 0xFF != 0: if (frame_len + response[offset + 1]) & 0xFF != 0:
raise RuntimeError('Response length checksum did not match length!') raise RuntimeError("Response length checksum did not match length!")
# Check frame checksum value matches bytes. # Check frame checksum value matches bytes.
checksum = sum(response[offset+2:offset+2+frame_len+1]) & 0xFF checksum = sum(response[offset + 2 : offset + 2 + frame_len + 1]) & 0xFF
if checksum != 0: if checksum != 0:
raise RuntimeError('Response checksum did not match expected value: ', checksum) raise RuntimeError(
"Response checksum did not match expected value: ", checksum
)
# Return frame data. # Return frame data.
return response[offset+2:offset+2+frame_len] return response[offset + 2 : offset + 2 + frame_len]
def call_function(self, command, response_length=0, params=[], timeout=1): # pylint: disable=dangerous-default-value def call_function(
self, command, response_length=0, params=[], timeout=1
): # pylint: disable=dangerous-default-value
"""Send specified command to the PN532 and expect up to response_length """Send specified command to the PN532 and expect up to response_length
bytes back in a response. Note that less than the expected bytes might bytes back in a response. Note that less than the expected bytes might
be returned! Params can optionally specify an array of bytes to send as be returned! Params can optionally specify an array of bytes to send as
@ -291,11 +296,11 @@ class PN532:
response is available within the timeout. response is available within the timeout.
""" """
# Build frame data with command and parameters. # Build frame data with command and parameters.
data = bytearray(2+len(params)) data = bytearray(2 + len(params))
data[0] = _HOSTTOPN532 data[0] = _HOSTTOPN532
data[1] = command & 0xFF data[1] = command & 0xFF
for i, val in enumerate(params): for i, val in enumerate(params):
data[2+i] = val data[2 + i] = val
# Send frame and wait for response. # Send frame and wait for response.
try: try:
self._write_frame(data) self._write_frame(data)
@ -306,14 +311,14 @@ class PN532:
return None return None
# Verify ACK response and wait to be ready for function response. # Verify ACK response and wait to be ready for function response.
if not _ACK == self._read_data(len(_ACK)): if not _ACK == self._read_data(len(_ACK)):
raise RuntimeError('Did not receive expected ACK from PN532!') raise RuntimeError("Did not receive expected ACK from PN532!")
if not self._wait_ready(timeout): if not self._wait_ready(timeout):
return None return None
# Read response bytes. # Read response bytes.
response = self._read_frame(response_length+2) response = self._read_frame(response_length + 2)
# Check that response is for the called function. # Check that response is for the called function.
if not (response[0] == _PN532TOHOST and response[1] == (command+1)): if not (response[0] == _PN532TOHOST and response[1] == (command + 1)):
raise RuntimeError('Received unexpected command response!') raise RuntimeError("Received unexpected command response!")
# Return response data. # Return response data.
return response[2:] return response[2:]
@ -323,10 +328,10 @@ class PN532:
""" """
response = self.call_function(_COMMAND_GETFIRMWAREVERSION, 4, timeout=0.5) response = self.call_function(_COMMAND_GETFIRMWAREVERSION, 4, timeout=0.5)
if response is None: if response is None:
raise RuntimeError('Failed to detect the PN532') raise RuntimeError("Failed to detect the PN532")
return tuple(response) return tuple(response)
def SAM_configuration(self): # pylint: disable=invalid-name def SAM_configuration(self): # pylint: disable=invalid-name
"""Configure the PN532 to read MiFare cards.""" """Configure the PN532 to read MiFare cards."""
# Send SAM configuration command with configuration for: # Send SAM configuration command with configuration for:
# - 0x01, normal mode # - 0x01, normal mode
@ -343,24 +348,28 @@ class PN532:
""" """
# Send passive read command for 1 card. Expect at most a 7 byte UUID. # Send passive read command for 1 card. Expect at most a 7 byte UUID.
try: try:
response = self.call_function(_COMMAND_INLISTPASSIVETARGET, response = self.call_function(
params=[0x01, card_baud], _COMMAND_INLISTPASSIVETARGET,
response_length=19, params=[0x01, card_baud],
timeout=timeout) response_length=19,
timeout=timeout,
)
except BusyError: except BusyError:
return None # no card found! return None # no card found!
# If no response is available return None to indicate no card is present. # If no response is available return None to indicate no card is present.
if response is None: if response is None:
return None return None
# Check only 1 card with up to a 7 byte UID is present. # Check only 1 card with up to a 7 byte UID is present.
if response[0] != 0x01: if response[0] != 0x01:
raise RuntimeError('More than one card detected!') raise RuntimeError("More than one card detected!")
if response[5] > 7: if response[5] > 7:
raise RuntimeError('Found card with unexpectedly long UID!') raise RuntimeError("Found card with unexpectedly long UID!")
# Return UID of card. # Return UID of card.
return response[6:6+response[5]] return response[6 : 6 + response[5]]
def mifare_classic_authenticate_block(self, uid, block_number, key_number, key): # pylint: disable=invalid-name def mifare_classic_authenticate_block(
self, uid, block_number, key_number, key
): # pylint: disable=invalid-name
"""Authenticate specified block number for a MiFare classic card. Uid """Authenticate specified block number for a MiFare classic card. Uid
should be a byte array with the UID of the card, block number should be should be a byte array with the UID of the card, block number should be
the block to authenticate, key number should be the key type (like the block to authenticate, key number should be the key type (like
@ -371,16 +380,16 @@ class PN532:
# Build parameters for InDataExchange command to authenticate MiFare card. # Build parameters for InDataExchange command to authenticate MiFare card.
uidlen = len(uid) uidlen = len(uid)
keylen = len(key) keylen = len(key)
params = bytearray(3+uidlen+keylen) params = bytearray(3 + uidlen + keylen)
params[0] = 0x01 # Max card numbers params[0] = 0x01 # Max card numbers
params[1] = key_number & 0xFF params[1] = key_number & 0xFF
params[2] = block_number & 0xFF params[2] = block_number & 0xFF
params[3:3+keylen] = key params[3 : 3 + keylen] = key
params[3+keylen:] = uid params[3 + keylen :] = uid
# Send InDataExchange request and verify response is 0x00. # Send InDataExchange request and verify response is 0x00.
response = self.call_function(_COMMAND_INDATAEXCHANGE, response = self.call_function(
params=params, _COMMAND_INDATAEXCHANGE, params=params, response_length=1
response_length=1) )
return response[0] == 0x00 return response[0] == 0x00
def mifare_classic_read_block(self, block_number): def mifare_classic_read_block(self, block_number):
@ -390,9 +399,11 @@ class PN532:
not read then None will be returned. not read then None will be returned.
""" """
# Send InDataExchange request to read block of MiFare data. # Send InDataExchange request to read block of MiFare data.
response = self.call_function(_COMMAND_INDATAEXCHANGE, response = self.call_function(
params=[0x01, MIFARE_CMD_READ, block_number & 0xFF], _COMMAND_INDATAEXCHANGE,
response_length=17) params=[0x01, MIFARE_CMD_READ, block_number & 0xFF],
response_length=17,
)
# Check first response is 0x00 to show success. # Check first response is 0x00 to show success.
if response[0] != 0x00: if response[0] != 0x00:
return None return None
@ -405,7 +416,9 @@ class PN532:
write. If the data is successfully written then True is returned, write. If the data is successfully written then True is returned,
otherwise False is returned. otherwise False is returned.
""" """
assert data is not None and len(data) == 16, 'Data must be an array of 16 bytes!' assert (
data is not None and len(data) == 16
), "Data must be an array of 16 bytes!"
# Build parameters for InDataExchange command to do MiFare classic write. # Build parameters for InDataExchange command to do MiFare classic write.
params = bytearray(19) params = bytearray(19)
params[0] = 0x01 # Max card numbers params[0] = 0x01 # Max card numbers
@ -413,9 +426,9 @@ class PN532:
params[2] = block_number & 0xFF params[2] = block_number & 0xFF
params[3:] = data params[3:] = data
# Send InDataExchange request. # Send InDataExchange request.
response = self.call_function(_COMMAND_INDATAEXCHANGE, response = self.call_function(
params=params, _COMMAND_INDATAEXCHANGE, params=params, response_length=1
response_length=1) )
return response[0] == 0x0 return response[0] == 0x0
def ntag2xx_write_block(self, block_number, data): def ntag2xx_write_block(self, block_number, data):
@ -424,17 +437,17 @@ class PN532:
write. If the data is successfully written then True is returned, write. If the data is successfully written then True is returned,
otherwise False is returned. otherwise False is returned.
""" """
assert data is not None and len(data) == 4, 'Data must be an array of 4 bytes!' assert data is not None and len(data) == 4, "Data must be an array of 4 bytes!"
# Build parameters for InDataExchange command to do NTAG203 classic write. # Build parameters for InDataExchange command to do NTAG203 classic write.
params = bytearray(3+len(data)) params = bytearray(3 + len(data))
params[0] = 0x01 # Max card numbers params[0] = 0x01 # Max card numbers
params[1] = MIFARE_ULTRALIGHT_CMD_WRITE params[1] = MIFARE_ULTRALIGHT_CMD_WRITE
params[2] = block_number & 0xFF params[2] = block_number & 0xFF
params[3:] = data params[3:] = data
# Send InDataExchange request. # Send InDataExchange request.
response = self.call_function(_COMMAND_INDATAEXCHANGE, response = self.call_function(
params=params, _COMMAND_INDATAEXCHANGE, params=params, response_length=1
response_length=1) )
return response[0] == 0x00 return response[0] == 0x00
def ntag2xx_read_block(self, block_number): def ntag2xx_read_block(self, block_number):
@ -443,4 +456,6 @@ class PN532:
data starting at the specified block will be returned. If the block is data starting at the specified block will be returned. If the block is
not read then None will be returned. not read then None will be returned.
""" """
return self.mifare_classic_read_block(block_number)[0:4] # only 4 bytes per page return self.mifare_classic_read_block(block_number)[
0:4
] # only 4 bytes per page

View file

@ -44,10 +44,12 @@ from micropython import const
from adafruit_pn532.adafruit_pn532 import PN532, BusyError, _reset from adafruit_pn532.adafruit_pn532 import PN532, BusyError, _reset
# pylint: disable=bad-whitespace # pylint: disable=bad-whitespace
_I2C_ADDRESS = const(0x24) _I2C_ADDRESS = const(0x24)
class PN532_I2C(PN532): class PN532_I2C(PN532):
"""Driver for the PN532 connected over I2C.""" """Driver for the PN532 connected over I2C."""
def __init__(self, i2c, *, irq=None, reset=None, req=None, debug=False): def __init__(self, i2c, *, irq=None, reset=None, req=None, debug=False):
"""Create an instance of the PN532 class using I2C. Note that PN532 """Create an instance of the PN532 class using I2C. Note that PN532
uses clock stretching. Optional IRQ pin (not used), uses clock stretching. Optional IRQ pin (not used),
@ -61,7 +63,7 @@ class PN532_I2C(PN532):
self._i2c = i2c_device.I2CDevice(i2c, _I2C_ADDRESS) self._i2c = i2c_device.I2CDevice(i2c, _I2C_ADDRESS)
super().__init__(debug=debug, reset=reset) super().__init__(debug=debug, reset=reset)
def _wakeup(self): # pylint: disable=no-self-use def _wakeup(self): # pylint: disable=no-self-use
"""Send any special commands/data to wake up PN532""" """Send any special commands/data to wake up PN532"""
if self._req: if self._req:
self._req.direction = Direction.OUTPUT self._req.direction = Direction.OUTPUT
@ -83,27 +85,26 @@ class PN532_I2C(PN532):
except OSError: except OSError:
self._wakeup() self._wakeup()
continue continue
if status == b'\x01': if status == b"\x01":
return True # No longer busy return True # No longer busy
else: time.sleep(0.05) # lets ask again soon!
time.sleep(0.05) # lets ask again soon!
# Timed out! # Timed out!
return False return False
def _read_data(self, count): def _read_data(self, count):
"""Read a specified count of bytes from the PN532.""" """Read a specified count of bytes from the PN532."""
# Build a read request frame. # Build a read request frame.
frame = bytearray(count+1) frame = bytearray(count + 1)
with self._i2c as i2c: with self._i2c as i2c:
i2c.readinto(frame, end=1) # read status byte! i2c.readinto(frame, end=1) # read status byte!
if frame[0] != 0x01: # not ready if frame[0] != 0x01: # not ready
raise BusyError raise BusyError
i2c.readinto(frame) # ok get the data, plus statusbyte i2c.readinto(frame) # ok get the data, plus statusbyte
if self.debug: if self.debug:
print("Reading: ", [hex(i) for i in frame[1:]]) print("Reading: ", [hex(i) for i in frame[1:]])
else: else:
time.sleep(0.1) time.sleep(0.1)
return frame[1:] # don't return the status byte return frame[1:] # don't return the status byte
def _write_data(self, framebytes): def _write_data(self, framebytes):
"""Write a specified count of bytes to the PN532""" """Write a specified count of bytes to the PN532"""

View file

@ -43,10 +43,11 @@ from micropython import const
from adafruit_pn532.adafruit_pn532 import PN532 from adafruit_pn532.adafruit_pn532 import PN532
# pylint: disable=bad-whitespace # pylint: disable=bad-whitespace
_SPI_STATREAD = const(0x02) _SPI_STATREAD = const(0x02)
_SPI_DATAWRITE = const(0x01) _SPI_DATAWRITE = const(0x01)
_SPI_DATAREAD = const(0x03) _SPI_DATAREAD = const(0x03)
_SPI_READY = const(0x01) _SPI_READY = const(0x01)
def reverse_bit(num): def reverse_bit(num):
"""Turn an LSB byte to an MSB byte, and vice versa. Used for SPI as """Turn an LSB byte to an MSB byte, and vice versa. Used for SPI as
@ -54,14 +55,16 @@ def reverse_bit(num):
result = 0 result = 0
for _ in range(8): for _ in range(8):
result <<= 1 result <<= 1
result += (num & 1) result += num & 1
num >>= 1 num >>= 1
return result return result
class PN532_SPI(PN532): class PN532_SPI(PN532):
"""Driver for the PN532 connected over SPI. Pass in a hardware or bitbang """Driver for the PN532 connected over SPI. Pass in a hardware or bitbang
SPI device & chip select digitalInOut pin. Optional IRQ pin (not used), SPI device & chip select digitalInOut pin. Optional IRQ pin (not used),
reset pin and debugging output.""" reset pin and debugging output."""
def __init__(self, spi, cs_pin, *, irq=None, reset=None, debug=False): def __init__(self, spi, cs_pin, *, irq=None, reset=None, debug=False):
"""Create an instance of the PN532 class using SPI""" """Create an instance of the PN532 class using SPI"""
self.debug = debug self.debug = debug
@ -73,7 +76,7 @@ class PN532_SPI(PN532):
"""Send any special commands/data to wake up PN532""" """Send any special commands/data to wake up PN532"""
with self._spi as spi: with self._spi as spi:
time.sleep(1) time.sleep(1)
spi.write(bytearray([0x00])) #pylint: disable=no-member spi.write(bytearray([0x00])) # pylint: disable=no-member
time.sleep(1) time.sleep(1)
def _wait_ready(self, timeout=1): def _wait_ready(self, timeout=1):
@ -83,27 +86,28 @@ class PN532_SPI(PN532):
timestamp = time.monotonic() timestamp = time.monotonic()
with self._spi as spi: with self._spi as spi:
while (time.monotonic() - timestamp) < timeout: while (time.monotonic() - timestamp) < timeout:
time.sleep(0.02) # required time.sleep(0.02) # required
spi.write_readinto(status_cmd, status_response) #pylint: disable=no-member spi.write_readinto(
status_cmd, status_response
) # pylint: disable=no-member
if reverse_bit(status_response[1]) == 0x01: # LSB data is read in MSB if reverse_bit(status_response[1]) == 0x01: # LSB data is read in MSB
return True # Not busy anymore! return True # Not busy anymore!
else: time.sleep(0.01) # pause a bit till we ask again
time.sleep(0.01) # pause a bit till we ask again
# We timed out! # We timed out!
return False return False
def _read_data(self, count): def _read_data(self, count):
"""Read a specified count of bytes from the PN532.""" """Read a specified count of bytes from the PN532."""
# Build a read request frame. # Build a read request frame.
frame = bytearray(count+1) frame = bytearray(count + 1)
# Add the SPI data read signal byte, but LSB'ify it # Add the SPI data read signal byte, but LSB'ify it
frame[0] = reverse_bit(_SPI_DATAREAD) frame[0] = reverse_bit(_SPI_DATAREAD)
with self._spi as spi: with self._spi as spi:
time.sleep(0.02) # required time.sleep(0.02) # required
spi.write_readinto(frame, frame) #pylint: disable=no-member spi.write_readinto(frame, frame) # pylint: disable=no-member
for i, val in enumerate(frame): for i, val in enumerate(frame):
frame[i] = reverse_bit(val) # turn LSB data to MSB frame[i] = reverse_bit(val) # turn LSB data to MSB
if self.debug: if self.debug:
print("Reading: ", [hex(i) for i in frame[1:]]) print("Reading: ", [hex(i) for i in frame[1:]])
return frame[1:] return frame[1:]
@ -116,5 +120,5 @@ class PN532_SPI(PN532):
if self.debug: if self.debug:
print("Writing: ", [hex(i) for i in rev_frame]) print("Writing: ", [hex(i) for i in rev_frame])
with self._spi as spi: with self._spi as spi:
time.sleep(0.02) # required time.sleep(0.02) # required
spi.write(bytes(rev_frame)) #pylint: disable=no-member spi.write(bytes(rev_frame)) # pylint: disable=no-member

View file

@ -41,8 +41,10 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
import time import time
from adafruit_pn532.adafruit_pn532 import PN532, BusyError from adafruit_pn532.adafruit_pn532 import PN532, BusyError
class PN532_UART(PN532): class PN532_UART(PN532):
"""Driver for the PN532 connected over Serial UART""" """Driver for the PN532 connected over Serial UART"""
def __init__(self, uart, *, irq=None, reset=None, debug=False): def __init__(self, uart, *, irq=None, reset=None, debug=False):
"""Create an instance of the PN532 class using Serial connection. """Create an instance of the PN532 class using Serial connection.
Optional IRQ pin (not used), reset pin and debugging output. Optional IRQ pin (not used), reset pin and debugging output.
@ -54,7 +56,7 @@ class PN532_UART(PN532):
def _wakeup(self): def _wakeup(self):
"""Send any special commands/data to wake up PN532""" """Send any special commands/data to wake up PN532"""
#self._write_frame([_HOSTTOPN532, _COMMAND_SAMCONFIGURATION, 0x01]) # self._write_frame([_HOSTTOPN532, _COMMAND_SAMCONFIGURATION, 0x01])
self.SAM_configuration() self.SAM_configuration()
def _wait_ready(self, timeout=1): def _wait_ready(self, timeout=1):
@ -75,7 +77,11 @@ class PN532_UART(PN532):
def _write_data(self, framebytes): def _write_data(self, framebytes):
"""Write a specified count of bytes to the PN532""" """Write a specified count of bytes to the PN532"""
while self._uart.read(1): # this would be a lot nicer if we could query the # of bytes while self._uart.read(
1
): # this would be a lot nicer if we could query the # of bytes
pass pass
self._uart.write('\x55\x55\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') # wake up! self._uart.write(
"\x55\x55\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
) # wake up!
self._uart.write(framebytes) self._uart.write(framebytes)

View file

@ -2,7 +2,8 @@
import os import os
import sys import sys
sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath(".."))
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
@ -10,10 +11,10 @@ sys.path.insert(0, os.path.abspath('..'))
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
extensions = [ extensions = [
'sphinx.ext.autodoc', "sphinx.ext.autodoc",
'sphinx.ext.intersphinx', "sphinx.ext.intersphinx",
'sphinx.ext.napoleon', "sphinx.ext.napoleon",
'sphinx.ext.todo', "sphinx.ext.todo",
] ]
# TODO: Please Read! # TODO: Please Read!
@ -23,29 +24,36 @@ extensions = [
autodoc_mock_imports = ["digitalio", "busio", "adafruit_bus_device", "micropython"] autodoc_mock_imports = ["digitalio", "busio", "adafruit_bus_device", "micropython"]
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'BusDevice': ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)} intersphinx_mapping = {
"python": ("https://docs.python.org/3.4", None),
"BusDevice": (
"https://circuitpython.readthedocs.io/projects/busdevice/en/latest/",
None,
),
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
}
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ["_templates"]
source_suffix = '.rst' source_suffix = ".rst"
# The master toctree document. # The master toctree document.
master_doc = 'index' master_doc = "index"
# General information about the project. # General information about the project.
project = u'Adafruit PN532 Library' project = u"Adafruit PN532 Library"
copyright = u'2018 ladyada' copyright = u"2018 ladyada"
author = u'ladyada' author = u"ladyada"
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = u'1.0' version = u"1.0"
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = u'1.0' release = u"1.0"
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
@ -57,7 +65,7 @@ language = None
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path # This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.env', 'CODE_OF_CONDUCT.md'] exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".env", "CODE_OF_CONDUCT.md"]
# The reST default role (used for this markup: `text`) to use for all # The reST default role (used for this markup: `text`) to use for all
# documents. # documents.
@ -69,7 +77,7 @@ default_role = "any"
add_function_parentheses = True add_function_parentheses = True
# The name of the Pygments (syntax highlighting) style to use. # The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx' pygments_style = "sphinx"
# If true, `todo` and `todoList` produce output, else they produce nothing. # If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False todo_include_todos = False
@ -84,59 +92,62 @@ napoleon_numpy_docstring = False
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
# #
on_rtd = os.environ.get('READTHEDOCS', None) == 'True' on_rtd = os.environ.get("READTHEDOCS", None) == "True"
if not on_rtd: # only import and set the theme if we're building docs locally if not on_rtd: # only import and set the theme if we're building docs locally
try: try:
import sphinx_rtd_theme import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.'] html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
except: except:
html_theme = 'default' html_theme = "default"
html_theme_path = ['.'] html_theme_path = ["."]
else: else:
html_theme_path = ['.'] html_theme_path = ["."]
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static'] html_static_path = ["_static"]
# The name of an image file (relative to this directory) to use as a favicon of # The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large. # pixels large.
# #
html_favicon = '_static/favicon.ico' html_favicon = "_static/favicon.ico"
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = 'AdafruitPn532Librarydoc' htmlhelp_basename = "AdafruitPn532Librarydoc"
# -- Options for LaTeX output --------------------------------------------- # -- Options for LaTeX output ---------------------------------------------
latex_elements = { latex_elements = {
# The paper size ('letterpaper' or 'a4paper'). # The paper size ('letterpaper' or 'a4paper').
# #
# 'papersize': 'letterpaper', # 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
# The font size ('10pt', '11pt' or '12pt'). #
# # 'pointsize': '10pt',
# 'pointsize': '10pt', # Additional stuff for the LaTeX preamble.
#
# Additional stuff for the LaTeX preamble. # 'preamble': '',
# # Latex figure (float) alignment
# 'preamble': '', #
# 'figure_align': 'htbp',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
} }
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, # (source start file, target name, title,
# author, documentclass [howto, manual, or own class]). # author, documentclass [howto, manual, or own class]).
latex_documents = [ latex_documents = [
(master_doc, 'AdafruitPN532Library.tex', u'AdafruitPN532 Library Documentation', (
author, 'manual'), master_doc,
"AdafruitPN532Library.tex",
u"AdafruitPN532 Library Documentation",
author,
"manual",
),
] ]
# -- Options for manual page output --------------------------------------- # -- Options for manual page output ---------------------------------------
@ -144,8 +155,13 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
(master_doc, 'AdafruitPN532library', u'Adafruit PN532 Library Documentation', (
[author], 1) master_doc,
"AdafruitPN532library",
u"Adafruit PN532 Library Documentation",
[author],
1,
)
] ]
# -- Options for Texinfo output ------------------------------------------- # -- Options for Texinfo output -------------------------------------------
@ -154,7 +170,13 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
(master_doc, 'AdafruitPN532Library', u'Adafruit PN532 Library Documentation', (
author, 'AdafruitPN532Library', 'One line description of project.', master_doc,
'Miscellaneous'), "AdafruitPN532Library",
u"Adafruit PN532 Library Documentation",
author,
"AdafruitPN532Library",
"One line description of project.",
"Miscellaneous",
),
] ]

View file

@ -29,15 +29,17 @@ type RFID tag
import board import board
import busio import busio
# Additional import needed for I2C/SPI # Additional import needed for I2C/SPI
#from digitalio import DigitalInOut # from digitalio import DigitalInOut
# #
# NOTE: pick the import that matches the interface being used # NOTE: pick the import that matches the interface being used
# #
from adafruit_pn532.adafruit_pn532 import MIFARE_CMD_AUTH_B from adafruit_pn532.adafruit_pn532 import MIFARE_CMD_AUTH_B
from adafruit_pn532.i2c import PN532_I2C from adafruit_pn532.i2c import PN532_I2C
#from adafruit_pn532.spi import PN532_SPI
#from adafruit_pn532.uart import PN532_UART # from adafruit_pn532.spi import PN532_SPI
# from adafruit_pn532.uart import PN532_UART
# I2C connection: # I2C connection:
i2c = busio.I2C(board.SCL, board.SDA) i2c = busio.I2C(board.SCL, board.SDA)
@ -47,42 +49,42 @@ pn532 = PN532_I2C(i2c, debug=False)
# With I2C, we recommend connecting RSTPD_N (reset) to a digital pin for manual # With I2C, we recommend connecting RSTPD_N (reset) to a digital pin for manual
# harware reset # harware reset
#reset_pin = DigitalInOut(board.D6) # reset_pin = DigitalInOut(board.D6)
# On Raspberry Pi, you must also connect a pin to P32 "H_Request" for hardware # 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 # wakeup! this means we don't need to do the I2C clock-stretch thing
#req_pin = DigitalInOut(board.D12) # req_pin = DigitalInOut(board.D12)
#pn532 = PN532_I2C(i2c, debug=False, reset=reset_pin, req=req_pin) # pn532 = PN532_I2C(i2c, debug=False, reset=reset_pin, req=req_pin)
# SPI connection: # SPI connection:
#spi = busio.SPI(board.SCK, board.MOSI, board.MISO) # spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
#cs_pin = DigitalInOut(board.D5) # cs_pin = DigitalInOut(board.D5)
#pn532 = PN532_SPI(spi, cs_pin, debug=False) # pn532 = PN532_SPI(spi, cs_pin, debug=False)
# UART connection # UART connection
#uart = busio.UART(board.TX, board.RX, baudrate=115200, timeout=100) # uart = busio.UART(board.TX, board.RX, baudrate=115200, timeout=100)
#pn532 = PN532_UART(uart, debug=False) # pn532 = PN532_UART(uart, debug=False)
ic, ver, rev, support = pn532.get_firmware_version() ic, ver, rev, support = pn532.get_firmware_version()
print('Found PN532 with firmware version: {0}.{1}'.format(ver, rev)) print("Found PN532 with firmware version: {0}.{1}".format(ver, rev))
# Configure PN532 to communicate with MiFare cards # Configure PN532 to communicate with MiFare cards
pn532.SAM_configuration() pn532.SAM_configuration()
print('Waiting for RFID/NFC card to write to!') print("Waiting for RFID/NFC card to write to!")
key = b'\xFF\xFF\xFF\xFF\xFF\xFF' key = b"\xFF\xFF\xFF\xFF\xFF\xFF"
while True: while True:
# Check if a card is available to read # Check if a card is available to read
uid = pn532.read_passive_target(timeout=0.5) uid = pn532.read_passive_target(timeout=0.5)
print('.', end="") print(".", end="")
# Try again if no card is available. # Try again if no card is available.
if uid is not None: if uid is not None:
break break
print("") print("")
print('Found card with UID:', [hex(i) for i in uid]) print("Found card with UID:", [hex(i) for i in uid])
print("Authenticating block 4 ...") print("Authenticating block 4 ...")
authenticated = pn532.mifare_classic_authenticate_block(uid, 4, MIFARE_CMD_AUTH_B, key) authenticated = pn532.mifare_classic_authenticate_block(uid, 4, MIFARE_CMD_AUTH_B, key)
@ -91,10 +93,12 @@ if not authenticated:
# Set 16 bytes of block to 0xFEEDBEEF # Set 16 bytes of block to 0xFEEDBEEF
data = bytearray(16) data = bytearray(16)
data[0:16] = b'\xFE\xED\xBE\xEF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' data[0:16] = b"\xFE\xED\xBE\xEF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
# Write 16 byte block. # Write 16 byte block.
pn532.mifare_classic_write_block(4, data) pn532.mifare_classic_write_block(4, data)
# Read block #6 # Read block #6
print('Wrote to block 4, now trying to read that data:', print(
[hex(x) for x in pn532.mifare_classic_read_block(4)]) "Wrote to block 4, now trying to read that data:",
[hex(x) for x in pn532.mifare_classic_read_block(4)],
)

View file

@ -28,26 +28,28 @@ type RFID tag
import board import board
import busio import busio
from digitalio import DigitalInOut from digitalio import DigitalInOut
# #
# NOTE: pick the import that matches the interface being used # NOTE: pick the import that matches the interface being used
# #
#from adafruit_pn532.i2c import PN532_I2C # from adafruit_pn532.i2c import PN532_I2C
from adafruit_pn532.spi import PN532_SPI from adafruit_pn532.spi import PN532_SPI
#from adafruit_pn532.uart import PN532_UART
# from adafruit_pn532.uart import PN532_UART
# I2C connection: # I2C connection:
#i2c = busio.I2C(board.SCL, board.SDA) # i2c = busio.I2C(board.SCL, board.SDA)
# Non-hardware reset/request with I2C # Non-hardware reset/request with I2C
#pn532 = PN532_I2C(i2c, debug=False) # pn532 = PN532_I2C(i2c, debug=False)
# With I2C, we recommend connecting RSTPD_N (reset) to a digital pin for manual # With I2C, we recommend connecting RSTPD_N (reset) to a digital pin for manual
# harware reset # harware reset
#reset_pin = DigitalInOut(board.D6) # reset_pin = DigitalInOut(board.D6)
# On Raspberry Pi, you must also connect a pin to P32 "H_Request" for hardware # 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 # wakeup! this means we don't need to do the I2C clock-stretch thing
#req_pin = DigitalInOut(board.D12) # req_pin = DigitalInOut(board.D12)
#pn532 = PN532_I2C(i2c, debug=False, reset=reset_pin, req=req_pin) # pn532 = PN532_I2C(i2c, debug=False, reset=reset_pin, req=req_pin)
# SPI connection: # SPI connection:
spi = busio.SPI(board.SCK, board.MOSI, board.MISO) spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
@ -55,32 +57,34 @@ cs_pin = DigitalInOut(board.D5)
pn532 = PN532_SPI(spi, cs_pin, debug=False) pn532 = PN532_SPI(spi, cs_pin, debug=False)
# UART connection # UART connection
#uart = busio.UART(board.TX, board.RX, baudrate=115200, timeout=100) # uart = busio.UART(board.TX, board.RX, baudrate=115200, timeout=100)
#pn532 = PN532_UART(uart, debug=False) # pn532 = PN532_UART(uart, debug=False)
ic, ver, rev, support = pn532.get_firmware_version() ic, ver, rev, support = pn532.get_firmware_version()
print('Found PN532 with firmware version: {0}.{1}'.format(ver, rev)) print("Found PN532 with firmware version: {0}.{1}".format(ver, rev))
# Configure PN532 to communicate with MiFare cards # Configure PN532 to communicate with MiFare cards
pn532.SAM_configuration() pn532.SAM_configuration()
print('Waiting for RFID/NFC card to write to!') print("Waiting for RFID/NFC card to write to!")
while True: while True:
# Check if a card is available to read # Check if a card is available to read
uid = pn532.read_passive_target(timeout=0.5) uid = pn532.read_passive_target(timeout=0.5)
print('.', end="") print(".", end="")
# Try again if no card is available. # Try again if no card is available.
if uid is not None: if uid is not None:
break break
print("") print("")
print('Found card with UID:', [hex(i) for i in uid]) print("Found card with UID:", [hex(i) for i in uid])
# Set 4 bytes of block to 0xFEEDBEEF # Set 4 bytes of block to 0xFEEDBEEF
data = bytearray(4) data = bytearray(4)
data[0:4] = b'\xFE\xED\xBE\xEF' data[0:4] = b"\xFE\xED\xBE\xEF"
# Write 4 byte block. # Write 4 byte block.
pn532.ntag2xx_write_block(6, data) pn532.ntag2xx_write_block(6, data)
# Read block #6 # Read block #6
print('Wrote to block 6, now trying to read that data:', print(
[hex(x) for x in pn532.ntag2xx_read_block(6)]) "Wrote to block 6, now trying to read that data:",
[hex(x) for x in pn532.ntag2xx_read_block(6)],
)

View file

@ -8,18 +8,20 @@ After initialization, try waving various 13.56MHz RFID cards over it!
import board import board
import busio import busio
from digitalio import DigitalInOut from digitalio import DigitalInOut
# #
# NOTE: pick the import that matches the interface being used # NOTE: pick the import that matches the interface being used
# #
from adafruit_pn532.i2c import PN532_I2C from adafruit_pn532.i2c import PN532_I2C
#from adafruit_pn532.spi import PN532_SPI
#from adafruit_pn532.uart import PN532_UART # from adafruit_pn532.spi import PN532_SPI
# from adafruit_pn532.uart import PN532_UART
# I2C connection: # I2C connection:
i2c = busio.I2C(board.SCL, board.SDA) i2c = busio.I2C(board.SCL, board.SDA)
# Non-hardware # Non-hardware
#pn532 = PN532_I2C(i2c, debug=False) # pn532 = PN532_I2C(i2c, debug=False)
# With I2C, we recommend connecting RSTPD_N (reset) to a digital pin for manual # With I2C, we recommend connecting RSTPD_N (reset) to a digital pin for manual
# harware reset # harware reset
@ -30,26 +32,26 @@ req_pin = DigitalInOut(board.D12)
pn532 = PN532_I2C(i2c, debug=False, reset=reset_pin, req=req_pin) pn532 = PN532_I2C(i2c, debug=False, reset=reset_pin, req=req_pin)
# SPI connection: # SPI connection:
#spi = busio.SPI(board.SCK, board.MOSI, board.MISO) # spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
#cs_pin = DigitalInOut(board.D5) # cs_pin = DigitalInOut(board.D5)
#pn532 = PN532_SPI(spi, cs_pin, debug=False) # pn532 = PN532_SPI(spi, cs_pin, debug=False)
# UART connection # UART connection
#uart = busio.UART(board.TX, board.RX, baudrate=115200, timeout=100) # uart = busio.UART(board.TX, board.RX, baudrate=115200, timeout=100)
#pn532 = PN532_UART(uart, debug=False) # pn532 = PN532_UART(uart, debug=False)
ic, ver, rev, support = pn532.get_firmware_version() ic, ver, rev, support = pn532.get_firmware_version()
print('Found PN532 with firmware version: {0}.{1}'.format(ver, rev)) print("Found PN532 with firmware version: {0}.{1}".format(ver, rev))
# Configure PN532 to communicate with MiFare cards # Configure PN532 to communicate with MiFare cards
pn532.SAM_configuration() pn532.SAM_configuration()
print('Waiting for RFID/NFC card...') print("Waiting for RFID/NFC card...")
while True: while True:
# Check if a card is available to read # Check if a card is available to read
uid = pn532.read_passive_target(timeout=0.5) uid = pn532.read_passive_target(timeout=0.5)
print('.', end="") print(".", end="")
# Try again if no card is available. # Try again if no card is available.
if uid is None: if uid is None:
continue continue
print('Found card with UID:', [hex(i) for i in uid]) print("Found card with UID:", [hex(i) for i in uid])

View file

@ -7,6 +7,7 @@ https://github.com/pypa/sampleproject
# Always prefer setuptools over distutils # Always prefer setuptools over distutils
from setuptools import setup, find_packages from setuptools import setup, find_packages
# To use a consistent encoding # To use a consistent encoding
from codecs import open from codecs import open
from os import path from os import path
@ -14,47 +15,42 @@ from os import path
here = path.abspath(path.dirname(__file__)) here = path.abspath(path.dirname(__file__))
# Get the long description from the README file # Get the long description from the README file
with open(path.join(here, 'README.rst'), encoding='utf-8') as f: with open(path.join(here, "README.rst"), encoding="utf-8") as f:
long_description = f.read() long_description = f.read()
setup( setup(
name='adafruit-circuitpython-pn532', name="adafruit-circuitpython-pn532",
use_scm_version=True, use_scm_version=True,
setup_requires=['setuptools_scm'], setup_requires=["setuptools_scm"],
description="CircuitPython library for controlling PN532 RFID/NFC reader-writer.",
description='CircuitPython library for controlling PN532 RFID/NFC reader-writer.',
long_description=long_description, long_description=long_description,
long_description_content_type='text/x-rst', long_description_content_type="text/x-rst",
# The project's main homepage. # The project's main homepage.
url='https://github.com/adafruit/Adafruit_CircuitPython_PN532', url="https://github.com/adafruit/Adafruit_CircuitPython_PN532",
# Author details # Author details
author='Adafruit Industries', author="Adafruit Industries",
author_email='circuitpython@adafruit.com', author_email="circuitpython@adafruit.com",
install_requires=[
install_requires=['Adafruit-Blinka', 'adafruit-circuitpython-busdevice', 'pyserial'], "Adafruit-Blinka",
"adafruit-circuitpython-busdevice",
"pyserial",
],
# Choose your license # Choose your license
license='MIT', license="MIT",
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', "Development Status :: 3 - Alpha",
'Intended Audience :: Developers', "Intended Audience :: Developers",
'Topic :: Software Development :: Libraries', "Topic :: Software Development :: Libraries",
'Topic :: System :: Hardware', "Topic :: System :: Hardware",
'License :: OSI Approved :: MIT License', "License :: OSI Approved :: MIT License",
'Programming Language :: Python :: 3', "Programming Language :: Python :: 3",
'Programming Language :: Python :: 3.4', "Programming Language :: Python :: 3.4",
'Programming Language :: Python :: 3.5', "Programming Language :: Python :: 3.5",
], ],
# What does your project relate to? # What does your project relate to?
keywords='adafruit pn532 rfid nfc hardware micropython circuitpython', keywords="adafruit pn532 rfid nfc hardware micropython circuitpython",
# You can just specify the packages manually here if your project is # You can just specify the packages manually here if your project is
# simple. Or you can use find_packages(). # simple. Or you can use find_packages().
packages=['adafruit_pn532'], packages=["adafruit_pn532"],
) )