read_line now returns String instead of Result<string>
maybe a worse interface than before ... will be revisited
This commit is contained in:
parent
a408544e4e
commit
626c47c58f
1 changed files with 30 additions and 38 deletions
68
src/modem.rs
68
src/modem.rs
|
@ -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"))
|
||||||
|
|
Loading…
Reference in a new issue