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

Response with \r\r\n confuses URC Parser #191

Open
patsoffice opened this issue Dec 7, 2023 · 1 comment
Open

Response with \r\r\n confuses URC Parser #191

patsoffice opened this issue Dec 7, 2023 · 1 comment

Comments

@patsoffice
Copy link

Hello,

I am attempting to make use of atat for an application to make and answer voice calls as well as sending and interpreting DTMF tones. The modem I'm using emits the following when a voice call comes in:

\r\r\nRING\r\r\n

I was able to return a single Urc on a ring with the following (note the urc_helper in impl Parser for Urc has a trailing '\r':

#[derive(Clone, Debug)]
pub enum Urc {
    // #[at_urc(b"RING")]
    Ring,
    // #[at_urc(b"RDY")]
    Ready,
    // #[at_urc(b"MISSED_CALL")]
    MissedCall,
    // #[at_urc(b"+RXDTMF")]
    Dtmf,
}

impl AtatUrc for Urc {
    type Response = Urc;
    #[inline]
    fn parse(resp: &[u8]) -> Option<Self::Response> {
        let index = resp.iter().position(|&x| x == b':').unwrap_or(resp.len());
        Some(match &resp[..index] {
            b"MISSED_CALL" => Urc::MissedCall,
            b"RING" => Urc::Ring,
            b"RDY" => Urc::Ready,
            b"+RXDTMF" => Urc::Dtmf,
            _ => return None,
        })
    }
}

impl Parser for Urc {
    fn parse<'a>(buf: &'a [u8]) -> Result<(&'a [u8], usize), ParseError> {
        let (_, r) = alt((
            urc_helper(&b"MISSED_CALL"[..]),
            urc_helper(&b"RING\r"[..]),
            urc_helper(&b"RDY"[..]),
            urc_helper(&b"+RXDTMF"[..]),
        ))(buf)?;
        Ok(r)
    }
}

However, if there is a subsequent \r\r\nRING\r\r\n I seem to stop getting any more data from the Digester (calls to try_next_message_pure() on the Urc subscription channel return None).

I'm not sure where exactly to begin to debug this further as I am quite the Rust n00b.

@patsoffice
Copy link
Author

I wrote a simple app (running on an ESP32) to demonstrate the behavior I'm seeing based on the unit test in ingress.rs:

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(utf8_chunks)]

use atat::atat_derive::AtatResp;
use atat::response_channel::ResponseChannel;
use atat::{AtDigester, AtatIngress, AtatUrcChannel, Ingress, UrcChannel};
use heapless::String;

#[derive(Clone, PartialEq, Debug)]
enum Urc {
    // #[at_urc(b"MISSED_CALL")]
    MissedCall,
    // #[at_urc(b"RING")]
    Ring,
}

impl atat::AtatUrc for Urc {
    type Response = Urc;
    #[inline]
    fn parse(resp: &[u8]) -> Option<Self::Response> {
        log::info!("resp: {:?}", resp);
        let index = resp.iter().position(|&x| x == b':').unwrap_or(resp.len());
        log::info!("index: {index}");
        Some(match &resp[..index] {
            b"MISSED_CALL" => Urc::MissedCall,
            b"RING" => Urc::Ring,
            _ => return None,
        })
    }
}

impl atat::Parser for Urc {
    fn parse<'a>(buf: &'a [u8]) -> Result<(&'a [u8], usize), atat::digest::ParseError> {
        log::info!("in parse()");
        let (_, r) = atat::nom::branch::alt((
            atat::digest::parser::urc_helper(&b"MISSED_CALL"[..]),
            atat::digest::parser::urc_helper(&b"RING\r"[..]),
        ))(buf)?;
        Ok(r)
    }
}

#[derive(Debug, Clone, AtatResp)]
pub struct MissedCall {
    #[at_arg(position = 0)]
    pub info: String<32>,
}

#[derive(Debug, Clone, AtatResp)]
pub struct Ring;

#[no_mangle]
fn main() {
    esp_idf_svc::sys::link_patches();
    esp_idf_svc::log::EspLogger::initialize_default();

    let res_channel = ResponseChannel::<100>::new();
    let urc_channel = UrcChannel::<Urc, 10, 1>::new();
    let mut ingress: Ingress<_, Urc, 100, 10, 1> = Ingress::new(
        AtDigester::<Urc>::new(),
        res_channel.publisher().unwrap(),
        urc_channel.publisher(),
    );

    let mut sub = urc_channel.subscribe().unwrap();

    let buf = ingress.write_buf();
    let data = b"\r\r\nRING\r\r\n\r\r\nRING\r\r\n\r\nMISSED_CALL: 10:24PM +15558675309\r\n";
    buf[..data.len()].copy_from_slice(data);
    ingress.try_advance(data.len()).unwrap();

    loop {
        let rc = sub.try_next_message_pure();    

        if rc.is_none() {
            break
        }
        log::info!("got {:?}", rc);
    }
}

The output is:

I (377) main_task: Calling app_main()
I (377) playground_atat: in parse()
I (377) playground_atat: resp: [82, 73, 78, 71]
I (387) playground_atat: index: 4
I (387) playground_atat: in parse()
I (397) playground_atat: resp: [82, 73, 78, 71]
I (397) playground_atat: index: 4
I (407) playground_atat: in parse()
I (407) playground_atat: got Some(Ring)
I (407) playground_atat: got Some(Ring)
I (417) main_task: Returned from app_main()

If there is only one \r\r\nRING\r\r\n then I successfully parse the MISSED_CALL.

@patsoffice patsoffice changed the title Response with \r\r\n confuses Parser Response with \r\r\n confuses URC Parser Dec 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant