Skip to content

Commit 24b4410

Browse files
author
Paolo Calao
authored
Upgrade arduino-cli (#88)
Update arduino-cli dependency and adapt to its breaking changes: - new way to create instance - board list command requires a request param with a timeout - upload command requires both the address and protocol of the serial port.
1 parent 13499b1 commit 24b4410

File tree

11 files changed

+463
-123
lines changed

11 files changed

+463
-123
lines changed

arduino/cli/commander.go

+19-5
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ package cli
1919

2020
import (
2121
"context"
22+
"errors"
2223
"fmt"
2324
"os"
2425
"path/filepath"
26+
"time"
2527

2628
"github.com/arduino/arduino-cli/cli/instance"
2729
"github.com/arduino/arduino-cli/commands/board"
@@ -45,9 +47,17 @@ func NewCommander() (arduino.Commander, error) {
4547
// Initialize arduino-cli configuration
4648
configuration.Settings = configuration.Init(configuration.FindConfigFileInArgsOrWorkingDirectory(os.Args))
4749
// Create arduino-cli instance, needed to execute arduino-cli commands
48-
inst, err := instance.CreateInstance()
50+
inst, err := instance.Create()
4951
if err != nil {
50-
err = fmt.Errorf("%s: %w", "creating arduino-cli instance", err)
52+
err = fmt.Errorf("creating arduino-cli instance: %w", err)
53+
return nil, err
54+
}
55+
errs := instance.Init(inst)
56+
if len(errs) > 0 {
57+
err = errors.New("initializing arduino-cli instance: received errors: ")
58+
for _, e := range errs {
59+
err = fmt.Errorf("%w%v; ", err, e)
60+
}
5161
return nil, err
5262
}
5363

@@ -60,7 +70,11 @@ func NewCommander() (arduino.Commander, error) {
6070
// BoardList executes the 'arduino-cli board list' command
6171
// and returns its result.
6272
func (c *commander) BoardList() ([]*rpc.DetectedPort, error) {
63-
ports, err := board.List(c.GetId())
73+
req := &rpc.BoardListRequest{
74+
Instance: c.Instance,
75+
Timeout: time.Second.Milliseconds(),
76+
}
77+
ports, err := board.List(req)
6478
if err != nil {
6579
err = fmt.Errorf("%s: %w", "detecting boards", err)
6680
return nil, err
@@ -70,13 +84,13 @@ func (c *commander) BoardList() ([]*rpc.DetectedPort, error) {
7084

7185
// UploadBin executes the 'arduino-cli upload -i' command
7286
// and returns its result.
73-
func (c *commander) UploadBin(fqbn, bin, port string) error {
87+
func (c *commander) UploadBin(fqbn, bin, address, protocol string) error {
7488
req := &rpc.UploadRequest{
7589
Instance: c.Instance,
7690
Fqbn: fqbn,
7791
SketchPath: filepath.Dir(bin),
7892
ImportFile: bin,
79-
Port: port,
93+
Port: &rpc.Port{Address: address, Protocol: protocol},
8094
Verbose: false,
8195
}
8296

arduino/commander.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ import (
2525
// the arduino-cli commands in a programmatic way.
2626
type Commander interface {
2727
BoardList() ([]*rpc.DetectedPort, error)
28-
UploadBin(fqbn, bin, port string) error
28+
UploadBin(fqbn, bin, address, protocol string) error
2929
//Compile() error
3030
}

arduino/grpc/client.go

+19-20
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,11 @@ func NewClient() (arduino.Commander, func() error, error) {
5353
return nil, func() error { return nil }, err
5454
}
5555

56-
serv := &service{}
56+
serv := &service{
57+
serviceClient: rpc.NewArduinoCoreServiceClient(conn),
58+
settingsClient: settings.NewSettingsServiceClient(conn),
59+
}
5760
// Create an instance of the gRPC clients.
58-
serv.serviceClient = rpc.NewArduinoCoreServiceClient(conn)
59-
serv.settingsClient = settings.NewSettingsServiceClient(conn)
6061
serv.instance, err = initInstance(serv.serviceClient)
6162
if err != nil {
6263
conn.Close()
@@ -72,13 +73,17 @@ func NewClient() (arduino.Commander, func() error, error) {
7273
}
7374

7475
func initInstance(client rpc.ArduinoCoreServiceClient) (*rpc.Instance, error) {
75-
initRespStream, err := client.Init(context.Background(), &rpc.InitRequest{})
76+
createResp, err := client.Create(context.Background(), &rpc.CreateRequest{})
7677
if err != nil {
7778
err = fmt.Errorf("%s: %w", "Error creating server instance", err)
7879
return nil, err
7980
}
81+
initRespStream, err := client.Init(context.Background(), &rpc.InitRequest{Instance: createResp.GetInstance()})
82+
if err != nil {
83+
err = fmt.Errorf("%s: %w", "Error initializing server instance", err)
84+
return nil, err
85+
}
8086

81-
var instance *rpc.Instance
8287
// Loop and consume the server stream until all the setup procedures are done.
8388
for {
8489
initResp, err := initRespStream.Recv()
@@ -93,22 +98,16 @@ func initInstance(client rpc.ArduinoCoreServiceClient) (*rpc.Instance, error) {
9398
return nil, err
9499
}
95100

96-
// The server sent us a valid instance, let's print its ID.
97-
if initResp.GetInstance() != nil {
98-
instance = initResp.GetInstance()
99-
//fmt.Printf("Got a new instance with ID: %v", instance.GetId())
100-
}
101-
102-
// When a download is ongoing, log the progress
103-
if initResp.GetDownloadProgress() != nil {
104-
fmt.Printf("DOWNLOAD: %s", initResp.GetDownloadProgress())
105-
}
106-
107-
// When an overall task is ongoing, log the progress
108-
if initResp.GetTaskProgress() != nil {
109-
fmt.Printf("TASK: %s", initResp.GetTaskProgress())
101+
// When a download or task is ongoing, log the progress
102+
if progress := initResp.GetInitProgress(); progress != nil {
103+
if progress.DownloadProgress != nil {
104+
fmt.Printf("DOWNLOAD: %s", progress.DownloadProgress)
105+
}
106+
if progress.TaskProgress != nil {
107+
fmt.Printf("TASK: %s", progress.TaskProgress)
108+
}
110109
}
111110
}
112111

113-
return instance, nil
112+
return createResp.GetInstance(), nil
114113
}

arduino/grpc/compile.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ func (c compileHandler) Compile() error {
3838

3939
// Upload executes the 'arduino-cli upload -i' command
4040
// and returns its result.
41-
func (c compileHandler) UploadBin(fqbn, bin, port string) error {
41+
func (c compileHandler) UploadBin(fqbn, bin, address, protocol string) error {
4242
stream, err := c.serviceClient.Upload(context.Background(),
4343
&rpc.UploadRequest{
4444
Instance: c.instance,
4545
Fqbn: fqbn,
4646
SketchPath: filepath.Dir(bin),
4747
ImportFile: bin,
48-
Port: port,
48+
Port: &rpc.Port{Address: address, Protocol: protocol},
4949
Verbose: true,
5050
})
5151

command/device/board.go

+13-11
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@ var (
4141

4242
// board contains details of a physical arduino board.
4343
type board struct {
44-
fqbn string
45-
serial string
46-
dType string
47-
port string
44+
fqbn string
45+
serial string
46+
dType string
47+
address string
48+
protocol string
4849
}
4950

5051
// isCrypto checks if the board is a valid arduino board with a
@@ -75,13 +76,14 @@ func boardFromPorts(ports []*rpc.DetectedPort, params *CreateParams) *board {
7576
if portFilter(port, params) {
7677
continue
7778
}
78-
boardFound := boardFilter(port.Boards, params)
79+
boardFound := boardFilter(port.MatchingBoards, params)
7980
if boardFound != nil {
8081
b := &board{
81-
fqbn: boardFound.Fqbn,
82-
serial: port.SerialNumber,
83-
dType: strings.Split(boardFound.Fqbn, ":")[2],
84-
port: port.Address,
82+
fqbn: boardFound.Fqbn,
83+
serial: port.Port.Properties["serialNumber"],
84+
dType: strings.Split(boardFound.Fqbn, ":")[2],
85+
address: port.Port.Address,
86+
protocol: port.Port.Protocol,
8587
}
8688
return b
8789
}
@@ -97,10 +99,10 @@ func boardFromPorts(ports []*rpc.DetectedPort, params *CreateParams) *board {
9799
// true -> to skip the port.
98100
// false -> to keep the port.
99101
func portFilter(port *rpc.DetectedPort, params *CreateParams) bool {
100-
if len(port.Boards) == 0 {
102+
if len(port.MatchingBoards) == 0 {
101103
return true
102104
}
103-
if params.Port != nil && *params.Port != port.Address {
105+
if params.Port != nil && *params.Port != port.Port.Address {
104106
return true
105107
}
106108
return false

command/device/board_test.go

+16-16
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,25 @@ import (
2727
var (
2828
portsNoBoards = []*rpc.DetectedPort{
2929
{
30-
Address: "ACM0",
31-
Boards: []*rpc.BoardListItem{},
30+
Port: &rpc.Port{Address: "ACM0"},
31+
MatchingBoards: []*rpc.BoardListItem{},
3232
},
3333
{
34-
Address: "ACM1",
35-
Boards: []*rpc.BoardListItem{},
34+
Port: &rpc.Port{Address: "ACM1"},
35+
MatchingBoards: []*rpc.BoardListItem{},
3636
},
3737
}
3838

3939
portsTwoBoards = []*rpc.DetectedPort{
4040
{
41-
Address: "ACM0",
42-
Boards: []*rpc.BoardListItem{
41+
Port: &rpc.Port{Address: "ACM0"},
42+
MatchingBoards: []*rpc.BoardListItem{
4343
{Fqbn: "arduino:samd:nano_33_iot"},
4444
},
4545
},
4646
{
47-
Address: "ACM1",
48-
Boards: []*rpc.BoardListItem{
47+
Port: &rpc.Port{Address: "ACM1"},
48+
MatchingBoards: []*rpc.BoardListItem{
4949
{Fqbn: "arduino:avr:uno"},
5050
},
5151
},
@@ -68,14 +68,14 @@ func TestBoardFromPorts(t *testing.T) {
6868
name: "port-filter",
6969
filter: &CreateParams{FQBN: nil, Port: stringPointer("ACM1")},
7070
ports: portsTwoBoards,
71-
want: &board{fqbn: "arduino:avr:uno", port: "ACM1"},
71+
want: &board{fqbn: "arduino:avr:uno", address: "ACM1"},
7272
},
7373

7474
{
7575
name: "fqbn-filter",
7676
filter: &CreateParams{FQBN: stringPointer("arduino:avr:uno"), Port: nil},
7777
ports: portsTwoBoards,
78-
want: &board{fqbn: "arduino:avr:uno", port: "ACM1"},
78+
want: &board{fqbn: "arduino:avr:uno", address: "ACM1"},
7979
},
8080

8181
{
@@ -90,7 +90,7 @@ func TestBoardFromPorts(t *testing.T) {
9090
filter: &CreateParams{FQBN: nil, Port: nil},
9191
ports: portsTwoBoards,
9292
// first board found is selected
93-
want: &board{fqbn: "arduino:samd:nano_33_iot", port: "ACM0"},
93+
want: &board{fqbn: "arduino:samd:nano_33_iot", address: "ACM0"},
9494
},
9595

9696
{
@@ -104,7 +104,7 @@ func TestBoardFromPorts(t *testing.T) {
104104
name: "both-filter-found",
105105
filter: &CreateParams{FQBN: stringPointer("arduino:avr:uno"), Port: stringPointer("ACM1")},
106106
ports: portsTwoBoards,
107-
want: &board{fqbn: "arduino:avr:uno", port: "ACM1"},
107+
want: &board{fqbn: "arduino:avr:uno", address: "ACM1"},
108108
},
109109

110110
{
@@ -123,14 +123,14 @@ func TestBoardFromPorts(t *testing.T) {
123123
return
124124

125125
} else if got != nil && tt.want == nil {
126-
t.Errorf("Expected nil board, received not nil board with port %s and fqbn %s", got.port, got.fqbn)
126+
t.Errorf("Expected nil board, received not nil board with port %s and fqbn %s", got.address, got.fqbn)
127127

128128
} else if got == nil && tt.want != nil {
129-
t.Errorf("Expected not nil board with port %s and fqbn %s, received a nil board", tt.want.port, tt.want.fqbn)
129+
t.Errorf("Expected not nil board with port %s and fqbn %s, received a nil board", tt.want.address, tt.want.fqbn)
130130

131-
} else if got.port != tt.want.port || got.fqbn != tt.want.fqbn {
131+
} else if got.address != tt.want.address || got.fqbn != tt.want.fqbn {
132132
t.Errorf("Expected board with port %s and fqbn %s, received board with port %s and fqbn %s",
133-
tt.want.port, tt.want.fqbn, got.port, got.fqbn)
133+
tt.want.address, tt.want.fqbn, got.address, got.fqbn)
134134
}
135135
})
136136
}

command/device/create.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func Create(params *CreateParams) (*DeviceInfo, error) {
5959
"Try the 'create-lora' command instead if it's a LoRa device"+
6060
" or 'create-generic' otherwise",
6161
board.fqbn,
62-
board.port,
62+
board.address,
6363
)
6464
}
6565

command/device/createlora.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func CreateLora(params *CreateLoraParams) (*DeviceLoraInfo, error) {
8484
" Try the 'create' command instead if it's a device with a supported crypto-chip"+
8585
" or 'create-generic' otherwise",
8686
board.fqbn,
87-
board.port,
87+
board.address,
8888
)
8989
}
9090

@@ -96,13 +96,13 @@ func CreateLora(params *CreateLoraParams) (*DeviceLoraInfo, error) {
9696
logrus.Infof("%s", "Uploading deveui sketch on the LoRa board")
9797
errMsg := "Error while uploading the LoRa provisioning binary"
9898
err = retry(deveuiUploadAttempts, deveuiUploadWait*time.Millisecond, errMsg, func() error {
99-
return comm.UploadBin(board.fqbn, bin, board.port)
99+
return comm.UploadBin(board.fqbn, bin, board.address, board.protocol)
100100
})
101101
if err != nil {
102102
return nil, fmt.Errorf("failed to upload LoRa provisioning binary: %w", err)
103103
}
104104

105-
eui, err := extractEUI(board.port)
105+
eui, err := extractEUI(board.address)
106106
if err != nil {
107107
return nil, err
108108
}

command/device/provision.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func (p provision) run() error {
8686
errMsg := "Error while uploading the provisioning sketch"
8787
err = retry(5, time.Millisecond*1000, errMsg, func() error {
8888
//serialutils.Reset(dev.port, true, nil)
89-
return p.UploadBin(p.board.fqbn, bin, p.board.port)
89+
return p.UploadBin(p.board.fqbn, bin, p.board.address, p.board.protocol)
9090
})
9191
if err != nil {
9292
return err
@@ -98,7 +98,7 @@ func (p provision) run() error {
9898
p.ser = serial.NewSerial()
9999
errMsg = "Error while connecting to the board"
100100
err = retry(5, time.Millisecond*1000, errMsg, func() error {
101-
return p.ser.Connect(p.board.port)
101+
return p.ser.Connect(p.board.address)
102102
})
103103
if err != nil {
104104
return err

0 commit comments

Comments
 (0)