diff --git a/README.md b/README.md index 73ec756a..f8d625f6 100644 --- a/README.md +++ b/README.md @@ -75,3 +75,7 @@ Delete a thing with the following command: Extract a template from an existing thing: `$ iot-cloud-cli thing extract --id --outfile ` + +Bind a thing to an existing device: + +`$ iot-cloud-cli thing bind --id --device-id ` diff --git a/cli/thing/bind.go b/cli/thing/bind.go new file mode 100644 index 00000000..5f940655 --- /dev/null +++ b/cli/thing/bind.go @@ -0,0 +1,43 @@ +package thing + +import ( + "fmt" + + "github.com/arduino/iot-cloud-cli/command/thing" + "github.com/spf13/cobra" +) + +var bindFlags struct { + id string + deviceID string +} + +func initBindCommand() *cobra.Command { + bindCommand := &cobra.Command{ + Use: "bind", + Short: "Bind a thing to a device", + Long: "Bind a thing to a device on Arduino IoT Cloud", + RunE: runBindCommand, + } + bindCommand.Flags().StringVarP(&bindFlags.id, "id", "i", "", "Thing ID") + bindCommand.Flags().StringVarP(&bindFlags.deviceID, "device-id", "d", "", "Device ID") + bindCommand.MarkFlagRequired("id") + bindCommand.MarkFlagRequired("device-id") + return bindCommand +} + +func runBindCommand(cmd *cobra.Command, args []string) error { + fmt.Printf("Binding thing %s to device%s\n", bindFlags.id, bindFlags.deviceID) + + params := &thing.BindParams{ + ID: bindFlags.id, + DeviceID: bindFlags.deviceID, + } + err := thing.Bind(params) + if err != nil { + return err + } + + fmt.Println("Thing-Device bound successfully updated") + return nil +} diff --git a/cli/thing/thing.go b/cli/thing/thing.go index b371c985..a95dd358 100644 --- a/cli/thing/thing.go +++ b/cli/thing/thing.go @@ -15,6 +15,7 @@ func NewCommand() *cobra.Command { thingCommand.AddCommand(initListCommand()) thingCommand.AddCommand(initDeleteCommand()) thingCommand.AddCommand(initExtractCommand()) + thingCommand.AddCommand(initBindCommand()) return thingCommand } diff --git a/command/thing/bind.go b/command/thing/bind.go new file mode 100644 index 00000000..49674631 --- /dev/null +++ b/command/thing/bind.go @@ -0,0 +1,40 @@ +package thing + +import ( + iotclient "github.com/arduino/iot-client-go" + "github.com/arduino/iot-cloud-cli/internal/config" + "github.com/arduino/iot-cloud-cli/internal/iot" +) + +// BindParams contains the parameters needed to +// bind a thing to a device. +// ID indicates the thing to bind. +// deviceID indicates the device bind. +type BindParams struct { + ID string + DeviceID string +} + +// Bind command is used to bind a thing to a device +// on Arduino IoT Cloud. +func Bind(params *BindParams) error { + conf, err := config.Retrieve() + if err != nil { + return err + } + iotClient, err := iot.NewClient(conf.Client, conf.Secret) + if err != nil { + return err + } + + thing := &iotclient.Thing{ + DeviceId: params.DeviceID, + } + + err = iotClient.UpdateThing(params.ID, thing, true) + if err != nil { + return err + } + + return nil +} diff --git a/internal/iot/client.go b/internal/iot/client.go index 51688def..b7955f46 100644 --- a/internal/iot/client.go +++ b/internal/iot/client.go @@ -16,6 +16,7 @@ type Client interface { ListDevices() ([]iotclient.ArduinoDevicev2, error) AddCertificate(id, csr string) (*iotclient.ArduinoCompressedv2, error) AddThing(thing *iotclient.Thing, force bool) (string, error) + UpdateThing(id string, thing *iotclient.Thing, force bool) error DeleteThing(id string) error GetThing(id string) (*iotclient.ArduinoThing, error) ListThings(ids []string, device *string, props bool) ([]iotclient.ArduinoThing, error) @@ -108,6 +109,16 @@ func (cl *client) AddThing(thing *iotclient.Thing, force bool) (string, error) { return newThing.Id, nil } +// AddThing updates a thing on Arduino IoT Cloud. +func (cl *client) UpdateThing(id string, thing *iotclient.Thing, force bool) error { + opt := &iotclient.ThingsV2UpdateOpts{Force: optional.NewBool(force)} + _, _, err := cl.api.ThingsV2Api.ThingsV2Update(cl.ctx, id, *thing, opt) + if err != nil { + return fmt.Errorf("%s: %v", "updating thing", err) + } + return nil +} + // DeleteThing deletes a thing from Arduino IoT Cloud. func (cl *client) DeleteThing(id string) error { _, err := cl.api.ThingsV2Api.ThingsV2Delete(cl.ctx, id, nil)