200 lines
4.5 KiB
Go
200 lines
4.5 KiB
Go
package core
|
|
|
|
import (
|
|
"fmt"
|
|
"git.timovolkmann.de/gyrogpsc/ublox"
|
|
"github.com/sirupsen/logrus"
|
|
"go.bug.st/serial"
|
|
"net"
|
|
"os"
|
|
"sync"
|
|
)
|
|
|
|
type Collector interface {
|
|
Collect()
|
|
Close()
|
|
}
|
|
|
|
type CollectorType uint8
|
|
|
|
const (
|
|
SERIAL CollectorType = iota
|
|
TCP
|
|
)
|
|
|
|
var tcpSingleton *tcpCollector
|
|
|
|
func NewCollector(typ CollectorType, proc Pusher, config *Configuration) Collector {
|
|
var coll Collector
|
|
switch typ {
|
|
case SERIAL:
|
|
coll = newSerial(proc, config)
|
|
case TCP:
|
|
if tcpSingleton == nil {
|
|
tcpSingleton = newTcp(proc, config)
|
|
} else {
|
|
tcpSingleton.SetProcessor(proc)
|
|
}
|
|
coll = tcpSingleton
|
|
default:
|
|
panic("selected collector type not implemented")
|
|
}
|
|
return coll
|
|
}
|
|
|
|
type serialCollector struct {
|
|
active bool
|
|
proc Pusher
|
|
config *Configuration
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
func (s *serialCollector) isSerialCollActive() bool {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
return s.active
|
|
}
|
|
|
|
|
|
func (s *serialCollector) Collect() {
|
|
s.mu.Lock()
|
|
s.active = true
|
|
s.mu.Unlock()
|
|
go func() {
|
|
logrus.Println("start serial collector")
|
|
mode := &serial.Mode{
|
|
BaudRate: 115200,
|
|
}
|
|
port, err := serial.Open(s.config.Collectors.SerialCollectorPort, mode)
|
|
if err != nil {
|
|
logrus.Fatalln("can't open serial port:", err.Error())
|
|
}
|
|
defer port.Close()
|
|
|
|
decoder := ublox.NewDecoder(port)
|
|
|
|
for s.isSerialCollActive() {
|
|
meas, err := decoder.Decode()
|
|
if err != nil {
|
|
if err.Error() == "NMEA not implemented" {
|
|
continue
|
|
}
|
|
logrus.Println("serial read err:", err)
|
|
break
|
|
}
|
|
sd, err := ConvertUbxToSensorData(meas)
|
|
if err != nil {
|
|
logrus.Println("convert err:", err, meas, sd)
|
|
continue
|
|
}
|
|
// skip irrelevant messages
|
|
if sd == nil {
|
|
continue
|
|
}
|
|
|
|
err = s.proc.Push(sd)
|
|
if err != nil {
|
|
logrus.Println("process err:", err, *sd)
|
|
continue
|
|
}
|
|
}
|
|
logrus.Println("serial collector stopped")
|
|
}()
|
|
}
|
|
|
|
|
|
|
|
func (s *serialCollector) Close() {
|
|
s.mu.Lock()
|
|
s.active = false
|
|
s.mu.Unlock()
|
|
}
|
|
|
|
func newSerial(proc Pusher, config *Configuration) *serialCollector {
|
|
return &serialCollector{
|
|
active: false,
|
|
proc: proc,
|
|
config: config,
|
|
}
|
|
}
|
|
|
|
type tcpCollector struct {
|
|
active bool
|
|
processor Pusher
|
|
//config *Configuration
|
|
}
|
|
|
|
func (t *tcpCollector) Collect() {
|
|
t.active = true
|
|
}
|
|
|
|
func (t *tcpCollector) Close() {
|
|
t.active = false
|
|
}
|
|
|
|
func (t *tcpCollector) SetProcessor(p Pusher) {
|
|
t.processor = p
|
|
}
|
|
|
|
func newTcp(proc Pusher, config *Configuration) *tcpCollector {
|
|
logrus.Println("start tcp collector")
|
|
|
|
listener, err := net.Listen("tcp", config.Collectors.TcpCollectorPort)
|
|
if err != nil {
|
|
fmt.Println("Error listening:", err)
|
|
//os.Exit(1)
|
|
}
|
|
coll := &tcpCollector{
|
|
active: false,
|
|
processor: proc,
|
|
}
|
|
go func() {
|
|
for {
|
|
// Listen for an incoming connection.
|
|
conn, err := listener.Accept()
|
|
if err != nil {
|
|
fmt.Println("Error accepting: ", err.Error())
|
|
os.Exit(1)
|
|
}
|
|
logrus.Println("...new incoming tcp connection...")
|
|
|
|
// Handle connections in a new goroutine.
|
|
go coll.jsonHandler(conn)
|
|
}
|
|
}()
|
|
return coll
|
|
}
|
|
|
|
// handles incoming tcp connections with json payload.
|
|
func (c *tcpCollector) jsonHandler(conn net.Conn) {
|
|
|
|
defer conn.Close()
|
|
|
|
// TRY reader := bufio.NewReader(conn) OR NewScanner(conn)
|
|
buf := make([]byte, 2048)
|
|
for {
|
|
// Read the incoming connection into the buffer.
|
|
n, err := conn.Read(buf)
|
|
if err != nil {
|
|
fmt.Println("TCP error - reading from connection:", n, err.Error())
|
|
break
|
|
}
|
|
//json := pretty.Pretty(buf[:n])
|
|
//fmt.Println(string(json))
|
|
//fmt.Println(string(buf[:n]))
|
|
sd, err := ConvertSensorDataPhone(buf[:n])
|
|
if err != nil {
|
|
logrus.Println(err)
|
|
continue
|
|
}
|
|
if !c.active {
|
|
//time.Sleep(50 * time.Millisecond)
|
|
continue
|
|
}
|
|
err = c.processor.Push(sd)
|
|
if err != nil {
|
|
logrus.Fatalln(err)
|
|
}
|
|
}
|
|
}
|