123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- //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
- }
|