seeed_lora_e5_at_commands/
digester.rs

1#[cfg(feature = "debug")]
2use atat::helpers::LossyStr;
3use atat::{
4    digest::{parser, ParseError},
5    InternalError,
6};
7use atat::{
8    nom,
9    nom::{branch, bytes, combinator, sequence},
10    DigestResult, Digester, Parser,
11};
12
13#[cfg(feature = "debug")]
14use crate::urc::LORA_LATEST_BUF;
15
16use crate::urc::URCMessages;
17#[cfg(feature = "debug")]
18use defmt::{debug, trace};
19
20#[derive(Default)]
21pub struct LoraE5Digester {}
22
23impl LoraE5Digester {
24    pub fn custom_error(buf: &[u8]) -> Result<(&[u8], usize), ParseError> {
25        let (_reminder, (head, data, tail)) = branch::alt((
26            sequence::tuple((
27                combinator::recognize(sequence::tuple((
28                    bytes::streaming::take_until(": "),
29                    bytes::streaming::tag(b": "),
30                ))),
31                bytes::streaming::tag(b"ERROR(-1)"),
32                bytes::streaming::tag(b"\r\n"),
33            )),
34            sequence::tuple((
35                combinator::recognize(sequence::tuple((
36                    bytes::streaming::take_until(": "),
37                    bytes::streaming::tag(b": "),
38                ))),
39                bytes::streaming::tag(b"ERROR(-10)"),
40                bytes::streaming::tag(b"\r\n"),
41            )),
42            sequence::tuple((
43                combinator::recognize(sequence::tuple((
44                    bytes::streaming::take_until(": "),
45                    bytes::streaming::tag(b": "),
46                ))),
47                bytes::streaming::tag(b"ERROR(-11)"),
48                bytes::streaming::tag(b"\r\n"),
49            )),
50            sequence::tuple((
51                combinator::recognize(sequence::tuple((
52                    bytes::streaming::take_until(": "),
53                    bytes::streaming::tag(b": "),
54                ))),
55                bytes::streaming::tag(b"ERROR(-12)"),
56                bytes::streaming::tag(b"\r\n"),
57            )),
58            sequence::tuple((
59                combinator::recognize(sequence::tuple((
60                    bytes::streaming::take_until(": "),
61                    bytes::streaming::tag(b": "),
62                ))),
63                bytes::streaming::tag(b"ERROR(-20)"),
64                bytes::streaming::tag(b"\r\n"),
65            )),
66            sequence::tuple((
67                combinator::recognize(sequence::tuple((
68                    bytes::streaming::take_until(": "),
69                    bytes::streaming::tag(b": "),
70                ))),
71                bytes::streaming::tag(b"ERROR(-21)"),
72                bytes::streaming::tag(b"\r\n"),
73            )),
74            sequence::tuple((
75                combinator::recognize(sequence::tuple((
76                    bytes::streaming::take_until(": "),
77                    bytes::streaming::tag(b": "),
78                ))),
79                bytes::streaming::tag(b"ERROR(-22)"),
80                bytes::streaming::tag(b"\r\n"),
81            )),
82            sequence::tuple((
83                combinator::recognize(sequence::tuple((
84                    bytes::streaming::take_until(": "),
85                    bytes::streaming::tag(b": "),
86                ))),
87                bytes::streaming::tag(b"ERROR(-23)"),
88                bytes::streaming::tag(b"\r\n"),
89            )),
90            sequence::tuple((
91                combinator::recognize(sequence::tuple((
92                    bytes::streaming::take_until(": "),
93                    bytes::streaming::tag(b": "),
94                ))),
95                bytes::streaming::tag(b"ERROR(-24)"),
96                bytes::streaming::tag(b"\r\n"),
97            )),
98        ))(buf)?;
99        #[cfg(feature = "debug")]
100        debug!("Custom error {:?}", LossyStr(data));
101        Ok((data, head.len() + data.len() + tail.len()))
102    }
103
104    pub fn custom_success(buf: &[u8]) -> Result<(&[u8], usize), ParseError> {
105        #[cfg(feature = "debug")]
106        if buf.is_empty() {
107            match LORA_LATEST_BUF.try_write(buf) {
108                Ok(_) => {}
109                Err(_) => {
110                    trace!("Failed to write to LORA_LATEST_BUF");
111                }
112            }
113        }
114        #[cfg(feature = "debug")]
115        trace!("Custom success start {:?}", LossyStr(buf));
116        let (_reminder, (head, data, tail)) = branch::alt((
117            // AT command
118            sequence::tuple((
119                combinator::success(&b""[..]),
120                combinator::recognize(sequence::tuple((
121                    bytes::streaming::tag(b"+AT: "),
122                    bytes::streaming::take_until("\r\n"),
123                ))),
124                bytes::streaming::tag("\r\n"),
125            )),
126            // ATE
127            sequence::tuple((
128                combinator::success(&b""[..]),
129                combinator::recognize(sequence::tuple((
130                    bytes::streaming::tag(b"+ATE: "),
131                    bytes::streaming::take_until("\r\n"),
132                ))),
133                branch::alt((
134                    bytes::streaming::tag("\r\n"),
135                    bytes::streaming::tag("OK\r\n"),
136                )),
137            )),
138            // +RESET / Startup preamble
139            sequence::tuple((
140                bytes::streaming::tag(b"+RESET: "),
141                bytes::streaming::take_until("\r\n\x00"),
142                bytes::streaming::tag("\r\n\x00"),
143            )),
144            // +ID
145            sequence::tuple((
146                combinator::recognize(sequence::tuple((
147                    bytes::streaming::tag(b"+ID: "),
148                    bytes::streaming::take_until(" "),
149                    bytes::streaming::tag(b" "),
150                ))),
151                bytes::streaming::take_until("\r\n"),
152                bytes::streaming::tag("\r\n"),
153            )),
154            // +MODE
155            sequence::tuple((
156                bytes::streaming::tag(b"+MODE: "),
157                bytes::streaming::take_until("\r\n"),
158                bytes::streaming::tag("\r\n"),
159            )),
160            // +VER
161            sequence::tuple((
162                bytes::streaming::tag(b"+VER: "),
163                bytes::streaming::take_until("\r\n"),
164                bytes::streaming::tag("\r\n"),
165            )),
166            // +DR
167            sequence::tuple((
168                bytes::streaming::tag(b"+DR: "),
169                bytes::streaming::take_until("\r\n"),
170                bytes::streaming::tag("\r\n"),
171            )),
172            // +CLASS
173            sequence::tuple((
174                bytes::streaming::tag(b"+CLASS: "),
175                bytes::streaming::take_until("\r\n"),
176                bytes::streaming::tag("\r\n"),
177            )),
178            // +ADR
179            sequence::tuple((
180                bytes::streaming::tag(b"+ADR: "),
181                bytes::streaming::take_until("\r\n"),
182                bytes::streaming::tag("\r\n"),
183            )),
184            // +LW
185            sequence::tuple((
186                bytes::streaming::tag(b"+LW: "),
187                bytes::streaming::take_until("\r\n"),
188                bytes::streaming::tag("\r\n"),
189            )),
190            // +JOIN
191            sequence::tuple((
192                bytes::streaming::tag(b"+JOIN: "),
193                bytes::streaming::take_until("\r\n"),
194                bytes::streaming::tag("\r\n"),
195            )),
196            // +PORT
197            sequence::tuple((
198                bytes::streaming::tag(b"+PORT: "),
199                bytes::streaming::take_until("\r\n"),
200                bytes::streaming::tag("\r\n"),
201            )),
202            // +RETRY
203            sequence::tuple((
204                bytes::streaming::tag(b"+RETRY: "),
205                bytes::streaming::take_until("\r\n"),
206                bytes::streaming::tag("\r\n"),
207            )),
208            // +REPT
209            sequence::tuple((
210                bytes::streaming::tag(b"+REPT: "),
211                bytes::streaming::take_until("\r\n"),
212                bytes::streaming::tag("\r\n"),
213            )),
214            // +KEY
215            sequence::tuple((
216                combinator::recognize(sequence::tuple((
217                    bytes::streaming::tag(b"+KEY: "),
218                    bytes::streaming::take_until(" "),
219                    bytes::streaming::tag(b" "),
220                ))),
221                bytes::streaming::take_until("\r\n"),
222                bytes::streaming::tag("\r\n"),
223            )),
224            // Receive bytes
225            sequence::tuple((
226                bytes::streaming::tag(b"+RECVB: "),
227                // combinator::success(&b""[..]),
228                combinator::recognize(sequence::tuple((
229                    // bytes::streaming::tag(b"+RECVB: "),
230                    bytes::streaming::take_until("\r\n"),
231                    bytes::streaming::tag("\r\n"),
232                ))),
233                combinator::success(&b""[..]),
234            )),
235            // Uplink frame count
236            sequence::tuple((
237                combinator::success(&b""[..]),
238                combinator::recognize(sequence::tuple((
239                    bytes::streaming::tag(b"+UP_CNT: "),
240                    bytes::streaming::take_until("\r\n"),
241                ))),
242                bytes::streaming::tag("\r\n"),
243            )),
244            // Downlink frame count
245            sequence::tuple((
246                combinator::success(&b""[..]),
247                combinator::recognize(sequence::tuple((
248                    bytes::streaming::tag(b"+DOWN_CNT: "),
249                    bytes::streaming::take_until("\r\n"),
250                ))),
251                bytes::streaming::tag("\r\n"),
252            )),
253        ))(buf)?;
254        #[cfg(feature = "debug")]
255        trace!("Custom success ! [{:?}]", LossyStr(data));
256
257        Ok((data, head.len() + data.len() + tail.len()))
258    }
259}
260
261impl Digester for LoraE5Digester {
262    fn digest<'a>(&mut self, input: &'a [u8]) -> (DigestResult<'a>, usize) {
263        #[cfg(feature = "debug")]
264        let s = LossyStr(input);
265        #[cfg(feature = "debug")]
266        trace!("Digesting: {:?}", s);
267
268        // Incomplete. Eat the echo and do nothing else.
269        let incomplete = (DigestResult::None, 0);
270
271        // Stray OK\r\n
272        if input == b"OK\r\n" {
273            return (DigestResult::None, 4);
274        }
275
276        // Generic success replies
277        match parser::success_response(input) {
278            Ok((_, (result, len))) => return (result, len),
279            Err(nom::Err::Incomplete(_)) => return incomplete,
280            _ => {}
281        }
282
283        // 2. Match for URC's
284        match <URCMessages as Parser>::parse(input) {
285            Ok((urc, len)) => return (DigestResult::Urc(urc), len),
286            Err(ParseError::Incomplete) => return incomplete,
287            _ => {}
288        }
289
290        // 3. Parse for success responses
291        // Custom successful replies first, if any
292        match (LoraE5Digester::custom_success)(input) {
293            Ok((response, len)) => return (DigestResult::Response(Ok(response)), len),
294            Err(ParseError::Incomplete) => return incomplete,
295            _ => {}
296        }
297
298        // 4. Parse for error responses
299        // Custom error matches first, if any
300        match (LoraE5Digester::custom_error)(input) {
301            Ok((response, len)) => {
302                return (
303                    DigestResult::Response(Err(InternalError::Custom(response))),
304                    len,
305                )
306            }
307            Err(ParseError::Incomplete) => return incomplete,
308            _ => {}
309        }
310
311        // Generic error matches
312        if let Ok((_, (result, len))) = parser::error_response(input) {
313            return (result, len);
314        }
315
316        // No matches at all.
317        incomplete
318    }
319}