mfrc522: Add support for 7-bytes UUID (#442)

Add ReadUID example.
pull/1/head
SystemGlitch 6 years ago committed by GitHub
parent eff9c2ce8c
commit 4f5701e9eb

@ -35,9 +35,9 @@ type AuthStatus byte
// NewLowLevelSPI creates and initializes the RFID card reader attached to SPI.
//
// spiPort - the SPI device to use.
// resetPin - reset GPIO pin.
// irqPin - irq GPIO pin.
// spiPort - the SPI device to use.
// resetPin - reset GPIO pin.
// irqPin - irq GPIO pin.
func NewLowLevelSPI(spiPort spi.Port, resetPin gpio.PinOut, irqPin gpio.PinIn) (*LowLevel, error) {
if resetPin == nil {
return nil, wrapf("reset pin is not set")

@ -17,6 +17,7 @@ const (
PICC_REQIDL = 0x26
PICC_REQALL = 0x52
PICC_ANTICOLL = 0x93
PICC_ANTICOLL2 = 0x95
PICC_SElECTTAG = 0x93
PICC_AUTHENT1A = 0x60
PICC_AUTHENT1B = 0x61

@ -23,7 +23,7 @@ func Example() {
log.Fatal(err)
}
// Using SPI as an example. See package ./spi/spireg for more details.
// Using SPI as an example. See package "periph.io/x/periph/conn/spi/spireg" for more details.
p, err := spireg.Open("")
if err != nil {
log.Fatal(err)
@ -102,3 +102,75 @@ func Example() {
}
}
}
func ExampleDev_ReadUID() {
// Make sure periph is initialized.
if _, err := host.Init(); err != nil {
log.Fatal(err)
}
// Using SPI as an example. See package "periph.io/x/periph/conn/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
}
}
}

@ -123,6 +123,20 @@ func (r *Dev) SetAntennaGain(gain int) error {
return nil
}
// ReadUID reads the card UID with IRQ event timeout.
//
// timeout the operation timeout
func (r *Dev) ReadUID(timeout time.Duration) (uid []byte, err error) {
r.beforeCall()
defer func() {
r.afterCall()
if err == nil {
err = r.LowLevel.StopCrypto()
}
}()
return r.selectCard(timeout)
}
// ReadCard reads the card sector/block with IRQ event timeout.
//
// timeout the operation timeout
@ -303,6 +317,35 @@ func (r *Dev) antiColl() ([]byte, error) {
return backData, nil
}
// antiColl2 performs additional anticollision check for UIDs with more than 4 bytes.
func (r *Dev) antiColl2() ([]byte, error) {
if err := r.LowLevel.DevWrite(commands.BitFramingReg, 0x00); err != nil {
return nil, err
}
serial := []byte{commands.PICC_ANTICOLL2, 0x20}
check := byte(0)
backData, _, err := r.LowLevel.CardWrite(commands.PCD_TRANSCEIVE, serial)
if err != nil {
return nil, err
}
if len(backData) != 5 {
return nil, wrapf("Anticoll2 error, response is %d bytes-long, expected 5", len(backData))
}
for i := 0; i < 4; i++ {
check ^= backData[i]
}
if check != backData[4] {
return nil, wrapf("Anticoll2 error, check failed")
}
return backData, nil
}
// selectTag selects the FOB device by device UUID.
func (r *Dev) selectTag(serial []byte) (byte, error) {
dataBuf := make([]byte, len(serial)+2)
@ -355,6 +398,17 @@ func (r *Dev) selectCard(timeout time.Duration) ([]byte, error) {
if _, err := r.selectTag(uuid); err != nil {
return nil, err
}
if uuid[0] == 0x88 { // Incomplete UID
// Get remaining bytes
uuidEnd, err := r.antiColl2()
if err != nil {
return nil, err
}
uuid = uuid[1 : len(uuid)-1]
uuid = append(uuid, uuidEnd[:len(uuidEnd)-1]...)
}
return uuid, nil
}

Loading…
Cancel
Save