diff --git a/cli/ping/ping.go b/cli/ping/ping.go new file mode 100644 index 00000000..1a579a12 --- /dev/null +++ b/cli/ping/ping.go @@ -0,0 +1,48 @@ +package ping + +import ( + "github.com/bcmi-labs/iot-cloud-cli/command/ping" + "github.com/spf13/cobra" +) + +var ( + host string + username string + password string + thingID string + troubleshooting bool +) + +func NewCommand() *cobra.Command { + pingCommand := &cobra.Command{ + Use: "ping", + Short: "Ping Arduino IoT Cloud", + Long: "Ping Arduino IoT Cloud", + RunE: runPingCommand, + } + + pingCommand.Flags().StringVarP(&host, "host", "b", "tcps://mqtts-up.iot.arduino.cc:8884", "Broker endpoint (required)") + pingCommand.Flags().StringVarP(&username, "username", "u", "", "Username (required)") + pingCommand.Flags().StringVarP(&password, "password", "p", "", "Password (required)") + pingCommand.Flags().StringVarP(&thingID, "thing_id", "t", "", "Thing ID (required)") + + pingCommand.Flags().BoolVar(&troubleshooting, "troubleshooting", false, "Enable troubleshooting mode (full logs from the MQTT client)") + + pingCommand.MarkFlagRequired("username") + pingCommand.MarkFlagRequired("password") + pingCommand.MarkFlagRequired("thing_id") + + return pingCommand +} + +func runPingCommand(cmd *cobra.Command, args []string) error { + params := &ping.Params{ + Host: host, + Username: username, + Password: password, + ThingID: thingID, + Troubleshooting: troubleshooting, + } + + return ping.Ping(params) +} diff --git a/cli/root.go b/cli/root.go new file mode 100644 index 00000000..3e158bda --- /dev/null +++ b/cli/root.go @@ -0,0 +1,18 @@ +package cli + +import ( + "fmt" + "os" + + "github.com/bcmi-labs/iot-cloud-cli/cli/ping" + "github.com/spf13/cobra" +) + +func Execute() { + rootCmd := &cobra.Command{} + rootCmd.AddCommand(ping.NewCommand()) + + if err := rootCmd.Execute(); err != nil { + fmt.Fprintln(os.Stderr, err) + } +} diff --git a/command/ping.go b/command/ping.go deleted file mode 100644 index 2be7cacb..00000000 --- a/command/ping.go +++ /dev/null @@ -1,117 +0,0 @@ -package command - -import ( - "fmt" - "log" - "math/rand" - "os" - "os/signal" - "syscall" - "time" - - "github.com/bcmi-labs/iot-cloud-cli/adapters/mqtt" - "github.com/bcmi-labs/iot-cloud-cli/internal/properties" - paho "github.com/eclipse/paho.mqtt.golang" - "github.com/spf13/cobra" -) - -var ( - host string - username string - password string - thingID string - troubleshooting bool -) - -func init() { - pingCommand.Flags().StringVarP(&host, "host", "b", "tcps://mqtts-up.iot.arduino.cc:8884", "Broker endpoint (required)") - pingCommand.Flags().StringVarP(&username, "username", "u", "", "Username (required)") - pingCommand.Flags().StringVarP(&password, "password", "p", "", "Password (required)") - pingCommand.Flags().StringVarP(&thingID, "thing_id", "t", "", "Thing ID (required)") - - pingCommand.Flags().BoolVar(&troubleshooting, "troubleshooting", false, "Enable troubleshooting mode (full logs from the MQTT client)") - - pingCommand.MarkFlagRequired("username") - pingCommand.MarkFlagRequired("password") - pingCommand.MarkFlagRequired("thing_id") - - RootCmd.AddCommand(pingCommand) -} - -var pingCommand = &cobra.Command{ - Use: "ping", - Short: "Ping Arduino IoT Cloud", - Long: "Ping Arduino IoT Cloud", - RunE: func(cmd *cobra.Command, args []string) error { - - if troubleshooting { - paho.ERROR = log.New(os.Stdout, "[ERROR] ", 0) - paho.CRITICAL = log.New(os.Stdout, "[CRIT] ", 0) - paho.WARN = log.New(os.Stdout, "[WARN] ", 0) - paho.DEBUG = log.New(os.Stdout, "[DEBUG] ", 0) - } - - mqttAdapter := mqtt.NewAdapterWithAuth( - host, - username, - username, - password, - ) - - err := mqttAdapter.Connect() - if err != nil { - return err - } - fmt.Println("Connected to Arduino IoT Cloud") - - inboundTopic := fmt.Sprintf("/a/t/%s/e/i", thingID) - outboundTopic := fmt.Sprintf("/a/t/%s/e/o", thingID) - - // Subscribing to the thing inbound topic to received new properties - // values from the cloud. - ok, _ := mqttAdapter.On(inboundTopic, func(msg paho.Message) { - fmt.Println("received a message", msg) - }) - fmt.Println("Subscribed", ok) - - // Sending new random values (in the 0-100 range) to the thing specified - // using the flags - go func() { - for { - randomValue := rand.Intn(100) - - property, err := properties.NewInteger("counter", randomValue) - if err != nil { - fmt.Println("Failed to encode property value", err) - } - - // Publishing a new random value to the outbound topic of the thing - err = mqttAdapter.Publish(outboundTopic, property) - if err != nil { - fmt.Println("Failed to send property to Arduino IoT Cloud", err) - } - fmt.Println("Property value sent successfully", randomValue) - - wait := 3 - time.Sleep(time.Duration(wait) * time.Second) - } - }() - - // Wait for a sigterm signal (CTRL+C) to disconnect from the broker - // and say good bye - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT) - - // blocking here waiting for a signal from the terminal 😪 - <-c - - mqttAdapter.Disconnect() - if err != nil { - return err - } - fmt.Println("Disconnected from Arduino IoT Cloud.") - fmt.Println("Completed successfully.") - - return nil - }, -} diff --git a/command/ping/ping.go b/command/ping/ping.go new file mode 100644 index 00000000..f07e30e2 --- /dev/null +++ b/command/ping/ping.go @@ -0,0 +1,95 @@ +package ping + +import ( + "fmt" + "log" + "math/rand" + "os" + "os/signal" + "syscall" + "time" + + "github.com/bcmi-labs/iot-cloud-cli/internal/mqtt" + "github.com/bcmi-labs/iot-cloud-cli/internal/properties" + paho "github.com/eclipse/paho.mqtt.golang" +) + +type Params struct { + Host string + Username string + Password string + ThingID string + Troubleshooting bool +} + +func Ping(params *Params) error { + if params.Troubleshooting { + paho.ERROR = log.New(os.Stdout, "[ERROR] ", 0) + paho.CRITICAL = log.New(os.Stdout, "[CRIT] ", 0) + paho.WARN = log.New(os.Stdout, "[WARN] ", 0) + paho.DEBUG = log.New(os.Stdout, "[DEBUG] ", 0) + } + + mqttAdapter := mqtt.NewAdapterWithAuth( + params.Host, + params.Username, + params.Username, + params.Password, + ) + + err := mqttAdapter.Connect() + if err != nil { + return err + } + fmt.Println("Connected to Arduino IoT Cloud") + + inboundTopic := fmt.Sprintf("/a/t/%s/e/i", params.ThingID) + outboundTopic := fmt.Sprintf("/a/t/%s/e/o", params.ThingID) + + // Subscribing to the thing inbound topic to received new properties + // values from the cloud. + ok, _ := mqttAdapter.On(inboundTopic, func(msg paho.Message) { + fmt.Println("received a message", msg) + }) + fmt.Println("Subscribed", ok) + + // Sending new random values (in the 0-100 range) to the thing specified + // using the flags + go func() { + for { + randomValue := rand.Intn(100) + + property, err := properties.NewInteger("counter", randomValue) + if err != nil { + fmt.Println("Failed to encode property value", err) + } + + // Publishing a new random value to the outbound topic of the thing + err = mqttAdapter.Publish(outboundTopic, property) + if err != nil { + fmt.Println("Failed to send property to Arduino IoT Cloud", err) + } + fmt.Println("Property value sent successfully", randomValue) + + wait := 3 + time.Sleep(time.Duration(wait) * time.Second) + } + }() + + // Wait for a sigterm signal (CTRL+C) to disconnect from the broker + // and say good bye + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT) + + // blocking here waiting for a signal from the terminal 😪 + <-c + + mqttAdapter.Disconnect() + if err != nil { + return err + } + + fmt.Println("Disconnected from Arduino IoT Cloud.") + fmt.Println("Completed successfully.") + return nil +} diff --git a/command/root.go b/command/root.go deleted file mode 100644 index 3c45d23c..00000000 --- a/command/root.go +++ /dev/null @@ -1,16 +0,0 @@ -package command - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" -) - -var RootCmd = &cobra.Command{} - -func Execute() { - if err := RootCmd.Execute(); err != nil { - fmt.Fprintln(os.Stderr, err) - } -} diff --git a/adapters/mqtt/adapter.go b/internal/mqtt/adapter.go similarity index 100% rename from adapters/mqtt/adapter.go rename to internal/mqtt/adapter.go diff --git a/utils/topic.go b/internal/mqtt/topic.go similarity index 99% rename from utils/topic.go rename to internal/mqtt/topic.go index 400c3ff2..34449f63 100644 --- a/utils/topic.go +++ b/internal/mqtt/topic.go @@ -1,4 +1,4 @@ -package utils +package mqtt import ( "regexp" diff --git a/main.go b/main.go index e973b9fc..519bd385 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,7 @@ package main -import "github.com/bcmi-labs/iot-cloud-cli/command" +import "github.com/bcmi-labs/iot-cloud-cli/cli" func main() { - command.Execute() + cli.Execute() }