Dmitry Yu Okunev лет назад: 7
Сommit
43d2e6e28f
4 измененных файлов с 182 добавлено и 0 удалено
  1. 2 0
      .gitignore
  2. 153 0
      main.go
  3. 13 0
      models/keepalive_record.go
  4. 14 0
      models/log_record.go

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+cardlogger-parser
+models/*_reform.go

+ 153 - 0
main.go

@@ -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
+}

+ 13 - 0
models/keepalive_record.go

@@ -0,0 +1,13 @@
+//go:generate reform --gofmt=false
+package models
+
+import (
+	"time"
+)
+
+//reform:keepalive
+type KeepaliveRecord struct {
+	Port      int       `reform:"port,pk"`
+	Counter   int64     `reform:"counter"`
+	UpdatedAt time.Time `reform:"updated_at"`
+}

+ 14 - 0
models/log_record.go

@@ -0,0 +1,14 @@
+//go:generate reform --gofmt=false
+package models
+
+import (
+	"time"
+)
+
+//reform:log
+type LogRecord struct {
+	Id        int       `reform:"id,pk"`
+	Port      int       `reform:"port"`
+	Value     int       `reform:"value"`
+	CreatedAt time.Time `reform:"created_at"`
+}