mfrc522

package
v3.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2023 License: Apache-2.0 Imports: 7 Imported by: 5

Documentation

Overview

Package mfrc522 controls a Mifare RFID card reader.

Datasheet

https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf

Package mfrc522 controls a Mifare RFID card reader.

Datasheet

https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf

Example
// Make sure periph is initialized.
if _, err := host.Init(); err != nil {
	log.Fatal(err)
}

// Using SPI as an example. See package "periph.io/x/conn/v3/spi/spireg" for more details.
p, err := spireg.Open("")
if err != nil {
	log.Fatal(err)
}
defer p.Close()

rfid, err := mfrc522.NewSPI(p, rpi.P1_13, rpi.P1_11)
if err != nil {
	log.Fatal(err)
}

// Idling device on exit.
defer rfid.Halt()

// Setting the antenna signal strength.
rfid.SetAntennaGain(5)

// Converting access key.
// This value corresponds to first pi "numbers": 3 14 15 92 65 35.
hexKey, _ := hex.DecodeString("030e0f5c4123")
var key [6]byte
copy(key[:], hexKey)

// Converting expected data.
// This value corresponds to string "@~>f=Um[X{LRwA3}".
expected, _ := hex.DecodeString("407e3e663d556d5b587b4c527741337d")

timedOut := false
cb := make(chan []byte)
timer := time.NewTimer(10 * time.Second)

// Stopping timer, flagging reader thread as timed out
defer func() {
	timer.Stop()
	timedOut = true
	close(cb)
}()

go func() {
	log.Printf("Started %s", rfid.String())

	for {
		// Trying to read data from sector 1 block 0
		data, err := rfid.ReadCard(10*time.Second, byte(commands.PICC_AUTHENT1B), 1, 0, key)

		// If main thread timed out just exiting.
		if timedOut {
			return
		}

		// Some devices tend to send wrong data while RFID chip is already detected
		// but still "too far" from a receiver.
		// Especially some cheap CN clones which you can find on GearBest, AliExpress, etc.
		// This will suppress such errors.
		if err != nil {
			continue
		}

		cb <- data
	}
}()

