package shroom_internals import ( "database/sql" "encoding/json" "log" "net" "sync" ) func newlinePos(s []byte) int { for i, v := range s { if v == '\n' { return i } } return -1 } type ShroomData struct { Time uint64 Temperature float32 Humidity float32 HumidifierVolts float32 Status uint32 } type ShroomStatusData struct { Status uint32 NumConnections int } type ShroomStatus struct { Status uint32 NumConnections int Lock sync.RWMutex } func InitTcpServer(db *sql.DB, status *ShroomStatus) { // TODO start TCP server for the pipe from the raspberry pi ln, err := net.Listen("tcp", ":9876") if err != nil { log.Fatal("unable to open tcp server: ", err) } go func() { for { conn, err := ln.Accept() if err != nil { log.Println("tcp accept error: ", err) continue } status.Lock.Lock() status.NumConnections += 1 status.Lock.Unlock() defer func() { status.Lock.Lock() status.NumConnections -= 1 status.Lock.Unlock() log.Println("connection disconnected") }() log.Println("connection started") go func() { // TODO deal with the write side of the connection }() // deal with the read side of the connection buf := make([]byte, 128) left := buf for { num_read, err := conn.Read(left) left = left[num_read:] //log.Println("buf ", buf) //log.Println("left ", left) if err != nil { log.Println("tcp read error: ", err) _ = conn.Close() log.Println("disconnected from client") break } // parse the message to see if it's finished unread := buf[:len(buf)-len(left)] for newlinePos(unread) != -1 { end := newlinePos(unread) line := unread[:end] unread = unread[end+1:] //log.Println("line ", line) //log.Println("unread ", unread) // skip empty lines if len(line) == 0 { continue } data := ShroomData{ Time: 0, Temperature: -1, Humidity: -1, HumidifierVolts: -1, Status: 0, } err := json.Unmarshal(line, &data) if err != nil { log.Println("unable to read humdifier data: ", err) log.Println(string(line)) log.Println(line) continue } if data.Time > 0 && data.Temperature > 0 && data.Humidity > 0 && data.HumidifierVolts > 0 { // we got a data packet _, err = db.Exec("INSERT INTO shrooms (time, temperature, humidity, humidifier_volts) VALUES (?, ?, ?, ?)", data.Time, data.Temperature, data.Humidity, data.HumidifierVolts) if err != nil { log.Println("unable to write to database: ", err) } } else if data.Status > 0 { status.Lock.Lock() // TODO change to have more detailed data status.Status = data.Status status.Lock.Unlock() } else { log.Println("unknown packet: ", line) } } // shift the remaining data back to the start of the buffer copy(buf[:len(unread)], unread) left = buf[len(unread):] } } }() }