Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(*): add automatic retries to AtatClient::send implementation #124

Merged
merged 6 commits into from
Apr 11, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix clippy warnings
  • Loading branch information
MathiasKoch committed Apr 8, 2022
commit 7d4098e3612862a454de0db7b23e4200089835b9
20 changes: 9 additions & 11 deletions atat/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ where
&mut self,
cmd: &A,
) -> nb::Result<A::Response, Error> {
if let ClientState::Idle = self.state {
if self.state == ClientState::Idle {
// compare the time of the last response or URC and ensure at least
// `self.config.cmd_cooldown` ms have passed before sending a new
// command
Expand Down Expand Up @@ -159,7 +159,7 @@ where
.parse(ResponseHeader::from_bytes(res_grant.as_ref()))
.map_err(nb::Error::from)
.and_then(|r| {
if let ClientState::AwaitingResponse = self.state {
if self.state == ClientState::Idle {
self.timer.start(self.config.cmd_cooldown.millis()).ok();
self.state = ClientState::Idle;
Ok(r)
Expand All @@ -172,16 +172,14 @@ where
self.state = ClientState::Idle;
e
});
} else if let Mode::Timeout = self.config.mode {
if self.timer.wait().is_ok() {
self.state = ClientState::Idle;
// Tell the parser to reset to initial state due to timeout
if self.com_p.enqueue(Command::Reset).is_err() {
// TODO: Consider how to act in this situation.
error!("Failed to signal parser to clear buffer on timeout!");
}
return Err(nb::Error::Other(Error::Timeout));
} else if self.config.mode == Mode::Timeout && self.timer.wait().is_ok() {
self.state = ClientState::Idle;
// Tell the parser to reset to initial state due to timeout
if self.com_p.enqueue(Command::Reset).is_err() {
// TODO: Consider how to act in this situation.
error!("Failed to signal parser to clear buffer on timeout!");
}
return Err(nb::Error::Other(Error::Timeout));
}
Err(nb::Error::WouldBlock)
}
Expand Down
27 changes: 18 additions & 9 deletions atat/src/digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@ pub trait Digester {
}

pub trait Parser {
fn parse<'a>(buf: &'a [u8]) -> Result<(&'a [u8], usize), ParseError>;
fn parse(buf: &[u8]) -> Result<(&[u8], usize), ParseError>;
}

pub type CustomResponse = fn(&[u8]) -> Result<(&[u8], usize), ParseError>;
pub type CustomPrompt = fn(&[u8]) -> Result<(u8, usize), ParseError>;

/// A Digester that tries to implement the basic AT standard.
/// This digester should work for most usecases of ATAT.
///
Expand Down Expand Up @@ -59,9 +62,9 @@ pub trait Parser {
/// Usually \<PROMPT> can be one of \['>', '@'], and is command specific and only valid for few selected commands.
pub struct AtDigester<P: Parser> {
_urc_parser: PhantomData<P>,
custom_success: fn(&[u8]) -> Result<(&[u8], usize), ParseError>,
custom_error: fn(&[u8]) -> Result<(&[u8], usize), ParseError>,
custom_prompt: fn(&[u8]) -> Result<(u8, usize), ParseError>,
custom_success: CustomResponse,
custom_error: CustomResponse,
custom_prompt: CustomPrompt,
}

impl<P: Parser> AtDigester<P> {
Expand All @@ -74,28 +77,34 @@ impl<P: Parser> AtDigester<P> {
}
}

pub fn with_custom_success(self, f: fn(&[u8]) -> Result<(&[u8], usize), ParseError>) -> Self {
pub fn with_custom_success(self, f: CustomResponse) -> Self {
Self {
custom_success: f,
..self
}
}

pub fn with_custom_error(self, f: fn(&[u8]) -> Result<(&[u8], usize), ParseError>) -> Self {
pub fn with_custom_error(self, f: CustomResponse) -> Self {
Self {
custom_error: f,
..self
}
}

pub fn with_custom_prompt(self, f: fn(&[u8]) -> Result<(u8, usize), ParseError>) -> Self {
pub fn with_custom_prompt(self, f: CustomPrompt) -> Self {
Self {
custom_prompt: f,
..self
}
}
}

impl<P: Parser> Default for AtDigester<P> {
fn default() -> Self {
Self::new()
}
}

impl<P: Parser> Digester for AtDigester<P> {
fn digest<'a>(&mut self, input: &'a [u8]) -> (DigestResult<'a>, usize) {
// 1. Optionally discard echo
Expand Down Expand Up @@ -319,7 +328,7 @@ pub mod parser {
recognize(nom::bytes::complete::take_until("\r\n"))(buf)
}

fn take_until_including<'a, T, Input, Error: ParseError<Input>>(
fn take_until_including<T, Input, Error: ParseError<Input>>(
tag: T,
) -> impl Fn(Input) -> IResult<Input, (Input, Input), Error>
where
Expand Down Expand Up @@ -455,7 +464,7 @@ mod test {
enum UrcTestParser {}

impl Parser for UrcTestParser {
fn parse<'a>(buf: &'a [u8]) -> Result<(&'a [u8], usize), ParseError> {
fn parse(buf: &[u8]) -> Result<(&[u8], usize), ParseError> {
let (_, r) = nom::branch::alt((urc_helper("+UUSORD"), urc_helper("+CIEV")))(buf)?;

Ok(r)
Expand Down
2 changes: 1 addition & 1 deletion atat/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl<'a> InternalError<'a> {
InternalError::CmeError(e) => Encoded::Array(0x08, (*e as u16).to_le_bytes()),
InternalError::CmsError(e) => Encoded::Array(0x09, (*e as u16).to_le_bytes()),
InternalError::ConnectionError(e) => Encoded::Nested(0x10, *e as u8),
InternalError::Custom(e) => Encoded::Slice(0x11, e.as_ref()),
InternalError::Custom(e) => Encoded::Slice(0x11, e),
}
}

Expand Down
2 changes: 1 addition & 1 deletion atat/src/ingress_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ mod test {
enum UrcTestParser {}

impl Parser for UrcTestParser {
fn parse<'a>(_buf: &'a [u8]) -> Result<(&'a [u8], usize), ParseError> {
fn parse(_buf: &[u8]) -> Result<(&[u8], usize), ParseError> {
Err(ParseError::NoMatch)
}
}
Expand Down
2 changes: 1 addition & 1 deletion atat/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ impl ResponseHeader {
}
}

pub fn from_bytes<'a>(bytes: &'a [u8]) -> Result<&'a [u8], InternalError<'a>> {
pub fn from_bytes(bytes: &[u8]) -> Result<&[u8], InternalError> {
match bytes[0] {
0xFF => Ok(&bytes[1..]),
_ => Err(InternalError::decode(bytes)),
Expand Down
3 changes: 1 addition & 2 deletions atat/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ pub trait AtatClient {
}

match self.send(cmd) {
e @ Err(nb::Error::Other(Error::Timeout))
| e @ Err(nb::Error::Other(Error::Parse)) => {
e @ Err(nb::Error::Other(Error::Parse | Error::Timeout)) => {
error = e;
}
r => return r,
Expand Down
6 changes: 3 additions & 3 deletions atat_derive/src/urc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ pub fn atat_urc(input: TokenStream) -> TokenStream {

#[automatically_derived]
impl #impl_generics atat::Parser for #ident #ty_generics #where_clause {
fn parse<'a>(
buf: &'a [u8],
) -> Result<(&'a [u8], usize), atat::digest::ParseError> {
fn parse(
buf: &[u8],
) -> Result<(&[u8], usize), atat::digest::ParseError> {
let (_, r) = atat::nom::branch::alt((
#(
#digest_arms
Expand Down