From 61a4b67e18ce5cfa556c3f933b0fa66db546773a Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Wed, 7 Feb 2024 16:42:09 +0100 Subject: [PATCH 1/5] Base command for mass device creation --- cli/device/device.go | 1 + cli/device/masscreate.go | 117 +++++++++++++++++++++++++++++++++++ command/device/masscreate.go | 83 +++++++++++++++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 cli/device/masscreate.go create mode 100644 command/device/masscreate.go diff --git a/cli/device/device.go b/cli/device/device.go index 86e313a5..103c4c35 100644 --- a/cli/device/device.go +++ b/cli/device/device.go @@ -30,6 +30,7 @@ func NewCommand() *cobra.Command { } deviceCommand.AddCommand(initCreateCommand()) + deviceCommand.AddCommand(initMassCreateCommand()) deviceCommand.AddCommand(initListCommand()) deviceCommand.AddCommand(initDeleteCommand()) deviceCommand.AddCommand(tag.InitCreateTagsCommand()) diff --git a/cli/device/masscreate.go b/cli/device/masscreate.go new file mode 100644 index 00000000..f37f86c8 --- /dev/null +++ b/cli/device/masscreate.go @@ -0,0 +1,117 @@ +// This file is part of arduino-cloud-cli. +// +// Copyright (C) 2021 ARDUINO SA (http://www.arduino.cc/) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package device + +import ( + "context" + "fmt" + "os" + + "github.com/arduino/arduino-cli/cli/errorcodes" + "github.com/arduino/arduino-cli/cli/feedback" + "github.com/arduino/arduino-cloud-cli/command/device" + "github.com/arduino/arduino-cloud-cli/config" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "go.bug.st/cleanup" +) + +type massCreateFlags struct { + name string + fqbn string + ctype string +} + +func initMassCreateCommand() *cobra.Command { + flags := &massCreateFlags{} + createCommand := &cobra.Command{ + Use: "mass-create", + Short: "Mass create a device provisioning the onboard secure element with a valid certificate", + Long: "Mass create a device for Arduino IoT Cloud provisioning the onboard secure element with a valid certificate", + Run: func(cmd *cobra.Command, args []string) { + if err := runMassCreateCommand(flags); err != nil { + feedback.Errorf("Error during device create: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + }, + } + createCommand.Flags().StringVarP(&flags.name, "name", "n", "", "Device name") + createCommand.Flags().StringVarP(&flags.fqbn, "fqbn", "b", "", "Device fqbn") + createCommand.Flags().StringVarP(&flags.ctype, "connection", "c", "", "Device connection type") + //createCommand.MarkFlagRequired("name") + return createCommand +} + + +func runMassCreateCommand(flags *massCreateFlags) error { + logrus.Infof("Creating device with name %s", flags.name) + + cred, err := config.RetrieveCredentials() + if err != nil { + return fmt.Errorf("retrieving credentials: %w", err) + } + + ctx, cancel := cleanup.InterruptableContext(context.Background()) + defer cancel() + + boards, err := device.ListAllConnectedBoardsWithCrypto() + if err != nil { + return err + } + + for _, board := range boards { + params := &device.CreateParams{ + Name: flags.name, + Port: &board.address, + } + if flags.ctype != "" { + params.ConnectionType = &flags.ctype + } + if flags.fqbn != "" { + params.FQBN = &flags.fqbn + } + + dev, err := device.Create(ctx, params, cred) + if err != nil { + return err + } + + feedback.PrintResult(createResult{dev}) + } + + return nil +} + +type massCreateResult struct { + device *device.DeviceInfo +} + +func (r massCreateResult) Data() interface{} { + return r.device +} + +func (r massCreateResult) String() string { + return fmt.Sprintf( + "name: %s\nid: %s\nboard: %s\nserial_number: %s\nfqbn: %s", + r.device.Name, + r.device.ID, + r.device.Board, + r.device.Serial, + r.device.FQBN, + ) +} diff --git a/command/device/masscreate.go b/command/device/masscreate.go new file mode 100644 index 00000000..a9586517 --- /dev/null +++ b/command/device/masscreate.go @@ -0,0 +1,83 @@ +package device + +import ( + "context" + "errors" + "strings" + + rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1" + "github.com/arduino/arduino-cloud-cli/arduino/cli" + "go.bug.st/cleanup" +) + +func ListAllConnectedBoardsWithCrypto() ([]*board, error) { + comm, err := ListAllConnectedBoards() + if err != nil { + return nil, err + } + var withcrypto []*board + for _, b := range comm { + if b.isCrypto() { + withcrypto = append(withcrypto, b) + } + } + return withcrypto, nil +} + +func ListAllConnectedBoards() ([]*board, error) { + comm, err := cli.NewCommander() + if err != nil { + return nil, err + } + + ctx, cancel := cleanup.InterruptableContext(context.Background()) + defer cancel() + + ports, err := comm.BoardList(ctx) + if err != nil { + return nil, err + } + + board := boardsFromPorts(ports, nil) + if board == nil { + err = errors.New("no board found") + return nil, err + } + + return board, nil +} + +// boardsFromPorts returns boards that matches all the criteria +func boardsFromPorts(ports []*rpc.DetectedPort, fqbn *string) []*board { + var boards []*board + for _, port := range ports { + boardsFound := boardsFilter(port.MatchingBoards, fqbn) + if len(boardsFound) > 0 { + for _, boardFound := range boardsFound { + b := &board{ + fqbn: boardFound.Fqbn, + serial: port.Port.Properties["serialNumber"], + dType: strings.Split(boardFound.Fqbn, ":")[2], + address: port.Port.Address, + protocol: port.Port.Protocol, + } + b.isCrypto() + boards = append(boards, b) + } + } + } + return boards +} + +func boardsFilter(boards []*rpc.BoardListItem, fqbn *string) (board []*rpc.BoardListItem) { + if fqbn == nil { + return boards + } + var filtered []*rpc.BoardListItem + for _, b := range boards { + if b.Fqbn == *fqbn { + filtered = append(filtered, b) + } + } + return filtered +} From 1770dfbba71e99984feef8763bd28b8f1751465b Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Thu, 8 Feb 2024 09:45:57 +0100 Subject: [PATCH 2/5] Refactored strcuture --- cli/device/masscreate.go | 2 +- command/device/board.go | 34 +++++++++++++++++----------------- command/device/board_test.go | 18 +++++++++--------- command/device/create.go | 6 +++--- command/device/createlora.go | 12 ++++++------ command/device/masscreate.go | 22 +++++++++++----------- command/device/provision.go | 8 ++++---- 7 files changed, 51 insertions(+), 51 deletions(-) diff --git a/cli/device/masscreate.go b/cli/device/masscreate.go index f37f86c8..f2e653f2 100644 --- a/cli/device/masscreate.go +++ b/cli/device/masscreate.go @@ -77,7 +77,7 @@ func runMassCreateCommand(flags *massCreateFlags) error { for _, board := range boards { params := &device.CreateParams{ Name: flags.name, - Port: &board.address, + Port: &board.Address, } if flags.ctype != "" { params.ConnectionType = &flags.ctype diff --git a/command/device/board.go b/command/device/board.go index 568285c2..f2e3fe42 100644 --- a/command/device/board.go +++ b/command/device/board.go @@ -43,19 +43,19 @@ var ( ) // board contains details of a physical arduino board. -type board struct { - fqbn string - serial string - dType string - address string - protocol string +type Board struct { + Fqbn string + Serial string + DType string + Address string + Protocol string } // isCrypto checks if the board is a valid arduino board with a // supported crypto-chip. -func (b *board) isCrypto() bool { +func (b *Board) isCrypto() bool { for _, f := range cryptoFQBN { - if b.fqbn == f { + if b.Fqbn == f { return true } } @@ -63,9 +63,9 @@ func (b *board) isCrypto() bool { } // isLora checks if the board is a valid LoRa arduino board. -func (b *board) isLora() bool { +func (b *Board) isLora() bool { for _, f := range loraFQBN { - if b.fqbn == f { + if b.Fqbn == f { return true } } @@ -74,19 +74,19 @@ func (b *board) isLora() bool { // boardFromPorts returns a board that matches all the criteria // passed in. If no criteria are passed, it returns the first board found. -func boardFromPorts(ports []*rpc.DetectedPort, params *CreateParams) *board { +func boardFromPorts(ports []*rpc.DetectedPort, params *CreateParams) *Board { for _, port := range ports { if portFilter(port, params) { continue } boardFound := boardFilter(port.MatchingBoards, params) if boardFound != nil { - b := &board{ - fqbn: boardFound.Fqbn, - serial: port.Port.Properties["serialNumber"], - dType: strings.Split(boardFound.Fqbn, ":")[2], - address: port.Port.Address, - protocol: port.Port.Protocol, + b := &Board{ + Fqbn: boardFound.Fqbn, + Serial: port.Port.Properties["serialNumber"], + DType: strings.Split(boardFound.Fqbn, ":")[2], + Address: port.Port.Address, + Protocol: port.Port.Protocol, } return b } diff --git a/command/device/board_test.go b/command/device/board_test.go index e83baa4d..45b0d93d 100644 --- a/command/device/board_test.go +++ b/command/device/board_test.go @@ -61,21 +61,21 @@ func TestBoardFromPorts(t *testing.T) { name string filter *CreateParams ports []*rpc.DetectedPort - want *board + want *Board }{ { name: "port-filter", filter: &CreateParams{FQBN: nil, Port: stringPointer("ACM1")}, ports: portsTwoBoards, - want: &board{fqbn: "arduino:avr:uno", address: "ACM1"}, + want: &Board{Fqbn: "arduino:avr:uno", Address: "ACM1"}, }, { name: "fqbn-filter", filter: &CreateParams{FQBN: stringPointer("arduino:avr:uno"), Port: nil}, ports: portsTwoBoards, - want: &board{fqbn: "arduino:avr:uno", address: "ACM1"}, + want: &Board{Fqbn: "arduino:avr:uno", Address: "ACM1"}, }, { @@ -90,7 +90,7 @@ func TestBoardFromPorts(t *testing.T) { filter: &CreateParams{FQBN: nil, Port: nil}, ports: portsTwoBoards, // first board found is selected - want: &board{fqbn: "arduino:samd:nano_33_iot", address: "ACM0"}, + want: &Board{Fqbn: "arduino:samd:nano_33_iot", Address: "ACM0"}, }, { @@ -104,7 +104,7 @@ func TestBoardFromPorts(t *testing.T) { name: "both-filter-found", filter: &CreateParams{FQBN: stringPointer("arduino:avr:uno"), Port: stringPointer("ACM1")}, ports: portsTwoBoards, - want: &board{fqbn: "arduino:avr:uno", address: "ACM1"}, + want: &Board{Fqbn: "arduino:avr:uno", Address: "ACM1"}, }, { @@ -123,14 +123,14 @@ func TestBoardFromPorts(t *testing.T) { return } else if got != nil && tt.want == nil { - t.Errorf("Expected nil board, received not nil board with port %s and fqbn %s", got.address, got.fqbn) + t.Errorf("Expected nil board, received not nil board with port %s and fqbn %s", got.Address, got.Fqbn) } else if got == nil && tt.want != nil { - t.Errorf("Expected not nil board with port %s and fqbn %s, received a nil board", tt.want.address, tt.want.fqbn) + t.Errorf("Expected not nil board with port %s and fqbn %s, received a nil board", tt.want.Address, tt.want.Fqbn) - } else if got.address != tt.want.address || got.fqbn != tt.want.fqbn { + } else if got.Address != tt.want.Address || got.Fqbn != tt.want.Fqbn { t.Errorf("Expected board with port %s and fqbn %s, received board with port %s and fqbn %s", - tt.want.address, tt.want.fqbn, got.address, got.fqbn) + tt.want.Address, tt.want.Fqbn, got.Address, got.Fqbn) } }) } diff --git a/command/device/create.go b/command/device/create.go index 33d5cd30..296e24b0 100644 --- a/command/device/create.go +++ b/command/device/create.go @@ -60,8 +60,8 @@ func Create(ctx context.Context, params *CreateParams, cred *config.Credentials) "board with fqbn %s found at port %s is not a device with a supported crypto-chip.\n"+ "Try the 'create-lora' command instead if it's a LoRa device"+ " or 'create-generic' otherwise", - board.fqbn, - board.address, + board.Fqbn, + board.Address, ) } @@ -71,7 +71,7 @@ func Create(ctx context.Context, params *CreateParams, cred *config.Credentials) } logrus.Info("Creating a new device on the cloud") - dev, err := iotClient.DeviceCreate(ctx, board.fqbn, params.Name, board.serial, board.dType, params.ConnectionType) + dev, err := iotClient.DeviceCreate(ctx, board.Fqbn, params.Name, board.Serial, board.DType, params.ConnectionType) if err != nil { return nil, err } diff --git a/command/device/createlora.go b/command/device/createlora.go index 821d5018..e1ec49dc 100644 --- a/command/device/createlora.go +++ b/command/device/createlora.go @@ -84,12 +84,12 @@ func CreateLora(ctx context.Context, params *CreateLoraParams, cred *config.Cred "board with fqbn %s found at port %s is not a LoRa device."+ " Try the 'create' command instead if it's a device with a supported crypto-chip"+ " or 'create-generic' otherwise", - board.fqbn, - board.address, + board.Fqbn, + board.Address, ) } - bin, err := downloadProvisioningFile(ctx, board.fqbn) + bin, err := downloadProvisioningFile(ctx, board.Fqbn) if err != nil { return nil, err } @@ -97,13 +97,13 @@ func CreateLora(ctx context.Context, params *CreateLoraParams, cred *config.Cred logrus.Infof("%s", "Uploading deveui sketch on the LoRa board") errMsg := "Error while uploading the LoRa provisioning binary" err = retry(ctx, deveuiUploadAttempts, deveuiUploadWait*time.Millisecond, errMsg, func() error { - return comm.UploadBin(ctx, board.fqbn, bin, board.address, board.protocol) + return comm.UploadBin(ctx, board.Fqbn, bin, board.Address, board.Protocol) }) if err != nil { return nil, fmt.Errorf("failed to upload LoRa provisioning binary: %w", err) } - eui, err := extractEUI(ctx, board.address) + eui, err := extractEUI(ctx, board.Address) if err != nil { return nil, err } @@ -114,7 +114,7 @@ func CreateLora(ctx context.Context, params *CreateLoraParams, cred *config.Cred } logrus.Info("Creating a new device on the cloud") - dev, err := iotClient.DeviceLoraCreate(ctx, params.Name, board.serial, board.dType, eui, params.FrequencyPlan) + dev, err := iotClient.DeviceLoraCreate(ctx, params.Name, board.Serial, board.DType, eui, params.FrequencyPlan) if err != nil { return nil, err } diff --git a/command/device/masscreate.go b/command/device/masscreate.go index a9586517..b04abf80 100644 --- a/command/device/masscreate.go +++ b/command/device/masscreate.go @@ -10,12 +10,12 @@ import ( "go.bug.st/cleanup" ) -func ListAllConnectedBoardsWithCrypto() ([]*board, error) { +func ListAllConnectedBoardsWithCrypto() ([]*Board, error) { comm, err := ListAllConnectedBoards() if err != nil { return nil, err } - var withcrypto []*board + var withcrypto []*Board for _, b := range comm { if b.isCrypto() { withcrypto = append(withcrypto, b) @@ -24,7 +24,7 @@ func ListAllConnectedBoardsWithCrypto() ([]*board, error) { return withcrypto, nil } -func ListAllConnectedBoards() ([]*board, error) { +func ListAllConnectedBoards() ([]*Board, error) { comm, err := cli.NewCommander() if err != nil { return nil, err @@ -48,18 +48,18 @@ func ListAllConnectedBoards() ([]*board, error) { } // boardsFromPorts returns boards that matches all the criteria -func boardsFromPorts(ports []*rpc.DetectedPort, fqbn *string) []*board { - var boards []*board +func boardsFromPorts(ports []*rpc.DetectedPort, fqbn *string) []*Board { + var boards []*Board for _, port := range ports { boardsFound := boardsFilter(port.MatchingBoards, fqbn) if len(boardsFound) > 0 { for _, boardFound := range boardsFound { - b := &board{ - fqbn: boardFound.Fqbn, - serial: port.Port.Properties["serialNumber"], - dType: strings.Split(boardFound.Fqbn, ":")[2], - address: port.Port.Address, - protocol: port.Port.Protocol, + b := &Board{ + Fqbn: boardFound.Fqbn, + Serial: port.Port.Properties["serialNumber"], + DType: strings.Split(boardFound.Fqbn, ":")[2], + Address: port.Port.Address, + Protocol: port.Port.Protocol, } b.isCrypto() boards = append(boards, b) diff --git a/command/device/provision.go b/command/device/provision.go index 58781a33..7e918058 100644 --- a/command/device/provision.go +++ b/command/device/provision.go @@ -74,13 +74,13 @@ type provision struct { arduino.Commander cert certificateCreator ser *serial.Serial - board *board + board *Board id string } // run provisioning procedure for boards with crypto-chip. func (p provision) run(ctx context.Context) error { - bin, err := downloadProvisioningFile(ctx, p.board.fqbn) + bin, err := downloadProvisioningFile(ctx, p.board.Fqbn) if err != nil { return err } @@ -93,7 +93,7 @@ func (p provision) run(ctx context.Context) error { errMsg := "Error while uploading the provisioning sketch" err = retry(ctx, 5, time.Millisecond*1000, errMsg, func() error { //serialutils.Reset(dev.port, true, nil) - return p.UploadBin(ctx, p.board.fqbn, bin, p.board.address, p.board.protocol) + return p.UploadBin(ctx, p.board.Fqbn, bin, p.board.Address, p.board.Protocol) }) if err != nil { return err @@ -107,7 +107,7 @@ func (p provision) run(ctx context.Context) error { p.ser = serial.NewSerial() errMsg = "Error while connecting to the board" err = retry(ctx, 5, time.Millisecond*1000, errMsg, func() error { - return p.ser.Connect(p.board.address) + return p.ser.Connect(p.board.Address) }) if err != nil { return err From 04958b9d86e9e1aea249b0a5857b1d9c2f207694 Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Thu, 8 Feb 2024 10:27:57 +0100 Subject: [PATCH 3/5] Code cleaning --- cli/device/masscreate.go | 45 +++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/cli/device/masscreate.go b/cli/device/masscreate.go index f2e653f2..ed996c17 100644 --- a/cli/device/masscreate.go +++ b/cli/device/masscreate.go @@ -34,15 +34,14 @@ import ( type massCreateFlags struct { name string fqbn string - ctype string } func initMassCreateCommand() *cobra.Command { flags := &massCreateFlags{} createCommand := &cobra.Command{ Use: "mass-create", - Short: "Mass create a device provisioning the onboard secure element with a valid certificate", - Long: "Mass create a device for Arduino IoT Cloud provisioning the onboard secure element with a valid certificate", + Short: "Mass create a set of devices provisioning the onboard secure element with a valid certificate", + Long: "Mass create a set of devices for Arduino IoT Cloud provisioning the onboard secure element with a valid certificate", Run: func(cmd *cobra.Command, args []string) { if err := runMassCreateCommand(flags); err != nil { feedback.Errorf("Error during device create: %v", err) @@ -50,10 +49,10 @@ func initMassCreateCommand() *cobra.Command { } }, } - createCommand.Flags().StringVarP(&flags.name, "name", "n", "", "Device name") + createCommand.Flags().StringVarP(&flags.name, "name", "n", "", "Base device name") createCommand.Flags().StringVarP(&flags.fqbn, "fqbn", "b", "", "Device fqbn") - createCommand.Flags().StringVarP(&flags.ctype, "connection", "c", "", "Device connection type") - //createCommand.MarkFlagRequired("name") + createCommand.MarkFlagRequired("name") + createCommand.MarkFlagRequired("fqbn") return createCommand } @@ -74,14 +73,12 @@ func runMassCreateCommand(flags *massCreateFlags) error { return err } + var results []*device.DeviceInfo for _, board := range boards { params := &device.CreateParams{ Name: flags.name, Port: &board.Address, } - if flags.ctype != "" { - params.ConnectionType = &flags.ctype - } if flags.fqbn != "" { params.FQBN = &flags.fqbn } @@ -90,28 +87,34 @@ func runMassCreateCommand(flags *massCreateFlags) error { if err != nil { return err } - - feedback.PrintResult(createResult{dev}) + + results = append(results, dev) } + feedback.PrintResult(massCreateResult{results}) + return nil } type massCreateResult struct { - device *device.DeviceInfo + devices []*device.DeviceInfo } func (r massCreateResult) Data() interface{} { - return r.device + return r.devices } func (r massCreateResult) String() string { - return fmt.Sprintf( - "name: %s\nid: %s\nboard: %s\nserial_number: %s\nfqbn: %s", - r.device.Name, - r.device.ID, - r.device.Board, - r.device.Serial, - r.device.FQBN, - ) + var result string + for _, device := range r.devices { + result += fmt.Sprintf( + "name: %s\nid: %s\nboard: %s\nserial_number: %s\nfqbn: %s\n-------------\n", + device.Name, + device.ID, + device.Board, + device.Serial, + device.FQBN, + ) + } + return result } From 42638df498d28f3257b19448da550a7e1ed3c83d Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Thu, 8 Feb 2024 10:58:31 +0100 Subject: [PATCH 4/5] name provisioning --- cli/device/masscreate.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/cli/device/masscreate.go b/cli/device/masscreate.go index ed996c17..846bfaf3 100644 --- a/cli/device/masscreate.go +++ b/cli/device/masscreate.go @@ -58,7 +58,7 @@ func initMassCreateCommand() *cobra.Command { func runMassCreateCommand(flags *massCreateFlags) error { - logrus.Infof("Creating device with name %s", flags.name) + logrus.Infof("Mass provisioning devices. Base name: %s", flags.name) cred, err := config.RetrieveCredentials() if err != nil { @@ -72,15 +72,21 @@ func runMassCreateCommand(flags *massCreateFlags) error { if err != nil { return err } + if len(boards) == 0 { + return fmt.Errorf("no boards of type %s detected", flags.fqbn) + } var results []*device.DeviceInfo - for _, board := range boards { + for idx, board := range boards { + if len(board.Address) == 0{ + continue + } + logrus.Infof("Provisioning board on port: %s", board.Address) + bname := fmt.Sprintf("%s-%d", flags.name, idx) params := &device.CreateParams{ - Name: flags.name, + Name: bname, Port: &board.Address, - } - if flags.fqbn != "" { - params.FQBN = &flags.fqbn + FQBN: &flags.fqbn, } dev, err := device.Create(ctx, params, cred) From 7a7fa2c8bd345430741253de6769975db217f633 Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Thu, 8 Feb 2024 11:29:30 +0100 Subject: [PATCH 5/5] added filtering --- cli/device/masscreate.go | 5 ++--- command/device/masscreate.go | 6 +++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cli/device/masscreate.go b/cli/device/masscreate.go index 846bfaf3..02929446 100644 --- a/cli/device/masscreate.go +++ b/cli/device/masscreate.go @@ -52,7 +52,6 @@ func initMassCreateCommand() *cobra.Command { createCommand.Flags().StringVarP(&flags.name, "name", "n", "", "Base device name") createCommand.Flags().StringVarP(&flags.fqbn, "fqbn", "b", "", "Device fqbn") createCommand.MarkFlagRequired("name") - createCommand.MarkFlagRequired("fqbn") return createCommand } @@ -68,7 +67,7 @@ func runMassCreateCommand(flags *massCreateFlags) error { ctx, cancel := cleanup.InterruptableContext(context.Background()) defer cancel() - boards, err := device.ListAllConnectedBoardsWithCrypto() + boards, err := device.ListAllConnectedBoardsWithCrypto(&flags.fqbn) if err != nil { return err } @@ -86,7 +85,7 @@ func runMassCreateCommand(flags *massCreateFlags) error { params := &device.CreateParams{ Name: bname, Port: &board.Address, - FQBN: &flags.fqbn, + FQBN: &board.Fqbn, } dev, err := device.Create(ctx, params, cred) diff --git a/command/device/masscreate.go b/command/device/masscreate.go index b04abf80..1118cfbd 100644 --- a/command/device/masscreate.go +++ b/command/device/masscreate.go @@ -10,13 +10,17 @@ import ( "go.bug.st/cleanup" ) -func ListAllConnectedBoardsWithCrypto() ([]*Board, error) { +func ListAllConnectedBoardsWithCrypto(fqbn *string) ([]*Board, error) { comm, err := ListAllConnectedBoards() if err != nil { return nil, err } var withcrypto []*Board for _, b := range comm { + if len(*fqbn) > 0 && b.Fqbn != *fqbn { + // Skipp not matching board + continue + } if b.isCrypto() { withcrypto = append(withcrypto, b) }