Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
237 changes: 199 additions & 38 deletions mfrc522/MFRC522.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import time
import logging


class MFRC522:
MAX_LEN = 16

Expand Down Expand Up @@ -125,31 +126,35 @@ class MFRC522:

serNum = []

def __init__(self, bus=0, device=0, spd=1000000, pin_mode=10, pin_rst=-1, debugLevel='WARNING'):
def __init__(self, bus=0, device=0, spd=1000000, pin_mode=GPIO.BOARD, pin_rst=-1, log_verbose=False):
self.logger = logging.getLogger(self.__class__.__name__)
# Don't change the logger's level based on log_verbose
# This ensures that ERROR messages are always logged at ERROR level
# The log_verbose flag will be used by individual log statements
self.log_verbose = log_verbose

self.logger.debug('Setting up SPI')
self.spi = spidev.SpiDev()
self.spi.open(bus, device)
self.spi.max_speed_hz = spd

self.logger = logging.getLogger('mfrc522Logger')
self.logger.addHandler(logging.StreamHandler())
level = logging.getLevelName(debugLevel)
self.logger.setLevel(level)

gpioMode = GPIO.getmode()

if gpioMode is None:
GPIO.setmode(pin_mode)
else:
pin_mode = gpioMode

if pin_rst == -1:
if pin_mode == 11:
pin_rst = 15
else:
pin_rst = 22


self.logger.debug('Setting up RST')
GPIO.setup(pin_rst, GPIO.OUT)
GPIO.output(pin_rst, 1)

self.logger.debug('Setting up MFRC522')
self.MFRC522_Init()

def MFRC522_Reset(self):
Expand Down Expand Up @@ -191,6 +196,13 @@ def MFRC522_ToCard(self, command, sendData):
lastBits = None
n = 0

# Log command as hex value
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_ToCard_start',
'command': f'0x{command:02X}' # Log command as hex value
})

if command == self.PCD_AUTHENT:
irqEn = 0x12
waitIRq = 0x10
Expand Down Expand Up @@ -246,35 +258,64 @@ def MFRC522_ToCard(self, command, sendData):
else:
status = self.MI_ERR

# Log status and command as hex values
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_ToCard_complete',
'command': f'0x{command:02X}', # Log command as hex value
'status': f'0x{status:02X}', # Log status as hex value
'backLen': backLen
})

return (status, backData, backLen)

def MFRC522_Request(self, reqMode):
status = None
backBits = None
TagType = []

# Log reqMode as hex value
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Request_start',
'reqMode': f'0x{reqMode:02X}' # Log reqMode as hex value
})

self.Write_MFRC522(self.BitFramingReg, 0x07)

TagType.append(reqMode)
(status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, TagType)
(status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,
TagType)

if ((status != self.MI_OK) | (backBits != 0x10)):
status = self.MI_ERR

# Log status and reqMode as hex values
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Request_complete',
'reqMode': f'0x{reqMode:02X}', # Log reqMode as hex value
'status': f'0x{status:02X}' # Log status as hex value
})

return (status, backBits)

def MFRC522_Anticoll(self):
backData = []
serNumCheck = 0

serNum = []

# Log start of anticoll
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Anticoll_start',
'command': f'0x{self.PCD_TRANSCEIVE:02X}' # Log command as hex value
})

self.Write_MFRC522(self.BitFramingReg, 0x00)

serNum.append(self.PICC_ANTICOLL)
serNum.append(0x20)

(status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, serNum)
(status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,
serNum)

if (status == self.MI_OK):
i = 0
Expand All @@ -286,6 +327,13 @@ def MFRC522_Anticoll(self):
else:
status = self.MI_ERR

# Log status as hex value
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Anticoll_complete',
'status': f'0x{status:02X}' # Log status as hex value
})

return (status, backData)

def CalulateCRC(self, pIndata):
Expand All @@ -308,28 +356,55 @@ def CalulateCRC(self, pIndata):
return pOutData

def MFRC522_SelectTag(self, serNum):
backData = []
buf = []
buf.append(self.PICC_SElECTTAG)
buf.append(0x70)


# Log start of select tag
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_SelectTag_start',
'command': f'0x{self.PCD_TRANSCEIVE:02X}', # Log command as hex value
'select_tag': f'0x{self.PICC_SElECTTAG:02X}' # Log select tag as hex value
})

for i in range(5):
buf.append(serNum[i])

pOut = self.CalulateCRC(buf)
buf.append(pOut[0])
buf.append(pOut[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,
buf)

# Log status as hex value
if (status == self.MI_OK) and (backLen == 0x18):
self.logger.debug("Size: " + str(backData[0]))
return backData[0]
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_SelectTag_complete',
'status': f'0x{status:02X}', # Log status as hex value
'size': backData[0]
})
return status, backData[0]
else:
return 0
self.logger.debug({
'action': 'MFRC522_SelectTag_failed',
'status': f'0x{status:02X}' # Log status as hex value
})
return status, None

def MFRC522_Auth(self, authMode, BlockAddr, Sectorkey, serNum):
buff = []

# Log start of auth with authMode as hex value
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Auth_start',
'authMode': f'0x{authMode:02X}', # Log authMode as hex value
'blockAddr': BlockAddr,
'command': f'0x{self.PCD_AUTHENT:02X}' # Log command as hex value
})

