├── .gitignore ├── LICENSE ├── README.md ├── mfrc522 ├── MFRC522.py ├── SimpleMFRC522.py └── __init__.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled python modules. 2 | *.pyc 3 | 4 | # Setuptools distribution folder. 5 | /dist/ 6 | 7 | # Python egg metadata, regenerated from source files by setuptools. 8 | /*.egg-info 9 | 10 | # Build folder 11 | /build/ 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mfrc522 2 | 3 | A python library to read/write RFID tags via the budget MFRC522 RFID module. 4 | 5 | This code was published in relation to a [blog post](https://pimylifeup.com/raspberry-pi-rfid-rc522/) and you can find out more about how to hook up your MFRC reader to a Raspberry Pi there. 6 | 7 | ## Installation 8 | 9 | Until the package is on PyPi, clone this repository and run `python setup.py install` in the top level directory. 10 | 11 | ## Example Code 12 | 13 | The following code will read a tag from the MFRC522 14 | 15 | ```python 16 | from time import sleep 17 | import sys 18 | from mfrc522 import SimpleMFRC522 19 | reader = SimpleMFRC522() 20 | 21 | try: 22 | while True: 23 | print("Hold a tag near the reader") 24 | id, text = reader.read() 25 | print("ID: %s\nText: %s" % (id,text)) 26 | sleep(5) 27 | except KeyboardInterrupt: 28 | GPIO.cleanup() 29 | raise 30 | ``` 31 | -------------------------------------------------------------------------------- /mfrc522/MFRC522.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf8 -*- 3 | # 4 | # Copyright 2014,2018 Mario Gomez 5 | # 6 | # This file is part of MFRC522-Python 7 | # MFRC522-Python is a simple Python implementation for 8 | # the MFRC522 NFC Card Reader for the Raspberry Pi. 9 | # 10 | # MFRC522-Python is free software: you can redistribute it and/or modify 11 | # it under the terms of the GNU Lesser General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # MFRC522-Python is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU Lesser General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU Lesser General Public License 21 | # along with MFRC522-Python. If not, see . 22 | # 23 | import RPi.GPIO as GPIO 24 | import spidev 25 | import signal 26 | import time 27 | import logging 28 | 29 | class MFRC522: 30 | MAX_LEN = 16 31 | 32 | PCD_IDLE = 0x00 33 | PCD_AUTHENT = 0x0E 34 | PCD_RECEIVE = 0x08 35 | PCD_TRANSMIT = 0x04 36 | PCD_TRANSCEIVE = 0x0C 37 | PCD_RESETPHASE = 0x0F 38 | PCD_CALCCRC = 0x03 39 | 40 | PICC_REQIDL = 0x26 41 | PICC_REQALL = 0x52 42 | PICC_ANTICOLL = 0x93 43 | PICC_SElECTTAG = 0x93 44 | PICC_AUTHENT1A = 0x60 45 | PICC_AUTHENT1B = 0x61 46 | PICC_READ = 0x30 47 | PICC_WRITE = 0xA0 48 | PICC_DECREMENT = 0xC0 49 | PICC_INCREMENT = 0xC1 50 | PICC_RESTORE = 0xC2 51 | PICC_TRANSFER = 0xB0 52 | PICC_HALT = 0x50 53 | 54 | MI_OK = 0 55 | MI_NOTAGERR = 1 56 | MI_ERR = 2 57 | 58 | Reserved00 = 0x00 59 | CommandReg = 0x01 60 | CommIEnReg = 0x02 61 | DivlEnReg = 0x03 62 | CommIrqReg = 0x04 63 | DivIrqReg = 0x05 64 | ErrorReg = 0x06 65 | Status1Reg = 0x07 66 | Status2Reg = 0x08 67 | FIFODataReg = 0x09 68 | FIFOLevelReg = 0x0A 69 | WaterLevelReg = 0x0B 70 | ControlReg = 0x0C 71 | BitFramingReg = 0x0D 72 | CollReg = 0x0E 73 | Reserved01 = 0x0F 74 | 75 | Reserved10 = 0x10 76 | ModeReg = 0x11 77 | TxModeReg = 0x12 78 | RxModeReg = 0x13 79 | TxControlReg = 0x14 80 | TxAutoReg = 0x15 81 | TxSelReg = 0x16 82 | RxSelReg = 0x17 83 | RxThresholdReg = 0x18 84 | DemodReg = 0x19 85 | Reserved11 = 0x1A 86 | Reserved12 = 0x1B 87 | MifareReg = 0x1C 88 | Reserved13 = 0x1D 89 | Reserved14 = 0x1E 90 | SerialSpeedReg = 0x1F 91 | 92 | Reserved20 = 0x20 93 | CRCResultRegM = 0x21 94 | CRCResultRegL = 0x22 95 | Reserved21 = 0x23 96 | ModWidthReg = 0x24 97 | Reserved22 = 0x25 98 | RFCfgReg = 0x26 99 | GsNReg = 0x27 100 | CWGsPReg = 0x28 101 | ModGsPReg = 0x29 102 | TModeReg = 0x2A 103 | TPrescalerReg = 0x2B 104 | TReloadRegH = 0x2C 105 | TReloadRegL = 0x2D 106 | TCounterValueRegH = 0x2E 107 | TCounterValueRegL = 0x2F 108 | 109 | Reserved30 = 0x30 110 | TestSel1Reg = 0x31 111 | TestSel2Reg = 0x32 112 | TestPinEnReg = 0x33 113 | TestPinValueReg = 0x34 114 | TestBusReg = 0x35 115 | AutoTestReg = 0x36 116 | VersionReg = 0x37 117 | AnalogTestReg = 0x38 118 | TestDAC1Reg = 0x39 119 | TestDAC2Reg = 0x3A 120 | TestADCReg = 0x3B 121 | Reserved31 = 0x3C 122 | Reserved32 = 0x3D 123 | Reserved33 = 0x3E 124 | Reserved34 = 0x3F 125 | 126 | serNum = [] 127 | 128 | def __init__(self, bus=0, device=0, spd=1000000, pin_mode=10, pin_rst=-1, debugLevel='WARNING'): 129 | self.spi = spidev.SpiDev() 130 | self.spi.open(bus, device) 131 | self.spi.max_speed_hz = spd 132 | 133 | self.logger = logging.getLogger('mfrc522Logger') 134 | self.logger.addHandler(logging.StreamHandler()) 135 | level = logging.getLevelName(debugLevel) 136 | self.logger.setLevel(level) 137 | 138 | gpioMode = GPIO.getmode() 139 | 140 | if gpioMode is None: 141 | GPIO.setmode(pin_mode) 142 | else: 143 | pin_mode = gpioMode 144 | 145 | if pin_rst == -1: 146 | if pin_mode == 11: 147 | pin_rst = 15 148 | else: 149 | pin_rst = 22 150 | 151 | GPIO.setup(pin_rst, GPIO.OUT) 152 | GPIO.output(pin_rst, 1) 153 | self.MFRC522_Init() 154 | 155 | def MFRC522_Reset(self): 156 | self.Write_MFRC522(self.CommandReg, self.PCD_RESETPHASE) 157 | 158 | def Write_MFRC522(self, addr, val): 159 | val = self.spi.xfer2([(addr << 1) & 0x7E, val]) 160 | 161 | def Read_MFRC522(self, addr): 162 | val = self.spi.xfer2([((addr << 1) & 0x7E) | 0x80, 0]) 163 | return val[1] 164 | 165 | def Close_MFRC522(self): 166 | self.spi.close() 167 | GPIO.cleanup() 168 | 169 | def SetBitMask(self, reg, mask): 170 | tmp = self.Read_MFRC522(reg) 171 | self.Write_MFRC522(reg, tmp | mask) 172 | 173 | def ClearBitMask(self, reg, mask): 174 | tmp = self.Read_MFRC522(reg) 175 | self.Write_MFRC522(reg, tmp & (~mask)) 176 | 177 | def AntennaOn(self): 178 | temp = self.Read_MFRC522(self.TxControlReg) 179 | if (~(temp & 0x03)): 180 | self.SetBitMask(self.TxControlReg, 0x03) 181 | 182 | def AntennaOff(self): 183 | self.ClearBitMask(self.TxControlReg, 0x03) 184 | 185 | def MFRC522_ToCard(self, command, sendData): 186 | backData = [] 187 | backLen = 0 188 | status = self.MI_ERR 189 | irqEn = 0x00 190 | waitIRq = 0x00 191 | lastBits = None 192 | n = 0 193 | 194 | if command == self.PCD_AUTHENT: 195 | irqEn = 0x12 196 | waitIRq = 0x10 197 | if command == self.PCD_TRANSCEIVE: 198 | irqEn = 0x77 199 | waitIRq = 0x30 200 | 201 | self.Write_MFRC522(self.CommIEnReg, irqEn | 0x80) 202 | self.ClearBitMask(self.CommIrqReg, 0x80) 203 | self.SetBitMask(self.FIFOLevelReg, 0x80) 204 | 205 | self.Write_MFRC522(self.CommandReg, self.PCD_IDLE) 206 | 207 | for i in range(len(sendData)): 208 | self.Write_MFRC522(self.FIFODataReg, sendData[i]) 209 | 210 | self.Write_MFRC522(self.CommandReg, command) 211 | 212 | if command == self.PCD_TRANSCEIVE: 213 | self.SetBitMask(self.BitFramingReg, 0x80) 214 | 215 | i = 2000 216 | while True: 217 | n = self.Read_MFRC522(self.CommIrqReg) 218 | i -= 1 219 | if ~((i != 0) and ~(n & 0x01) and ~(n & waitIRq)): 220 | break 221 | 222 | self.ClearBitMask(self.BitFramingReg, 0x80) 223 | 224 | if i != 0: 225 | if (self.Read_MFRC522(self.ErrorReg) & 0x1B) == 0x00: 226 | status = self.MI_OK 227 | 228 | if n & irqEn & 0x01: 229 | status = self.MI_NOTAGERR 230 | 231 | if command == self.PCD_TRANSCEIVE: 232 | n = self.Read_MFRC522(self.FIFOLevelReg) 233 | lastBits = self.Read_MFRC522(self.ControlReg) & 0x07 234 | if lastBits != 0: 235 | backLen = (n - 1) * 8 + lastBits 236 | else: 237 | backLen = n * 8 238 | 239 | if n == 0: 240 | n = 1 241 | if n > self.MAX_LEN: 242 | n = self.MAX_LEN 243 | 244 | for i in range(n): 245 | backData.append(self.Read_MFRC522(self.FIFODataReg)) 246 | else: 247 | status = self.MI_ERR 248 | 249 | return (status, backData, backLen) 250 | 251 | def MFRC522_Request(self, reqMode): 252 | status = None 253 | backBits = None 254 | TagType = [] 255 | 256 | self.Write_MFRC522(self.BitFramingReg, 0x07) 257 | 258 | TagType.append(reqMode) 259 | (status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, TagType) 260 | 261 | if ((status != self.MI_OK) | (backBits != 0x10)): 262 | status = self.MI_ERR 263 | 264 | return (status, backBits) 265 | 266 | def MFRC522_Anticoll(self): 267 | backData = [] 268 | serNumCheck = 0 269 | 270 | serNum = [] 271 | 272 | self.Write_MFRC522(self.BitFramingReg, 0x00) 273 | 274 | serNum.append(self.PICC_ANTICOLL) 275 | serNum.append(0x20) 276 | 277 | (status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, serNum) 278 | 279 | if (status == self.MI_OK): 280 | i = 0 281 | if len(backData) == 5: 282 | for i in range(4): 283 | serNumCheck = serNumCheck ^ backData[i] 284 | if serNumCheck != backData[4]: 285 | status = self.MI_ERR 286 | else: 287 | status = self.MI_ERR 288 | 289 | return (status, backData) 290 | 291 | def CalulateCRC(self, pIndata): 292 | self.ClearBitMask(self.DivIrqReg, 0x04) 293 | self.SetBitMask(self.FIFOLevelReg, 0x80) 294 | 295 | for i in range(len(pIndata)): 296 | self.Write_MFRC522(self.FIFODataReg, pIndata[i]) 297 | 298 | self.Write_MFRC522(self.CommandReg, self.PCD_CALCCRC) 299 | i = 0xFF 300 | while True: 301 | n = self.Read_MFRC522(self.DivIrqReg) 302 | i -= 1 303 | if not ((i != 0) and not (n & 0x04)): 304 | break 305 | pOutData = [] 306 | pOutData.append(self.Read_MFRC522(self.CRCResultRegL)) 307 | pOutData.append(self.Read_MFRC522(self.CRCResultRegM)) 308 | return pOutData 309 | 310 | def MFRC522_SelectTag(self, serNum): 311 | backData = [] 312 | buf = [] 313 | buf.append(self.PICC_SElECTTAG) 314 | buf.append(0x70) 315 | 316 | for i in range(5): 317 | buf.append(serNum[i]) 318 | 319 | pOut = self.CalulateCRC(buf) 320 | buf.append(pOut[0]) 321 | buf.append(pOut[1]) 322 | (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf) 323 | 324 | if (status == self.MI_OK) and (backLen == 0x18): 325 | self.logger.debug("Size: " + str(backData[0])) 326 | return backData[0] 327 | else: 328 | return 0 329 | 330 | def MFRC522_Auth(self, authMode, BlockAddr, Sectorkey, serNum): 331 | buff = [] 332 | 333 | # First byte should be the authMode (A or B) 334 | buff.append(authMode) 335 | 336 | # Second byte is the trailerBlock (usually 7) 337 | buff.append(BlockAddr) 338 | 339 | # Now we need to append the authKey which usually is 6 bytes of 0xFF 340 | for i in range(len(Sectorkey)): 341 | buff.append(Sectorkey[i]) 342 | 343 | # Next we append the first 4 bytes of the UID 344 | for i in range(4): 345 | buff.append(serNum[i]) 346 | 347 | # Now we start the authentication itself 348 | (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_AUTHENT, buff) 349 | 350 | # Check if an error occurred 351 | if not (status == self.MI_OK): 352 | self.logger.error("AUTH ERROR!!") 353 | if not (self.Read_MFRC522(self.Status2Reg) & 0x08) != 0: 354 | self.logger.error("AUTH ERROR(status2reg & 0x08) != 0") 355 | 356 | # Return the status 357 | return status 358 | 359 | def MFRC522_StopCrypto1(self): 360 | self.ClearBitMask(self.Status2Reg, 0x08) 361 | 362 | def MFRC522_Read(self, blockAddr): 363 | recvData = [] 364 | recvData.append(self.PICC_READ) 365 | recvData.append(blockAddr) 366 | pOut = self.CalulateCRC(recvData) 367 | recvData.append(pOut[0]) 368 | recvData.append(pOut[1]) 369 | (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, recvData) 370 | if not (status == self.MI_OK): 371 | self.logger.error("Error while reading!") 372 | 373 | if len(backData) == 16: 374 | self.logger.debug("Sector " + str(blockAddr) + " " + str(backData)) 375 | return backData 376 | else: 377 | return None 378 | 379 | def MFRC522_Write(self, blockAddr, writeData): 380 | buff = [] 381 | buff.append(self.PICC_WRITE) 382 | buff.append(blockAddr) 383 | crc = self.CalulateCRC(buff) 384 | buff.append(crc[0]) 385 | buff.append(crc[1]) 386 | (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buff) 387 | if not (status == self.MI_OK) or not (backLen == 4) or not ((backData[0] & 0x0F) == 0x0A): 388 | status = self.MI_ERR 389 | 390 | self.logger.debug("%s backdata &0x0F == 0x0A %s" % (backLen, backData[0] & 0x0F)) 391 | if status == self.MI_OK: 392 | buf = [] 393 | for i in range(16): 394 | buf.append(writeData[i]) 395 | 396 | crc = self.CalulateCRC(buf) 397 | buf.append(crc[0]) 398 | buf.append(crc[1]) 399 | (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf) 400 | if not (status == self.MI_OK) or not (backLen == 4) or not ((backData[0] & 0x0F) == 0x0A): 401 | self.logger.error("Error while writing") 402 | if status == self.MI_OK: 403 | self.logger.debug("Data written") 404 | 405 | 406 | def MFRC522_DumpClassic1K(self, key, uid): 407 | for i in range(64): 408 | status = self.MFRC522_Auth(self.PICC_AUTHENT1A, i, key, uid) 409 | # Check if authenticated 410 | if status == self.MI_OK: 411 | self.MFRC522_Read(i) 412 | else: 413 | self.logger.error("Authentication error") 414 | 415 | def MFRC522_Init(self): 416 | self.MFRC522_Reset() 417 | 418 | self.Write_MFRC522(self.TModeReg, 0x8D) 419 | self.Write_MFRC522(self.TPrescalerReg, 0x3E) 420 | self.Write_MFRC522(self.TReloadRegL, 30) 421 | self.Write_MFRC522(self.TReloadRegH, 0) 422 | 423 | self.Write_MFRC522(self.TxAutoReg, 0x40) 424 | self.Write_MFRC522(self.ModeReg, 0x3D) 425 | self.AntennaOn() 426 | -------------------------------------------------------------------------------- /mfrc522/SimpleMFRC522.py: -------------------------------------------------------------------------------- 1 | # Code by Simon Monk https://github.com/simonmonk/ 2 | 3 | from . import MFRC522 4 | import RPi.GPIO as GPIO 5 | 6 | class SimpleMFRC522: 7 | 8 | READER = None 9 | 10 | KEY = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] 11 | BLOCK_ADDRS = [8, 9, 10] 12 | 13 | def __init__(self): 14 | self.READER = MFRC522() 15 | 16 | def read(self): 17 | id, text = self.read_no_block() 18 | while not id: 19 | id, text = self.read_no_block() 20 | return id, text 21 | 22 | def read_id(self): 23 | id = self.read_id_no_block() 24 | while not id: 25 | id = self.read_id_no_block() 26 | return id 27 | 28 | def read_id_no_block(self): 29 | (status, TagType) = self.READER.MFRC522_Request(self.READER.PICC_REQIDL) 30 | if status != self.READER.MI_OK: 31 | return None 32 | (status, uid) = self.READER.MFRC522_Anticoll() 33 | if status != self.READER.MI_OK: 34 | return None 35 | return self.uid_to_num(uid) 36 | 37 | def read_no_block(self): 38 | (status, TagType) = self.READER.MFRC522_Request(self.READER.PICC_REQIDL) 39 | if status != self.READER.MI_OK: 40 | return None, None 41 | (status, uid) = self.READER.MFRC522_Anticoll() 42 | if status != self.READER.MI_OK: 43 | return None, None 44 | id = self.uid_to_num(uid) 45 | self.READER.MFRC522_SelectTag(uid) 46 | status = self.READER.MFRC522_Auth(self.READER.PICC_AUTHENT1A, 11, self.KEY, uid) 47 | data = [] 48 | text_read = '' 49 | if status == self.READER.MI_OK: 50 | for block_num in self.BLOCK_ADDRS: 51 | block = self.READER.MFRC522_Read(block_num) 52 | if block: 53 | data += block 54 | if data: 55 | text_read = ''.join(chr(i) for i in data) 56 | self.READER.MFRC522_StopCrypto1() 57 | return id, text_read 58 | 59 | def write(self, text): 60 | id, text_in = self.write_no_block(text) 61 | while not id: 62 | id, text_in = self.write_no_block(text) 63 | return id, text_in 64 | 65 | def write_no_block(self, text): 66 | (status, TagType) = self.READER.MFRC522_Request(self.READER.PICC_REQIDL) 67 | if status != self.READER.MI_OK: 68 | return None, None 69 | (status, uid) = self.READER.MFRC522_Anticoll() 70 | if status != self.READER.MI_OK: 71 | return None, None 72 | id = self.uid_to_num(uid) 73 | self.READER.MFRC522_SelectTag(uid) 74 | status = self.READER.MFRC522_Auth(self.READER.PICC_AUTHENT1A, 11, self.KEY, uid) 75 | self.READER.MFRC522_Read(11) 76 | if status == self.READER.MI_OK: 77 | data = bytearray() 78 | data.extend(bytearray(text.ljust(len(self.BLOCK_ADDRS) * 16).encode('ascii'))) 79 | i = 0 80 | for block_num in self.BLOCK_ADDRS: 81 | self.READER.MFRC522_Write(block_num, data[(i*16):(i+1)*16]) 82 | i += 1 83 | self.READER.MFRC522_StopCrypto1() 84 | return id, text[0:(len(self.BLOCK_ADDRS) * 16)] 85 | 86 | def uid_to_num(self, uid): 87 | n = 0 88 | for i in range(0, 5): 89 | n = n * 256 + uid[i] 90 | return n 91 | -------------------------------------------------------------------------------- /mfrc522/__init__.py: -------------------------------------------------------------------------------- 1 | from .MFRC522 import MFRC522 2 | from .SimpleMFRC522 import SimpleMFRC522 3 | 4 | name = "mfrc522" 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open("README.md", "r") as fh: 4 | long_description = fh.read() 5 | 6 | setuptools.setup( 7 | name="mfrc522", 8 | version="0.0.7", 9 | author="Pi My Life Up", 10 | author_email="support@pimylifeup.com", 11 | description="A library to integrate the MFRC522 RFID readers with the Raspberry Pi", 12 | long_description=long_description, 13 | long_description_content_type="text/markdown", 14 | url="https://github.com/pimylifeup/MFRC522-python", 15 | packages=setuptools.find_packages(), 16 | install_requires=[ 17 | 'RPi.GPIO', 18 | 'spidev' 19 | ], 20 | classifiers=[ 21 | "Programming Language :: Python :: 2.7", 22 | "Programming Language :: Python :: 3", 23 | "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)", 24 | "Operating System :: POSIX :: Linux", 25 | 'Topic :: System :: Hardware', 26 | ], 27 | ) 28 | --------------------------------------------------------------------------------