seeed_lora_e5_at_commands/
urc.rs

1//! # URC parser implementation
2//!
3//! This is just used internally, but needs to be public for passing [URCMessages] as a generic to
4//! [AtDigester](atat::digest::AtDigester): `AtDigester<URCMessages>`.
5
6use crate::client::asynch::JoinStatus;
7use crate::lora::urc::{JoinUrc, MessageHexSend, MessageReceived};
8use crate::signal::Signal;
9use atat::digest::ParseError;
10use atat::{
11    nom::{branch, bytes, combinator, sequence},
12    AtatUrc, Parser,
13};
14use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
15
16#[cfg(feature = "debug")]
17use embassy_sync::pipe::Pipe;
18
19/// URC definitions, needs to passed as generic of [AtDigester](atat::digest::AtDigester): `AtDigester<URCMessages>`
20#[derive(Debug, PartialEq, Clone)]
21pub enum URCMessages {
22    /// Unknown URC message
23    Unknown,
24    /// Join
25    Join(JoinUrc),
26    /// Message Hex Sen
27    MessageHexSend(MessageHexSend),
28    /// Message received
29    MessageReceived(MessageReceived),
30}
31
32pub struct ReceivedMessage {
33    pub port: u8,
34    pub payload: [u8; 243],
35    pub length: usize,
36}
37
38pub struct MessageStats {
39    pub rxwin: u8,
40    pub rssi: i8,
41    pub snr: f32,
42}
43
44pub enum SentMessage {
45    Failed,
46    Success(MessageStats),
47}
48
49pub static LAST_LORA_MESSAGE_RECEIVED: Signal<CriticalSectionRawMutex, ReceivedMessage> =
50    Signal::new();
51pub static LORA_MESSAGE_RECEIVED_COUNT: Signal<CriticalSectionRawMutex, u32> = Signal::new();
52pub static LORA_MESSAGE_RECEIVED_STATS: Signal<CriticalSectionRawMutex, MessageStats> =
53    Signal::new();
54pub static LAST_LORA_MESSAGE_SENT: Signal<CriticalSectionRawMutex, MessageStats> = Signal::new();
55pub static LORA_JOIN_STATUS: Signal<CriticalSectionRawMutex, JoinStatus> = Signal::new();
56
57#[cfg(feature = "debug")]
58pub static LORA_LATEST_BUF: Pipe<CriticalSectionRawMutex, 50> = Pipe::new();
59
60impl URCMessages {}
61
62impl AtatUrc for URCMessages {
63    type Response = Self;
64
65    fn parse(resp: &[u8]) -> Option<Self::Response> {
66        match resp {
67            b if b.starts_with(b"+JOIN: ") => JoinUrc::parse(resp).ok().map(URCMessages::Join),
68            b if b.starts_with(b"+MSGHEX: ") || b.starts_with(b"+CMSGHEX: ") => {
69                MessageHexSend::parse(resp)
70                    .ok()
71                    .map(URCMessages::MessageHexSend)
72            }
73            b if b.starts_with(b"+MSG: ") => MessageReceived::parse(resp)
74                .ok()
75                .map(URCMessages::MessageReceived),
76            _ => None,
77        }
78    }
79}
80
81impl Parser for URCMessages {
82    fn parse(buf: &[u8]) -> Result<(&[u8], usize), ParseError> {
83        // Check if this is a join started message
84        match buf {
85            b if b.starts_with(b"+JOIN: Auto-Join ") => return Err(ParseError::NoMatch),
86            b if b.starts_with(b"+JOIN: Start") => return Err(ParseError::NoMatch),
87            _ => {}
88        }
89
90        let (_reminder, (head, data, tail)) = branch::alt((
91            // Join messages
92            sequence::tuple((
93                combinator::success(&b""[..]),
94                combinator::recognize(sequence::tuple((
95                    bytes::streaming::tag("+JOIN: "),
96                    bytes::streaming::take_until("\r\n"),
97                ))),
98                bytes::streaming::tag("\r\n"),
99            )),
100            // Message Hex Send
101            sequence::tuple((
102                combinator::success(&b""[..]),
103                combinator::recognize(sequence::tuple((
104                    branch::alt((
105                        bytes::streaming::tag("+MSGHEX: "),
106                        bytes::streaming::tag("+CMSGHEX: "),
107                    )),
108                    bytes::streaming::take_until("\r\n"),
109                ))),
110                bytes::streaming::tag("\r\n"),
111            )),
112            // Message Hex Receive
113            sequence::tuple((
114                combinator::success(&b""[..]),
115                combinator::recognize(sequence::tuple((
116                    bytes::streaming::tag("+MSG: "),
117                    bytes::streaming::take_until("\r\n"),
118                ))),
119                bytes::streaming::tag("\r\n"),
120            )),
121        ))(buf)?;
122        Ok((data, head.len() + data.len() + tail.len()))
123    }
124}