1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use super::sender_can::SenderCANHandle;
use super::ctrlc::CtrlCActorHandle;
use super::commands;
use super::receiver_can::ReceiverCANHandle;
use std::io;
use std::io::Write; 

struct StdInLines {
    line_receiver: tokio::sync::mpsc::Receiver<String>,
    watch_receiver: CtrlCActorHandle,
    sender: SenderCANHandle,
    receiver: ReceiverCANHandle
}


impl StdInLines {
    fn new (
        line_receiver: tokio::sync::mpsc::Receiver<String>,
        watch_receiver: CtrlCActorHandle,
        sender: SenderCANHandle,
        receiver: ReceiverCANHandle
    ) -> StdInLines {
        StdInLines { line_receiver, watch_receiver, sender, receiver }
    }

    async fn handle_command(&mut self, msg: String) -> bool {
        println!("msg recebida -> {:?}", msg);
        
        let parse_result = commands::parse(&msg);

        match parse_result {
            Ok(commands::ParsedCommand::Boss(cmd)) => {
                let _cmd_output = self.execute_command(cmd).await;
                true
            }
            Ok(commands::ParsedCommand::Exit) => {
                println!("exiting manually..."); 
                false
            },
            Err(e) => {
                println!("{}",e);
                true
            }
        }
        // match msg.as_str() {
        //     "exit" => { 
        //         println!("exiting manually..."); 
        //         false 
        //     },
        //     "send" => {
        //         self.sender.send_can_message(0x69, [1,2,3]).await;
        //         true
        //     },
        //     unexpected_line => {
        //         println!("unexpected command: {}", unexpected_line);
        //         true
        //     }
        // }
        //true
    }

    async fn execute_command(&mut self, cmd: BossCommand) -> impl std::fmt::Display {

        match cmd {
            BossCommand::SendCan { id, message, cycletime } => self.sender.send_can_message(123, 123, 0).await,
            BossCommand::ReceiveCan { id, nrofmessages } => self.receiver.receive_can_msg(id, nrofmessages).await,
        };
        //format!("ran command: {:?}", test)
        format!("ran command: ")
    }
}


#[derive(Debug)]
pub enum BossCommand {
    SendCan {
        id: Option<String>,
        message: Option<String>,
        cycletime: Option<String>,
    },
    ReceiveCan {
        id: Option<String>,
        nrofmessages: Option<String>
    },
}


async fn run(mut actor: StdInLines) {
    println!("Processing INPUTS");
    loop {
        print!("> ");
        io::stdout().flush().unwrap();
        tokio::select! {
            Some(line) = actor.line_receiver.recv() => {
                if !actor.handle_command(line).await {
                    break;
                }
            }
            Ok(_) = actor.watch_receiver.wait_for_shutdown() => {
                println!("shutdown");
                break;
            }
        }
    }
}


fn reading_stdin_lines(
    runtime: tokio::runtime::Handle,
    sender: tokio::sync::mpsc::Sender<String>
) {
    std::thread::spawn(move || {
        let stdin = std::io::stdin();
        let mut line_buf = String::new();
        while let Ok(_) = stdin.read_line(&mut line_buf) {
            let line = line_buf.trim_end().to_string();
            line_buf.clear();
            let sender2 = sender.clone();

            runtime.spawn(async move {
                let result = sender2.send(line).await;
                if let Err(error) = result {
                    println!("start_reading_stdin_lines send error: {:?}", error);
                }
            });
        }
    });
}

pub struct StdInLinesHandle {
    pub spawn_handle: tokio::task::JoinHandle<()>
}

impl StdInLinesHandle {

    pub fn new(
        runtime: tokio::runtime::Handle,
        watch_receiver: CtrlCActorHandle,
        sender: SenderCANHandle,
        receiver: ReceiverCANHandle
    ) -> StdInLinesHandle {

        let (line_sender, line_receiver) = tokio::sync::mpsc::channel(1);

        reading_stdin_lines(runtime, line_sender);

        let actor = StdInLines::new(line_receiver, watch_receiver, sender, receiver);

        let spawn_handle = tokio::spawn(run(actor));

        Self {spawn_handle}
    }
}