-
Notifications
You must be signed in to change notification settings - Fork 1
/
serial.go
107 lines (85 loc) · 2.33 KB
/
serial.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package core
import (
"fmt"
"os"
"os/signal"
"syscall"
log "github.com/sirupsen/logrus"
"github.com/tarm/serial"
)
// SerialPort represents a board port on which to stream logs
//go:generate mockgen -destination=../mocks/mock_serial.go -package=mocks github.com/robgonnella/ardi/v2/core SerialPort
type SerialPort interface {
Watch() error
Stop()
IsStreaming() bool
}
// ArdiSerialPort represents our serial port wrapper
type ArdiSerialPort struct {
stream *serial.Port
name string
baud int
logger *log.Logger
}
// NewArdiSerialPort returns instance of serial port wrapper
func NewArdiSerialPort(name string, baud int, logger *log.Logger) SerialPort {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
serialPort := &ArdiSerialPort{
name: name,
baud: baud,
logger: logger,
}
go func() {
<-sigs
logger.Debug("gracefully shutting down serial port stream")
serialPort.Stop()
}()
return serialPort
}
// Watch connects to a serial port and prints any logs received.
func (p *ArdiSerialPort) Watch() error {
defer p.Stop()
logFields := log.Fields{"baud": p.baud, "name": p.name}
p.Stop()
p.logger.Info("Watching logs...")
config := &serial.Config{Name: p.name, Baud: p.baud}
stream, err := serial.OpenPort(config)
if err != nil {
p.logger.WithError(err).WithFields(logFields).Warn("Failed to read from device")
return err
}
p.stream = stream
for {
if p.stream == nil {
break
}
var buf = make([]byte, 128)
n, err := stream.Read(buf)
if err != nil {
p.logger.WithError(err).WithFields(logFields).Warn("Failed to read from serial port")
return err
}
fmt.Printf("%s", buf[:n])
}
return nil
}
// Stop printing serial port logs
func (p *ArdiSerialPort) Stop() {
logWithField := p.logger.WithField("name", p.name)
if p.stream != nil {
logWithField.Debug("Closing serial port connection")
if err := p.stream.Flush(); err != nil {
logWithField.WithError(err).Debug("Failed to flush serial port connection")
}
if err := p.stream.Close(); err != nil {
logWithField.WithError(err).Debug("Failed to close serial port connection")
}
p.stream = nil
logWithField.Debug("Serial port closed")
}
}
// IsStreaming returns whether or not we are currently printing logs from port
func (p *ArdiSerialPort) IsStreaming() bool {
return p.stream != nil
}