package main import ( "encoding/binary" "encoding/hex" "fmt" "golang.org/x/crypto/scrypt" "time" ) import ( "github.com/warthog618/gpiod" ) type Wiegand struct { aLine *gpiod.Line bLine *gpiod.Line bits [64]bool bitNr int bitTimeout time.Duration bitTimeoutTimer *time.Timer solenoidLine *gpiod.Line } func (w *Wiegand) OpenDoor() { fmt.Println("Open") w.solenoidLine.SetValue(1) d, _ := time.ParseDuration("500ms") time.Sleep(d) w.solenoidLine.SetValue(0) fmt.Println("Close") } func printCardId(card uint64) { for i := 0; i < 7; i++ { fmt.Printf("%02x", (card>>(8*i))&0xff) } fmt.Printf("\n") } func (w *Wiegand) cardRunner(validUids ValidUids) { for { // Wait for bit timeout fmt.Printf("Waiting for bit timeout\n") <-w.bitTimeoutTimer.C fmt.Printf("\n") if w.bitNr != 64 { fmt.Printf("We got less than 64 bits: %d\n", w.bitNr) } var card uint64 = 0 for i := 63; i != 0; i-- { if w.bits[i] == true { card |= 1 << (63 - i) } } printCardId(card) b := make([]byte, 8) binary.LittleEndian.PutUint64(b, card) hashed, err := scrypt.Key(b, []byte("hashsah"), 16384, 8, 1, 64) if err != nil { panic(err) } hashedHex := hex.EncodeToString(hashed) fmt.Println(hashedHex) _, ok := validUids[hashedHex] if ok { fmt.Println("Opening door") w.OpenDoor() } else { fmt.Println("Unknown card") } w.bitNr = 0 } } func (w *Wiegand) wiegandAEvent(evt gpiod.LineEvent) { w.bitTimeoutTimer.Reset(w.bitTimeout) w.bits[w.bitNr] = false fmt.Printf("0") w.bitNr += 1 } func (w *Wiegand) wiegandBEvent(evt gpiod.LineEvent) { w.bitTimeoutTimer.Reset(w.bitTimeout) w.bits[w.bitNr] = true fmt.Printf("1") w.bitNr += 1 } func WiegandSetup(a int, b int, bitTimeout time.Duration, solenoid int) *Wiegand { var wiegand Wiegand wiegand.bitTimeout = bitTimeout wiegand.bitTimeoutTimer = time.NewTimer(wiegand.bitTimeout) if !wiegand.bitTimeoutTimer.Stop() { <-wiegand.bitTimeoutTimer.C } wa, err := gpiod.RequestLine("gpiochip0", a, gpiod.AsInput, gpiod.WithFallingEdge, gpiod.WithEventHandler(wiegand.wiegandAEvent)) if err != nil { panic(err) } wiegand.aLine = wa wb, err := gpiod.RequestLine("gpiochip0", b, gpiod.AsInput, gpiod.WithFallingEdge, gpiod.WithEventHandler(wiegand.wiegandBEvent)) if err != nil { panic(err) } wiegand.bLine = wb solenoidLine, err := gpiod.RequestLine("gpiochip0", solenoid, gpiod.AsOutput(0)) if err != nil { panic(err) } wiegand.solenoidLine = solenoidLine return &wiegand } func (w *Wiegand) WiegandClose() { w.aLine.Close() w.bLine.Close() w.solenoidLine.Close() }