seeed_lora_e5_at_commands/
urc.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! # URC parser implementation
//!
//! This is just used internally, but needs to be public for passing [URCMessages] as a generic to
//! [AtDigester](atat::digest::AtDigester): `AtDigester<URCMessages>`.

use crate::client::asynch::JoinStatus;
use crate::lora::urc::{JoinUrc, MessageHexSend, MessageReceived};
use crate::signal::Signal;
use atat::digest::ParseError;
use atat::{
    nom::{branch, bytes, combinator, sequence},
    AtatUrc, Parser,
};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;

#[cfg(feature = "debug")]
use embassy_sync::pipe::Pipe;

/// URC definitions, needs to passed as generic of [AtDigester](atat::digest::AtDigester): `AtDigester<URCMessages>`
#[derive(Debug, PartialEq, Clone)]
pub enum URCMessages {
    /// Unknown URC message
    Unknown,
    /// Join
    Join(JoinUrc),
    /// Message Hex Sen
    MessageHexSend(MessageHexSend),
    /// Message received
    MessageReceived(MessageReceived),
}

pub struct ReceivedMessage {
    pub port: u8,
    pub payload: [u8; 243],
    pub length: usize,
}

pub struct MessageStats {
    pub rxwin: u8,
    pub rssi: i8,
    pub snr: f32,
}

pub enum SentMessage {
    Failed,
    Success(MessageStats),
}

pub static LAST_LORA_MESSAGE_RECEIVED: Signal<CriticalSectionRawMutex, ReceivedMessage> =
    Signal::new();
pub static LORA_MESSAGE_RECEIVED_COUNT: Signal<CriticalSectionRawMutex, u32> = Signal::new();
pub static LORA_MESSAGE_RECEIVED_STATS: Signal<CriticalSectionRawMutex, MessageStats> =
    Signal::new();
pub static LAST_LORA_MESSAGE_SENT: Signal<CriticalSectionRawMutex, MessageStats> = Signal::new();
pub static LORA_JOIN_STATUS: Signal<CriticalSectionRawMutex, JoinStatus> = Signal::new();

#[cfg(feature = "debug")]
pub static LORA_LATEST_BUF: Pipe<CriticalSectionRawMutex, 50> = Pipe::new();

impl URCMessages {}

impl AtatUrc for URCMessages {
    type Response = Self;

    fn parse(resp: &[u8]) -> Option<Self::Response> {
        match resp {
            b if b.starts_with(b"+JOIN: ") => JoinUrc::parse(resp).ok().map(URCMessages::Join),
            b if b.starts_with(b"+MSGHEX: ") || b.starts_with(b"+CMSGHEX: ") => {
                MessageHexSend::parse(resp)
                    .ok()
                    .map(URCMessages::MessageHexSend)
            }
            b if b.starts_with(b"+MSG: ") => MessageReceived::parse(resp)
                .ok()
                .map(URCMessages::MessageReceived),
            _ => None,
        }
    }
}

impl Parser for URCMessages {
    fn parse(buf: &[u8]) -> Result<(&[u8], usize), ParseError> {
        // Check if this is a join started message
        match buf {
            b if b.starts_with(b"+JOIN: Auto-Join ") => return Err(ParseError::NoMatch),
            b if b.starts_with(b"+JOIN: Start") => return Err(ParseError::NoMatch),
            _ => {}
        }

        let (_reminder, (head, data, tail)) = branch::alt((
            // Join messages
            sequence::tuple((
                combinator::success(&b""[..]),
                combinator::recognize(sequence::tuple((
                    bytes::streaming::tag("+JOIN: "),
                    bytes::streaming::take_until("\r\n"),
                ))),
                bytes::streaming::tag("\r\n"),
            )),
            // Message Hex Send
            sequence::tuple((
                combinator::success(&b""[..]),
                combinator::recognize(sequence::tuple((
                    branch::alt((
                        bytes::streaming::tag("+MSGHEX: "),
                        bytes::streaming::tag("+CMSGHEX: "),
                    )),
                    bytes::streaming::take_until("\r\n"),
                ))),
                bytes::streaming::tag("\r\n"),
            )),
            // Message Hex Receive
            sequence::tuple((
                combinator::success(&b""[..]),
                combinator::recognize(sequence::tuple((
                    bytes::streaming::tag("+MSG: "),
                    bytes::streaming::take_until("\r\n"),
                ))),
                bytes::streaming::tag("\r\n"),
            )),
        ))(buf)?;
        Ok((data, head.len() + data.len() + tail.len()))
    }
}