Skip to content

Commit 5d00ed2

Browse files
committed
board list command now uses pluggable-discoveries
1 parent ace6552 commit 5d00ed2

File tree

1 file changed

+107
-75
lines changed

1 file changed

+107
-75
lines changed

commands/board/list.go

+107-75
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@
1818
package board
1919

2020
import (
21+
"encoding/json"
2122
"fmt"
23+
"os"
24+
"sort"
2225
"time"
2326

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"
2530
"github.com/arduino/arduino-cli/commands"
31+
"github.com/arduino/arduino-cli/commands/core"
2632
"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"
3033
"github.com/spf13/cobra"
3134
)
3235

@@ -50,95 +53,124 @@ var listFlags struct {
5053
}
5154

5255
// runListCommand detects and lists the connected arduino boards
53-
// (either via serial or network ports).
5456
func runListCommand(cmd *cobra.Command, args []string) {
5557
pm := commands.InitPackageManager()
5658

57-
monitor := discovery.New(time.Millisecond)
58-
monitor.Start()
59-
duration, err := time.ParseDuration(listFlags.timeout)
59+
timeout, err := time.ParseDuration(listFlags.timeout)
6060
if err != nil {
61-
duration = time.Second * 5
61+
formatter.PrintError(err, "Invalid timeout.")
62+
os.Exit(commands.ErrBadArgument)
6263
}
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("\rDiscovering. ")
72-
time.Sleep(time.Millisecond * 500)
73-
fmt.Print("\rDiscovering.. ")
74-
time.Sleep(time.Millisecond * 500)
75-
fmt.Print("\rDiscovering...")
76-
time.Sleep(time.Millisecond * 500)
77-
}
78-
}
79-
})
8064

81-
fmt.Print("\r")
8265

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+
}
8895
}
96+
output.Emit(&detectedPorts{
97+
Ports: res,
98+
})
99+
}
89100

90-
formatter.Print(NewBoardList(pm, monitor))
101+
type detectedPorts struct {
102+
Ports []*detectedPort `json:"ports"`
103+
}
91104

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"`
94110
}
95111

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+
}
101118

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
107124
}
125+
return x.FQBN < y.FQBN
126+
}
108127

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+
}
119139

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)
127145
}
146+
return string(d)
147+
}
128148

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)
134173
}
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-
})
142174
}
143-
return ret
175+
return table.Render()
144176
}

0 commit comments

Comments
 (0)