From ee563320cb215d557cc7b6481be42ba02bb0ca5a Mon Sep 17 00:00:00 2001 From: Alex Resnick Date: Tue, 14 Apr 2026 19:54:33 -0500 Subject: [PATCH 1/6] Fix Formating Command --- cmd/usb.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/cmd/usb.go b/cmd/usb.go index bd5ae92..e44fe59 100644 --- a/cmd/usb.go +++ b/cmd/usb.go @@ -79,20 +79,13 @@ var formatCmd = &cobra.Command{ } fmt.Println(out) - mountCmdStr := fmt.Sprintf("mount %s /media/sda1", device) - out, err = client.Run(mountCmdStr) + rebootCmdStr := fmt.Sprint("reboot") + out, err = client.Run(rebootCmdStr) if err != nil { return err } fmt.Println(out) - out, err = client.Run("RESTART=yes /usr/local/frc/bin/frcKillRobot.sh") - if err != nil { - return err - } - fmt.Println(out) - - fmt.Println(out) return nil }, } From e4554364d3a106e781d029eeeeac8010659ab27c Mon Sep 17 00:00:00 2001 From: Alex Resnick Date: Tue, 14 Apr 2026 20:40:51 -0500 Subject: [PATCH 2/6] Add event and match type filtering --- cmd/logs.go | 61 +++++++++++++++++++++++++++++++----- internal/sshclient/client.go | 21 +++++++++++-- internal/ui/filepicker.go | 2 +- internal/ui/progress.go | 6 +--- internal/utils/file.go | 12 +++++-- 5 files changed, 85 insertions(+), 17 deletions(-) diff --git a/cmd/logs.go b/cmd/logs.go index f448401..bf86917 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -1,10 +1,14 @@ package cmd import ( + "bufio" "fmt" + "os" + "strings" "rioctl/internal/transfer" "rioctl/internal/ui" + "rioctl/internal/utils" "github.com/spf13/cobra" ) @@ -41,6 +45,10 @@ var logsPullCmd = &cobra.Command{ } dest, _ := cmd.Flags().GetString("dest") + eventCode, _ := cmd.Flags().GetString("event") + practice, _ := cmd.Flags().GetBool("practice") + qual, _ := cmd.Flags().GetBool("qual") + elim, _ := cmd.Flags().GetBool("elim") var files []string @@ -49,19 +57,54 @@ var logsPullCmd = &cobra.Command{ files = args } else { fmt.Println("Fetching file list...") - allFiles, err := client.ListFiles(source) if err != nil { return err } + if eventCode != "" || practice || qual || elim { + allFiles, err := client.ListFiles(source) + if err != nil { + return err + } + var totalSize int64 + for _, file := range allFiles { + if eventCode != "" && file.Event != eventCode { + continue + } + if !practice && !elim && !qual { + files = append(files, file.Name) + totalSize += file.Size + } else if practice && file.MatchType == "p" { + files = append(files, file.Name) + totalSize += file.Size + } else if qual && file.MatchType == "q" { + files = append(files, file.Name) + totalSize += file.Size + } else if elim && file.MatchType == "e" { + files = append(files, file.Name) + totalSize += file.Size + } + } + + fmt.Printf("⚠️ This will pull %d files (%s). Continue? (yes/no): ", len(files), utils.Humanize(totalSize)) + + reader := bufio.NewReader(os.Stdin) + text, _ := reader.ReadString('\n') + + if strings.ToLower(text) != "yes\n" { + fmt.Println("Aborted.") + return nil + } - // Launch TUI selector - selected, err := ui.RunFilePicker(allFiles) - if err != nil { - return err - } + } else { + // Launch TUI selector + selected, err := ui.RunFilePicker(allFiles) + if err != nil { + return err + } - files = selected + files = selected + } } fmt.Println("Downloading selected files...") @@ -72,6 +115,10 @@ var logsPullCmd = &cobra.Command{ func init() { logsPullCmd.Flags().String("source", "/media/sda1", "Source directory") logsPullCmd.Flags().String("dest", "./logs", "Destination directory") + logsPullCmd.Flags().String("event", "", "Event Code to download Event only logs") + logsPullCmd.Flags().Bool("practice", false, "Pull Practice Match Logs") + logsPullCmd.Flags().Bool("qual", false, "Pull Qual Match Logs") + logsPullCmd.Flags().Bool("elim", false, "Pull Elim Match Logs") logsCmd.AddCommand(logsPullCmd) rootCmd.AddCommand(logsCmd) diff --git a/internal/sshclient/client.go b/internal/sshclient/client.go index bcdc974..06edac9 100644 --- a/internal/sshclient/client.go +++ b/internal/sshclient/client.go @@ -2,6 +2,7 @@ package sshclient import ( "fmt" + "regexp" "rioctl/internal/utils" "slices" "strconv" @@ -10,6 +11,8 @@ import ( "github.com/melbahja/goph" ) +var fileRE = regexp.MustCompile(`^akit_.*_(\w+)_([peq])\d+\.wpilog$`) + type Client struct { client *goph.Client } @@ -39,7 +42,7 @@ func (c *Client) Close() error { } func (c *Client) ListFiles(dir string) ([]utils.File, error) { - out, err := c.Run(fmt.Sprintf("ls -lh %s | grep .wpilog | awk '{ print $5\",\"$9 }'", dir)) + out, err := c.Run(fmt.Sprintf("ls -l %s | grep .wpilog | awk '{ print $5\",\"$9 }'", dir)) if err != nil { return nil, err } @@ -51,8 +54,22 @@ func (c *Client) ListFiles(dir string) ([]utils.File, error) { if l == "" { continue } + eventCode := "" + matchType := "" stringArr := strings.Split(l, ",") - files = append(files, utils.File{Name: stringArr[1], Size: stringArr[0]}) + name := stringArr[1] + + size, err := strconv.ParseInt(strings.TrimSpace(stringArr[0]), 10, 64) + if err != nil { + continue + } + if fileRE.MatchString(name) { + matches := fileRE.FindStringSubmatch(name) + eventCode = matches[1] + matchType = matches[2] + } + + files = append(files, utils.File{Name: name, Size: size, Event: eventCode, MatchType: matchType}) } slices.Reverse(files) return files, nil diff --git a/internal/ui/filepicker.go b/internal/ui/filepicker.go index adab305..20f455d 100644 --- a/internal/ui/filepicker.go +++ b/internal/ui/filepicker.go @@ -103,7 +103,7 @@ func NewFilePicker(files []utils.File) model { choices := make([]*item, len(files)) for i, f := range files { - it := &item{title: f.Name, size: f.Size} + it := &item{title: f.Name, size: utils.Humanize(f.Size)} items[i] = it choices[i] = it } diff --git a/internal/ui/progress.go b/internal/ui/progress.go index 7e86df6..40657c4 100644 --- a/internal/ui/progress.go +++ b/internal/ui/progress.go @@ -91,7 +91,7 @@ func (m progressModel) View() tea.View { return tea.NewView("\n\n" + a + fmt.Sprintf("Downloading %s (%d/%d)", m.currentFile, m.finished+1, m.total) + "\n\n" + m.progress.ViewAs(current) + "\n\n" + - pad + helpStyle(fmt.Sprintf("%s / %s", humanize(m.currentFileBytes), humanize((m.totalFileBytes))))) + pad + helpStyle(fmt.Sprintf("%s / %s", utils.Humanize(m.currentFileBytes), utils.Humanize((m.totalFileBytes))))) } func RunProgress(total int, current <-chan utils.FileUpload, finished <-chan int) { @@ -124,7 +124,3 @@ func RunProgress1(total int, stuff []string) { p.Run() } - -func humanize(b int64) string { - return fmt.Sprintf("%.2f MB", float64(b)/1024/1024) -} diff --git a/internal/utils/file.go b/internal/utils/file.go index 6a3b133..4712aa4 100644 --- a/internal/utils/file.go +++ b/internal/utils/file.go @@ -1,5 +1,7 @@ package utils +import "fmt" + type FileUpload struct { Size int64 Current int64 @@ -20,6 +22,12 @@ func NewFile(size int64, current int64, name string) FileUpload { } type File struct { - Size string - Name string + Size int64 + Name string + Event string + MatchType string +} + +func Humanize(b int64) string { + return fmt.Sprintf("%.2f MB", float64(b)/1024/1024) } From 1ad3020f6581fafdc66dec1adf3bb2911b9d656d Mon Sep 17 00:00:00 2001 From: Alex Resnick Date: Wed, 15 Apr 2026 06:26:02 -0500 Subject: [PATCH 3/6] minor linting --- cmd/usb.go | 3 +-- internal/ui/progress.go | 13 ------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/cmd/usb.go b/cmd/usb.go index e44fe59..48489f1 100644 --- a/cmd/usb.go +++ b/cmd/usb.go @@ -79,8 +79,7 @@ var formatCmd = &cobra.Command{ } fmt.Println(out) - rebootCmdStr := fmt.Sprint("reboot") - out, err = client.Run(rebootCmdStr) + out, err = client.Run("reboot") if err != nil { return err } diff --git a/internal/ui/progress.go b/internal/ui/progress.go index 40657c4..5d4aab8 100644 --- a/internal/ui/progress.go +++ b/internal/ui/progress.go @@ -111,16 +111,3 @@ func RunProgress(total int, current <-chan utils.FileUpload, finished <-chan int p.Run() } - -func RunProgress1(total int, stuff []string) { - m := NewProgress(total) - p := tea.NewProgram(m) - - go func() { - for u := range stuff { - p.Send(u) - } - }() - - p.Run() -} From c8c9f66e5d256ac9a1a3cfc351b9e56d3922a7de Mon Sep 17 00:00:00 2001 From: Alex Resnick Date: Wed, 15 Apr 2026 06:37:21 -0500 Subject: [PATCH 4/6] minor things --- internal/ui/filepicker.go | 2 +- internal/ui/progress.go | 4 ++-- internal/utils/file.go | 15 +++++++++++---- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/internal/ui/filepicker.go b/internal/ui/filepicker.go index 20f455d..936adb4 100644 --- a/internal/ui/filepicker.go +++ b/internal/ui/filepicker.go @@ -103,7 +103,7 @@ func NewFilePicker(files []utils.File) model { choices := make([]*item, len(files)) for i, f := range files { - it := &item{title: f.Name, size: utils.Humanize(f.Size)} + it := &item{title: f.Name, size: f.HumanizedSize()} items[i] = it choices[i] = it } diff --git a/internal/ui/progress.go b/internal/ui/progress.go index 5d4aab8..f79d6ea 100644 --- a/internal/ui/progress.go +++ b/internal/ui/progress.go @@ -64,8 +64,8 @@ func (m progressModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } case utils.FileUpload: m.currentFileBytes = msg.Current - m.totalFileBytes = msg.Size - m.currentFile = msg.Name + m.totalFileBytes = msg.File.Size + m.currentFile = msg.File.Name if m.currentFileBytes >= m.totalFileBytes { m.completedFiles = append(m.completedFiles, m.currentFile) } diff --git a/internal/utils/file.go b/internal/utils/file.go index 4712aa4..62f0eb4 100644 --- a/internal/utils/file.go +++ b/internal/utils/file.go @@ -3,9 +3,10 @@ package utils import "fmt" type FileUpload struct { - Size int64 + File File + // Size int64 Current int64 - Name string + // Name string } func (m FileUpload) UpdateCurrent(current int64) FileUpload { @@ -15,9 +16,11 @@ func (m FileUpload) UpdateCurrent(current int64) FileUpload { func NewFile(size int64, current int64, name string) FileUpload { return FileUpload{ - Name: name, + File: File{ + Name: name, + Size: size, + }, Current: current, - Size: size, } } @@ -28,6 +31,10 @@ type File struct { MatchType string } +func (f File) HumanizedSize() string { + return Humanize(f.Size) +} + func Humanize(b int64) string { return fmt.Sprintf("%.2f MB", float64(b)/1024/1024) } From 34e30f54af068b9fc40ff3350ff14a6cd5aa5a13 Mon Sep 17 00:00:00 2001 From: Alex Resnick Date: Wed, 15 Apr 2026 06:38:07 -0500 Subject: [PATCH 5/6] remove test stuff --- cmd/test copy.go | 18 ------------------ cmd/test.go | 42 ------------------------------------------ 2 files changed, 60 deletions(-) delete mode 100644 cmd/test copy.go delete mode 100644 cmd/test.go diff --git a/cmd/test copy.go b/cmd/test copy.go deleted file mode 100644 index 54a02bb..0000000 --- a/cmd/test copy.go +++ /dev/null @@ -1,18 +0,0 @@ -package cmd - -// var test2CMD = &cobra.Command{ -// Use: "test2", -// Short: "test operations", -// Args: cobra.ArbitraryArgs, -// RunE: func(cmd *cobra.Command, args []string) error { - -// allFiles := []string{"asdf", "asdf"} -// _, err := ui.RunFilePicker(allFiles) -// return err -// }, -// } - -// func init() { - -// rootCmd.AddCommand(test2CMD) -// } diff --git a/cmd/test.go b/cmd/test.go deleted file mode 100644 index 82bb440..0000000 --- a/cmd/test.go +++ /dev/null @@ -1,42 +0,0 @@ -package cmd - -import ( - "os" - "rioctl/internal/ui" - - "github.com/spf13/cobra" - - "charm.land/lipgloss/v2" -) - -const ( - padding = 2 - maxWidth = 80 -) - -var helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#626262")).Render - -var testCMD = &cobra.Command{ - Use: "test", - Short: "test operations", - Args: cobra.ArbitraryArgs, - RunE: func(cmd *cobra.Command, args []string) error { - progressChan := make(chan int) - files := []string{"asdf", "qwer", "1234"} - // for i, _ := range files { - // // fmt.Printf("Downloading File %s", file) - // time.Sleep(4 * time.Second) // Pauses for 1 second - // progressChan <- i + 1 - // } - ui.RunProgress1(len(files), files) - - close(progressChan) - os.Exit(0) - return nil - }, -} - -func init() { - - rootCmd.AddCommand(testCMD) -} From 9c95b6e83186f9976ef569c8b0b37901ff80cac4 Mon Sep 17 00:00:00 2001 From: Alex Resnick Date: Wed, 15 Apr 2026 06:50:51 -0500 Subject: [PATCH 6/6] loop through rio addresses --- cmd/logs.go | 8 ++++---- cmd/ssh.go | 19 ++++++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/cmd/logs.go b/cmd/logs.go index bf86917..f979aad 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -17,7 +17,7 @@ var logsCmd = &cobra.Command{ Use: "logs", Short: "Log operations", } - +var defaultSource = "/media/sda1" var logsPullCmd = &cobra.Command{ Use: "pull [files...]", Short: "Pull logs from RoboRIO", @@ -32,13 +32,13 @@ var logsPullCmd = &cobra.Command{ source, _ := cmd.Flags().GetString("source") // If no dir provided → prompt if source == "" { - input, err := ui.RunTextInput("/media/sda1") + input, err := ui.RunTextInput(defaultSource) if err != nil { return err } if input == "" { - source = "/media/sda1" + source = defaultSource } else { source = input } @@ -113,7 +113,7 @@ var logsPullCmd = &cobra.Command{ } func init() { - logsPullCmd.Flags().String("source", "/media/sda1", "Source directory") + logsPullCmd.Flags().String("source", "", "Source directory") logsPullCmd.Flags().String("dest", "./logs", "Destination directory") logsPullCmd.Flags().String("event", "", "Event Code to download Event only logs") logsPullCmd.Flags().Bool("practice", false, "Pull Practice Match Logs") diff --git a/cmd/ssh.go b/cmd/ssh.go index b6ef0a0..69c5995 100644 --- a/cmd/ssh.go +++ b/cmd/ssh.go @@ -20,9 +20,18 @@ func getSSHClient(cmd *cobra.Command) (*sshclient.Client, error) { return nil, fmt.Errorf("team number is required") } - host := teamToIP(team) - - fmt.Printf("Connecting to %s as %s...\n", host, user) - - return sshclient.New(host, user, pass) + hostOptions := []string{ + teamToIP(team), + fmt.Sprintf("roboRIO-%d-FRC.local", team), + "172.22.11.2", + } + for _, host := range hostOptions { + fmt.Printf("Connecting to %s as %s...\n", host, user) + client, err := sshclient.New(host, user, pass) + if err == nil { + return client, nil + } + fmt.Printf("Connection to %s failed\n", host) + } + return nil, fmt.Errorf("Could not connect to RoboRio on any IP/Hostname") }