@@ -18,6 +18,7 @@ package arguments
18
18
import (
19
19
"fmt"
20
20
"net/url"
21
+ "time"
21
22
22
23
"github.com/arduino/arduino-cli/arduino/discovery"
23
24
"github.com/arduino/arduino-cli/arduino/sketch"
@@ -34,25 +35,21 @@ import (
34
35
type Port struct {
35
36
address string
36
37
protocol string
38
+ timeout time.Duration
37
39
}
38
40
39
41
// AddToCommand adds the flags used to set port and protocol to the specified Command
40
42
func (p * Port ) AddToCommand (cmd * cobra.Command ) {
41
43
cmd .Flags ().StringVarP (& p .address , "port" , "p" , "" , "Upload port address, e.g.: COM3 or /dev/ttyACM2" )
42
44
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" )
43
46
}
44
47
45
48
// GetPort returns the Port obtained by parsing command line arguments.
46
49
// The extra metadata for the ports is obtained using the pluggable discoveries.
47
50
func (p * Port ) GetPort (instance * rpc.Instance , sk * sketch.Sketch ) (* discovery.Port , error ) {
48
51
address := p .address
49
52
protocol := p .protocol
50
- if address != "" && protocol != "" {
51
- return & discovery.Port {
52
- Address : address ,
53
- Protocol : protocol ,
54
- }, nil
55
- }
56
53
57
54
if address == "" && sk != nil && sk .Metadata != nil {
58
55
deviceURI , err := url .Parse (sk .Metadata .CPU .Port )
@@ -76,8 +73,9 @@ func (p *Port) GetPort(instance *rpc.Instance, sk *sketch.Sketch) (*discovery.Po
76
73
if err := pm .DiscoveryManager ().RunAll (); err != nil {
77
74
return nil , err
78
75
}
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 )
81
79
}
82
80
83
81
defer func () {
@@ -88,28 +86,27 @@ func (p *Port) GetPort(instance *rpc.Instance, sk *sketch.Sketch) (*discovery.Po
88
86
}
89
87
}()
90
88
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
+ }
92
100
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
101
108
}
109
+ return nil , fmt .Errorf ("port not found: %s %s" , address , protocol )
102
110
}
103
111
}
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
115
112
}
0 commit comments