diff --git a/api/notify.go b/api/notify.go new file mode 100644 index 0000000..ccc2b6e --- /dev/null +++ b/api/notify.go @@ -0,0 +1,14 @@ +package api + +import "go.arsenm.dev/itd/internal/types" + +func (c *Client) Notify(title string, body string) error { + _, err := c.request(types.Request{ + Type: types.ReqTypeNotify, + Data: types.ReqDataNotify{ + Title: title, + Body: body, + }, + }) + return err +} \ No newline at end of file diff --git a/cmd/itctl/firmware/upgrade.go b/cmd/itctl/firmware/upgrade.go index fb90458..18f5372 100644 --- a/cmd/itctl/firmware/upgrade.go +++ b/cmd/itctl/firmware/upgrade.go @@ -19,15 +19,11 @@ package firmware import ( - "bufio" - "encoding/json" - "net" - "github.com/cheggaaa/pb/v3" - "github.com/mitchellh/mapstructure" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" + "go.arsenm.dev/itd/api" "go.arsenm.dev/itd/internal/types" ) @@ -36,47 +32,34 @@ type DFUProgress struct { Total int64 `mapstructure:"total"` } - // upgradeCmd represents the upgrade command var upgradeCmd = &cobra.Command{ Use: "upgrade", Short: "Upgrade InfiniTime firmware using files or archive", Aliases: []string{"upg"}, Run: func(cmd *cobra.Command, args []string) { - // Connect to itd UNIX socket - conn, err := net.Dial("unix", viper.GetString("sockPath")) - if err != nil { - log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?") - } - defer conn.Close() + client := viper.Get("client").(*api.Client) - var data types.ReqDataFwUpgrade + var upgType api.UpgradeType + var files []string // Get relevant data struct if viper.GetString("archive") != "" { // Get archive data struct - data = types.ReqDataFwUpgrade{ - Type: types.UpgradeTypeArchive, - Files: []string{viper.GetString("archive")}, - } + upgType = types.UpgradeTypeArchive + files = []string{viper.GetString("archive")} } else if viper.GetString("initPkt") != "" && viper.GetString("firmware") != "" { // Get files data struct - data = types.ReqDataFwUpgrade{ - Type: types.UpgradeTypeFiles, - Files: []string{viper.GetString("initPkt"), viper.GetString("firmware")}, - } + upgType = types.UpgradeTypeFiles + files = []string{viper.GetString("initPkt"), viper.GetString("firmware")} } else { cmd.Usage() log.Warn().Msg("Upgrade command requires either archive or init packet and firmware.") return } - // Encode response into connection - err = json.NewEncoder(conn).Encode(types.Request{ - Type: types.ReqTypeFwUpgrade, - Data: data, - }) + progress, err := client.FirmwareUpgrade(upgType, files...) if err != nil { - log.Fatal().Err(err).Msg("Error making request") + log.Fatal().Err(err).Msg("Error initiating DFU") } // Create progress bar template @@ -84,23 +67,7 @@ var upgradeCmd = &cobra.Command{ // Start full bar at 0 total bar := pb.ProgressBarTemplate(barTmpl).Start(0) // Create new scanner of connection - scanner := bufio.NewScanner(conn) - for scanner.Scan() { - var res types.Response - // Decode scanned line into response struct - err = json.Unmarshal(scanner.Bytes(), &res) - if err != nil { - log.Fatal().Err(err).Msg("Error decoding JSON response") - } - if res.Error { - log.Fatal().Msg(res.Message) - } - var event DFUProgress - // Decode response data into progress struct - err = mapstructure.Decode(res.Value, &event) - if err != nil { - log.Fatal().Err(err).Msg("Error decoding response data") - } + for event := range progress { // Set total bytes in progress bar bar.SetTotal(event.Total) // Set amount of bytes received in progress bar @@ -112,9 +79,6 @@ var upgradeCmd = &cobra.Command{ } // Finish progress bar bar.Finish() - if scanner.Err() != nil { - log.Fatal().Err(scanner.Err()).Msg("Error while scanning output") - } }, } diff --git a/cmd/itctl/firmware/version.go b/cmd/itctl/firmware/version.go index 8a978b0..d1f0f43 100644 --- a/cmd/itctl/firmware/version.go +++ b/cmd/itctl/firmware/version.go @@ -19,15 +19,12 @@ package firmware import ( - "bufio" - "encoding/json" "fmt" - "net" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" - "go.arsenm.dev/itd/internal/types" + "go.arsenm.dev/itd/api" ) // versionCmd represents the version command @@ -36,40 +33,14 @@ var versionCmd = &cobra.Command{ Aliases: []string{"ver"}, Short: "Get firmware version of InfiniTime", Run: func(cmd *cobra.Command, args []string) { - // Connect to itd UNIX socket - conn, err := net.Dial("unix", viper.GetString("sockPath")) + client := viper.Get("client").(*api.Client) + + version, err := client.Version() if err != nil { - log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?") - } - defer conn.Close() - - // Encode request into connection - err = json.NewEncoder(conn).Encode(types.Request{ - Type: types.ReqTypeFwVersion, - }) - if err != nil { - log.Fatal().Err(err).Msg("Error making request") + log.Fatal().Err(err).Msg("Error getting firmware version") } - // Read one line from connection - line, _, err := bufio.NewReader(conn).ReadLine() - if err != nil { - log.Fatal().Err(err).Msg("Error reading line from connection") - } - - var res types.Response - // Decode line into response - err = json.Unmarshal(line, &res) - if err != nil { - log.Fatal().Err(err).Msg("Error decoding JSON data") - } - - if res.Error { - log.Fatal().Msg(res.Message) - } - - // Print returned value - fmt.Println(res.Value) + fmt.Println(version) }, } diff --git a/cmd/itctl/get/address.go b/cmd/itctl/get/address.go index 1048a0c..3e131bd 100644 --- a/cmd/itctl/get/address.go +++ b/cmd/itctl/get/address.go @@ -19,15 +19,12 @@ package get import ( - "bufio" - "encoding/json" "fmt" - "net" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" - "go.arsenm.dev/itd/internal/types" + "go.arsenm.dev/itd/api" ) // addressCmd represents the address command @@ -36,40 +33,14 @@ var addressCmd = &cobra.Command{ Aliases: []string{"addr"}, Short: "Get InfiniTime's bluetooth address", Run: func(cmd *cobra.Command, args []string) { - // Connect to itd UNIX socket - conn, err := net.Dial("unix", viper.GetString("sockPath")) + client := viper.Get("client").(*api.Client) + + address, err := client.Address() if err != nil { - log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?") - } - defer conn.Close() - - // Encode request into connection - err = json.NewEncoder(conn).Encode(types.Request{ - Type: types.ReqTypeBtAddress, - }) - if err != nil { - log.Fatal().Err(err).Msg("Error making request") + log.Fatal().Err(err).Msg("Error getting bluetooth address") } - // Read one line from connection - line, _, err := bufio.NewReader(conn).ReadLine() - if err != nil { - log.Fatal().Err(err).Msg("Error reading line from connection") - } - - var res types.Response - // Decode line into response - err = json.Unmarshal(line, &res) - if err != nil { - log.Fatal().Err(err).Msg("Error decoding JSON data") - } - - if res.Error { - log.Fatal().Msg(res.Message) - } - - // Print returned value - fmt.Println(res.Value) + fmt.Println(address) }, } diff --git a/cmd/itctl/get/battery.go b/cmd/itctl/get/battery.go index 91a5eb8..34fabeb 100644 --- a/cmd/itctl/get/battery.go +++ b/cmd/itctl/get/battery.go @@ -19,15 +19,12 @@ package get import ( - "bufio" - "encoding/json" "fmt" - "net" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" - "go.arsenm.dev/itd/internal/types" + "go.arsenm.dev/itd/api" ) // batteryCmd represents the batt command @@ -36,40 +33,15 @@ var batteryCmd = &cobra.Command{ Aliases: []string{"batt"}, Short: "Get battery level from InfiniTime", Run: func(cmd *cobra.Command, args []string) { - // Connect to itd UNIX socket - conn, err := net.Dial("unix", viper.GetString("sockPath")) - if err != nil { - log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?") - } - defer conn.Close() + client := viper.Get("client").(*api.Client) - // Encode request into connection - err = json.NewEncoder(conn).Encode(types.Request{ - Type: types.ReqTypeBattLevel, - }) + battLevel, err := client.BatteryLevel() if err != nil { - log.Fatal().Err(err).Msg("Error making request") - } - - // Read one line from connection - line, _, err := bufio.NewReader(conn).ReadLine() - if err != nil { - log.Fatal().Err(err).Msg("Error reading line from connection") - } - - var res types.Response - // Deocde line into response - err = json.Unmarshal(line, &res) - if err != nil { - log.Fatal().Err(err).Msg("Error decoding JSON data") - } - - if res.Error { - log.Fatal().Msg(res.Message) + log.Fatal().Err(err).Msg("Error getting battery level") } // Print returned percentage - fmt.Printf("%d%%\n", int(res.Value.(float64))) + fmt.Printf("%d%%\n", battLevel) }, } diff --git a/cmd/itctl/get/heart.go b/cmd/itctl/get/heart.go index 329c82e..fe83381 100644 --- a/cmd/itctl/get/heart.go +++ b/cmd/itctl/get/heart.go @@ -19,15 +19,12 @@ package get import ( - "bufio" - "encoding/json" "fmt" - "net" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" - "go.arsenm.dev/itd/internal/types" + "go.arsenm.dev/itd/api" ) // heartCmd represents the heart command @@ -35,40 +32,15 @@ var heartCmd = &cobra.Command{ Use: "heart", Short: "Get heart rate from InfiniTime", Run: func(cmd *cobra.Command, args []string) { - // Connect to itd UNIX socket - conn, err := net.Dial("unix", viper.GetString("sockPath")) - if err != nil { - log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?") - } - defer conn.Close() + client := viper.Get("client").(*api.Client) - // Encode request into connection - err = json.NewEncoder(conn).Encode(types.Request{ - Type: types.ReqTypeHeartRate, - }) + heartRate, err := client.HeartRate() if err != nil { - log.Fatal().Err(err).Msg("Error making request") - } - - // Read one line from connection - line, _, err := bufio.NewReader(conn).ReadLine() - if err != nil { - log.Fatal().Err(err).Msg("Error reading line from connection") - } - - var res types.Response - // Decode line into response - err = json.Unmarshal(line, &res) - if err != nil { - log.Fatal().Err(err).Msg("Error decoding JSON data") - } - - if res.Error { - log.Fatal().Msg(res.Message) + log.Fatal().Err(err).Msg("Error getting heart rate") } // Print returned BPM - fmt.Printf("%d BPM\n", int(res.Value.(float64))) + fmt.Printf("%d BPM\n", heartRate) }, } diff --git a/cmd/itctl/get/motion.go b/cmd/itctl/get/motion.go index f90d896..2a31655 100644 --- a/cmd/itctl/get/motion.go +++ b/cmd/itctl/get/motion.go @@ -19,16 +19,12 @@ package get import ( - "bufio" - "encoding/json" "fmt" - "net" - "github.com/mitchellh/mapstructure" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" - "go.arsenm.dev/itd/internal/types" + "go.arsenm.dev/itd/api" ) // steps.goCmd represents the steps.go command @@ -36,42 +32,11 @@ var motionCmd = &cobra.Command{ Use: "motion", Short: "Get motion values from InfiniTime", Run: func(cmd *cobra.Command, args []string) { - // Connect to itd UNIX socket - conn, err := net.Dial("unix", viper.GetString("sockPath")) - if err != nil { - log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?") - } - defer conn.Close() + client := viper.Get("client").(*api.Client) - // Encode request into connection - err = json.NewEncoder(conn).Encode(types.Request{ - Type: types.ReqTypeMotion, - }) + motionVals, err := client.Motion() if err != nil { - log.Fatal().Err(err).Msg("Error making request") - } - - // Read one line from connection - line, _, err := bufio.NewReader(conn).ReadLine() - if err != nil { - log.Fatal().Err(err).Msg("Error reading line from connection") - } - - var res types.Response - // Decode line into response - err = json.Unmarshal(line, &res) - if err != nil { - log.Fatal().Err(err).Msg("Error decoding JSON data") - } - - var motionVals types.MotionValues - err = mapstructure.Decode(res.Value, &motionVals) - if err != nil { - log.Fatal().Err(err).Msg("Error decoding motion values") - } - - if res.Error { - log.Fatal().Msg(res.Message) + log.Fatal().Err(err).Msg("Error getting motion values") } if viper.GetBool("shell") { diff --git a/cmd/itctl/get/steps.go b/cmd/itctl/get/steps.go index 6d29d45..7c0f445 100644 --- a/cmd/itctl/get/steps.go +++ b/cmd/itctl/get/steps.go @@ -19,15 +19,12 @@ package get import ( - "bufio" - "encoding/json" "fmt" - "net" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" - "go.arsenm.dev/itd/internal/types" + "go.arsenm.dev/itd/api" ) // steps.goCmd represents the steps.go command @@ -35,40 +32,15 @@ var stepsCmd = &cobra.Command{ Use: "steps", Short: "Get step count from InfiniTime", Run: func(cmd *cobra.Command, args []string) { - // Connect to itd UNIX socket - conn, err := net.Dial("unix", viper.GetString("sockPath")) - if err != nil { - log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?") - } - defer conn.Close() + client := viper.Get("client").(*api.Client) - // Encode request into connection - err = json.NewEncoder(conn).Encode(types.Request{ - Type: types.ReqTypeStepCount, - }) + stepCount, err := client.StepCount() if err != nil { - log.Fatal().Err(err).Msg("Error making request") - } - - // Read one line from connection - line, _, err := bufio.NewReader(conn).ReadLine() - if err != nil { - log.Fatal().Err(err).Msg("Error reading line from connection") - } - - var res types.Response - // Decode line into response - err = json.Unmarshal(line, &res) - if err != nil { - log.Fatal().Err(err).Msg("Error decoding JSON data") - } - - if res.Error { - log.Fatal().Msg(res.Message) + log.Fatal().Err(err).Msg("Error getting step count") } // Print returned BPM - fmt.Printf("%d Steps\n", int(res.Value.(float64))) + fmt.Printf("%d Steps\n", stepCount) }, } diff --git a/cmd/itctl/notify/notify.go b/cmd/itctl/notify/notify.go index 5238003..9e035cf 100644 --- a/cmd/itctl/notify/notify.go +++ b/cmd/itctl/notify/notify.go @@ -19,15 +19,11 @@ package notify import ( - "bufio" - "encoding/json" - "net" - "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" + "go.arsenm.dev/itd/api" "go.arsenm.dev/itd/cmd/itctl/root" - "go.arsenm.dev/itd/internal/types" ) // notifyCmd represents the notify command @@ -41,40 +37,11 @@ var notifyCmd = &cobra.Command{ log.Fatal().Msg("Command notify requires two arguments") } - // Connect to itd UNIX socket - conn, err := net.Dial("unix", viper.GetString("sockPath")) - if err != nil { - log.Fatal().Err(err).Msg("Error dialing socket. Is itd running?") - } - defer conn.Close() + client := viper.Get("client").(*api.Client) - // Encode request into connection - err = json.NewEncoder(conn).Encode(types.Request{ - Type: types.ReqTypeNotify, - Data: types.ReqDataNotify{ - Title: args[0], - Body: args[1], - }, - }) + err := client.Notify(args[0], args[1]) if err != nil { - log.Fatal().Err(err).Msg("Error making request") - } - - // Read one line from connection - line, _, err := bufio.NewReader(conn).ReadLine() - if err != nil { - log.Fatal().Err(err).Msg("Error reading line from connection") - } - - var res types.Response - // Decode line into response - err = json.Unmarshal(line, &res) - if err != nil { - log.Fatal().Err(err).Msg("Error decoding JSON data") - } - - if res.Error { - log.Fatal().Msg(res.Message) + log.Fatal().Err(err).Msg("Error sending notification") } }, } diff --git a/cmd/itctl/root/root.go b/cmd/itctl/root/root.go index 209c948..91034ed 100644 --- a/cmd/itctl/root/root.go +++ b/cmd/itctl/root/root.go @@ -20,8 +20,10 @@ package root import ( "github.com/abiosoft/ishell" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/spf13/viper" + "go.arsenm.dev/itd/api" ) // RootCmd represents the base command when called without any subcommands @@ -61,18 +63,25 @@ var RootCmd = &cobra.Command{ // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { + client, err := api.New(viper.GetString("sockPath")) + if err != nil { + log.Fatal().Err(err).Msg("Error connecting to socket. Is itd running?") + } + defer client.Close() + viper.Set("client", client) RootCmd.CompletionOptions.DisableDefaultCmd = true cobra.CheckErr(RootCmd.Execute()) + } func init() { // Register flag for socket path - RootCmd.Flags().StringP("socket-path", "s", "", "Path to itd socket") + RootCmd.Flags().StringP("socket-path", "s", api.DefaultAddr, "Path to itd socket") // Bind flag and environment variable to viper key viper.BindPFlag("sockPath", RootCmd.Flags().Lookup("socket-path")) viper.BindEnv("sockPath", "ITCTL_SOCKET_PATH") // Set default value for socket path - viper.SetDefault("sockPath", "/tmp/itd/socket") + viper.SetDefault("sockPath", api.DefaultAddr) }