# First byte should be the authMode (A or B)
buff.append(authMode)

Expand All @@ -345,13 +420,30 @@ def MFRC522_Auth(self, authMode, BlockAddr, Sectorkey, serNum):
buff.append(serNum[i])

# Now we start the authentication itself
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_AUTHENT, buff)
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_AUTHENT,
buff)

# Check if an error occurred
if not (status == self.MI_OK):
self.logger.error("AUTH ERROR!!")
self.logger.error({
'error': "AUTH ERROR!!",
'status': f'0x{status:02X}' # Log status as hex value
})

if not (self.Read_MFRC522(self.Status2Reg) & 0x08) != 0:
self.logger.error("AUTH ERROR(status2reg & 0x08) != 0")
status2reg = self.Read_MFRC522(self.Status2Reg)
self.logger.error({
'error': "AUTH ERROR(status2reg & 0x08) != 0",
'status': f'0x{status:02X}', # Log status as hex value
'status2reg': f'0x{status2reg:02X}' # Log status2reg as hex value
})

# Log completion with status as hex value
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Auth_complete',
'status': f'0x{status:02X}' # Log status as hex value
})

# Return the status
return status
Expand All @@ -366,12 +458,40 @@ def MFRC522_Read(self, blockAddr):
pOut = self.CalulateCRC(recvData)
recvData.append(pOut[0])
recvData.append(pOut[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, recvData)

# Log start of read operation
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Read_start',
'blockAddr': blockAddr,
'command': f'0x{self.PCD_TRANSCEIVE:02X}' # Log command as hex value
})

(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,
recvData)
if not (status == self.MI_OK):
self.logger.error("Error while reading!")

self.logger.error({
'error': "Error while reading!",
'status': f'0x{status:02X}', # Log status as hex value
'blockAddr': blockAddr
})

# Log completion with status as hex value
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Read_complete',
'status': f'0x{status:02X}', # Log status as hex value
'blockAddr': blockAddr,
'success': status == self.MI_OK
})

if len(backData) == 16:
self.logger.debug("Sector " + str(blockAddr) + " " + str(backData))
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Read_data',
'blockAddr': blockAddr,
'data': str(backData)
})
return backData
else:
return None
Expand All @@ -380,14 +500,39 @@ def MFRC522_Write(self, blockAddr, writeData):
buff = []
buff.append(self.PICC_WRITE)
buff.append(blockAddr)

# Log start of write operation
if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Write_start',
'blockAddr': blockAddr,
'command': f'0x{self.PCD_TRANSCEIVE:02X}', # Log command as hex value
'write_command': f'0x{self.PICC_WRITE:02X}' # Log write command as hex value
})

crc = self.CalulateCRC(buff)
buff.append(crc[0])
buff.append(crc[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buff)
if not (status == self.MI_OK) or not (backLen == 4) or not ((backData[0] & 0x0F) == 0x0A):
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,
buff)
if not (status == self.MI_OK) or not (backLen == 4) or not (
(backData[0] & 0x0F) == 0x0A):
status = self.MI_ERR

self.logger.debug("%s backdata &0x0F == 0x0A %s" % (backLen, backData[0] & 0x0F))
self.logger.error({
'action': 'MFRC522_Write_first_phase_failed',
'status': f'0x{status:02X}', # Log status as hex value
'backLen': backLen,
'backData': str(backData) if backData else "None"
})

if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Write_first_phase',
'backLen': backLen,
'backData_check': f'0x{backData[0] & 0x0F:02X}', # Log as hex value
'status': f'0x{status:02X}' # Log status as hex value
})

if status == self.MI_OK:
buf = []
for i in range(16):
Expand All @@ -396,12 +541,24 @@ def MFRC522_Write(self, blockAddr, writeData):
crc = self.CalulateCRC(buf)
buf.append(crc[0])
buf.append(crc[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)
if not (status == self.MI_OK) or not (backLen == 4) or not ((backData[0] & 0x0F) == 0x0A):
self.logger.error("Error while writing")
(status, backData, backLen) = self.MFRC522_ToCard(
self.PCD_TRANSCEIVE, buf)
if not (status == self.MI_OK) or not (backLen == 4) or not (
(backData[0] & 0x0F) == 0x0A):
self.logger.error({
'error': "Error while writing",
'status': f'0x{status:02X}', # Log status as hex value
'backLen': backLen,
'backData': str(backData) if backData else "None"
})
if status == self.MI_OK:
self.logger.debug("Data written")

if self.log_verbose:
self.logger.debug({
'action': 'MFRC522_Write_complete',
'status': f'0x{status:02X}', # Log status as hex value
'blockAddr': blockAddr,
'success': True
})

def MFRC522_DumpClassic1K(self, key, uid):
for i in range(64):
Expand All @@ -410,7 +567,11 @@ def MFRC522_DumpClassic1K(self, key, uid):
if status == self.MI_OK:
self.MFRC522_Read(i)
else:
self.logger.error("Authentication error")
self.logger.error({
'error': "Authentication error",
'status': f'0x{status:02X}', # Log status as hex value
'block': i
})

def MFRC522_Init(self):
self.MFRC522_Reset()
Expand Down
Loading