18
18
package board
19
19
20
20
import (
21
+ "encoding/json"
21
22
"fmt"
23
+ "os"
24
+ "sort"
22
25
"time"
23
26
24
- "github.com/arduino/arduino-cli/arduino/cores/packagemanager"
27
+ "github.com/arduino/arduino-cli/output"
28
+
29
+ "github.com/arduino/arduino-cli/arduino/discovery"
25
30
"github.com/arduino/arduino-cli/commands"
31
+ "github.com/arduino/arduino-cli/commands/core"
26
32
"github.com/arduino/arduino-cli/common/formatter"
27
- "github.com/arduino/arduino-cli/common/formatter/output"
28
- "github.com/arduino/board-discovery"
29
- "github.com/codeclysm/cc"
30
33
"github.com/spf13/cobra"
31
34
)
32
35
@@ -50,95 +53,124 @@ var listFlags struct {
50
53
}
51
54
52
55
// runListCommand detects and lists the connected arduino boards
53
- // (either via serial or network ports).
54
56
func runListCommand (cmd * cobra.Command , args []string ) {
55
57
pm := commands .InitPackageManager ()
56
58
57
- monitor := discovery .New (time .Millisecond )
58
- monitor .Start ()
59
- duration , err := time .ParseDuration (listFlags .timeout )
59
+ timeout , err := time .ParseDuration (listFlags .timeout )
60
60
if err != nil {
61
- duration = time .Second * 5
61
+ formatter .PrintError (err , "Invalid timeout." )
62
+ os .Exit (commands .ErrBadArgument )
62
63
}
63
- if formatter .IsCurrentFormat ("text" ) {
64
- stoppable := cc .Run (func (stop chan struct {}) {
65
- for {
66
- select {
67
- case <- stop :
68
- fmt .Print ("\r \r " )
69
- return
70
- default :
71
- fmt .Print ("\r Discovering. " )
72
- time .Sleep (time .Millisecond * 500 )
73
- fmt .Print ("\r Discovering.. " )
74
- time .Sleep (time .Millisecond * 500 )
75
- fmt .Print ("\r Discovering..." )
76
- time .Sleep (time .Millisecond * 500 )
77
- }
78
- }
79
- })
80
64
81
- fmt .Print ("\r " )
82
65
83
- time .Sleep (duration )
84
- stoppable .Stop ()
85
- <- stoppable .Stopped
86
- } else {
87
- time .Sleep (duration )
66
+ discoveries := discovery .ExtractDiscoveriesFromPlatforms (pm )
67
+
68
+ res := []* detectedPort {}
69
+ for discName , disc := range discoveries {
70
+ disc .Timeout = timeout
71
+ disc .Start ()
72
+ defer disc .Close ()
73
+
74
+ ports , err := disc .List ()
75
+ if err != nil {
76
+ fmt .Printf ("Error getting port list from discovery %s: %s\n " , discName , err )
77
+ continue
78
+ }
79
+ for _ , port := range ports {
80
+ b := detectedBoards {}
81
+ for _ , board := range pm .IdentifyBoard (port .IdentificationPrefs ) {
82
+ b = append (b , & detectedBoard {
83
+ Name : board .Name (),
84
+ FQBN : board .FQBN (),
85
+ })
86
+ }
87
+ p := & detectedPort {
88
+ Address : port .Address ,
89
+ Protocol : port .Protocol ,
90
+ ProtocolLabel : port .ProtocolLabel ,
91
+ Boards : b ,
92
+ }
93
+ res = append (res , p )
94
+ }
88
95
}
96
+ output .Emit (& detectedPorts {
97
+ Ports : res ,
98
+ })
99
+ }
89
100
90
- formatter .Print (NewBoardList (pm , monitor ))
101
+ type detectedPorts struct {
102
+ Ports []* detectedPort `json:"ports"`
103
+ }
91
104
92
- //monitor.Stop() //If called will slow like 1sec the program to close after print, with the same result (tested).
93
- // it closes ungracefully, but at the end of the command we can't have races.
105
+ type detectedPort struct {
106
+ Address string `json:"address"`
107
+ Protocol string `json:"protocol"`
108
+ ProtocolLabel string `json:"protocol_label"`
109
+ Boards detectedBoards `json:"boards"`
94
110
}
95
111
96
- // NewBoardList returns a new board list by adding discovered boards from the board list and a monitor.
97
- func NewBoardList (pm * packagemanager.PackageManager , monitor * discovery.Monitor ) * output.AttachedBoardList {
98
- if monitor == nil {
99
- return nil
100
- }
112
+ type detectedBoards []* detectedBoard
113
+
114
+ type detectedBoard struct {
115
+ Name string `json:"name"`
116
+ FQBN string `json:"fqbn"`
117
+ }
101
118
102
- serialDevices := monitor . Serial ()
103
- networkDevices := monitor . Network ()
104
- ret := & output. AttachedBoardList {
105
- SerialBoards : make ([]output. SerialBoardListItem , 0 , len ( serialDevices )),
106
- NetworkBoards : make ([]output. NetworkBoardListItem , 0 , len ( networkDevices )),
119
+ func ( b detectedBoards ) Less ( i , j int ) bool {
120
+ x := b [ i ]
121
+ y := b [ j ]
122
+ if x . Name < y . Name {
123
+ return true
107
124
}
125
+ return x .FQBN < y .FQBN
126
+ }
108
127
109
- for _ , item := range serialDevices {
110
- boards := pm .FindBoardsWithVidPid (item .VendorID , item .ProductID )
111
- if len (boards ) == 0 {
112
- ret .SerialBoards = append (ret .SerialBoards , output.SerialBoardListItem {
113
- Name : "unknown" ,
114
- Port : item .Port ,
115
- UsbID : fmt .Sprintf ("%s:%s - %s" , item .VendorID [2 :], item .ProductID [2 :], item .SerialNumber ),
116
- })
117
- continue
118
- }
128
+ func (p detectedPorts ) Less (i , j int ) bool {
129
+ x := p .Ports [i ]
130
+ y := p .Ports [j ]
131
+ if x .Protocol < y .Protocol {
132
+ return true
133
+ }
134
+ if x .Address < y .Address {
135
+ return true
136
+ }
137
+ return false
138
+ }
119
139
120
- board := boards [0 ]
121
- ret .SerialBoards = append (ret .SerialBoards , output.SerialBoardListItem {
122
- Name : board .Name (),
123
- Fqbn : board .FQBN (),
124
- Port : item .Port ,
125
- UsbID : fmt .Sprintf ("%s:%s - %s" , item .VendorID [2 :], item .ProductID [2 :], item .SerialNumber ),
126
- })
140
+ func (p detectedPorts ) EmitJSON () string {
141
+ d , err := json .MarshalIndent (p , "" , " " )
142
+ if err != nil {
143
+ formatter .PrintError (err , "Error encoding json" )
144
+ os .Exit (commands .ErrGeneric )
127
145
}
146
+ return string (d )
147
+ }
128
148
129
- for _ , item := range networkDevices {
130
- boards := pm .FindBoardsWithID (item .Name )
131
- if len (boards ) == 0 {
132
- // skip it if not recognized
133
- continue
149
+ func (p detectedPorts ) EmitTerminal () string {
150
+ sort .Slice (p .Ports , p .Less )
151
+ table := output .NewTable ()
152
+ table .SetHeader ("Port" , "Type" , "Board Name" , "FQBN" )
153
+ for _ , port := range p .Ports {
154
+ address := port .Protocol + "://" + port .Address
155
+ if port .Protocol == "serial" {
156
+ address = port .Address
157
+ }
158
+ protocol := port .ProtocolLabel
159
+ if len (port .Boards ) > 0 {
160
+ sort .Slice (port .Boards , port .Boards .Less )
161
+ for _ , b := range port .Boards {
162
+ board := b .Name
163
+ fqbn := b .FQBN
164
+ table .AddRow (address , protocol , board , fqbn )
165
+ // show address and protocol only on the first row
166
+ address = ""
167
+ protocol = ""
168
+ }
169
+ } else {
170
+ board := "Unknown"
171
+ fqbn := ""
172
+ table .AddRow (address , protocol , board , fqbn )
134
173
}
135
-
136
- board := boards [0 ]
137
- ret .NetworkBoards = append (ret .NetworkBoards , output.NetworkBoardListItem {
138
- Name : board .Name (),
139
- Fqbn : board .FQBN (),
140
- Location : fmt .Sprintf ("%s:%d" , item .Address , item .Port ),
141
- })
142
174
}
143
- return ret
175
+ return table . Render ()
144
176
}
0 commit comments