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
1 changed files with 30 additions and 38 deletions

View File

@ -19,7 +19,7 @@ pub struct Modem<UART: serial::Uart> {
pub enum ModemError {
CommandError(String),
SetupError(String),
ReadError,
SendDataError,
TimeoutError,
}
@ -41,6 +41,11 @@ impl<UART: serial::Uart> IterableRx<UART> {
self.timeout = timeout;
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> {
@ -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.
///
fn read_line(&mut self, timeout: Duration) -> Result<String> {
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<UART: serial::Uart> Modem<UART> {
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<UART: serial::Uart> Modem<UART> {
}
} else {
println!("-----------------------------------------------------------");
println!("Read line {:?}", rdln);
println!("got empty line from read_line :(");
break Err(ModemError::TimeoutError)
}
}
@ -168,39 +161,42 @@ impl<UART: serial::Uart> Modem<UART> {
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<String> {
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<String> {
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<String> {
@ -223,10 +219,6 @@ impl<UART: serial::Uart> Modem<UART> {
Ok(())
}
pub fn probe(&mut self)-> Result<String> {
self.send_command(Command::probe())
}
pub fn is_gprs_attached(&mut self)-> Result<bool> {
let res = self.send_command(Command::is_gprs_attached())?;
Ok(res.contains("+CGATT: 1"))