Skip to content

Refactor things [IOT-1310] #27

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

Merged
merged 4 commits into from
Aug 30, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,22 @@ Devices currently present on Arduino IoT Cloud can be retrieved by using this co

## Thing commands

Things can be created starting from a template or by cloning another thing. Additionally, a thing name should be specified.
Things can be created starting from a template or by cloning another thing.

Create a thing from a template:
Create a thing from a thing template. The name parameter is optional. If it is provided then it overrides the name retrieved from the template:

`$ iot-cloud-cli thing create --name <thingName> --template <template.json>`

Create a thing by cloning another thing:
Create a thing by cloning another thing, here the *name is mandatory*:

`$ iot-cloud-cli thing create --name <thingName> --clone-id <thingToCloneID>`
`$ iot-cloud-cli thing clone --name <thingName> --clone-id <thingToCloneID>`


Things can be printed thanks to a list command.

Print a list of available things and their properties by using this command:
Print a list of available things and their variables by using this command:

`$ iot-cloud-cli thing list --properties`
`$ iot-cloud-cli thing list --show-variables`

Print a *filtered* list of available things, print only things belonging to the ids list:

Expand Down
44 changes: 44 additions & 0 deletions cli/thing/clone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package thing

import (
"fmt"

"github.com/arduino/iot-cloud-cli/command/thing"
"github.com/spf13/cobra"
)

var cloneFlags struct {
name string
cloneID string
}

func initCloneCommand() *cobra.Command {
cloneCommand := &cobra.Command{
Use: "clone",
Short: "Clone a thing",
Long: "Clone a thing for Arduino IoT Cloud",
RunE: runCloneCommand,
}
cloneCommand.Flags().StringVarP(&cloneFlags.name, "name", "n", "", "Thing name")
cloneCommand.Flags().StringVarP(&cloneFlags.cloneID, "clone-id", "c", "", "ID of Thing to be cloned")
cloneCommand.MarkFlagRequired("name")
cloneCommand.MarkFlagRequired("clone-id")
return cloneCommand
}

