diff --git a/README.md b/README.md index 500b9b96..fe9748e5 100644 --- a/README.md +++ b/README.md @@ -32,3 +32,11 @@ When provisioning a device, you can optionally specify the port to which the dev Use this command to provision a device: `$ iot-cloud-cli device create --name --port --fqbn ` + +## Device commands + +Once a device has been created thorugh the provisioning procedure, it can be deleted by using the following command: +`$ iot-cloud-cli device delete --id ` + +Devices currently present on Arduino IoT Cloud can be retrieved by using this command: +`$ iot-cloud-cli device list` diff --git a/cli/device/delete.go b/cli/device/delete.go new file mode 100644 index 00000000..5b10765e --- /dev/null +++ b/cli/device/delete.go @@ -0,0 +1,36 @@ +package device + +import ( + "fmt" + + "github.com/arduino/iot-cloud-cli/command/device" + "github.com/spf13/cobra" +) + +var deleteFlags struct { + id string +} + +func initDeleteCommand() *cobra.Command { + deleteCommand := &cobra.Command{ + Use: "delete", + Short: "Delete a device", + Long: "Delete a device from Arduino IoT Cloud", + RunE: runDeleteCommand, + } + deleteCommand.Flags().StringVarP(&deleteFlags.id, "id", "i", "", "Device ID") + deleteCommand.MarkFlagRequired("id") + return deleteCommand +} + +func runDeleteCommand(cmd *cobra.Command, args []string) error { + fmt.Printf("Deleting device %s\n", deleteFlags.id) + + params := &device.DeleteParams{ID: deleteFlags.id} + err := device.Delete(params) + if err != nil { + return err + } + + return nil +} diff --git a/cli/device/device.go b/cli/device/device.go index a9088dab..020d4935 100644 --- a/cli/device/device.go +++ b/cli/device/device.go @@ -12,6 +12,8 @@ func NewCommand() *cobra.Command { } deviceCommand.AddCommand(initCreateCommand()) + deviceCommand.AddCommand(initListCommand()) + deviceCommand.AddCommand(initDeleteCommand()) return deviceCommand } diff --git a/cli/device/list.go b/cli/device/list.go new file mode 100644 index 00000000..e7f86540 --- /dev/null +++ b/cli/device/list.go @@ -0,0 +1,59 @@ +package device + +import ( + "fmt" + + "github.com/arduino/arduino-cli/cli/feedback" + "github.com/arduino/arduino-cli/table" + "github.com/arduino/iot-cloud-cli/command/device" + "github.com/spf13/cobra" +) + +func initListCommand() *cobra.Command { + listCommand := &cobra.Command{ + Use: "list", + Short: "List devices", + Long: "List devices on Arduino IoT Cloud", + RunE: runListCommand, + } + return listCommand +} + +func runListCommand(cmd *cobra.Command, args []string) error { + fmt.Println("Listing devices") + + devs, err := device.List() + if err != nil { + return err + } + + feedback.PrintResult(result{devs}) + + return nil +} + +type result struct { + devices []device.DeviceInfo +} + +func (r result) Data() interface{} { + return r.devices +} + +func (r result) String() string { + if len(r.devices) == 0 { + return "No devices found." + } + t := table.New() + t.SetHeader("Name", "ID", "Board", "FQBN", "SerialNumber") + for _, device := range r.devices { + t.AddRow( + device.Name, + device.ID, + device.Board, + device.FQBN, + device.Serial, + ) + } + return t.Render() +} diff --git a/command/device/delete.go b/command/device/delete.go new file mode 100644 index 00000000..527d1bf2 --- /dev/null +++ b/command/device/delete.go @@ -0,0 +1,27 @@ +package device + +import ( + "github.com/arduino/iot-cloud-cli/internal/config" + "github.com/arduino/iot-cloud-cli/internal/iot" +) + +// DeleteParams contains the parameters needed to +// delete a device from Arduino IoT Cloud. +type DeleteParams struct { + ID string +} + +// Delete command is used to delete a device +// from Arduino IoT Cloud. +func Delete(params *DeleteParams) error { + conf, err := config.Retrieve() + if err != nil { + return err + } + iotClient, err := iot.NewClient(conf.Client, conf.Secret) + if err != nil { + return err + } + + return iotClient.DeleteDevice(params.ID) +} diff --git a/command/device/list.go b/command/device/list.go new file mode 100644 index 00000000..739e2a62 --- /dev/null +++ b/command/device/list.go @@ -0,0 +1,48 @@ +package device + +import ( + "github.com/arduino/iot-cloud-cli/internal/config" + "github.com/arduino/iot-cloud-cli/internal/iot" +) + +// DeviceInfo contains the most interesting +// parameters of an Arduino IoT Cloud device. +type DeviceInfo struct { + Name string + ID string + Board string + Serial string + FQBN string +} + +// List command is used to list +// the devices of Arduino IoT Cloud. +func List() ([]DeviceInfo, error) { + conf, err := config.Retrieve() + if err != nil { + return nil, err + } + iotClient, err := iot.NewClient(conf.Client, conf.Secret) + if err != nil { + return nil, err + } + + foundDevices, err := iotClient.ListDevices() + if err != nil { + return nil, err + } + + var devices []DeviceInfo + for _, foundDev := range foundDevices { + dev := DeviceInfo{ + Name: foundDev.Name, + ID: foundDev.Id, + Board: foundDev.Type, + Serial: foundDev.Serial, + FQBN: foundDev.Fqbn, + } + devices = append(devices, dev) + } + + return devices, nil +} diff --git a/internal/iot/client.go b/internal/iot/client.go index fe68ccb0..16899c75 100644 --- a/internal/iot/client.go +++ b/internal/iot/client.go @@ -10,6 +10,8 @@ import ( // Client can be used to perform actions on the arduino iot cloud. type Client interface { AddDevice(fqbn, name, serial, devType string) (string, error) + DeleteDevice(id string) error + ListDevices() ([]iotclient.ArduinoDevicev2, error) AddCertificate(id, csr string) (*iotclient.ArduinoCompressedv2, error) } @@ -47,6 +49,28 @@ func (cl *client) AddDevice(fqbn, name, serial, dType string) (string, error) { return dev.Id, nil } +// DeleteDevice deletes the device corresponding to the passed ID +// from Arduino IoT Cloud. +func (cl *client) DeleteDevice(id string) error { + _, err := cl.api.DevicesV2Api.DevicesV2Delete(cl.ctx, id) + if err != nil { + err = fmt.Errorf("deleting device: %w", err) + return err + } + return nil +} + +// ListDevices retrieves and returns a list of all Arduino IoT Cloud devices +// belonging to the user performing the request. +func (cl *client) ListDevices() ([]iotclient.ArduinoDevicev2, error) { + devices, _, err := cl.api.DevicesV2Api.DevicesV2List(cl.ctx, nil) + if err != nil { + err = fmt.Errorf("listing devices: %w", err) + return nil, err + } + return devices, nil +} + // AddCertifcate allows to upload a certificate on arduino iot cloud. // It returns the certificate parameters populated by the cloud. func (cl *client) AddCertificate(id, csr string) (*iotclient.ArduinoCompressedv2, error) {