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 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 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 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)]
274enum 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}