1pub use clap::Parser;
2use std::path::PathBuf;
3
4#[derive(Debug, clap::Parser)]
5#[command(
6 name = "ev3-runner",
7 version,
8 about = "Upload and run binaries on LEGO EV3 robots",
9 long_about = "A tool to upload and execute programs on LEGO EV3 robots running ev3dev.\n\
10 Uses hash-based deduplication to skip uploads when files haven't changed.\n\
11 Supports password protection and real-time output streaming."
12)]
13pub struct Cli {
14 #[clap(
15 short,
16 long,
17 global = true,
18 action = clap::ArgAction::Count,
19 help = "Increase logging verbosity (-v: INFO, -vv: DEBUG, -vvv: TRACE)"
20 )]
21 pub verbose: u8,
22 #[command(subcommand)]
23 pub command: Commands,
24}
25
26#[derive(Debug, clap::Subcommand)]
27pub enum Commands {
28 #[command(
30 long_about = "Start the server to accept file uploads and execute programs.\n\
31 This mode should be run on the EV3 robot."
32 )]
33 Server(Server),
34 #[command(
36 long_about = "Connect to a server to upload files or execute programs.\n\
37 This mode should be run on your development machine."
38 )]
39 Client(Client),
40}
41
42#[derive(Debug, clap::Args)]
43pub struct Client {
44 #[command(subcommand)]
45 pub action: Action,
46}
47
48#[derive(Debug, clap::Subcommand)]
49pub enum Action {
50 #[command(long_about = "Upload a file to the server without executing it.\n\
52 The file will be made executable on the server.")]
53 Upload(ClientArgs),
54 #[command(
56 long_about = "Upload a file to the server and execute it immediately.\n\
57 Output from the program will be streamed back in real-time.\n\
58 If the file hash matches what's already on the server, upload is skipped."
59 )]
60 Run(ClientArgs),
61}
62
63#[derive(Debug, clap::Args)]
64pub struct ClientArgs {
65 #[arg(value_name = "FILE")]
67 pub filepath: PathBuf,
68
69 #[clap(
71 long,
72 default_value = "127.0.0.1:6767",
73 value_name = "HOST:PORT",
74 help = "Server address in format IP:PORT"
75 )]
76 pub host: String,
77
78 #[clap(
80 short,
81 long,
82 value_name = "PATH",
83 help = "Remote file path (default: same filename as local)"
84 )]
85 pub remote_path: Option<PathBuf>,
86
87 #[clap(
89 short,
90 long,
91 default_value = "maker",
92 value_name = "PASSWORD",
93 help = "Password to authenticate with the server"
94 )]
95 pub password: String,
96
97 #[clap(short, long, help = "If the program should be started using brickrun")]
99 pub brickrun: bool,
100
101 #[clap(short, long, help = "If compression should be used to send the file")]
103 pub compression: bool,
104}
105
106#[derive(Debug, clap::Args)]
107pub struct Server {
108 #[clap(
110 short,
111 long,
112 default_value = "6767",
113 value_name = "PORT",
114 help = "TCP port for incoming connections"
115 )]
116 pub server_port: u16,
117
118 #[clap(
120 short,
121 long,
122 default_value = "maker",
123 value_name = "PASSWORD",
124 help = "Password required for client authentication"
125 )]
126 pub password: String,
127}