Checkpoint 5
This commit is contained in:
parent
9116635efc
commit
9b1eba127a
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
.idea
|
||||
godoor
|
||||
godoor_server/godoor_server
|
||||
godoor_server/keys.json
|
||||
|
4
Makefile
Normal file
4
Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
dev:
|
||||
GOOS=linux GOARCH=arm64 go build .
|
||||
scp godoor workshopdoor:/tmp/
|
||||
ssh workshopdoor 'mv -f /tmp/godoor ~/ && sudo systemctl restart godoor'
|
3
build.sh
3
build.sh
@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
GOOS=linux GOARCH=arm64 go build && scp godoor rpi4b:
|
83
godoor.go
83
godoor.go
@ -6,7 +6,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/joho/godotenv"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -15,8 +14,12 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"godoor/hash"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
import "time"
|
||||
|
||||
const wiegand_a = 17
|
||||
const wiegand_b = 18
|
||||
@ -54,12 +57,20 @@ type KeepDoorOpen struct {
|
||||
timer *time.Timer
|
||||
}
|
||||
|
||||
type OpenedTimestamp struct {
|
||||
Opened time.Time
|
||||
Closed *time.Time
|
||||
}
|
||||
|
||||
var config Config
|
||||
var globalLock sync.Mutex
|
||||
var validUids ValidUids
|
||||
var wiegand Wiegand
|
||||
var keepDoorOpen KeepDoorOpen
|
||||
|
||||
var lastSyncedTimestamp *time.Time
|
||||
var openDoorTimestamps []OpenedTimestamp
|
||||
|
||||
func main() {
|
||||
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
@ -85,6 +96,7 @@ func main() {
|
||||
|
||||
// cleanup
|
||||
}
|
||||
|
||||
func setup() {
|
||||
log.Println("Started Setup")
|
||||
|
||||
@ -99,6 +111,8 @@ func setup() {
|
||||
}
|
||||
log.Println("HW Setup done")
|
||||
|
||||
http.DefaultClient.Timeout = 120 * time.Second
|
||||
|
||||
go func() {
|
||||
for {
|
||||
waitEvents()
|
||||
@ -107,8 +121,6 @@ func setup() {
|
||||
|
||||
log.Println("Initialized longpoll event loop")
|
||||
|
||||
http.DefaultClient.Timeout = 120 * time.Second
|
||||
|
||||
for {
|
||||
log.Println("Start initial token population")
|
||||
err := reloadTokens()
|
||||
@ -120,6 +132,8 @@ func setup() {
|
||||
time.Sleep(10 * time.Second)
|
||||
}
|
||||
|
||||
go runHttpServer()
|
||||
|
||||
log.Println("Initial token population success")
|
||||
|
||||
go cardRunner(wiegand)
|
||||
@ -127,13 +141,36 @@ func setup() {
|
||||
log.Println("Setup completed")
|
||||
}
|
||||
|
||||
func runHttpServer() {
|
||||
http.HandleFunc("/lastsync", func(w http.ResponseWriter, r *http.Request) {
|
||||
e := json.NewEncoder(w)
|
||||
e.Encode(map[string]any{
|
||||
"last_synced": lastSyncedTimestamp,
|
||||
})
|
||||
})
|
||||
http.HandleFunc("/opened", func(w http.ResponseWriter, r *http.Request) {
|
||||
e := json.NewEncoder(w)
|
||||
e.Encode(map[string]any{
|
||||
"open_timestamps": openDoorTimestamps,
|
||||
})
|
||||
})
|
||||
http.HandleFunc("/isopen", func(w http.ResponseWriter, r *http.Request) {
|
||||
e := json.NewEncoder(w)
|
||||
open, _ := wiegand.IsDoorOpen()
|
||||
e.Encode(map[string]any{
|
||||
"open": open,
|
||||
})
|
||||
})
|
||||
http.ListenAndServe(":3334", nil)
|
||||
}
|
||||
|
||||
func OpenAndCloseDoor(w Wiegand) error {
|
||||
err := w.OpenDoor()
|
||||
err := OpenDoor(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if keepDoorOpen.until.After(time.Now().Add(5 * time.Second)) {
|
||||
if keepDoorOpen.until.After(time.Now()) {
|
||||
fmt.Println("Door is already open")
|
||||
return nil
|
||||
}
|
||||
@ -142,7 +179,7 @@ func OpenAndCloseDoor(w Wiegand) error {
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
err = w.CloseDoor()
|
||||
err = CloseDoor(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -151,6 +188,27 @@ func OpenAndCloseDoor(w Wiegand) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func OpenDoor(w Wiegand) error {
|
||||
open, _ := w.IsDoorOpen()
|
||||
if open {
|
||||
return nil
|
||||
}
|
||||
w.OpenDoor()
|
||||
openDoorTimestamps = append(openDoorTimestamps, OpenedTimestamp{Opened: time.Now(), Closed: nil})
|
||||
return nil
|
||||
}
|
||||
|
||||
func CloseDoor(w Wiegand) error {
|
||||
open, _ := w.IsDoorOpen()
|
||||
if !open {
|
||||
return nil
|
||||
}
|
||||
w.CloseDoor()
|
||||
t := time.Now()
|
||||
openDoorTimestamps[len(openDoorTimestamps)-1].Closed = &t
|
||||
return nil
|
||||
}
|
||||
|
||||
func cardRunner(w Wiegand) {
|
||||
for {
|
||||
card, err := w.GetCardUid()
|
||||
@ -159,7 +217,7 @@ func cardRunner(w Wiegand) {
|
||||
}
|
||||
|
||||
printCardId(card)
|
||||
hashedHex := hashCardUid(card)
|
||||
hashedHex := hash.HashCardUid(card)
|
||||
log.Println(hashedHex)
|
||||
|
||||
globalLock.Lock()
|
||||
@ -287,6 +345,9 @@ func reloadTokens() error {
|
||||
updateKeepOpenDoor(*cl.KeepOpenUntil)
|
||||
}
|
||||
|
||||
t := time.Now()
|
||||
lastSyncedTimestamp = &t
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -300,20 +361,20 @@ func updateKeepOpenDoor(newKeepOpenTime time.Time) {
|
||||
|
||||
if newKeepOpenTime.After(time.Now()) {
|
||||
log.Printf("Keeping door open until %v", newKeepOpenTime)
|
||||
wiegand.OpenDoor()
|
||||
OpenDoor(wiegand)
|
||||
timer := time.AfterFunc(time.Until(newKeepOpenTime), handleKeepDoorOpenCloseCleanup)
|
||||
keepDoorOpen = KeepDoorOpen{
|
||||
timer: timer,
|
||||
until: newKeepOpenTime,
|
||||
}
|
||||
} else {
|
||||
wiegand.CloseDoor()
|
||||
CloseDoor(wiegand)
|
||||
}
|
||||
}
|
||||
|
||||
func handleKeepDoorOpenCloseCleanup() {
|
||||
fmt.Println("Keep door open time is reached!")
|
||||
wiegand.CloseDoor()
|
||||
CloseDoor(wiegand)
|
||||
keepDoorOpen = KeepDoorOpen{}
|
||||
}
|
||||
|
||||
|
4
godoor_server/Makefile
Normal file
4
godoor_server/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
dev:
|
||||
GOOS=linux GOARCH=arm64 go build .
|
||||
scp godoor_server workshopdoor:/tmp/
|
||||
ssh workshopdoor 'mv -f /tmp/godoor_server ~/'
|
@ -1 +0,0 @@
|
||||
[{"token":{"uid_hash":"873636abbcf597a4835afc1c9b16a72eb6175b7ab278a8f18ab13c50172c90ea97cc3e258efd9cc1d885d7ea32d87fd006907892793e7cd6c468417bd8b8421a"}},{"token":{"uid_hash":"a08094343b4057777af4935b79df586d7eb999117883a53393e8b46f1ab19577b12039a5d2e0b9d0364bbed5c82d83a507492fea47ace633acf23da2dcf1560e"}},{"token":{"uid_hash":"d78271547cde009726b159dca09e53bee72feebe90b3eb7cb6e394caafc30bdb1f1567efc2f19bbdf3c6922e0bebed910ee4fa4f5b13bd379651da4f620f3559"}},{"token":{"uid_hash":"d72c87d0f077c7766f2985dfab30e8955c373a13a1e93d315203939f542ff86e73ee37c31f4c4b571f4719fa8e3589f12db8dcb57ea9f56764bb7d58f64cf705"}},{"token":{"uid_hash":"873636abbcf597a4835afc1c9b16a72eb6175b7ab278a8f18ab13c50172c90ea97cc3e258efd9cc1d885d7ea32d87fd006907892793e7cd6c468417bd8b8421a"}},{"token":{"uid_hash":"a08094343b4057777af4935b79df586d7eb999117883a53393e8b46f1ab19577b12039a5d2e0b9d0364bbed5c82d83a507492fea47ace633acf23da2dcf1560e"}},{"token":{"uid_hash":"d78271547cde009726b159dca09e53bee72feebe90b3eb7cb6e394caafc30bdb1f1567efc2f19bbdf3c6922e0bebed910ee4fa4f5b13bd379651da4f620f3559"}},{"token":{"uid_hash":"873636abbcf597a4835afc1c9b16a72eb6175b7ab278a8f18ab13c50172c90ea97cc3e258efd9cc1d885d7ea32d87fd006907892793e7cd6c468417bd8b8421a"}},{"token":{"uid_hash":"a08094343b4057777af4935b79df586d7eb999117883a53393e8b46f1ab19577b12039a5d2e0b9d0364bbed5c82d83a507492fea47ace633acf23da2dcf1560e"}},{"token":{"uid_hash":"d78271547cde009726b159dca09e53bee72feebe90b3eb7cb6e394caafc30bdb1f1567efc2f19bbdf3c6922e0bebed910ee4fa4f5b13bd379651da4f620f3559"}}]
|
40
hash/godoor_test.go
Normal file
40
hash/godoor_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package hash
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHash(t *testing.T) {
|
||||
hash := HashCardUid(0x000000000F0AD2301)
|
||||
if hash != "a6d9ba36ecb5f8e6312f40ee260ad59e9cca3c6ce073bf072df3324c0072886196e6823a7c758ab567fc53e91fbbda297a4efe0072e41316c56446ef126a5180" {
|
||||
t.Errorf("WRONG Key generated: %q", hash)
|
||||
}
|
||||
|
||||
hash = HashCardUid(0x3CBB5AAD)
|
||||
if hash != "1e7bbc1aeeff4bfe58ea8d97df7cd0f97599fa31633d3a1f57d138549b3968c20affb186fe0b85570d34718b273d269bcd28b2be59faf8122451d91a2cdc5f18" {
|
||||
t.Errorf("WRONG Key generated: %q", hash)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBits(t *testing.T) {
|
||||
|
||||
bits := make([]bool, 64)
|
||||
trueBits := []int{0, 1, 2, 3, 8, 10, 12, 13, 15, 18, 22, 23, 31}
|
||||
for _, i := range trueBits {
|
||||
bits[i] = true
|
||||
}
|
||||
|
||||
var card uint64 = 0
|
||||
for i := 63; i >= 0; i-- {
|
||||
if bits[i] == true {
|
||||
card |= 1 << (63 - i)
|
||||
}
|
||||
}
|
||||
|
||||
cardId := fmt.Sprintf("%x", card)
|
||||
fmt.Println(cardId)
|
||||
if card != 0xF0AD230100000000 {
|
||||
panic(fmt.Errorf("WROOONG: %x", card))
|
||||
}
|
||||
}
|
21
hash/hash.go
Normal file
21
hash/hash.go
Normal file
@ -0,0 +1,21 @@
|
||||
package hash
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
|
||||
"golang.org/x/crypto/scrypt"
|
||||
)
|
||||
|
||||
func HashCardUid(card uint64) string {
|
||||
b := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(b, card)
|
||||
|
||||
hashed, err := scrypt.Key(b, []byte("hkRXwLlQKmCJoy5qaahp"), 16384, 8, 1, 64)
|
||||
if err != nil {
|
||||
panic(err) // can only happen when scrypt params are garbage
|
||||
}
|
||||
|
||||
hashedHex := hex.EncodeToString(hashed)
|
||||
return hashedHex
|
||||
}
|
63
wiegand.go
63
wiegand.go
@ -1,15 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"golang.org/x/crypto/scrypt"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
import (
|
||||
"github.com/warthog618/gpiod"
|
||||
)
|
||||
|
||||
@ -29,41 +25,45 @@ type WiegandHW struct {
|
||||
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 printCardId(card uint64) {
|
||||
for i := 0; i < 7; i++ {
|
||||
fmt.Printf("%02x", (card>>(8*i))&0xff)
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
|
||||
func hashCardUid(card uint64) string {
|
||||
b := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(b, card)
|
||||
hashed, err := scrypt.Key(b, []byte(config.uidSalt), 16384, 8, 1, 64)
|
||||
if err != nil {
|
||||
panic(err) // can only happen when scrypt params are garbage
|
||||
}
|
||||
|
||||
hashedHex := hex.EncodeToString(hashed)
|
||||
return hashedHex
|
||||
}
|
||||
|
||||
func (w *WiegandHW) GetCardUid() (uint64, error) {
|
||||
// Wait for bit timeout
|
||||
@ -78,7 +78,7 @@ func (w *WiegandHW) GetCardUid() (uint64, error) {
|
||||
}
|
||||
|
||||
var card uint64 = 0
|
||||
for i := 63; i != 0; i-- {
|
||||
for i := 63; i >= 0; i-- {
|
||||
if w.bits[i] == true {
|
||||
card |= 1 << (63 - i)
|
||||
}
|
||||
@ -89,15 +89,15 @@ func (w *WiegandHW) GetCardUid() (uint64, error) {
|
||||
|
||||
func (w *WiegandHW) wiegandAEvent(evt gpiod.LineEvent) {
|
||||
w.bitTimeoutTimer.Reset(w.bitTimeout)
|
||||
w.bits[w.bitNr] = false
|
||||
fmt.Printf("0")
|
||||
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] = true
|
||||
fmt.Printf("1")
|
||||
w.bits[w.bitNr] = false
|
||||
fmt.Printf("0")
|
||||
w.bitNr += 1
|
||||
}
|
||||
|
||||
@ -139,3 +139,10 @@ func (w *WiegandHW) WiegandClose() {
|
||||
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")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user