package main import ( "fmt" "log" "sync" "time" "github.com/warthog618/gpiod" ) type Wiegand interface { GetCardUid() (uint64, error) OpenDoor() error CloseDoor() error IsDoorOpen() (bool, error) } type WiegandHW struct { aLine *gpiod.Line bLine *gpiod.Line bits [64]bool bitNr int bitTimeout time.Duration bitTimeoutTimer *time.Timer solenoidLine *gpiod.Line lock sync.RWMutex } func (w *WiegandHW) OpenDoor() error { w.lock.Lock() defer w.lock.Unlock() open, _ := w.isDoorOpen() if open { return nil } return w.solenoidLine.SetValue(1) } func (w *WiegandHW) CloseDoor() error { w.lock.Lock() defer w.lock.Unlock() open, _ := w.isDoorOpen() if !open { return nil } return w.solenoidLine.SetValue(0) } func (w *WiegandHW) IsDoorOpen() (bool, error) { w.lock.RLock() defer w.lock.RUnlock() return w.isDoorOpen() } func (w *WiegandHW) isDoorOpen() (bool, error) { i, err := w.solenoidLine.Value() if err != nil { return false, err } return i == 1, nil } func (w *WiegandHW) GetCardUid() (uint64, error) { // Wait for bit timeout log.Printf("Waiting for bit timeout\n") <-w.bitTimeoutTimer.C defer func() { w.bitNr = 0 }() if w.bitNr != 64 { return 0, fmt.Errorf("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) } } return card, nil } func (w *WiegandHW) wiegandAEvent(evt gpiod.LineEvent) { w.bitTimeoutTimer.Reset(w.bitTimeout) w.bits[w.bitNr] = true //fmt.Printf("1") w.bitNr += 1 } func (w *WiegandHW) wiegandBEvent(evt gpiod.LineEvent) { w.bitTimeoutTimer.Reset(w.bitTimeout) w.bits[w.bitNr] = false //fmt.Printf("0") w.bitNr += 1 } func WiegandSetup(a int, b int, bitTimeout time.Duration, solenoid int) *WiegandHW { log.Printf("Wiegand GPIO-s: A:%d B:%d Solenoid:%d", a, b, solenoid) var wiegand WiegandHW 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.LineBiasPullUp, gpiod.WithEventHandler(wiegand.wiegandAEvent)) if err != nil { panic(err) } wiegand.aLine = wa wb, err := gpiod.RequestLine("gpiochip0", b, gpiod.AsInput, gpiod.WithFallingEdge, gpiod.LineBiasPullUp, 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 *WiegandHW) WiegandClose() { w.aLine.Close() w.bLine.Close() w.solenoidLine.Close() } func printCardId(card uint64) { for i := 0; i < 7; i++ { fmt.Printf("%02x", (card>>(8*i))&0xff) } fmt.Printf("\n") }