Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 1 | // This binary lets users interact with the scouting web server in order to |
| 2 | // debug it. Run with `--help` to see all the options. |
| 3 | |
| 4 | package main |
| 5 | |
| 6 | import ( |
| 7 | "flag" |
| 8 | "io/ioutil" |
| 9 | "log" |
| 10 | "os" |
| 11 | "os/exec" |
| 12 | "path/filepath" |
| 13 | |
Philipp Schrader | d3fac19 | 2022-03-02 20:35:46 -0800 | [diff] [blame^] | 14 | "github.com/davecgh/go-spew/spew" |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 15 | "github.com/frc971/971-Robot-Code/scouting/webserver/requests/debug" |
| 16 | ) |
| 17 | |
| 18 | // Returns the absolute path of the specified path. This is an unwrapped |
| 19 | // version of `filepath.Abs`. |
| 20 | func absPath(path string) string { |
| 21 | result, err := filepath.Abs(path) |
| 22 | if err != nil { |
| 23 | log.Fatal("Failed to determine absolute path for ", path, ": ", err) |
| 24 | } |
| 25 | return result |
| 26 | } |
| 27 | |
| 28 | // Parses the specified JSON file into a binary version (i.e. serialized |
| 29 | // flatbuffer). This uses the `flatc` binary and the JSON's corresponding |
| 30 | // `.fbs` file. |
| 31 | func parseJson(fbsPath string, jsonPath string) []byte { |
| 32 | // Work inside a temporary directory since `flatc` doesn't allow us to |
| 33 | // customize the name of the output file. |
| 34 | dir, err := ioutil.TempDir("", "webserver_debug_cli") |
| 35 | if err != nil { |
| 36 | log.Fatal("Failed to create temporary directory: ", err) |
| 37 | } |
| 38 | defer os.RemoveAll(dir) |
| 39 | |
| 40 | // Turn these paths absolute so that it everything still works from |
| 41 | // inside the temporary directory. |
| 42 | absFlatcPath := absPath("external/com_github_google_flatbuffers/flatc") |
| 43 | absFbsPath := absPath(fbsPath) |
| 44 | |
| 45 | // Create a symlink to the .fbs file so that the output filename that |
| 46 | // `flatc` generates is predictable. I.e. `fb.json` gets serialized |
| 47 | // into `fb.bin`. |
| 48 | jsonSymlink := filepath.Join(dir, "fb.json") |
| 49 | os.Symlink(jsonPath, jsonSymlink) |
| 50 | |
| 51 | // Execute the `flatc` command. |
| 52 | flatcCommand := exec.Command(absFlatcPath, "--binary", absFbsPath, jsonSymlink) |
| 53 | flatcCommand.Dir = dir |
Philipp Schrader | cbf5c6a | 2022-02-27 23:25:19 -0800 | [diff] [blame] | 54 | output, err := flatcCommand.CombinedOutput() |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 55 | if err != nil { |
Philipp Schrader | cbf5c6a | 2022-02-27 23:25:19 -0800 | [diff] [blame] | 56 | log.Fatal("Failed to execute flatc: ", err, ": ", string(output)) |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 57 | } |
| 58 | |
| 59 | // Read the serialized flatbuffer and return it. |
| 60 | binaryPath := filepath.Join(dir, "fb.bin") |
| 61 | binaryFb, err := os.ReadFile(binaryPath) |
| 62 | if err != nil { |
| 63 | log.Fatal("Failed to read flatc output ", binaryPath, ": ", err) |
| 64 | } |
| 65 | return binaryFb |
| 66 | } |
| 67 | |
| 68 | func main() { |
| 69 | // Parse command line arguments. |
| 70 | addressPtr := flag.String("address", "http://localhost:8080", |
| 71 | "The end point where the server is listening.") |
| 72 | submitDataScoutingPtr := flag.String("submitDataScouting", "", |
| 73 | "If specified, parse the file as a SubmitDataScouting JSON request.") |
Philipp Schrader | cbf5c6a | 2022-02-27 23:25:19 -0800 | [diff] [blame] | 74 | requestAllMatchesPtr := flag.String("requestAllMatches", "", |
| 75 | "If specified, parse the file as a RequestAllMatches JSON request.") |
Philipp Schrader | d1c4bef | 2022-02-28 22:51:30 -0800 | [diff] [blame] | 76 | requestMatchesForTeamPtr := flag.String("requestMatchesForTeam", "", |
| 77 | "If specified, parse the file as a RequestMatchesForTeam JSON request.") |
Philipp Schrader | acf9623 | 2022-03-01 22:03:30 -0800 | [diff] [blame] | 78 | requestDataScoutingPtr := flag.String("requestDataScouting", "", |
| 79 | "If specified, parse the file as a RequestDataScouting JSON request.") |
Philipp Schrader | d3fac19 | 2022-03-02 20:35:46 -0800 | [diff] [blame^] | 80 | refreshMatchListPtr := flag.String("refreshMatchList", "", |
| 81 | "If specified, parse the file as a RefreshMatchList JSON request.") |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 82 | flag.Parse() |
| 83 | |
| 84 | // Handle the actual arguments. |
| 85 | if *submitDataScoutingPtr != "" { |
| 86 | log.Printf("Sending SubmitDataScouting to %s", *addressPtr) |
| 87 | binaryRequest := parseJson( |
| 88 | "scouting/webserver/requests/messages/submit_data_scouting.fbs", |
| 89 | *submitDataScoutingPtr) |
| 90 | response, err := debug.SubmitDataScouting(*addressPtr, binaryRequest) |
| 91 | if err != nil { |
| 92 | log.Fatal("Failed SubmitDataScouting: ", err) |
| 93 | } |
Philipp Schrader | d3fac19 | 2022-03-02 20:35:46 -0800 | [diff] [blame^] | 94 | spew.Dump(*response) |
Philipp Schrader | cbf5c6a | 2022-02-27 23:25:19 -0800 | [diff] [blame] | 95 | } |
| 96 | if *requestAllMatchesPtr != "" { |
| 97 | log.Printf("Sending RequestAllMatches to %s", *addressPtr) |
| 98 | binaryRequest := parseJson( |
| 99 | "scouting/webserver/requests/messages/request_all_matches.fbs", |
| 100 | *requestAllMatchesPtr) |
| 101 | response, err := debug.RequestAllMatches(*addressPtr, binaryRequest) |
| 102 | if err != nil { |
| 103 | log.Fatal("Failed RequestAllMatches: ", err) |
| 104 | } |
Philipp Schrader | d3fac19 | 2022-03-02 20:35:46 -0800 | [diff] [blame^] | 105 | spew.Dump(*response) |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 106 | } |
Philipp Schrader | d1c4bef | 2022-02-28 22:51:30 -0800 | [diff] [blame] | 107 | if *requestMatchesForTeamPtr != "" { |
| 108 | log.Printf("Sending RequestMatchesForTeam to %s", *addressPtr) |
| 109 | binaryRequest := parseJson( |
| 110 | "scouting/webserver/requests/messages/request_matches_for_team.fbs", |
| 111 | *requestMatchesForTeamPtr) |
| 112 | response, err := debug.RequestMatchesForTeam(*addressPtr, binaryRequest) |
| 113 | if err != nil { |
| 114 | log.Fatal("Failed RequestMatchesForTeam: ", err) |
| 115 | } |
Philipp Schrader | d3fac19 | 2022-03-02 20:35:46 -0800 | [diff] [blame^] | 116 | spew.Dump(*response) |
Philipp Schrader | d1c4bef | 2022-02-28 22:51:30 -0800 | [diff] [blame] | 117 | } |
Philipp Schrader | acf9623 | 2022-03-01 22:03:30 -0800 | [diff] [blame] | 118 | if *requestDataScoutingPtr != "" { |
| 119 | log.Printf("Sending RequestDataScouting to %s", *addressPtr) |
| 120 | binaryRequest := parseJson( |
| 121 | "scouting/webserver/requests/messages/request_data_scouting.fbs", |
| 122 | *requestDataScoutingPtr) |
| 123 | response, err := debug.RequestDataScouting(*addressPtr, binaryRequest) |
| 124 | if err != nil { |
| 125 | log.Fatal("Failed RequestDataScouting: ", err) |
| 126 | } |
Philipp Schrader | d3fac19 | 2022-03-02 20:35:46 -0800 | [diff] [blame^] | 127 | spew.Dump(*response) |
| 128 | } |
| 129 | if *refreshMatchListPtr != "" { |
| 130 | log.Printf("Sending RefreshMatchList to %s", *addressPtr) |
| 131 | binaryRequest := parseJson( |
| 132 | "scouting/webserver/requests/messages/refresh_match_list.fbs", |
| 133 | *refreshMatchListPtr) |
| 134 | response, err := debug.RefreshMatchList(*addressPtr, binaryRequest) |
| 135 | if err != nil { |
| 136 | log.Fatal("Failed RefreshMatchList: ", err) |
| 137 | } |
| 138 | spew.Dump(*response) |
Philipp Schrader | acf9623 | 2022-03-01 22:03:30 -0800 | [diff] [blame] | 139 | } |
Philipp Schrader | d9096a3 | 2022-02-24 17:53:09 -0800 | [diff] [blame] | 140 | } |