Skip to content

Commit 0a6a83c

Browse files
authored
[skip changelog] Some PluggableMonitor client improvements (arduino#1475)
* Addde QUIT command in monitor-client * Use rpc.Port in pluggable monitor Open method * Slightly improved monitor client error messages * Fixed resource leaking in PluggableMonitor client * fixed i18n * Fixed test... ooops
1 parent 4708cde commit 0a6a83c

File tree

4 files changed

+79
-48
lines changed

4 files changed

+79
-48
lines changed

arduino/monitor/monitor.go

+48-26
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ import (
2424
"sync"
2525
"time"
2626

27-
"github.com/arduino/arduino-cli/arduino/discovery"
2827
"github.com/arduino/arduino-cli/cli/globals"
2928
"github.com/arduino/arduino-cli/executils"
3029
"github.com/arduino/arduino-cli/i18n"
30+
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
3131
"github.com/pkg/errors"
3232
"github.com/sirupsen/logrus"
3333
)
@@ -45,6 +45,7 @@ const (
4545
// PluggableMonitor is a tool that communicates with a board through a communication port.
4646
type PluggableMonitor struct {
4747
id string
48+
processArgs []string
4849
process *executils.Process
4950
outgoingCommandsPipe io.Writer
5051
incomingMessagesChan <-chan *monitorMessage
@@ -96,29 +97,12 @@ func (msg monitorMessage) String() string {
9697
var tr = i18n.Tr
9798

9899
// New create and connect to the given pluggable monitor
99-
func New(id string, args ...string) (*PluggableMonitor, error) {
100-
proc, err := executils.NewProcess(args...)
101-
if err != nil {
102-
return nil, err
103-
}
104-
stdout, err := proc.StdoutPipe()
105-
if err != nil {
106-
return nil, err
107-
}
108-
stdin, err := proc.StdinPipe()
109-
if err != nil {
110-
return nil, err
100+
func New(id string, args ...string) *PluggableMonitor {
101+
return &PluggableMonitor{
102+
id: id,
103+
processArgs: args,
104+
state: Dead,
111105
}
112-
messageChan := make(chan *monitorMessage)
113-
disc := &PluggableMonitor{
114-
id: id,
115-
process: proc,
116-
incomingMessagesChan: messageChan,
117-
outgoingCommandsPipe: stdin,
118-
state: Dead,
119-
}
120-
go disc.jsonDecodeLoop(stdout, messageChan)
121-
return disc, nil
122106
}
123107

124108
// GetID returns the identifier for this monitor
@@ -195,6 +179,25 @@ func (mon *PluggableMonitor) sendCommand(command string) error {
195179

196180
func (mon *PluggableMonitor) runProcess() error {
197181
logrus.Infof("starting monitor %s process", mon.id)
182+
proc, err := executils.NewProcess(mon.processArgs...)
183+
if err != nil {
184+
return err
185+
}
186+
stdout, err := proc.StdoutPipe()
187+
if err != nil {
188+
return err
189+
}
190+
stdin, err := proc.StdinPipe()
191+
if err != nil {
192+
return err
193+
}
194+
mon.outgoingCommandsPipe = stdin
195+
mon.process = proc
196+
197+
messageChan := make(chan *monitorMessage)
198+
mon.incomingMessagesChan = messageChan
199+
go mon.jsonDecodeLoop(stdout, messageChan)
200+
198201
if err := mon.process.Start(); err != nil {
199202
return err
200203
}
@@ -210,6 +213,9 @@ func (mon *PluggableMonitor) killProcess() error {
210213
if err := mon.process.Kill(); err != nil {
211214
return err
212215
}
216+
if err := mon.process.Wait(); err != nil {
217+
return err
218+
}
213219
mon.statusMutex.Lock()
214220
defer mon.statusMutex.Unlock()
215221
mon.state = Dead
@@ -284,14 +290,14 @@ func (mon *PluggableMonitor) Configure(param, value string) error {
284290
} else if msg.EventType != "configure" {
285291
return errors.Errorf(tr("communication out of sync, expected 'configure', received '%s'"), msg.EventType)
286292
} else if msg.Message != "OK" || msg.Error {
287-
return errors.Errorf(tr("command failed: %s"), msg.Message)
293+
return errors.Errorf(tr("configure failed: %s"), msg.Message)
288294
} else {
289295
return nil
290296
}
291297
}
292298

293299
// Open connects to the given Port. A communication channel is opened
294-
func (mon *PluggableMonitor) Open(port *discovery.Port) (io.ReadWriter, error) {
300+
func (mon *PluggableMonitor) Open(port *rpc.Port) (io.ReadWriter, error) {
295301
mon.statusMutex.Lock()
296302
defer mon.statusMutex.Unlock()
297303

@@ -320,7 +326,7 @@ func (mon *PluggableMonitor) Open(port *discovery.Port) (io.ReadWriter, error) {
320326
} else if msg.EventType != "open" {
321327
return nil, errors.Errorf(tr("communication out of sync, expected 'open', received '%s'"), msg.EventType)
322328
} else if msg.Message != "OK" || msg.Error {
323-
return nil, errors.Errorf(tr("command failed: %s"), msg.Message)
329+
return nil, errors.Errorf(tr("open failed: %s"), msg.Message)
324330
}
325331

326332
conn, err := tcpListener.Accept()
@@ -354,3 +360,19 @@ func (mon *PluggableMonitor) Close() error {
354360
return nil
355361
}
356362
}
363+
364+
// Quit terminates the monitor. No more commands can be accepted by the monitor.
365+
func (mon *PluggableMonitor) Quit() error {
366+
if err := mon.sendCommand("QUIT\n"); err != nil {
367+
return err
368+
}
369+
if msg, err := mon.waitMessage(time.Second * 10); err != nil {
370+
return fmt.Errorf(tr("calling %[1]s: %[2]w"), "QUIT", err)
371+
} else if msg.EventType != "quit" {
372+
return errors.Errorf(tr("communication out of sync, expected 'quit', received '%s'"), msg.EventType)
373+
} else if msg.Message != "OK" || msg.Error {
374+
return errors.Errorf(tr("command failed: %s"), msg.Message)
375+
}
376+
mon.killProcess()
377+
return nil
378+
}

arduino/monitor/monitor_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ func TestDummyMonitor(t *testing.T) {
4444
require.NoError(t, builder.Run())
4545

4646
// Run dummy-monitor and test if everything is working as expected
47-
mon, err := New("dummy", "testdata/dummy-monitor")
48-
require.NoError(t, err)
47+
mon := New("dummy", "testdata/dummy-monitor")
4948
err = mon.Run()
5049
require.NoError(t, err)
5150

@@ -60,11 +59,12 @@ func TestDummyMonitor(t *testing.T) {
6059
err = mon.Configure("speed", "38400")
6160
require.NoError(t, err)
6261

63-
rw, err := mon.Open(&discovery.Port{Address: "/dev/ttyACM0", Protocol: "test"})
62+
port := &discovery.Port{Address: "/dev/ttyACM0", Protocol: "test"}
63+
rw, err := mon.Open(port.ToRPC())
6464
require.NoError(t, err)
6565

6666
// Double open -> error: port already opened
67-
_, err = mon.Open(&discovery.Port{Address: "/dev/ttyACM0", Protocol: "test"})
67+
_, err = mon.Open(port.ToRPC())
6868
require.Error(t, err)
6969

7070
// Write "TEST"
@@ -93,7 +93,7 @@ func TestDummyMonitor(t *testing.T) {
9393
time.Sleep(100 * time.Millisecond)
9494
require.Equal(t, int32(1), atomic.LoadInt32(&completed))
9595

96-
rw, err = mon.Open(&discovery.Port{Address: "/dev/ttyACM0", Protocol: "test"})
96+
rw, err = mon.Open(port.ToRPC())
9797
require.NoError(t, err)
9898
n, err = rw.Write([]byte("TEST"))
9999
require.NoError(t, err)

i18n/data/en.po

+22-13
Original file line numberDiff line numberDiff line change
@@ -2394,7 +2394,8 @@ msgstr "boardname"
23942394
#: arduino/discovery/discovery.go:375
23952395
#: arduino/discovery/discovery.go:392
23962396
#: arduino/discovery/discovery.go:415
2397-
#: arduino/monitor/monitor.go:246
2397+
#: arduino/monitor/monitor.go:252
2398+
#: arduino/monitor/monitor.go:370
23982399
msgid "calling %[1]s: %[2]w"
23992400
msgstr "calling %[1]s: %[2]w"
24002401

@@ -2447,40 +2448,40 @@ msgstr "command"
24472448
#: arduino/discovery/discovery.go:379
24482449
#: arduino/discovery/discovery.go:396
24492450
#: arduino/discovery/discovery.go:419
2450-
#: arduino/monitor/monitor.go:250
2451-
#: arduino/monitor/monitor.go:270
2452-
#: arduino/monitor/monitor.go:287
2453-
#: arduino/monitor/monitor.go:323
2454-
#: arduino/monitor/monitor.go:351
2451+
#: arduino/monitor/monitor.go:256
2452+
#: arduino/monitor/monitor.go:276
2453+
#: arduino/monitor/monitor.go:357
2454+
#: arduino/monitor/monitor.go:374
24552455
msgid "command failed: %s"
24562456
msgstr "command failed: %s"
24572457

2458-
#: arduino/monitor/monitor.go:349
2458+
#: arduino/monitor/monitor.go:355
24592459
msgid "communication out of sync, expected 'close', received '%s'"
24602460
msgstr "communication out of sync, expected 'close', received '%s'"
24612461

2462-
#: arduino/monitor/monitor.go:285
2462+
#: arduino/monitor/monitor.go:291
24632463
msgid "communication out of sync, expected 'configure', received '%s'"
24642464
msgstr "communication out of sync, expected 'configure', received '%s'"
24652465

2466-
#: arduino/monitor/monitor.go:268
2466+
#: arduino/monitor/monitor.go:274
24672467
msgid "communication out of sync, expected 'describe', received '%s'"
24682468
msgstr "communication out of sync, expected 'describe', received '%s'"
24692469

24702470
#: arduino/discovery/discovery.go:313
2471-
#: arduino/monitor/monitor.go:248
2471+
#: arduino/monitor/monitor.go:254
24722472
msgid "communication out of sync, expected 'hello', received '%s'"
24732473
msgstr "communication out of sync, expected 'hello', received '%s'"
24742474

24752475
#: arduino/discovery/discovery.go:394
24762476
msgid "communication out of sync, expected 'list', received '%s'"
24772477
msgstr "communication out of sync, expected 'list', received '%s'"
24782478

2479-
#: arduino/monitor/monitor.go:321
2479+
#: arduino/monitor/monitor.go:327
24802480
msgid "communication out of sync, expected 'open', received '%s'"
24812481
msgstr "communication out of sync, expected 'open', received '%s'"
24822482

24832483
#: arduino/discovery/discovery.go:377
2484+
#: arduino/monitor/monitor.go:372
24842485
msgid "communication out of sync, expected 'quit', received '%s'"
24852486
msgstr "communication out of sync, expected 'quit', received '%s'"
24862487

@@ -2500,6 +2501,10 @@ msgstr "communication out of sync, expected 'stop', received '%s'"
25002501
msgid "computing hash: %s"
25012502
msgstr "computing hash: %s"
25022503

2504+
#: arduino/monitor/monitor.go:293
2505+
msgid "configure failed: %s"
2506+
msgstr "configure failed: %s"
2507+
25032508
#: commands/upload/upload.go:611
25042509
msgid "could not find a valid build artifact"
25052510
msgstr "could not find a valid build artifact"
@@ -2962,6 +2967,10 @@ msgstr "no valid sketch found in %[1]s: missing %[2]s"
29622967
msgid "no versions available for the current OS"
29632968
msgstr "no versions available for the current OS"
29642969

2970+
#: arduino/monitor/monitor.go:329
2971+
msgid "open failed: %s"
2972+
msgstr "open failed: %s"
2973+
29652974
#: arduino/resources/checksums.go:72
29662975
#: arduino/resources/install.go:59
29672976
msgid "opening archive file: %s"
@@ -3051,7 +3060,7 @@ msgid "port not found: %[1]s %[2]s"
30513060
msgstr "port not found: %[1]s %[2]s"
30523061

30533062
#: arduino/discovery/discovery.go:317
3054-
#: arduino/monitor/monitor.go:252
3063+
#: arduino/monitor/monitor.go:258
30553064
msgid "protocol version not supported: requested 1, got %d"
30563065
msgstr "protocol version not supported: requested 1, got %d"
30573066

@@ -3241,7 +3250,7 @@ msgstr "the server responded with status %s"
32413250
msgid "timeout waiting for message from %s"
32423251
msgstr "timeout waiting for message from %s"
32433252

3244-
#: arduino/monitor/monitor.go:177
3253+
#: arduino/monitor/monitor.go:161
32453254
msgid "timeout waiting for message from monitor %s"
32463255
msgstr "timeout waiting for message from monitor %s"
32473256

i18n/rice-box.go

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)