Skip to content

Commit 6e589c1

Browse files
authored
Allows UnoQ boards detection even if platform is not installed (#636)
1 parent 423b30d commit 6e589c1

File tree

1 file changed

+94
-58
lines changed

1 file changed

+94
-58
lines changed

pkg/board/board.go

Lines changed: 94 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/arduino/arduino-cli/pkg/fqbn"
1616
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
1717
"github.com/sirupsen/logrus"
18+
"go.bug.st/f"
1819

1920
"github.com/bcmi-labs/orchestrator/pkg/board/remote"
2021
"github.com/bcmi-labs/orchestrator/pkg/board/remote/adb"
@@ -42,6 +43,26 @@ const (
4243
SerialPath = "/sys/devices/soc0/serial_number"
4344
)
4445

46+
func identifyUnoQ(p *rpc.DetectedPort) {
47+
const UnoQVID = "0x2341"
48+
const UnoQPID = "0x0078"
49+
const UnoQBoardID = "unoq"
50+
51+
// If the board has been already identified as Uno Q, just return true
52+
for _, b := range p.GetMatchingBoards() {
53+
if b.GetFqbn() == ArduinoUnoQ {
54+
return
55+
}
56+
}
57+
58+
// Otherwise check the VID/PID or board ID
59+
props := p.GetPort().GetProperties()
60+
isUnoQ := props["board"] == UnoQBoardID || (props["vid"] == UnoQVID && props["pid"] == UnoQPID)
61+
if isUnoQ {
62+
p.MatchingBoards = append(p.MatchingBoards, &rpc.BoardListItem{Name: "Arduino UNO Q", Fqbn: ArduinoUnoQ})
63+
}
64+
}
65+
4566
// Cache the initialized Arduino CLI service, so it don't need to be re-initialized
4667
// TODO: provide a way to get the board information by event instead of polling.
4768
var arduinoCLIServer rpc.ArduinoCoreServiceServer
@@ -96,80 +117,95 @@ func FromFQBN(ctx context.Context, fqbn string) ([]Board, error) {
96117
arduinoCLIInstance = inst
97118
}
98119

99-
list, err := arduinoCLIServer.BoardList(ctx, &rpc.BoardListRequest{
120+
listReq := &rpc.BoardListRequest{
100121
Instance: arduinoCLIInstance,
101-
Timeout: 2000, // 2 seconds
102-
Fqbn: fqbn,
103-
})
122+
Timeout: 100, // 100 ms
123+
}
124+
list, err := arduinoCLIServer.BoardList(ctx, listReq)
104125
if err != nil {
105126
return nil, fmt.Errorf("failed to get info for FQBN %s: %w", fqbn, err)
106127
}
107128

108-
if ports := list.GetPorts(); len(ports) != 0 {
109-
var boards []Board
110-
for _, port := range ports {
111-
if port.GetPort() == nil {
112-
continue
113-
}
129+
ports := list.GetPorts()
130+
for _, p := range ports {
131+
identifyUnoQ(p)
132+
}
114133

115-
var boardName string
116-
if len(port.GetMatchingBoards()) > 0 {
117-
boardName = port.GetMatchingBoards()[0].GetName()
118-
}
134+
portMatchFqbn := func(p *rpc.DetectedPort) bool {
135+
return slices.ContainsFunc(
136+
p.GetMatchingBoards(),
137+
func(b *rpc.BoardListItem) bool {
138+
return b.GetFqbn() == fqbn
139+
},
140+
)
141+
}
142+
ports = f.Filter(ports, portMatchFqbn)
119143

120-
switch port.GetPort().GetProtocol() {
121-
case SerialProtocol:
122-
serial := strings.ToLower(port.GetPort().GetHardwareId()) // in windows this is uppercase.
144+
if len(ports) == 0 {
145+
return nil, fmt.Errorf("no hardware ID found for FQBN %s", fqbn)
146+
}
123147

124-
// TODO: we should store the board custom name in the product id so we can get it from the discovery service.
125-
var customName string
126-
if conn, err := adb.FromSerial(serial, ""); err == nil {
127-
if name, err := GetCustomName(ctx, conn); err == nil {
128-
customName = name
129-
}
130-
}
148+
var boards []Board
149+
for _, port := range ports {
150+
if port.GetPort() == nil {
151+
continue
152+
}
131153

132-
boards = append(boards, Board{
133-
Protocol: SerialProtocol,
134-
Serial: serial,
135-
BoardName: boardName,
136-
CustomName: customName,
137-
})
138-
case NetworkProtocol:
139-
var customName string
140-
if name, ok := port.GetPort().GetProperties()["hostname"]; ok {
141-
// take the part before the first dot as custom name
142-
idx := strings.Index(name, ".")
143-
if idx == -1 {
144-
idx = len(name)
145-
}
146-
customName = name[:idx]
147-
}
154+
var boardName string
155+
if len(port.GetMatchingBoards()) > 0 {
156+
boardName = port.GetMatchingBoards()[0].GetName()
157+
}
158+
159+
switch port.GetPort().GetProtocol() {
160+
case SerialProtocol:
161+
serial := strings.ToLower(port.GetPort().GetHardwareId()) // in windows this is uppercase.
148162

149-
boards = append(boards, Board{
150-
Protocol: NetworkProtocol,
151-
Address: port.GetPort().GetAddress(),
152-
BoardName: boardName,
153-
CustomName: customName,
154-
})
155-
default:
156-
slog.Warn("unknown protocol", "protocol", port.GetPort().GetProtocol())
163+
// TODO: we should store the board custom name in the product id so we can get it from the discovery service.
164+
var customName string
165+
if conn, err := adb.FromSerial(serial, ""); err == nil {
166+
if name, err := GetCustomName(ctx, conn); err == nil {
167+
customName = name
168+
}
157169
}
158-
}
159170

160-
// Sort serial first
161-
slices.SortFunc(boards, func(a, b Board) int {
162-
if a.Protocol == "serial" {
163-
return -1
164-
} else {
165-
return 1
171+
boards = append(boards, Board{
172+
Protocol: SerialProtocol,
173+
Serial: serial,
174+
BoardName: boardName,
175+
CustomName: customName,
176+
})
177+
case NetworkProtocol:
178+
var customName string
179+
if name, ok := port.GetPort().GetProperties()["hostname"]; ok {
180+
// take the part before the first dot as custom name
181+
idx := strings.Index(name, ".")
182+
if idx == -1 {
183+
idx = len(name)
184+
}
185+
customName = name[:idx]
166186
}
167-
})
168187

169-
return boards, nil
188+
boards = append(boards, Board{
189+
Protocol: NetworkProtocol,
190+
Address: port.GetPort().GetAddress(),
191+
BoardName: boardName,
192+
CustomName: customName,
193+
})
194+
default:
195+
slog.Warn("unknown protocol", "protocol", port.GetPort().GetProtocol())
196+
}
170197
}
171198

172-
return nil, fmt.Errorf("no hardware ID found for FQBN %s", fqbn)
199+
// Sort serial first
200+
slices.SortFunc(boards, func(a, b Board) int {
201+
if a.Protocol == "serial" {
202+
return -1
203+
} else {
204+
return 1
205+
}
206+
})
207+
208+
return boards, nil
173209
}
174210

175211
func (b *Board) GetConnection(optPassword ...string) (remote.RemoteConn, error) {

0 commit comments

Comments
 (0)