for {
	select {
	case <-timer.C:
		log.Fatal("Didn't receive device data")
		return
	case data := <-cb:
		if !reflect.DeepEqual(data, expected) {
			log.Fatal("Received data is incorrect")
		} else {
			log.Println("Received data is correct")
		}

		return
	}
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultKey = Key{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}

DefaultKey provides the default bytes for card authentication for method B.

Functions

func WithBogusUID added in v3.6.13

func WithBogusUID() configF

WithBogusUID sets the card reader to return incorrect 4-byte UIDs. In version 3.6.12 and earlier this package ruturned 5-bytes for tags with a 4-byte UID with bytes 0 to 3 being the correct UID and byte 4 being an XOR of bytes 0 to 3. 7-byte UIDs are correct regardless of this configuration.

func WithSync

func WithSync() configF

WithSync sets the synchronization for the entire device, using internal mutex.

func WithTimeout

func WithTimeout(timeout time.Duration) configF

WithTimeout updates the default device-wide configuration timeout.

Types

type BlockAccess

type BlockAccess byte

BlockAccess defines the block access bits.

const (
	AnyKeyRWID    BlockAccess = 0x0  // Any key (A or B) can read, write, increment and decrement block.
	RAB_WN_IN_DN  BlockAccess = 0x02 // Read (A or B), Write (None), Increment (None), Decrement (None)
	RAB_WB_IN_DN  BlockAccess = 0x04 // Read (A orB), Write (B), Increment (None), Decrement (None)
	RAB_WB_IB_DAB BlockAccess = 0x06 // Read (A or B), Write (B), Icrement (B), Decrement (A or B)
	RAB_WN_IN_DAB BlockAccess = 0x01 // Read (A or B), Write (None), Increment (None), Decrment (A or B)
	RB_WB_IN_DN   BlockAccess = 0x03 // Read (B), Write (B), Increment (None), Decrement (None)
	RB_WN_IN_DN   BlockAccess = 0x05 // Read (B), Write (None), Increment (None), Decrement (None)
	RN_WN_IN_DN   BlockAccess = 0x07 // Read (None), Write (None), Increment (None), Decrement (None)
)

Access bits for the sector data.

type BlocksAccess

type BlocksAccess struct {
	B0, B1, B2 BlockAccess
	B3         SectorTrailerAccess
}

BlocksAccess defines the access structure for first 3 blocks of the sector and the access bits for the sector trail.

func (*BlocksAccess) Init

func (ba *BlocksAccess) Init(ad []byte)

Init parses the given byte array into the block access structure.

func (*BlocksAccess) String

func (ba *BlocksAccess) String() string

type Dev

type Dev struct {
	LowLevel *commands.LowLevel
	// contains filtered or unexported fields
}

Dev is an handle to an MFRC522 RFID reader.

func NewSPI

func NewSPI(spiPort spi.Port, resetPin gpio.PinOut, irqPin gpio.PinIn, configs ...configF) (*Dev, error)

NewSPI creates and initializes the RFID card reader attached to SPI.

spiPort     the SPI device to use.
resetPin    reset GPIO pin.
irqPin      irq GPIO pin.
configs     configuration options

func (*Dev) Halt

func (r *Dev) Halt() error

Halt implements conn.Resource.

It soft-stops the chip - PowerDown bit set, command IDLE

func (*Dev) ReadAuth

func (r *Dev) ReadAuth(timeout time.Duration, auth byte, sector int, key Key) (data []byte, err error)

ReadAuth reads the card authentication data with IRQ event timeout.

timeout    the operation timeout
auth       authentication type
sector     the sector to authenticate on.
key        the key to be used for accessing the sector data.

func (*Dev) ReadCard

func (r *Dev) ReadCard(timeout time.Duration, auth byte, sector int, block int, key Key) (data []byte, err error)

ReadCard reads the card sector/block with IRQ event timeout.

timeout   the operation timeout
auth      the authentication mode.
sector    the sector to authenticate on.
block     the block within sector to authenticate.
key       the key to be used for accessing the sector data.

func (*Dev) ReadUID

func (r *Dev) ReadUID(timeout time.Duration) (uid []byte, err error)

ReadUID reads the 4-byte or 7-byte card UID with IRQ event timeout.

timeout   the operation timeout
Example
// Make sure periph is initialized.
if _, err := host.Init(); err != nil {
	log.Fatal(err)
}

// Using SPI as an example. See package "periph.io/x/conn/v3/spi/spireg" for more details.
p, err := spireg.Open("")
if err != nil {
	log.Fatal(err)
}
defer p.Close()

rfid, err := mfrc522.NewSPI(p, rpi.P1_22, rpi.P1_18)
if err != nil {
	log.Fatal(err)
}

// Idling device on exit.
defer rfid.Halt()

// Setting the antenna signal strength.
rfid.SetAntennaGain(5)

timedOut := false
cb := make(chan []byte)
timer := time.NewTimer(10 * time.Second)

// Stopping timer, flagging reader thread as timed out
defer func() {
	timer.Stop()
	timedOut = true
	close(cb)
}()

go func() {
	log.Printf("Started %s", rfid.String())

	for {
		// Trying to read card UID.
		uid, err := rfid.ReadUID(10 * time.Second)

		// If main thread timed out just exiting.
		if timedOut {
			return
		}

		// Some devices tend to send wrong data while RFID chip is already detected
		// but still "too far" from a receiver.
		// Especially some cheap CN clones which you can find on GearBest, AliExpress, etc.
		// This will suppress such errors.
		if err != nil {
			continue
		}

		cb <- uid
		return
	}
}()

for {
	select {
	case <-timer.C:
		log.Fatal("Didn't receive device data")
		return
	case data := <-cb:
		log.Println("UID:", hex.EncodeToString(data))
		return
	}
}
Output:

func (*Dev) SetAntennaGain

func (r *Dev) SetAntennaGain(gain int) error

SetAntennaGain configures antenna signal strength.

gain    signal strength from 0 to 7.

func (*Dev) String

func (r *Dev) String() string

String implements conn.Resource.

func (*Dev) WriteCard

func (r *Dev) WriteCard(timeout time.Duration, auth byte, sector int, block int, data [16]byte, key Key) (err error)

WriteCard writes the data into the card block with IRQ event timeout.

timeout     the operation timeout
auth        the authentiction mode.
sector      the sector on the card to write to.
block       the block within the sector to write into.
data        16 bytes if data to write
key          the key used to authenticate the card - depends on the used auth method.

func (*Dev) WriteSectorTrail

func (r *Dev) WriteSectorTrail(timeout time.Duration, auth byte, sector int, keyA Key, keyB Key, access *BlocksAccess, key Key) (err error)

WriteSectorTrail writes the sector trail with sector access bits with IRQ event timeout.

timeout   operation timeout
auth      authentication mode.
sector    sector to set authentication.
keyA      the key used for AuthA authentication scheme.
keyB      the key used for AuthB authentication scheme.
access    the block access structure.
key       the current key used to authenticate the provided sector.

type Key

type Key [6]byte

Key is the access key that consists of 6 bytes. There could be two types of keys - keyA and keyB. KeyA and KeyB correspond to the different sector trail and data access. Refer to the datasheet for more details.

type SectorTrailerAccess

type SectorTrailerAccess byte

SectorTrailerAccess defines the sector trailing block access bits.

const (
	KeyA_RN_WA_BITS_RA_WN_KeyB_RA_WA        SectorTrailerAccess = 0x0
	KeyA_RN_WN_BITS_RA_WN_KeyB_RA_WN        SectorTrailerAccess = 0x02
	KeyA_RN_WB_BITS_RAB_WN_KeyB_RN_WB       SectorTrailerAccess = 0x04
	KeyA_RN_WN_BITS_RAB_WN_KeyB_RN_WN       SectorTrailerAccess = 0x06
	KeyA_RN_WA_BITS_RA_WA_KeyB_RA_WA        SectorTrailerAccess = 0x01
	KeyA_RN_WB_BITS_RAB_WB_KeyB_RN_WB       SectorTrailerAccess = 0x03
	KeyA_RN_WN_BITS_RAB_WB_KeyB_RN_WN       SectorTrailerAccess = 0x05
	KeyA_RN_WN_BITS_RAB_WN_KeyB_RN_WN_EXTRA SectorTrailerAccess = 0x07
)

Access bits for the sector trail. Every trail sector has the options for controlling the access to the trailing sector bits. For example :

KeyA_R[Key]_W[Key]_BITS_R[Key]_W[Key]_KeyB_R[Key]_W[Key]

- KeyA
  - could be Read by providing [Key] ( where [Key] could be KeyA or KeyB )
  - could be Written by Providing [Key] ( where [Key] is KeyA or KeyB )
- access bits for the sector data (see above)
  - could be Read by providing [Key] ( where [Key] could be KeyA or KeyB )
  - could be Written by Providing [Key] ( where [Key] is KeyA or KeyB )
- KeyB
  - could be Read by providing [Key] ( where [Key] could be KeyA or KeyB )
  - could be Written by Providing [Key] ( where [Key] is KeyA or KeyB )

example:

 KeyA_RN_WA_BITS_RA_WA_KeyB_RA_WA means
 - KeyA could not be read but could be overwriten if KeyA is provided
 - Access bits could be read and overwritten if KeyA is provided during the card authentication
 - KeyB could be read and overriten if KeyA is provided during the card authentication
more on the matter: https://www.nxp.com/docs/en/data-sheet/MF1S50YYX_V1.pdf

Directories

Path Synopsis
Package commands contains the command that a MFRC522 supports.
Package commands contains the command that a MFRC522 supports.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL