semtech_udp/packet/
types.rs

1use serde::{Deserialize, Serialize};
2
3pub use data_rate::*;
4
5pub mod data_rate {
6    use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
7    use std::cmp::PartialEq;
8    use std::fmt::Display;
9    use std::str::FromStr;
10    use std::string::ToString;
11
12    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
13    pub struct DataRate(lora_modulation::SpreadingFactor, lora_modulation::Bandwidth);
14
15    impl Default for DataRate {
16        fn default() -> Self {
17            DataRate(
18                lora_modulation::SpreadingFactor::_7,
19                lora_modulation::Bandwidth::_250KHz,
20            )
21        }
22    }
23
24    impl DataRate {
25        pub fn new(
26            sf: lora_modulation::SpreadingFactor,
27            bw: lora_modulation::Bandwidth,
28        ) -> DataRate {
29            DataRate(sf, bw)
30        }
31        pub fn spreading_factor(&self) -> lora_modulation::SpreadingFactor {
32            self.0
33        }
34        pub fn bandwidth(&self) -> lora_modulation::Bandwidth {
35            self.1
36        }
37    }
38
39    impl FromStr for DataRate {
40        type Err = ParseError;
41        fn from_str(s: &str) -> Result<Self, Self::Err> {
42            let (sf, bw) = if s.len() > 8 {
43                (&s[..4], &s[4..])
44            } else if s.len() > 3 {
45                (&s[..3], &s[3..])
46            } else {
47                return Err(ParseError::InvalidSpreadingFactor);
48            };
49
50            Ok(DataRate(
51                SmtcSpreadingFactor::from_str(sf)?.into(),
52                SmtcBandwidth::from_str(bw)?.into(),
53            ))
54        }
55    }
56
57    impl Display for DataRate {
58        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59            let smtc_sf: SmtcSpreadingFactor = self.0.into();
60            let smtc_bw: SmtcBandwidth = self.1.into();
61            write!(f, "{smtc_sf}{smtc_bw}")
62        }
63    }
64
65    impl Serialize for DataRate {
66        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67        where
68            S: Serializer,
69        {
70            let str = self.to_string();
71            serializer.serialize_str(&str)
72        }
73    }
74
75    impl<'de> Deserialize<'de> for DataRate {
76        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
77        where
78            D: Deserializer<'de>,
79        {
80            let s = <&str>::deserialize(deserializer)?;
81            DataRate::from_str(s).map_err(de::Error::custom)
82        }
83    }
84
85    #[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
86    /// A local representation of the spreading factor specifically for JSON serde.
87    enum SmtcSpreadingFactor {
88        SF5,
89        SF6,
90        SF7,
91        SF8,
92        SF9,
93        SF10,
94        SF11,
95        SF12,
96    }
97
98    impl From<SmtcSpreadingFactor> for lora_modulation::SpreadingFactor {
99        fn from(sf: SmtcSpreadingFactor) -> lora_modulation::SpreadingFactor {
100            match sf {
101                SmtcSpreadingFactor::SF5 => lora_modulation::SpreadingFactor::_5,
102                SmtcSpreadingFactor::SF6 => lora_modulation::SpreadingFactor::_6,
103                SmtcSpreadingFactor::SF7 => lora_modulation::SpreadingFactor::_7,
104                SmtcSpreadingFactor::SF8 => lora_modulation::SpreadingFactor::_8,
105                SmtcSpreadingFactor::SF9 => lora_modulation::SpreadingFactor::_9,
106                SmtcSpreadingFactor::SF10 => lora_modulation::SpreadingFactor::_10,
107                SmtcSpreadingFactor::SF11 => lora_modulation::SpreadingFactor::_11,
108                SmtcSpreadingFactor::SF12 => lora_modulation::SpreadingFactor::_12,
109            }
110        }
111    }
112
113    impl From<lora_modulation::SpreadingFactor> for SmtcSpreadingFactor {
114        fn from(sf: lora_modulation::SpreadingFactor) -> SmtcSpreadingFactor {
115            match sf {
116                lora_modulation::SpreadingFactor::_5 => SmtcSpreadingFactor::SF5,
117                lora_modulation::SpreadingFactor::_6 => SmtcSpreadingFactor::SF6,
118                lora_modulation::SpreadingFactor::_7 => SmtcSpreadingFactor::SF7,
119                lora_modulation::SpreadingFactor::_8 => SmtcSpreadingFactor::SF8,
120                lora_modulation::SpreadingFactor::_9 => SmtcSpreadingFactor::SF9,
121                lora_modulation::SpreadingFactor::_10 => SmtcSpreadingFactor::SF10,
122                lora_modulation::SpreadingFactor::_11 => SmtcSpreadingFactor::SF11,
123                lora_modulation::SpreadingFactor::_12 => SmtcSpreadingFactor::SF12,
124            }
125        }
126    }
127
128    impl FromStr for SmtcSpreadingFactor {
129        type Err = ParseError;
130        fn from_str(s: &str) -> Result<Self, Self::Err> {
131            match s {
132                "SF5" => Ok(SmtcSpreadingFactor::SF5),
133                "SF6" => Ok(SmtcSpreadingFactor::SF6),
134                "SF7" => Ok(SmtcSpreadingFactor::SF7),
135                "SF8" => Ok(SmtcSpreadingFactor::SF8),
136                "SF9" => Ok(SmtcSpreadingFactor::SF9),
137                "SF10" => Ok(SmtcSpreadingFactor::SF10),
138                "SF11" => Ok(SmtcSpreadingFactor::SF11),
139                "SF12" => Ok(SmtcSpreadingFactor::SF12),
140                _ => Err(ParseError::InvalidSpreadingFactor),
141            }
142        }
143    }
144
145    #[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
146    /// A local representation of the bandwidth specifically for JSON serde.
147    enum SmtcBandwidth {
148        BW7,
149        BW10,
150        BW15,
151        BW20,
152        BW31,
153        BW41,
154        BW62,
155        BW125,
156        BW250,
157        BW500,
158    }
159
160    impl From<SmtcBandwidth> for lora_modulation::Bandwidth {
161        fn from(bw: SmtcBandwidth) -> lora_modulation::Bandwidth {
162            match bw {
163                SmtcBandwidth::BW7 => lora_modulation::Bandwidth::_7KHz,
164                SmtcBandwidth::BW10 => lora_modulation::Bandwidth::_10KHz,
165                SmtcBandwidth::BW15 => lora_modulation::Bandwidth::_15KHz,
166                SmtcBandwidth::BW20 => lora_modulation::Bandwidth::_20KHz,
167                SmtcBandwidth::BW31 => lora_modulation::Bandwidth::_31KHz,
168                SmtcBandwidth::BW41 => lora_modulation::Bandwidth::_41KHz,
169                SmtcBandwidth::BW62 => lora_modulation::Bandwidth::_62KHz,
170                SmtcBandwidth::BW125 => lora_modulation::Bandwidth::_125KHz,
171                SmtcBandwidth::BW250 => lora_modulation::Bandwidth::_250KHz,
172                SmtcBandwidth::BW500 => lora_modulation::Bandwidth::_500KHz,
173            }
174        }
175    }
176
177    impl From<lora_modulation::Bandwidth> for SmtcBandwidth {
178        fn from(bw: lora_modulation::Bandwidth) -> SmtcBandwidth {
179            match bw {
180                lora_modulation::Bandwidth::_7KHz => SmtcBandwidth::BW7,
181                lora_modulation::Bandwidth::_10KHz => SmtcBandwidth::BW10,
182                lora_modulation::Bandwidth::_15KHz => SmtcBandwidth::BW15,
183                lora_modulation::Bandwidth::_20KHz => SmtcBandwidth::BW20,
184                lora_modulation::Bandwidth::_31KHz => SmtcBandwidth::BW31,
185                lora_modulation::Bandwidth::_41KHz => SmtcBandwidth::BW41,
186                lora_modulation::Bandwidth::_62KHz => SmtcBandwidth::BW62,
187                lora_modulation::Bandwidth::_125KHz => SmtcBandwidth::BW125,
188                lora_modulation::Bandwidth::_250KHz => SmtcBandwidth::BW250,
189                lora_modulation::Bandwidth::_500KHz => SmtcBandwidth::BW500,
190            }
191        }
192    }
193
194    impl FromStr for SmtcBandwidth {
195        type Err = ParseError;
196        fn from_str(s: &str) -> Result<Self, Self::Err> {
197            match s {
198                "BW7" => Ok(SmtcBandwidth::BW7),
199                "BW10" => Ok(SmtcBandwidth::BW10),
200                "BW15" => Ok(SmtcBandwidth::BW15),
201                "BW20" => Ok(SmtcBandwidth::BW20),
202                "BW31" => Ok(SmtcBandwidth::BW31),
203                "BW41" => Ok(SmtcBandwidth::BW41),
204                "BW62" => Ok(SmtcBandwidth::BW62),
205                "BW125" => Ok(SmtcBandwidth::BW125),
206                "BW250" => Ok(SmtcBandwidth::BW250),
207                "BW500" => Ok(SmtcBandwidth::BW500),
208                _ => Err(ParseError::InvalidBandwidth),
209            }
210        }
211    }
212
213    impl Display for SmtcBandwidth {
214        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215            write!(f, "{self:?}")
216        }
217    }
218
219    impl Display for SmtcSpreadingFactor {
220        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221            write!(f, "{self:?}")
222        }
223    }
224
225    use thiserror::Error;
226
227    #[derive(Error, Debug)]
228    pub enum ParseError {
229        #[error("String with invalid Spreading Factor")]
230        InvalidSpreadingFactor,
231        #[error("String with invalid Bandwidth")]
232        InvalidBandwidth,
233    }
234
235    #[cfg(test)]
236    mod tests {
237        // Note this useful idiom: importing names from outer (for mod tests) scope.
238        use super::*;
239        use lora_modulation::{Bandwidth, SpreadingFactor};
240        #[test]
241        fn test_to_string_sf7() {
242            let datarate = DataRate(SpreadingFactor::_7, Bandwidth::_500KHz);
243            assert_eq!(datarate.to_string(), "SF7BW500")
244        }
245
246        #[test]
247        fn test_to_string_sf10() {
248            let datarate = DataRate(SpreadingFactor::_10, Bandwidth::_125KHz);
249            assert_eq!(datarate.to_string(), "SF10BW125")
250        }
251
252        #[test]
253        fn test_from_str_sf10() {
254            let datarate = DataRate::from_str("SF10BW125").unwrap();
255            assert_eq!(datarate, DataRate(SpreadingFactor::_10, Bandwidth::_125KHz))
256        }
257
258        #[test]
259        fn test_from_invalid_str() {
260            let datarate = DataRate::from_str("12");
261            assert!(datarate.is_err())
262        }
263
264        #[test]
265        fn test_from_str_sf7() {
266            let datarate = DataRate::from_str("SF7BW500").unwrap();
267            assert_eq!(datarate, DataRate(SpreadingFactor::_7, Bandwidth::_500KHz))
268        }
269    }
270}
271
272#[derive(Debug, Serialize, Deserialize, Copy, Clone)]
273#[allow(clippy::upper_case_acronyms)]
274/// A local representation of the coding rate specifically for JSON serde
275enum SmtcCodingRate {
276    #[serde(rename(serialize = "4/5", deserialize = "4/5"))]
277    _4_5,
278    #[serde(rename(serialize = "4/6", deserialize = "4/6"))]
279    _4_6,
280    #[serde(rename(serialize = "4/7", deserialize = "4/7"))]
281    _4_7,
282    #[serde(rename(serialize = "4/8", deserialize = "4/8"))]
283    _4_8,
284    OFF,
285}
286
287pub fn serialize_codr<S>(
288    codr: &Option<lora_modulation::CodingRate>,
289    serializer: S,
290) -> Result<S::Ok, S::Error>
291where
292    S: serde::Serializer,
293{
294    let inner_cdr = match codr {
295        None => SmtcCodingRate::OFF,
296        Some(lora_modulation::CodingRate::_4_5) => SmtcCodingRate::_4_5,
297        Some(lora_modulation::CodingRate::_4_6) => SmtcCodingRate::_4_6,
298        Some(lora_modulation::CodingRate::_4_7) => SmtcCodingRate::_4_7,
299        Some(lora_modulation::CodingRate::_4_8) => SmtcCodingRate::_4_8,
300    };
301    inner_cdr.serialize(serializer)
302}
303
304pub fn deserialize_codr<'de, D>(
305    deserializer: D,
306) -> Result<Option<lora_modulation::CodingRate>, D::Error>
307where
308    D: serde::Deserializer<'de>,
309{
310    let inner_cdr = SmtcCodingRate::deserialize(deserializer)?;
311    Ok(match inner_cdr {
312        SmtcCodingRate::OFF => None,
313        SmtcCodingRate::_4_5 => Some(lora_modulation::CodingRate::_4_5),
314        SmtcCodingRate::_4_6 => Some(lora_modulation::CodingRate::_4_6),
315        SmtcCodingRate::_4_7 => Some(lora_modulation::CodingRate::_4_7),
316        SmtcCodingRate::_4_8 => Some(lora_modulation::CodingRate::_4_8),
317    })
318}
319
320#[derive(Debug, Serialize, Deserialize, Clone)]
321pub enum Modulation {
322    LORA,
323    FSK,
324}
325
326pub(crate) mod base64 {
327    extern crate base64;
328    use crate::packet::types::base64::base64::Engine;
329    use serde::{de, Deserialize, Deserializer, Serializer};
330
331    pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
332    where
333        S: Serializer,
334    {
335        let b64 = base64::engine::general_purpose::STANDARD.encode(bytes);
336        serializer.serialize_str(&b64)
337    }
338
339    pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
340    where
341        D: Deserializer<'de>,
342    {
343        let s = <&str>::deserialize(deserializer)?;
344        base64::engine::general_purpose::STANDARD
345            .decode(s)
346            .map_err(de::Error::custom)
347    }
348}