1+ use clap:: Parser ;
12use std:: {
23 error:: Error ,
34 io:: { Read , Write } ,
45 path:: { Path , PathBuf } ,
56 process:: { Child , ChildStdin , ChildStdout , Stdio } ,
67 time:: Duration ,
78} ;
8-
99use STS1_EDU_Scheduler :: communication:: { CEPPacket , CommunicationHandle } ;
1010
11+ #[ derive( clap:: Parser ) ]
12+ enum Args {
13+ /// Simulate a serialport through socat, with the scheduler running on your host
14+ Simulate {
15+ #[ arg( default_value = "target/release" ) ]
16+ target_dir : PathBuf ,
17+ } ,
18+ /// Connect serialport which has an EDU already running
19+ Serial {
20+ serialport : String ,
21+ #[ arg( long, short, default_value_t = 115200 ) ]
22+ baudrate : u32 ,
23+ } ,
24+ }
25+
1126fn main ( ) {
12- let scheduler_path = PathBuf :: from (
13- std:: env:: args ( ) . nth ( 1 ) . expect ( "Pass in the directory containing the scheduler binary" ) ,
14- ) ;
15-
16- let mut serial = SocatSerialPort :: new ( & scheduler_path. join ( "virtualserial" ) ) ;
17- write_scheduler_config ( & scheduler_path) ;
18- let _scheduler = PoisonedChild (
19- std:: process:: Command :: new ( "./STS1_EDU_Scheduler" )
20- . current_dir ( & scheduler_path)
21- . spawn ( )
22- . unwrap ( ) ,
23- ) ;
27+ let args = Args :: parse ( ) ;
2428
29+ match args {
30+ Args :: Simulate { target_dir } => {
31+ write_scheduler_config ( & target_dir) ;
32+ let mut handle = SimulationContext :: new ( & target_dir. join ( "virtualserial" ) ) ;
33+ inquire_loop ( & mut handle) ;
34+ }
35+ Args :: Serial { serialport, baudrate } => {
36+ let mut serial = serialport:: new ( serialport, baudrate) . open ( ) . unwrap ( ) ;
37+ inquire_loop ( & mut serial) ;
38+ }
39+ } ;
40+ }
41+
42+ fn inquire_loop ( handle : & mut impl CommunicationHandle ) -> ! {
2543 loop {
26- inquire_and_send_command ( & mut serial , & scheduler_path ) . unwrap ( ) ;
44+ inquire_and_send_command ( handle ) . unwrap ( ) ;
2745 println ! ( "------------------------" ) ;
2846 std:: thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
2947 }
3048}
3149
32- pub struct SocatSerialPort < T : Read , U : Write > {
33- child : Child ,
50+ pub struct SimulationContext < T : Read , U : Write > {
51+ socat : Child ,
52+ _scheduler : PoisonedChild ,
3453 stdout : T ,
3554 stdin : U ,
3655}
3756
38- impl SocatSerialPort < ChildStdout , ChildStdin > {
57+ impl SimulationContext < ChildStdout , ChildStdin > {
3958 fn new ( path : & Path ) -> Self {
4059 let mut child = std:: process:: Command :: new ( "socat" )
4160 . arg ( "stdio" )
@@ -52,9 +71,13 @@ impl SocatSerialPort<ChildStdout, ChildStdin> {
5271 std:: thread:: sleep ( Duration :: from_millis ( 50 ) ) ;
5372 }
5473
74+ let scheduler = PoisonedChild (
75+ std:: process:: Command :: new ( "./STS1_EDU_Scheduler" ) . current_dir ( path) . spawn ( ) . unwrap ( ) ,
76+ ) ;
77+
5578 let stdout = child. stdout . take ( ) . unwrap ( ) ;
5679 let stdin = child. stdin . take ( ) . unwrap ( ) ;
57- Self { child, stdout, stdin }
80+ Self { socat : child, _scheduler : scheduler , stdout, stdin }
5881 }
5982}
6083
@@ -77,14 +100,8 @@ fn write_scheduler_config(path: &Path) {
77100const COMMANDS : & [ & str ] =
78101 & [ "StoreArchive" , "ExecuteProgram" , "StopProgram" , "GetStatus" , "ReturnResult" , "UpdateTime" ] ;
79102
80- fn inquire_and_send_command (
81- edu : & mut impl CommunicationHandle ,
82- path : & Path ,
83- ) -> Result < ( ) , Box < dyn Error > > {
84- let mut select = inquire:: Select :: new ( "Select command" , COMMANDS . to_vec ( ) ) ;
85- if path. join ( "updatepin" ) . exists ( ) {
86- select. help_message = Some ( "Update Pin is high" ) ;
87- }
103+ fn inquire_and_send_command ( edu : & mut impl CommunicationHandle ) -> Result < ( ) , Box < dyn Error > > {
104+ let select = inquire:: Select :: new ( "Select command" , COMMANDS . to_vec ( ) ) ;
88105 let command = select. prompt ( ) ?;
89106
90107 match command {
@@ -148,19 +165,30 @@ fn inquire_and_send_command(
148165 Err ( e) => println ! ( "Received {e:?}" ) ,
149166 }
150167 }
151- _ => ( ) ,
168+ "UpdateTime" => {
169+ let actual = std:: time:: SystemTime :: now ( )
170+ . duration_since ( std:: time:: UNIX_EPOCH )
171+ . unwrap ( )
172+ . as_secs ( ) ;
173+ let since_epoch = inquire:: prompt_u32 ( "Seconds since epoch (empty for current time):" )
174+ . unwrap_or ( actual as u32 ) ;
175+
176+ edu. send_packet ( & CEPPacket :: Data ( update_time ( since_epoch) ) ) ?;
177+ println ! ( "Received {:?}" , edu. receive_packet( ) ?) ;
178+ }
179+ c => unimplemented ! ( "{c}" ) ,
152180 }
153181
154182 Ok ( ( ) )
155183}
156184
157- impl < T : Read , U : Write > Read for SocatSerialPort < T , U > {
185+ impl < T : Read , U : Write > Read for SimulationContext < T , U > {
158186 fn read ( & mut self , buf : & mut [ u8 ] ) -> std:: io:: Result < usize > {
159187 self . stdout . read ( buf)
160188 }
161189}
162190
163- impl < T : Read , U : Write > Write for SocatSerialPort < T , U > {
191+ impl < T : Read , U : Write > Write for SimulationContext < T , U > {
164192 fn write ( & mut self , buf : & [ u8 ] ) -> std:: io:: Result < usize > {
165193 self . stdin . write ( buf)
166194 }
@@ -170,13 +198,13 @@ impl<T: Read, U: Write> Write for SocatSerialPort<T, U> {
170198 }
171199}
172200
173- impl < T : Read , U : Write > Drop for SocatSerialPort < T , U > {
201+ impl < T : Read , U : Write > Drop for SimulationContext < T , U > {
174202 fn drop ( & mut self ) {
175- self . child . kill ( ) . unwrap ( ) ;
203+ self . socat . kill ( ) . unwrap ( ) ;
176204 }
177205}
178206
179- impl < T : Read , U : Write > CommunicationHandle for SocatSerialPort < T , U > {
207+ impl < T : Read , U : Write > CommunicationHandle for SimulationContext < T , U > {
180208 const INTEGRITY_ACK_TIMEOUT : Duration = Duration :: MAX ;
181209 const UNLIMITED_TIMEOUT : Duration = Duration :: MAX ;
182210
@@ -223,3 +251,10 @@ pub fn return_result(program_id: u16, timestamp: u32) -> Vec<u8> {
223251 vec. extend ( timestamp. to_le_bytes ( ) ) ;
224252 vec
225253}
254+
255+ #[ must_use]
256+ pub fn update_time ( since_epoch : u32 ) -> Vec < u8 > {
257+ let mut vec = vec ! [ 6u8 ] ;
258+ vec. extend ( since_epoch. to_le_bytes ( ) ) ;
259+ vec
260+ }
0 commit comments