|
@@ -0,0 +1,153 @@
|
|
|
+//go:generate reform --gofmt=false models
|
|
|
+
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "database/sql"
|
|
|
+ "devel.mephi.ru/dyokunev/cardlogger-parser/models"
|
|
|
+ "fmt"
|
|
|
+ "net"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+func checkError(err error) {
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+type stage int
|
|
|
+const (
|
|
|
+ STAGE_IDLE stage = 0
|
|
|
+ STAGE_KEEPALIVE stage = 1
|
|
|
+ STAGE_STARTING stage = 2
|
|
|
+ STAGE_GETTINGVALUE stage = 3
|
|
|
+)
|
|
|
+
|
|
|
+type status struct {
|
|
|
+ Stage stage
|
|
|
+ Pos byte
|
|
|
+ T byte
|
|
|
+ Value [3]int
|
|
|
+}
|
|
|
+
|
|
|
+func gotKeepAlive(port int) {
|
|
|
+ //fmt.Println("gotKeepAlive(): port == ", port)
|
|
|
+
|
|
|
+ keepaliveRecord, err := models.KeepaliveRecordSQL.First(port)
|
|
|
+ if err != nil && err != sql.ErrNoRows {
|
|
|
+ fmt.Println("SQL error: ", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ keepaliveRecord.UpdatedAt = time.Now()
|
|
|
+ err = keepaliveRecord.Save()
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("SQL error: ", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func gotValue(port int, valueA [3]int) {
|
|
|
+ //fmt.Println("gotValue(): port == ", port, "; valueA == ", valueA)
|
|
|
+ if valueA[0] != valueA[1] || valueA[1] != valueA[2] {
|
|
|
+ fmt.Println("values doesn't match: ", valueA, "; port == ", port)
|
|
|
+ }
|
|
|
+
|
|
|
+ err := models.LogRecord{
|
|
|
+ Port: port,
|
|
|
+ Value: valueA[0],
|
|
|
+ CreatedAt: time.Now(),
|
|
|
+ }.Create()
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("SQL error: ", err)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func main() {
|
|
|
+ addr, err := net.ResolveUDPAddr("udp", ":36400")
|
|
|
+ checkError(err)
|
|
|
+
|
|
|
+ conn, err := net.ListenUDP("udp", addr)
|
|
|
+ checkError(err)
|
|
|
+ defer conn.Close()
|
|
|
+
|
|
|
+ buf := make([]byte, 1024)
|
|
|
+
|
|
|
+ curStatusMap := make(map[int]status)
|
|
|
+
|
|
|
+ considerChar := func(port int, c byte) {
|
|
|
+ curStatus := curStatusMap[port]
|
|
|
+ defer func() { /*fmt.Println("curStatus ->", curStatus);*/ curStatusMap[port] = curStatus }()
|
|
|
+
|
|
|
+ switch curStatus.Stage {
|
|
|
+ case STAGE_IDLE:
|
|
|
+ switch c {
|
|
|
+ case 0xfe:
|
|
|
+ curStatus.Stage = STAGE_KEEPALIVE
|
|
|
+ case 0xff:
|
|
|
+ curStatus.Stage = STAGE_STARTING
|
|
|
+ default:
|
|
|
+ goto errorReset
|
|
|
+ }
|
|
|
+ curStatus.Pos = 1
|
|
|
+ case STAGE_KEEPALIVE:
|
|
|
+ if c != 0xfe {
|
|
|
+ goto errorReset
|
|
|
+ }
|
|
|
+ curStatus.Pos++
|
|
|
+ if curStatus.Pos == 4 {
|
|
|
+ gotKeepAlive(port)
|
|
|
+ goto reset
|
|
|
+ }
|
|
|
+ return
|
|
|
+ case STAGE_STARTING:
|
|
|
+ if c != 0xff-curStatus.Pos {
|
|
|
+ goto errorReset
|
|
|
+ }
|
|
|
+ curStatus.Pos++
|
|
|
+ if curStatus.Pos == 4 {
|
|
|
+ curStatus.Pos = 0
|
|
|
+ curStatus.Stage = STAGE_GETTINGVALUE
|
|
|
+ return
|
|
|
+ }
|
|
|
+ case STAGE_GETTINGVALUE:
|
|
|
+ curStatus.Value[curStatus.T] |= int(c) << (curStatus.Pos * 8)
|
|
|
+ curStatus.Pos++
|
|
|
+ if curStatus.Pos != 4 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ curStatus.Pos = 0
|
|
|
+ curStatus.T++
|
|
|
+
|
|
|
+ if curStatus.T != 3 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ gotValue(port, curStatus.Value)
|
|
|
+ goto reset
|
|
|
+ default:
|
|
|
+ panic(fmt.Errorf("Unknown stage: %v", curStatus.Stage))
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+ errorReset:
|
|
|
+ fmt.Println("got invalid char (", c, ") from port ", port ,", reset (curStatus == ", curStatus, ").")
|
|
|
+ reset:
|
|
|
+// fmt.Println("reset")
|
|
|
+ curStatus = status{}
|
|
|
+ }
|
|
|
+
|
|
|
+ for {
|
|
|
+ n, addr, err := conn.ReadFromUDP(buf)
|
|
|
+
|
|
|
+ for i := 0; i < n; i++ {
|
|
|
+ considerChar(addr.Port, buf[i])
|
|
|
+ }
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error: ", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|