Skip to content

Commit 272e35d

Browse files
committed
Implemented port/protocol detection at CLI startup time
1 parent e6de840 commit 272e35d

File tree

1 file changed

+25
-28
lines changed

1 file changed

+25
-28
lines changed

cli/arguments/port.go

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package arguments
1818
import (
1919
"fmt"
2020
"net/url"
21+
"time"
2122

2223
"github.com/arduino/arduino-cli/arduino/discovery"
2324
"github.com/arduino/arduino-cli/arduino/sketch"
@@ -34,25 +35,21 @@ import (
3435
type Port struct {
3536
address string
3637
protocol string
38+
timeout time.Duration
3739
}
3840

3941
// AddToCommand adds the flags used to set port and protocol to the specified Command
4042
func (p *Port) AddToCommand(cmd *cobra.Command) {
4143
cmd.Flags().StringVarP(&p.address, "port", "p", "", "Upload port address, e.g.: COM3 or /dev/ttyACM2")
4244
cmd.Flags().StringVarP(&p.protocol, "protocol", "l", "", "Upload port protocol, e.g: serial")
45+
cmd.Flags().DurationVar(&p.timeout, "discovery-timeout", 5*time.Second, "Max time to wait for port discovery, e.g.: 30s, 1m")
4346
}
4447

4548
// GetPort returns the Port obtained by parsing command line arguments.
4649
// The extra metadata for the ports is obtained using the pluggable discoveries.
4750
func (p *Port) GetPort(instance *rpc.Instance, sk *sketch.Sketch) (*discovery.Port, error) {
4851
address := p.address
4952
protocol := p.protocol
50-
if address != "" && protocol != "" {
51-
return &discovery.Port{
52-
Address: address,
53-
Protocol: protocol,
54-
}, nil
55-
}
5653

5754
if address == "" && sk != nil && sk.Metadata != nil {
5855
deviceURI, err := url.Parse(sk.Metadata.CPU.Port)
@@ -76,8 +73,9 @@ func (p *Port) GetPort(instance *rpc.Instance, sk *sketch.Sketch) (*discovery.Po
7673
if err := pm.DiscoveryManager().RunAll(); err != nil {
7774
return nil, err
7875
}
79-
if err := pm.DiscoveryManager().StartAll(); err != nil {
80-
return nil, err
76+
eventChan, errs := pm.DiscoveryManager().StartSyncAll()
77+
if len(errs) > 0 {
78+
return nil, fmt.Errorf("%v", errs)
8179
}
8280

8381
defer func() {
@@ -88,28 +86,27 @@ func (p *Port) GetPort(instance *rpc.Instance, sk *sketch.Sketch) (*discovery.Po
8886
}
8987
}()
9088

91-
ports := pm.DiscoveryManager().List()
89+
deadline := time.After(p.timeout)
90+
for {
91+
select {
92+
case portEvent := <-eventChan:
93+
if portEvent.Type != "add" {
94+
continue
95+
}
96+
port := portEvent.Port
97+
if (protocol == "" || protocol == port.Protocol) && address == port.Address {
98+
return port, nil
99+
}
92100

93-
matchingPorts := []*discovery.Port{}
94-
for _, port := range ports {
95-
if address == port.Address {
96-
matchingPorts = append(matchingPorts, port)
97-
if len(matchingPorts) > 1 {
98-
// Too many matching ports found, can't handle this case.
99-
// This must never happen.
100-
return nil, fmt.Errorf("multiple ports found matching address %s", address)
101+
case <-deadline:
102+
// No matching port found
103+
if protocol == "" {
104+
return &discovery.Port{
105+
Address: address,
106+
Protocol: "serial",
107+
}, nil
101108
}
109+
return nil, fmt.Errorf("port not found: %s %s", address, protocol)
102110
}
103111
}
104-
105-
if len(matchingPorts) == 1 {
106-
// Only one matching port found, use it
107-
return matchingPorts[0], nil
108-
}
109-
110-
// In case no matching port is found assume the address refers to a serial port
111-
return &discovery.Port{
112-
Address: address,
113-
Protocol: "serial",
114-
}, nil
115112
}

0 commit comments

Comments
 (0)