diff --git a/src/modem.rs b/src/modem.rs index 82b55f3..a69989e 100644 --- a/src/modem.rs +++ b/src/modem.rs @@ -19,7 +19,7 @@ pub struct Modem { pub enum ModemError { CommandError(String), SetupError(String), - ReadError, + SendDataError, TimeoutError, } @@ -41,6 +41,11 @@ impl IterableRx { self.timeout = timeout; self } + + fn clear(&mut self) -> () { + println!("clearing serial rx"); + self.reset(Duration::from_millis(500)).for_each(drop); + } } impl Iterator for IterableRx { @@ -114,23 +119,11 @@ impl Modem { /// Reads a whole line (that ends with \\n) within the given `timeout` passed on input. /// - fn read_line(&mut self, timeout: Duration) -> Result { - let line: String = self.rx.reset(timeout) + fn read_line(&mut self, timeout: Duration) -> String { + self.rx.reset(timeout) .map(|b| char::from(b)) .take_while(|c| *c != '\n') - .collect(); - - // A necessary check because the actual timeout is in the Iterator implementation. The - // iterator exits when the returned Item is None, which happens when there's no data in - // the serial port and the timeout is breached. - // - // This check here is tested on sim800l and works only because the modem has \r\n as CRLF. - if line.ends_with("\r") { - Ok(format!("{}\n", line)) - } - else { - Err(ModemError::ReadError) - } + .collect() } /// Reads the serial RX until a \\n char is encoutered, or a timeout is reached. The timeout is @@ -145,8 +138,8 @@ impl Modem { let match_text: String = contains.unwrap_or("\n".to_string()); loop { - let rdln = self.read_line(timeout.saturating_sub(start.elapsed())); - if let Ok(line) = rdln { + let line = self.read_line(timeout.saturating_sub(start.elapsed())); + if line != "" { println!("Read {} bytes from serial ({})", line.len(), line); response.push_str(&line); if line.contains("ERROR") || line.contains(&match_text) { @@ -156,7 +149,7 @@ impl Modem { } } else { println!("-----------------------------------------------------------"); - println!("Read line {:?}", rdln); + println!("got empty line from read_line :("); break Err(ModemError::TimeoutError) } } @@ -168,39 +161,42 @@ impl Modem { Ok(()) } - fn send_bytes(&mut self, payload: &[u8]) -> Result<()> { + fn send_bytes(&mut self, payload: &[u8], eos: char) -> Result<()> { for b in payload.iter() { self.send(*b)?; } - self.send('\r' as u8)?; + self.send(eos as u8)?; Ok(()) } fn send_command(&mut self, cmd: Command) -> Result { println!("-----------------------------------------------------------"); println!("Sending {} ...", cmd.text); - let _ = self.send_bytes(cmd.text.as_bytes())?; + let _ = self.send_bytes(cmd.text.as_bytes(), '\r')?; self.read_response(cmd.contains, cmd.timeout) } fn send_data(&mut self, payload: &str) -> Result { - let _ = self.send_bytes("AT+CIPSEND".as_bytes())?; - for c in self.rx.reset(Duration::from_millis(2000)).map(char::from) { - println!("{}", c); - if c == '>' { - for b in payload.as_bytes() { - self.send(*b)?; - } - self.send(26)?; - return self.read_response(Some("DATA ACCEPT".to_string()), Duration::from_millis(3000)); - } + self.rx.clear(); + let _ = self.send_bytes("AT+CIPSEND".as_bytes(), '\r')?; + let send_request: String = self.rx.reset(Duration::from_millis(3000)) + .map(char::from) + .take_while(|c| *c != '>').collect(); + + if send_request == "" { + return Err(ModemError::SendDataError); } - self.send_command(Command { + + self.send_bytes(payload.as_bytes(), 26 as char)?; // 26_u8 = Ctrl+z - to end sending data + let _ = self.read_response(Some("DATA ACCEPT".to_string()), Duration::from_millis(3000)); + + self.rx.clear(); + let res = self.send_command(Command { text: "AT+CIPACK".to_string(), contains: Some("OK".to_string()), timeout: Duration::from_millis(3000), })?; - Ok("OK".to_string()) + Ok(res) } pub fn get_ip_addr(&mut self) -> Result { @@ -223,10 +219,6 @@ impl Modem { Ok(()) } - pub fn probe(&mut self)-> Result { - self.send_command(Command::probe()) - } - pub fn is_gprs_attached(&mut self)-> Result { let res = self.send_command(Command::is_gprs_attached())?; Ok(res.contains("+CGATT: 1"))