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

Firmware list command #51

Merged
merged 6 commits into from
Jun 10, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 22 additions & 19 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"strings"
"time"

"github.com/arduino/FirmwareUploader/cli/firmware"
"github.com/arduino/FirmwareUploader/cli/version"
"github.com/arduino/FirmwareUploader/modules/nina"
"github.com/arduino/FirmwareUploader/modules/sara"
Expand Down Expand Up @@ -55,7 +56,7 @@ var (

func NewCommand() *cobra.Command {
// FirmwareUploader is the root command
firmwareUploaderCli := &cobra.Command{
rootCmd := &cobra.Command{
Use: "FirmwareUploader",
Short: "FirmwareUploader.",
Long: "FirmwareUploader (FirmwareUploader).",
Expand All @@ -65,28 +66,30 @@ func NewCommand() *cobra.Command {
PersistentPreRun: preRun,
}

firmwareUploaderCli.AddCommand(version.NewCommand())
rootCmd.AddCommand(version.NewCommand())

firmwareUploaderCli.Flags().StringVar(&ctx.PortName, "port", "", "serial port to use for flashing")
firmwareUploaderCli.Flags().StringVar(&ctx.RootCertDir, "certs", "", "root certificate directory")
firmwareUploaderCli.Flags().StringSliceVar(&ctx.Addresses, "address", []string{}, "address (host:port) to fetch and flash root certificate for, multiple values allowed")
firmwareUploaderCli.Flags().StringVar(&ctx.FirmwareFile, "firmware", "", "firmware file to flash")
firmwareUploaderCli.Flags().BoolVar(&ctx.ReadAll, "read", false, "read all firmware and output to stdout")
firmwareUploaderCli.Flags().StringVar(&ctx.FWUploaderBinary, "flasher", "", "firmware upload binary (precompiled for the right target)")
firmwareUploaderCli.Flags().StringVar(&ctx.BinaryToRestore, "restore_binary", "", "binary to restore after the firmware upload (precompiled for the right target)")
firmwareUploaderCli.Flags().StringVar(&ctx.ProgrammerPath, "programmer", "", "path of programmer in use (avrdude/bossac)")
firmwareUploaderCli.Flags().StringVar(&ctx.Model, "model", "", "module model (winc, nina or sara)")
firmwareUploaderCli.Flags().StringVar(&ctx.BoardName, "get_available_for", "", "Ask for available firmwares matching a given board")
firmwareUploaderCli.Flags().IntVar(&ctx.Retries, "retries", 9, "Number of retries in case of upload failure")
rootCmd.AddCommand(firmware.NewCommand())

firmwareUploaderCli.PersistentFlags().StringVar(&outputFormat, "format", "text", "The output format, can be {text|json}.")
rootCmd.Flags().StringVar(&ctx.PortName, "port", "", "serial port to use for flashing")
rootCmd.Flags().StringVar(&ctx.RootCertDir, "certs", "", "root certificate directory")
rootCmd.Flags().StringSliceVar(&ctx.Addresses, "address", []string{}, "address (host:port) to fetch and flash root certificate for, multiple values allowed")
rootCmd.Flags().StringVar(&ctx.FirmwareFile, "firmware", "", "firmware file to flash")
rootCmd.Flags().BoolVar(&ctx.ReadAll, "read", false, "read all firmware and output to stdout")
rootCmd.Flags().StringVar(&ctx.FWUploaderBinary, "flasher", "", "firmware upload binary (precompiled for the right target)")
rootCmd.Flags().StringVar(&ctx.BinaryToRestore, "restore_binary", "", "binary to restore after the firmware upload (precompiled for the right target)")
rootCmd.Flags().StringVar(&ctx.ProgrammerPath, "programmer", "", "path of programmer in use (avrdude/bossac)")
rootCmd.Flags().StringVar(&ctx.Model, "model", "", "module model (winc, nina or sara)")
rootCmd.Flags().StringVar(&ctx.BoardName, "get_available_for", "", "Ask for available firmwares matching a given board")
rootCmd.Flags().IntVar(&ctx.Retries, "retries", 9, "Number of retries in case of upload failure")

firmwareUploaderCli.PersistentFlags().StringVar(&logFile, "log-file", "", "Path to the file where logs will be written")
firmwareUploaderCli.PersistentFlags().StringVar(&logFormat, "log-format", "", "The output format for the logs, can be {text|json}.")
firmwareUploaderCli.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Messages with this level and above will be logged. Valid levels are: trace, debug, info, warn, error, fatal, panic")
firmwareUploaderCli.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Print the logs on the standard output.")
rootCmd.PersistentFlags().StringVar(&outputFormat, "format", "text", "The output format, can be {text|json}.")

return firmwareUploaderCli
rootCmd.PersistentFlags().StringVar(&logFile, "log-file", "", "Path to the file where logs will be written")
rootCmd.PersistentFlags().StringVar(&logFormat, "log-format", "", "The output format for the logs, can be {text|json}.")
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "Messages with this level and above will be logged. Valid levels are: trace, debug, info, warn, error, fatal, panic")
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Print the logs on the standard output.")

return rootCmd
}

func run(cmd *cobra.Command, args []string) {
Expand Down
38 changes: 38 additions & 0 deletions cli/firmware/firmware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
FirmwareUploader
Copyright (c) 2021 Arduino LLC. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

package firmware

import (
"os"

"github.com/spf13/cobra"
)

func NewCommand() *cobra.Command {
firmwareCmd := &cobra.Command{
Use: "firmware",
Short: "Commands to operate on firmwares.",
Long: "A subset of commands to perform various firmware operations.",
Example: " " + os.Args[0] + " firmware ...",
}

firmwareCmd.AddCommand(newListCommand())
return firmwareCmd
}
95 changes: 95 additions & 0 deletions cli/firmware/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
FirmwareUploader
Copyright (c) 2021 Arduino LLC. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

package firmware

import (
"os"

"github.com/arduino/FirmwareUploader/indexes"
"github.com/arduino/arduino-cli/cli/feedback"
"github.com/arduino/arduino-cli/table"
"github.com/spf13/cobra"
)

func newListCommand() *cobra.Command {
var fqbn *string

listCmd := &cobra.Command{
Use: "list",
Short: "List available firmwares",
Long: "Displays the availale firmwares, is it possible to filter results for a specific board.",
Example: " " + os.Args[0] + " firmware list -b arduino:samd:mkr1000",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
list(*fqbn)
},
}
fqbn = listCmd.Flags().StringP("fqbn", "b", "", "Filter result for the specified board FQBN")
return listCmd
}

type FirmwareResult struct {
BoardName string `json:"board_name"`
BoardFQBN string `json:"board_fqbn"`
Module string `json:"module"`
FirmwareVersion string `json:"firmware_version"`
Latest bool
}

type FirmwareListResult []*FirmwareResult

func list(fqbn string) {
firmwareIndex, err := indexes.GetFirmwareIndex()
if err != nil {
feedback.Error(err)
}

res := FirmwareListResult{}
for _, board := range firmwareIndex.Boards {
if fqbn == "" || board.Fqbn == fqbn {
for _, firmware := range board.Firmwares {
res = append(res, &FirmwareResult{
BoardName: board.Name,
BoardFQBN: board.Fqbn,
Module: board.Module,
FirmwareVersion: firmware.Version,
})
}
}
}

feedback.PrintResult(res)
}

func (f FirmwareListResult) String() string {
if len(f) == 0 {
return "No firmwares available."
}
t := table.New()
t.SetHeader("Board", "FQBN", "Module", "Version")
for _, fw := range f {
t.AddRow(fw.BoardName, fw.BoardFQBN, fw.Module, fw.FirmwareVersion)
}
return t.Render()
}

func (f FirmwareListResult) Data() interface{} {
return f
}
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fluxio/iohelpers v0.0.0-20160419043813-3a4dd67a94d2/go.mod h1:c7sGIpDbBo0JZZ1tKyC1p5smWf8QcUjK4bFtZjHAecg=
github.com/fluxio/multierror v0.0.0-20160419044231-9c68d39025e5/go.mod h1:BEUDl7FG1cc76sM0J0x8dqr6RhiL4uqvk6oFkwuNyuM=
Expand Down
79 changes: 44 additions & 35 deletions indexes/firmwareindex/firmwareindex.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ type IndexFirmware struct {
URL string `json:"url,required"`
Checksum string `json:"checksum,required"`
Size json.Number `json:"size,required"`
Module string `json:module,required`
Module string `json:"module,required"`
}

// IndexLoaderSketch represents the sketch used to upload the new firmware on a board.
Expand Down Expand Up @@ -129,54 +129,63 @@ func LoadIndexNoSign(jsonIndexFile *paths.Path) (*Index, error) {
// GetLatestFirmwareURL takes the fqbn as parameter and returns the URL of the latest available firmware.
// Not currently implemented for SARA, as the version for it's firmware is a bit strange
func (i *Index) GetLatestFirmwareURL(fqbn string) (string, error) {
for _, board := range i.Boards {
var latestVersion *semver.RelaxedVersion
var latestFirmwareURL string
if board.Fqbn == fqbn && board.Module != "SARA" { // TODO togliere sara, lo assumo giá nel comando
for _, firmware := range board.Firmwares {
version := semver.ParseRelaxed(firmware.Version)
if latestVersion == nil || version.GreaterThan(latestVersion) { // TODO check the condition
latestVersion = version
latestFirmwareURL = firmware.URL
}
}
if latestVersion != nil {
return latestFirmwareURL, nil
} else {
return "", fmt.Errorf("cannot find latest version")
}
} else if board.Fqbn == fqbn { // SARA
// TODO implement?? by defualt you have to specify the version
return "", fmt.Errorf("not implemented for SARA module")
board := i.GetBoard(fqbn)
if board == nil {
return "", fmt.Errorf("invalid FQBN: %s", fqbn)
}
if board.Module == "SARA" { // TODO togliere sara, lo assumo giá nel comando
// TODO implement?? by defualt you have to specify the version
return "", fmt.Errorf("not implemented for SARA module")
}

var latestVersion *semver.RelaxedVersion
var latestFirmwareURL string
for _, firmware := range board.Firmwares {
version := semver.ParseRelaxed(firmware.Version)
if latestVersion == nil || version.GreaterThan(latestVersion) { // TODO check the condition
latestVersion = version
latestFirmwareURL = firmware.URL
}
}
return "", fmt.Errorf("invalid FQBN: %s", fqbn)
if latestVersion != nil {
return latestFirmwareURL, nil
} else {
return "", fmt.Errorf("cannot find latest version")
}
}

// GetFirmwareURL will take the fqbn of the required board and the version of the firmware as parameters.
// It will return the URL of the required firmware
// It will return the URL of the required firmware
func (i *Index) GetFirmwareURL(fqbn, version string) (string, error) {
for _, board := range i.Boards {
if board.Fqbn == fqbn {
for _, firmware := range board.Firmwares {
if firmware.Version == version {
return firmware.URL, nil
}
}
return "", fmt.Errorf("invalid version: %s", version)
board := i.GetBoard(fqbn)
if board == nil {
return "", fmt.Errorf("invalid FQBN: %s", fqbn)
}
for _, firmware := range board.Firmwares {
if firmware.Version == version {
return firmware.URL, nil
}
}
return "", fmt.Errorf("invalid FQBN: %s", fqbn)
return "", fmt.Errorf("invalid version: %s", version)
}

// GetLoaderSketchURL will take the board's fqbn and return the url of the loader sketch
func (i *Index) GetLoaderSketchURL(fqbn string) (string, error) {
for _, board := range i.Boards {
if board.Fqbn == fqbn {
return board.LoaderSketch.URL, nil
board := i.GetBoard(fqbn)
if board == nil {
return "", fmt.Errorf("invalid FQBN: %s", fqbn)
}
return board.LoaderSketch.URL, nil
}

// GetBoard returns the IndexBoard for the given FQBN
func (i *Index) GetBoard(fqbn string) *IndexBoard {
for _, b := range i.Boards {
if b.Fqbn == fqbn {
return b
}
}
return "", fmt.Errorf("invalid FQBN: %s", fqbn)
return nil
}

func (b *IndexBoard) GetUploaderCommand() string {
Expand Down
5 changes: 5 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ import (

func main() {
uploaderCmd := cli.NewCommand()
if len(os.Args) == 1 {
// Show help if user doesn't specify any parameter
uploaderCmd.Help()
os.Exit(1)
}
if err := uploaderCmd.Execute(); err != nil {
os.Exit(1)
}
Expand Down