/
monitor.go
134 lines (108 loc) · 2.88 KB
/
monitor.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright (C) 2021 Toitware ApS. All rights reserved.
// Use of this source code is governed by an MIT-style license that can be
// found in the LICENSE file.
package commands
import (
"bufio"
"fmt"
"io"
"os"
"time"
"github.com/spf13/cobra"
"go.bug.st/serial"
)
func MonitorCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "monitor",
Short: "Monitor the serial output of an ESP32",
Args: cobra.NoArgs,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
port, err := cmd.Flags().GetString("port")
if err != nil {
return err
}
if port, err = CheckPort(port); err != nil {
return err
}
baud, err := cmd.Flags().GetUint("baud")
if err != nil {
return err
}
attach, err := cmd.Flags().GetBool("attach")
if err != nil {
return err
}
pretty, err := cmd.Flags().GetBool("force-pretty")
if err != nil {
return err
}
plain, err := cmd.Flags().GetBool("force-plain")
if err != nil {
return err
}
fmt.Printf("Starting serial monitor of port '%s' ...\n", port)
dev, err := serialOpen(port, &serial.Mode{
BaudRate: int(baud),
})
if err != nil {
return err
}
if !attach {
dev.Reboot()
}
var logReader io.Reader = dev
shouldProxy, err := cmd.Flags().GetBool("proxy")
if err != nil {
return err
}
if shouldProxy {
ch1, ch2 := multiplexReader(dev)
logReader = ch1
go runUartProxy(dev, ch2)
}
scanner := bufio.NewScanner(logReader)
envelope, err := cmd.Flags().GetString("envelope")
if err != nil {
return err
}
decoder := NewDecoder(scanner, cmd.Context(), envelope)
decoder.decode(pretty, plain)
return scanner.Err()
},
}
cmd.Flags().StringP("port", "p", ConfiguredPort(), "port to monitor")
cmd.Flags().BoolP("attach", "a", false, "attach to the serial output without rebooting it")
cmd.Flags().BoolP("force-pretty", "r", false, "force output to use terminal graphics")
cmd.Flags().BoolP("force-plain", "l", false, "force output to use plain ASCII text")
cmd.Flags().Uint("baud", 115200, "the baud rate for serial monitoring")
cmd.Flags().Bool("proxy", false, "proxy the connected device to the local network")
cmd.Flags().String("envelope", "", "name or path of the firmware envelope")
return cmd
}
func serialOpen(port string, mode *serial.Mode) (*serialPort, error) {
dev, err := serial.Open(port, mode)
if os.IsNotExist(err) {
return nil, fmt.Errorf("the port '%s' was not found", port)
}
if err != nil {
return nil, err
}
return &serialPort{dev}, err
}
type serialPort struct {
serial.Port
}
func (s serialPort) Read(buf []byte) (n int, err error) {
n, err = s.Port.Read(buf)
if err == nil && n == 0 {
return 0, io.ErrUnexpectedEOF
}
return n, err
}
func (s *serialPort) Reboot() {
s.SetDTR(false)
s.SetRTS(true)
time.Sleep(100 * time.Millisecond)
s.SetRTS(false)
}