read_line now returns String instead of Result<string>

maybe a worse interface than before ... will be revisited
This commit is contained in:
Vladan Popovic 2022-06-20 17:02:42 +02:00
parent a408544e4e
commit 626c47c58f

View file

@ -19,7 +19,7 @@ pub struct Modem<UART: serial::Uart> {
pub enum ModemError { pub enum ModemError {
CommandError(String), CommandError(String),
SetupError(String), SetupError(String),
ReadError, SendDataError,
TimeoutError, TimeoutError,
} }
@ -41,6 +41,11 @@ impl<UART: serial::Uart> IterableRx<UART> {
self.timeout = timeout; self.timeout = timeout;
self self
} }
fn clear(&mut self) -> () {
println!("clearing serial rx");
self.reset(Duration::from_millis(500)).for_each(drop);
}
} }
impl<UART: serial::Uart> Iterator for IterableRx<UART> { impl<UART: serial::Uart> Iterator for IterableRx<UART> {
@ -114,23 +119,11 @@ impl<UART: serial::Uart> Modem<UART> {
/// Reads a whole line (that ends with \\n) within the given `timeout` passed on input. /// Reads a whole line (that ends with \\n) within the given `timeout` passed on input.
/// ///
fn read_line(&mut self, timeout: Duration) -> Result<String> { fn read_line(&mut self, timeout: Duration) -> String {
let line: String = self.rx.reset(timeout) self.rx.reset(timeout)
.map(|b| char::from(b)) .map(|b| char::from(b))
.take_while(|c| *c != '\n') .take_while(|c| *c != '\n')
.collect(); .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)
}
} }
/// Reads the serial RX until a \\n char is encoutered, or a timeout is reached. The timeout is /// Reads the serial RX until a \\n char is encoutered, or a timeout is reached. The timeout is
@ -145,8 +138,8 @@ impl<UART: serial::Uart> Modem<UART> {
let match_text: String = contains.unwrap_or("\n".to_string()); let match_text: String = contains.unwrap_or("\n".to_string());
loop { loop {
let rdln = self.read_line(timeout.saturating_sub(start.elapsed())); let line = self.read_line(timeout.saturating_sub(start.elapsed()));
if let Ok(line) = rdln { if line != "" {
println!("Read {} bytes from serial ({})", line.len(), line); println!("Read {} bytes from serial ({})", line.len(), line);
response.push_str(&line); response.push_str(&line);
if line.contains("ERROR") || line.contains(&match_text) { if line.contains("ERROR") || line.contains(&match_text) {
@ -156,7 +149,7 @@ impl<UART: serial::Uart> Modem<UART> {
} }
} else { } else {
println!("-----------------------------------------------------------"); println!("-----------------------------------------------------------");
println!("Read line {:?}", rdln); println!("got empty line from read_line :(");
break Err(ModemError::TimeoutError) break Err(ModemError::TimeoutError)
} }
} }
@ -168,39 +161,42 @@ impl<UART: serial::Uart> Modem<UART> {
Ok(()) Ok(())
} }
fn send_bytes(&mut self, payload: &[u8]) -> Result<()> { fn send_bytes(&mut self, payload: &[u8], eos: char) -> Result<()> {
for b in payload.iter() { for b in payload.iter() {
self.send(*b)?; self.send(*b)?;
} }
self.send('\r' as u8)?; self.send(eos as u8)?;
Ok(()) Ok(())
} }
fn send_command(&mut self, cmd: Command) -> Result<String> { fn send_command(&mut self, cmd: Command) -> Result<String> {
println!("-----------------------------------------------------------"); println!("-----------------------------------------------------------");
println!("Sending {} ...", cmd.text); 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) self.read_response(cmd.contains, cmd.timeout)
} }
fn send_data(&mut self, payload: &str) -> Result<String> { fn send_data(&mut self, payload: &str) -> Result<String> {
let _ = self.send_bytes("AT+CIPSEND".as_bytes())?; self.rx.clear();
for c in self.rx.reset(Duration::from_millis(2000)).map(char::from) { let _ = self.send_bytes("AT+CIPSEND".as_bytes(), '\r')?;
println!("{}", c); let send_request: String = self.rx.reset(Duration::from_millis(3000))
if c == '>' { .map(char::from)
for b in payload.as_bytes() { .take_while(|c| *c != '>').collect();
self.send(*b)?;
} if send_request == "" {
self.send(26)?; return Err(ModemError::SendDataError);
return self.read_response(Some("DATA ACCEPT".to_string()), Duration::from_millis(3000));
}
} }
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(), text: "AT+CIPACK".to_string(),
contains: Some("OK".to_string()), contains: Some("OK".to_string()),
timeout: Duration::from_millis(3000), timeout: Duration::from_millis(3000),
})?; })?;
Ok("OK".to_string()) Ok(res)
} }
pub fn get_ip_addr(&mut self) -> Result<String> { pub fn get_ip_addr(&mut self) -> Result<String> {
@ -223,10 +219,6 @@ impl<UART: serial::Uart> Modem<UART> {
Ok(()) Ok(())
} }
pub fn probe(&mut self)-> Result<String> {
self.send_command(Command::probe())
}
pub fn is_gprs_attached(&mut self)-> Result<bool> { pub fn is_gprs_attached(&mut self)-> Result<bool> {
let res = self.send_command(Command::is_gprs_attached())?; let res = self.send_command(Command::is_gprs_attached())?;
Ok(res.contains("+CGATT: 1")) Ok(res.contains("+CGATT: 1"))