Skip to content

Commit

Permalink
Add PN532 representation and in auto poll method
Browse files Browse the repository at this point in the history
  • Loading branch information
robertdijk committed Apr 2, 2023
1 parent e9807ad commit d6b1213
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 0 deletions.
69 changes: 69 additions & 0 deletions src/py_acr122u/nfc.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def __init__(self):
"""create an ACR122U object
doc available here: http://downloads.acs.com.hk/drivers/en/API-ACR122U-2.02.pdf"""
self.reader_name, self.connection = self.instantiate_reader()
self.pn532 = self._PN532(self)

@staticmethod
def instantiate_reader():
Expand Down Expand Up @@ -269,3 +270,71 @@ def print_data(data):
def print_sw1_sw2(sw1, sw2):
print(f"sw1 : {sw1} {hex(sw1)}\n"
f"sw2 : {sw2} {hex(sw2)}")

class _PN532:
"""the PN532 chip inside the ACR122U
Methods in the class can be used to communicate with the chip
see docs at: https://www.nxp.com/docs/en/user-guide/141520.pdf
"""

def __init__(self, acr122u):
"""create a PN532 object
Attributes:
acr122u: the reader used to communicate with the chip (i.e. the reader the chip is in)
"""
self.acr122u: Reader = acr122u

def transmit(self, payload: List[int]):
"""send a payload to the chip
Attributes:
payload: the payload to send
Returns:
the response from the chip
"""
return self.acr122u.direct_transmit(payload)

def command(self, mode, arguments=None):
"""send a command to the chip
Attributes:
mode: key value of option.pn532_options
arguments: replace `-1` in the payload by arguments
Returns:
the response from the chip
"""
payload = option.pn532_options.get(mode)

if not payload:
raise error.OptionOutOfRange(
"Option do not exist\nHint: try to call help(nfc.Reader().command) to see all options")

payload = utils.replace_arguments(payload, arguments)
result = self.transmit(payload)

return result

def in_auto_poll(self, poll_nr: int, period: int, type1: int, *types):
"""
this command is used to poll card(s) / target(s) of specified Type present in the RF field.
docs: https://www.nxp.com/docs/en/user-guide/141520.pdf section 7.3.13
Attributes:
poll_nr - specifies the number of polling (one polling is a polling for each Type j)
0x01: 0xFE:1 up to 254 polling
0xFF: Endless polling
period - (0x01 – 0x0F) indicates the polling period in units of 150 ms
type1 - indicates the mandatory target type to be polled at the 1st time
types - indicate the optional target types to be polled at the 2nd up to the Nth time (N ≤ 15).
Returns:
the response from the chip
"""
arguments = [poll_nr, period, type1] + list(types)

data = self.command("in_auto_poll", arguments)
return data
3 changes: 3 additions & 0 deletions src/py_acr122u/option.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@
"F0 11": "FeliCa 212K",
"F0 12": "FeliCa 424K"
}
pn532_options = {
"in_auto_poll": [0xD4, 0x60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
}
45 changes: 45 additions & 0 deletions tests/in_auto_poll_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import pytest

from py_acr122u.nfc import Reader


@pytest.fixture
def reader(mocker) -> Reader:
mocker.patch("py_acr122u.nfc.Reader.instantiate_reader", return_value=(None, None))
r = Reader()
return r

@pytest.mark.parametrize("transmitted, poll_nr, period, type1", [
([0xD4, 0x60, 0xFF, 0x01, 0x10], 0xff, 0x01, 0x10),
([0xD4, 0x60, 0x01, 0x02, 0x40], 0x01, 0x02, 0x40),
([0xD4, 0x60, 0xFE, 0x0F, 0x50], 0xFE, 0x0F, 0x50),
])
def test_in_aut_poll_commands(transmitted, poll_nr, period, type1, reader, mocker):
mock_transmit = mocker.patch("py_acr122u.nfc.Reader._PN532.transmit")

reader.pn532.in_auto_poll(poll_nr, period, type1,)

mock_transmit.assert_called_with(transmitted)

@pytest.mark.parametrize("transmitted, poll_nr, period, type1, type2", [
([0xD4, 0x60, 0xFF, 0x01, 0x10, 0x20], 0xff, 0x01, 0x10, 0x20),
([0xD4, 0x60, 0x01, 0x02, 0x40, 0x20], 0x01, 0x02, 0x40, 0x20),
([0xD4, 0x60, 0xFE, 0x0F, 0x50, 0x20], 0xFE, 0x0F, 0x50, 0x20),
])
def test_in_aut_poll_commands_more_types(transmitted, poll_nr, period, type1, type2, reader, mocker):
mock_transmit = mocker.patch("py_acr122u.nfc.Reader._PN532.transmit")

reader.pn532.in_auto_poll(poll_nr, period, type1, type2)

mock_transmit.assert_called_with(transmitted)
@pytest.mark.parametrize("transmitted, poll_nr, period, type1, type2, type3", [
([0xD4, 0x60, 0xFF, 0x01, 0x10, 0x20, 0x15], 0xff, 0x01, 0x10, 0x20, 0x15),
([0xD4, 0x60, 0x01, 0x02, 0x40, 0x20, 0x15], 0x01, 0x02, 0x40, 0x20, 0x15),
([0xD4, 0x60, 0xFE, 0x0F, 0x50, 0x20, 0x15], 0xFE, 0x0F, 0x50, 0x20, 0x15),
])
def test_in_aut_poll_commands_even_more_types(transmitted, poll_nr, period, type1, type2, type3, reader, mocker):
mock_transmit = mocker.patch("py_acr122u.nfc.Reader._PN532.transmit")

reader.pn532.in_auto_poll(poll_nr, period, type1, type2, type3)

mock_transmit.assert_called_with(transmitted)

0 comments on commit d6b1213

Please sign in to comment.