Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Detect board port change after upload #2253

Merged
merged 18 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions arduino/discovery/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ type Port struct {

var tr = i18n.Tr

// Equals returns true if the given port has the same address and protocol
// of the current port.
func (p *Port) Equals(o *Port) bool {
return p.Address == o.Address && p.Protocol == o.Protocol
}

// ToRPC converts Port into rpc.Port
func (p *Port) ToRPC() *rpc.Port {
props := p.Properties
Expand All @@ -113,13 +119,43 @@ func (p *Port) ToRPC() *rpc.Port {
}
}

// PortFromRPCPort converts an *rpc.Port to a *Port
func PortFromRPCPort(o *rpc.Port) (p *Port) {
if o == nil {
return nil
}
res := &Port{
Address: o.Address,
AddressLabel: o.Label,
Protocol: o.Protocol,
ProtocolLabel: o.ProtocolLabel,
HardwareID: o.HardwareId,
}
if o.Properties != nil {
res.Properties = properties.NewFromHashmap(o.Properties)
}
return res
}

func (p *Port) String() string {
if p == nil {
return "none"
}
return p.Address
}

// Clone creates a copy of this Port
func (p *Port) Clone() *Port {
if p == nil {
return nil
}
var res Port = *p
if p.Properties != nil {
res.Properties = p.Properties.Clone()
}
return &res
}

// Event is a pluggable discovery event
type Event struct {
Type string
Expand Down
10 changes: 6 additions & 4 deletions arduino/discovery/discovery_client/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ func main() {
fmt.Printf(" Address: %s\n", port.Address)
fmt.Printf(" Protocol: %s\n", port.Protocol)
if ev.Type == "add" {
keys := port.Properties.Keys()
sort.Strings(keys)
for _, k := range keys {
fmt.Printf(" %s=%s\n", k, port.Properties.Get(k))
if port.Properties != nil {
keys := port.Properties.Keys()
sort.Strings(keys)
for _, k := range keys {
fmt.Printf(" %s=%s\n", k, port.Properties.Get(k))
}
}
}
fmt.Println()
Expand Down
13 changes: 8 additions & 5 deletions commands/board/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/arduino/arduino-cli/commands"
"github.com/arduino/arduino-cli/internal/inventory"
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/arduino/go-properties-orderedmap"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -128,20 +129,22 @@ func apiByVidPid(vid, pid string) ([]*rpc.BoardListItem, error) {
}, nil
}

func identifyViaCloudAPI(port *discovery.Port) ([]*rpc.BoardListItem, error) {
func identifyViaCloudAPI(props *properties.Map) ([]*rpc.BoardListItem, error) {
// If the port is not USB do not try identification via cloud
id := port.Properties
if !id.ContainsKey("vid") || !id.ContainsKey("pid") {
if !props.ContainsKey("vid") || !props.ContainsKey("pid") {
return nil, nil
}

logrus.Debug("Querying builder API for board identification...")
return cachedAPIByVidPid(id.Get("vid"), id.Get("pid"))
return cachedAPIByVidPid(props.Get("vid"), props.Get("pid"))
}

// identify returns a list of boards checking first the installed platforms or the Cloud API
func identify(pme *packagemanager.Explorer, port *discovery.Port) ([]*rpc.BoardListItem, error) {
boards := []*rpc.BoardListItem{}
if port.Properties == nil {
return boards, nil
}

// first query installed cores through the Package Manager
logrus.Debug("Querying installed cores for board identification...")
Expand All @@ -167,7 +170,7 @@ func identify(pme *packagemanager.Explorer, port *discovery.Port) ([]*rpc.BoardL
// if installed cores didn't recognize the board, try querying
// the builder API if the board is a USB device port
if len(boards) == 0 {
items, err := identifyViaCloudAPI(port)
items, err := identifyViaCloudAPI(port.Properties)
if err != nil {
// this is bad, but keep going
logrus.WithError(err).Debug("Error querying builder API")
Expand Down
5 changes: 1 addition & 4 deletions commands/board/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,7 @@ func TestGetByVidPidMalformedResponse(t *testing.T) {
}

func TestBoardDetectionViaAPIWithNonUSBPort(t *testing.T) {
port := &discovery.Port{
Properties: properties.NewMap(),
}
items, err := identifyViaCloudAPI(port)
items, err := identifyViaCloudAPI(properties.NewMap())
require.NoError(t, err)
require.Empty(t, items)
}
Expand Down
24 changes: 18 additions & 6 deletions commands/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,15 +297,27 @@ func (s *ArduinoCoreServerImpl) PlatformList(ctx context.Context, req *rpc.Platf
// Upload FIXMEDOC
func (s *ArduinoCoreServerImpl) Upload(req *rpc.UploadRequest, stream rpc.ArduinoCoreService_UploadServer) error {
syncSend := NewSynchronizedSend(stream.Send)
outStream := feedStreamTo(func(data []byte) { syncSend.Send(&rpc.UploadResponse{OutStream: data}) })
errStream := feedStreamTo(func(data []byte) { syncSend.Send(&rpc.UploadResponse{ErrStream: data}) })
err := upload.Upload(stream.Context(), req, outStream, errStream)
outStream := feedStreamTo(func(data []byte) {
syncSend.Send(&rpc.UploadResponse{
Message: &rpc.UploadResponse_OutStream{OutStream: data},
})
})
errStream := feedStreamTo(func(data []byte) {
syncSend.Send(&rpc.UploadResponse{
Message: &rpc.UploadResponse_ErrStream{ErrStream: data},
})
})
res, err := upload.Upload(stream.Context(), req, outStream, errStream)
outStream.Close()
errStream.Close()
if err != nil {
return convertErrorToRPCStatus(err)
if res != nil {
syncSend.Send(&rpc.UploadResponse{
Message: &rpc.UploadResponse_Result{
Result: res,
},
})
}
return nil
return convertErrorToRPCStatus(err)
}

// UploadUsingProgrammer FIXMEDOC
Expand Down
2 changes: 1 addition & 1 deletion commands/upload/burnbootloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func BurnBootloader(ctx context.Context, req *rpc.BurnBootloaderRequest, outStre
}
defer release()

err := runProgramAction(
_, err := runProgramAction(
pme,
nil, // sketch
"", // importFile
Expand Down
Loading