func runCloneCommand(cmd *cobra.Command, args []string) error {
fmt.Printf("Cloning thing %s into a new thing called %s\n", cloneFlags.cloneID, cloneFlags.name)

params := &thing.CloneParams{
Name: cloneFlags.name,
CloneID: cloneFlags.cloneID,
}

thingID, err := thing.Clone(params)
if err != nil {
return err
}

fmt.Printf("IoT Cloud thing created with ID: %s\n", thingID)
return nil
}
14 changes: 4 additions & 10 deletions cli/thing/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,28 @@ import (

var createFlags struct {
name string
deviceID string
template string
cloneID string
}

func initCreateCommand() *cobra.Command {
createCommand := &cobra.Command{
Use: "create",
Short: "Create a thing",
Long: "Create a thing for Arduino IoT Cloud",
Short: "Create a thing from a template",
Long: "Create a thing from a template for Arduino IoT Cloud",
RunE: runCreateCommand,
}
createCommand.Flags().StringVarP(&createFlags.name, "name", "n", "", "Thing name")
createCommand.Flags().StringVarP(&createFlags.deviceID, "device-id", "d", "", "ID of Device to bind to the new thing")
createCommand.Flags().StringVarP(&createFlags.cloneID, "clone-id", "c", "", "ID of Thing to be cloned")
createCommand.Flags().StringVarP(&createFlags.template, "template", "t", "", "File containing a thing template")
createCommand.MarkFlagRequired("name")
createCommand.MarkFlagRequired("template")
return createCommand
}

func runCreateCommand(cmd *cobra.Command, args []string) error {
fmt.Printf("Creating thing with name %s\n", createFlags.name)
fmt.Printf("Creating thing from template %s\n", createFlags.template)

params := &thing.CreateParams{
Name: createFlags.name,
DeviceID: createFlags.deviceID,
Template: createFlags.template,
CloneID: createFlags.cloneID,
}

thingID, err := thing.Create(params)
Expand Down
8 changes: 4 additions & 4 deletions cli/thing/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ var extractFlags struct {
func initExtractCommand() *cobra.Command {
extractCommand := &cobra.Command{
Use: "extract",
Short: "Extract and save a thing",
Long: "Extract a thing from Arduino IoT Cloud and save it in a template file",
Short: "Extract a template from a thing",
Long: "Extract a template from a Arduino IoT Cloud thing and save it in a file",
RunE: runExtractCommand,
}
extractCommand.Flags().StringVarP(&extractFlags.id, "id", "i", "", "Thing ID")
Expand All @@ -26,7 +26,7 @@ func initExtractCommand() *cobra.Command {
}

func runExtractCommand(cmd *cobra.Command, args []string) error {
fmt.Printf("Extracting thing %s\n", extractFlags.id)
fmt.Printf("Extracting template from thing %s\n", extractFlags.id)

params := &thing.ExtractParams{ID: extractFlags.id}
if extractFlags.outfile != "" {
Expand All @@ -38,6 +38,6 @@ func runExtractCommand(cmd *cobra.Command, args []string) error {
return err
}

fmt.Println("Thing successfully extracted")
fmt.Println("Template successfully extracted")
return nil
}
20 changes: 10 additions & 10 deletions cli/thing/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
)

var listFlags struct {
ids []string
deviceID string
properties bool
ids []string
deviceID string
variables bool
}

func initListCommand() *cobra.Command {
Expand All @@ -27,16 +27,16 @@ func initListCommand() *cobra.Command {
listCommand.Flags().StringSliceVarP(&listFlags.ids, "ids", "i", []string{}, "List of thing IDs to be retrieved")
// list only the thing associated to the passed device id
listCommand.Flags().StringVarP(&listFlags.deviceID, "device-id", "d", "", "ID of Device associated to the thing to be retrieved")
listCommand.Flags().BoolVarP(&listFlags.properties, "properties", "p", false, "Show thing properties")
listCommand.Flags().BoolVarP(&listFlags.variables, "show-variables", "s", false, "Show thing variables")
return listCommand
}

func runListCommand(cmd *cobra.Command, args []string) error {
fmt.Println("Listing things")

params := &thing.ListParams{
IDs: listFlags.ids,
Properties: listFlags.properties,
IDs: listFlags.ids,
Variables: listFlags.variables,
}
if listFlags.deviceID != "" {
params.DeviceID = &listFlags.deviceID
Expand Down Expand Up @@ -66,15 +66,15 @@ func (r result) String() string {
t := table.New()

h := []interface{}{"Name", "ID", "Device"}
if listFlags.properties {
h = append(h, "Properties")
if listFlags.variables {
h = append(h, "Variables")
}
t.SetHeader(h...)

for _, thing := range r.things {
r := []interface{}{thing.Name, thing.ID, thing.DeviceID}
if listFlags.properties {
r = append(r, strings.Join(thing.Properties, ", "))
if listFlags.variables {
r = append(r, strings.Join(thing.Variables, ", "))
}
t.AddRow(r...)
}
Expand Down
1 change: 1 addition & 0 deletions cli/thing/thing.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func NewCommand() *cobra.Command {
}

thingCommand.AddCommand(initCreateCommand())
thingCommand.AddCommand(initCloneCommand())
thingCommand.AddCommand(initListCommand())
thingCommand.AddCommand(initDeleteCommand())
thingCommand.AddCommand(initExtractCommand())
Expand Down
66 changes: 66 additions & 0 deletions command/thing/clone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package thing

import (
"fmt"

iotclient "github.com/arduino/iot-client-go"
"github.com/arduino/iot-cloud-cli/internal/config"
"github.com/arduino/iot-cloud-cli/internal/iot"
)

// CloneParams contains the parameters needed to clone a thing.
type CloneParams struct {
// Mandatory - contains the name of the thing
Name string
// Mandatory - specifies ID of thing to be cloned
CloneID string
}

// Clone allows to create a new thing from an already existing one
func Clone(params *CloneParams) (string, error) {
conf, err := config.Retrieve()
if err != nil {
return "", err
}
iotClient, err := iot.NewClient(conf.Client, conf.Secret)
if err != nil {
return "", err
}

thing, err := retrieve(iotClient, params.CloneID)
if err != nil {
return "", err
}

thing.Name = params.Name
force := true
thingID, err := iotClient.AddThing(thing, force)
if err != nil {
return "", err
}

return thingID, nil
}

func retrieve(client iot.Client, thingID string) (*iotclient.Thing, error) {
clone, err := client.GetThing(thingID)
if err != nil {
return nil, fmt.Errorf("%s: %w", "retrieving the thing to be cloned", err)
}

thing := &iotclient.Thing{}

// Copy variables
for _, p := range clone.Properties {
thing.Properties = append(thing.Properties, iotclient.Property{
Name: p.Name,
Permission: p.Permission,
UpdateParameter: p.UpdateParameter,
UpdateStrategy: p.UpdateStrategy,
Type: p.Type,
VariableName: p.VariableName,
})
}

return thing, nil
}
Loading