1use core::convert::{TryFrom, TryInto};
13#[cfg(feature = "std")]
14use core::fmt;
15#[cfg(feature = "std")]
16use core::str::FromStr;
17use heapless::Vec;
18
19pub mod codec;
20
21const COBS_SENTINEL: u8 = 0x00;
22#[cfg(feature = "std")]
23pub const DEFAULT_MAX_MESSAGE_QUEUE_LENGTH: usize = 3;
24#[cfg(not(feature = "std"))]
25pub const DEFAULT_MAX_MESSAGE_QUEUE_LENGTH: usize = 3;
26pub const RAWIQ_DATA_LENGTH: usize = 2 * 16_536; pub const RAWIQ_SAMPLING_FREQ: u32 = 65000; pub const fn calculate_cobs_overhead(unecoded_message_size: usize) -> usize {
42 const COBS_OVERHEAD_MAXIMUM: usize = 254;
43 1 +
45 unecoded_message_size +
47 1 + (unecoded_message_size + COBS_OVERHEAD_MAXIMUM - 1) / COBS_OVERHEAD_MAXIMUM +
49 1
51}
52
53#[cfg(feature = "std")]
54pub const MAX_MESSAGE_LENGTH: usize = calculate_cobs_overhead(RAWIQ_DATA_LENGTH + 1);
55#[cfg(not(feature = "std"))]
56pub const MAX_MESSAGE_LENGTH: usize = calculate_cobs_overhead(255);
57pub type HostMessageVec = Vec<u8, MAX_MESSAGE_LENGTH>;
58
59#[derive(PartialEq)]
60#[cfg_attr(feature = "std", derive(Debug))]
61pub enum Error {
62 BufferFull,
63 BufferLengthNotSufficient,
64 MalformedMessage,
65 MessageQueueFull,
66 CannotAppendCommand,
67 CodecError(codec::CodecError),
68 CobsEncodeError,
69 CannotParseConfigNetwork,
70}
71
72impl From<codec::CodecError> for Error {
73 fn from(e: codec::CodecError) -> Error {
74 Error::CodecError(e)
75 }
76}
77
78#[derive(Clone, PartialEq)]
79#[cfg_attr(feature = "std", derive(Debug))]
80#[repr(u8)]
81pub enum StatusCode {
82 FrameReceived = 1,
83 CommandReceived = 2,
84 ErrUnknownCommmandReceived = 3,
85 ErrBusyLoraTransmitting = 4,
86 ErrMessageQueueFull = 5,
87 RadioNotConfigured = 6,
88}
89
90impl TryFrom<u8> for StatusCode {
91 type Error = &'static str;
92
93 fn try_from(value: u8) -> Result<Self, Self::Error> {
94 match value {
95 1 => Ok(StatusCode::FrameReceived),
96 2 => Ok(StatusCode::CommandReceived),
97 3 => Ok(StatusCode::ErrUnknownCommmandReceived),
98 4 => Ok(StatusCode::ErrBusyLoraTransmitting),
99 5 => Ok(StatusCode::ErrMessageQueueFull),
100 6 => Ok(StatusCode::RadioNotConfigured),
101 _ => Err("Unknown StatusCode"),
102 }
103 }
104}
105#[cfg(feature = "std")]
106impl fmt::Display for StatusCode {
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108 match *self {
109 StatusCode::FrameReceived => write!(f, "Single serial frame was successfuly received"),
110 StatusCode::CommandReceived => write!(f, "Command was successfully received"),
111 StatusCode::ErrUnknownCommmandReceived => write!(f, "Error: unknown command type"),
112 StatusCode::ErrBusyLoraTransmitting => write!(
113 f,
114 "Error: cannot execute sent command - radio is currently busy transmitting"
115 ),
116 StatusCode::ErrMessageQueueFull => write!(
117 f,
118 "Transmit queue is full, try sending SendData later again"
119 ),
120 StatusCode::RadioNotConfigured => write!(f, "Error: radio is not configured"),
121 }
122 }
123}
124
125#[derive(PartialEq)]
129pub enum Message {
130 SendData {
132 data: Vec<u8, { crate::MAX_LORA_PAYLOAD_LENGTH }>,
133 },
134 ReceiveData {
136 data: Vec<u8, { crate::MAX_LORA_PAYLOAD_LENGTH }>,
137 },
138 Configure {
140 region: u8,
141 spreading_factor: u8,
142 network: u16,
143 },
144 ReportRequest,
146 Report {
148 sn: u32,
150 version_data: Vec<u8, 9>,
152 region: u8,
153 spreading_factor: u8,
154 receive_queue_size: u8,
155 transmit_queue_size: u8,
156 network: u16,
157 },
158 Status { code: StatusCode },
160 UpgradeFirmwareRequest,
162 SetTimestamp { timestamp: u64 },
164 GetRawIq,
166 #[cfg(feature = "std")]
168 RawIq { data: Vec<u8, RAWIQ_DATA_LENGTH> },
169}
170
171#[cfg(feature = "std")]
174impl fmt::Debug for Message {
175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176 match self {
177 Message::SendData { data } => write!(f, "SendData {{ data: {:02x?} }}", data),
178 Message::ReceiveData { data } => write!(f, "ReceiveData {{ data: {:02x?} }}", data),
179 Message::Configure { region, spreading_factor, network } => write!(f, "Configure {{ region: {:02x?}, spreading_factor: {:?}, network: {:02x?} }}", region, spreading_factor, network.to_be_bytes()),
180 Message::ReportRequest => write!(f, "ReportRequest"),
181 Message::Report {
182 sn,
183 version_data,
184 region,
185 spreading_factor,
186 receive_queue_size,
187 transmit_queue_size,
188 network,
189 } => write!(f, "Report {{ sn: {:?}, version_data: {:02x?}, region: {:02x?}, spreading_factor: {:?}, receive_queue_size: {:?}, transmit_queue_size: {:?}, network: {:02x?}", sn, version_data, region, spreading_factor, receive_queue_size, transmit_queue_size, network.to_be_bytes()),
190 Message::Status { code } => write!(f, "Status({:?})", code),
191 Message::UpgradeFirmwareRequest => write!(f, "UpgradeFirmwareRequest"),
192 Message::SetTimestamp { timestamp } => write!(f, "SetTimestamp({:?})", timestamp),
193 Message::GetRawIq => write!(f, "GetRawIq"),
194 #[cfg(feature = "std")]
195 Message::RawIq { data } => write!(f, "RawIq {{ data: {:02x?} }}", data)
196 }
197 }
198}
199
200#[cfg_attr(feature = "std", derive(Debug, PartialEq))]
201pub enum ParseMessageError {
202 MissingSeparator,
203 InvalidMessage,
204 InvalidHex(base16::DecodeError),
205 InvalidHexConfigNetwork,
206 InvalidPayloadLength,
207 PayloadTooLong,
208 MissingConfigNetwork,
209}
210
211impl From<base16::DecodeError> for ParseMessageError {
212 fn from(e: base16::DecodeError) -> ParseMessageError {
213 ParseMessageError::InvalidHex(e)
214 }
215}
216
217#[cfg(feature = "std")]
218impl FromStr for Message {
219 type Err = ParseMessageError;
220
221 fn from_str(s: &str) -> Result<Self, ParseMessageError> {
222 if !s.contains('@') {
223 return Err(ParseMessageError::MissingSeparator);
224 }
225
226 let mut iter = s.split(|c| c == '@');
227 let cmd_type = iter.next().unwrap();
228 let val = iter.next().unwrap();
229 match cmd_type {
230 "send" => {
231 let mut data = Vec::<u8, { crate::MAX_LORA_PAYLOAD_LENGTH }>::new();
232 let clean_val = match val.starts_with("0x") || val.starts_with("0X") {
233 true => &val[2..],
234 false => &val,
235 };
236 if clean_val.len() / 2 > crate::MAX_LORA_PAYLOAD_LENGTH {
237 return Err(ParseMessageError::PayloadTooLong);
238 }
239 data.resize_default(clean_val.len() / 2)
240 .map_err(|_| ParseMessageError::InvalidPayloadLength)?;
241 if base16::decode_slice(clean_val, &mut data).is_err() {
242 return Err(ParseMessageError::InvalidPayloadLength);
243 }
244
245 Ok(Message::SendData { data })
246 }
247 "status" => Ok(Message::ReportRequest),
248 "config" => {
249 if !val.contains('|') {
250 return Err(ParseMessageError::MissingSeparator);
251 }
252 let mut iter = val.split(|c| c == '|');
253 let region = iter.next().unwrap();
254 let region = u8::from_str(region).unwrap();
255 let spreading_factor = iter.next().unwrap();
256 let spreading_factor = u8::from_str(spreading_factor).unwrap();
257 if spreading_factor < 7 || spreading_factor > 12 {
258 return Err(ParseMessageError::InvalidMessage);
259 }
260 let network = iter.next().ok_or(ParseMessageError::MissingConfigNetwork)?;
261 let network = u16::from_str_radix(network, 16)
262 .map_err(|_| ParseMessageError::InvalidHexConfigNetwork)?;
263 Ok(Message::Configure {
264 region,
265 spreading_factor,
266 network,
267 })
268 }
269 "ts" => Ok(Message::SetTimestamp {
270 timestamp: val.parse().unwrap(),
271 }),
272 "get_rawiq" => Ok(Message::GetRawIq),
273 "uf" => Ok(Message::UpgradeFirmwareRequest),
274 _ => Err(ParseMessageError::InvalidMessage),
275 }
276 }
277}
278
279impl TryFrom<&[u8]> for Message {
280 type Error = Error;
281
282 fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
283 match buf[0] {
284 0xc0 => Ok(Message::SendData {
285 data: Vec::<u8, 255>::from_slice(&buf[1..])
286 .map_err(|_| Error::BufferLengthNotSufficient)?,
287 }),
288 0xc1 => Ok(Message::ReceiveData {
289 data: Vec::<u8, 255>::from_slice(&buf[1..])
290 .map_err(|_| Error::BufferLengthNotSufficient)?,
291 }),
292 0xc2 => Ok(Message::Configure {
293 region: buf[1],
294 spreading_factor: buf[2],
295 network: u16::from_be_bytes(
296 buf[3..5]
297 .try_into()
298 .map_err(|_| Self::Error::CannotParseConfigNetwork)?,
299 ),
300 }),
301 0xc3 => Ok(Message::ReportRequest),
302 0xc4 => Ok(Message::Report {
303 sn: u32::from_be_bytes(buf[1..5].try_into().map_err(|_| Error::MalformedMessage)?),
304 version_data: Vec::<u8, 9>::from_slice(&buf[5..14])
305 .map_err(|_| Error::MalformedMessage)?,
306
307 region: buf[14],
308 spreading_factor: buf[15],
309 receive_queue_size: buf[16],
310 transmit_queue_size: buf[17],
311 network: u16::from_be_bytes(
312 buf[18..20]
313 .try_into()
314 .map_err(|_| Error::MalformedMessage)?,
315 ),
316 }),
317 0xc5 => Ok(Message::Status {
318 code: buf[1].try_into().map_err(|_| Error::MalformedMessage)?,
319 }),
320 0xc6 => Ok(Message::UpgradeFirmwareRequest),
321 0xc7 => Ok(Message::SetTimestamp {
322 timestamp: u64::from_be_bytes(
323 buf[1..9].try_into().map_err(|_| Error::MalformedMessage)?,
324 ),
325 }),
326 0xc8 => Ok(Message::GetRawIq),
327 #[cfg(feature = "std")]
328 0xc9 => Ok(Message::RawIq {
329 data: Vec::<u8, RAWIQ_DATA_LENGTH>::from_slice(&buf[1..])
330 .map_err(|_| Error::BufferLengthNotSufficient)?,
331 }),
332 _ => Err(Error::MalformedMessage),
333 }
334 }
335}
336
337#[allow(clippy::len_without_is_empty)]
338impl Message {
339 pub fn try_from_cobs(buf: &mut [u8]) -> Result<Message, Error> {
340 if buf.is_empty() {
341 return Err(Error::MalformedMessage);
342 };
343
344 let decoded_len = match cobs::decode_in_place_with_sentinel(buf, COBS_SENTINEL) {
345 Ok(len) => len,
346 Err(_) => return Err(Error::MalformedMessage),
347 };
348
349 Message::try_from(&buf[0..decoded_len])
350 }
351
352 pub fn len(&self) -> usize {
353 let variable_part_length = match self {
354 Message::SendData { data } => data.len(),
355 Message::ReceiveData { data } => data.len(),
356 Message::Configure { .. } => 4,
357 Message::ReportRequest => 0,
358 Message::Report { .. } => 19,
359 Message::Status { .. } => 1,
360 Message::UpgradeFirmwareRequest => 0,
361 Message::SetTimestamp { .. } => 8, Message::GetRawIq => 0,
363 #[cfg(feature = "std")]
364 Message::RawIq { data } => data.len(),
365 };
366
367 1 + variable_part_length
368 }
369
370 pub fn as_bytes(&self) -> Result<Vec<u8, MAX_MESSAGE_LENGTH>, Error> {
371 let mut res = Vec::new();
372 match self {
373 Message::SendData { data } => {
374 res.push(0xc0)
375 .map_err(|_| Error::BufferLengthNotSufficient)?;
376 res.extend_from_slice(&data)
377 .map_err(|_| Error::BufferLengthNotSufficient)?;
378 }
379 Message::ReceiveData { data } => {
380 res.push(0xc1)
381 .map_err(|_| Error::BufferLengthNotSufficient)?;
382 res.extend_from_slice(&data)
383 .map_err(|_| Error::BufferLengthNotSufficient)?;
384 }
385 Message::Configure {
386 region,
387 spreading_factor,
388 network,
389 } => {
390 res.extend_from_slice(&[0xc2, *region, *spreading_factor])
391 .map_err(|_| Error::BufferLengthNotSufficient)?;
392 res.extend_from_slice(&network.to_be_bytes())
393 .map_err(|_| Error::BufferLengthNotSufficient)?;
394 }
395 Message::ReportRequest => res
396 .push(0xc3)
397 .map_err(|_| Error::BufferLengthNotSufficient)?,
398 Message::Report {
400 sn,
401 version_data,
402 region,
403 spreading_factor,
404 receive_queue_size,
405 transmit_queue_size,
406 network,
407 } => {
408 res.push(0xc4)
409 .map_err(|_| Error::BufferLengthNotSufficient)?;
410 res.extend_from_slice(&u32::to_be_bytes(*sn))
411 .map_err(|_| Error::BufferLengthNotSufficient)?;
412 res.extend_from_slice(&version_data)
413 .map_err(|_| Error::BufferLengthNotSufficient)?;
414 res.extend_from_slice(&[
415 *region,
416 *spreading_factor,
417 *receive_queue_size,
418 *transmit_queue_size,
419 ])
420 .map_err(|_| Error::BufferLengthNotSufficient)?;
421 res.extend_from_slice(&network.to_be_bytes())
422 .map_err(|_| Error::BufferLengthNotSufficient)?;
423 }
424 Message::Status { code } => {
425 res.extend_from_slice(&[0xc5, code.clone() as u8])
426 .map_err(|_| Error::BufferLengthNotSufficient)?;
427 }
428 Message::UpgradeFirmwareRequest => res
429 .push(0xc6)
430 .map_err(|_| Error::BufferLengthNotSufficient)?,
431 Message::SetTimestamp { timestamp } => {
432 res.push(0xc7)
433 .map_err(|_| Error::BufferLengthNotSufficient)?;
434 res.extend_from_slice(&u64::to_be_bytes(*timestamp))
435 .map_err(|_| Error::BufferLengthNotSufficient)?
436 }
437 Message::GetRawIq => res
438 .push(0xc8)
439 .map_err(|_| Error::BufferLengthNotSufficient)?,
440 #[cfg(feature = "std")]
441 Message::RawIq { data } => {
442 res.push(0xc9)
443 .map_err(|_| Error::BufferLengthNotSufficient)?;
444 res.extend_from_slice(&data)
445 .map_err(|_| Error::BufferLengthNotSufficient)?;
446 }
447 };
448 Ok(res)
449 }
450
451 pub fn encode(&self) -> Result<HostMessageVec, Error> {
452 let mut result = HostMessageVec::new(); let mut encoded_len = cobs::max_encoding_length(self.len() + 1);
454 result
455 .resize_default(encoded_len)
456 .map_err(|_| Error::BufferLengthNotSufficient)?;
457 let mut enc = cobs::CobsEncoder::new(&mut result);
458 enc.push(self.as_bytes()?.as_slice())
459 .map_err(|_| Error::CobsEncodeError)?;
460
461 encoded_len = enc.finalize().map_err(|_| Error::CobsEncodeError)?;
462 result
463 .push(COBS_SENTINEL)
464 .map_err(|_| Error::BufferLengthNotSufficient)?;
465 result.truncate(encoded_len + 1_usize);
466 Ok(result)
467 }
468
469 pub fn encode_to_slice<'a>(&self, buf: &'a mut [u8]) -> Result<usize, Error> {
470 let mut enc = cobs::CobsEncoder::new(buf);
471 enc.push(self.as_bytes()?.as_slice())
472 .map_err(|_| Error::CobsEncodeError)?;
473
474 let encoded_len = enc.finalize().map_err(|_| Error::CobsEncodeError)?;
475 buf[encoded_len] = COBS_SENTINEL;
476 Ok(encoded_len + 1)
477 }
478
479 pub fn into_encoded_bytes(self) -> Result<HostMessageVec, Error> {
480 self.encode()
481 }
482
483 pub fn as_frames<C: codec::WireCodec>(&self) -> Result<C::Frames, Error> {
486 let mut result = self.encode()?;
487 let frames = C::get_frames(&mut result[..]).map_err(|e| Error::CodecError(e))?;
488 Ok(frames)
489 }
490}
491
492pub struct MessageReader<const BUFL: usize, const QL: usize> {
493 buf: Vec<u8, BUFL>,
494}
495
496impl<const BUFL: usize, const QL: usize> MessageReader<BUFL, QL> {
497 pub fn new() -> Self {
498 Self {
499 buf: Vec::<u8, BUFL>::new(),
500 }
501 }
502
503 pub fn process_bytes<C: codec::WireCodec>(
504 &mut self,
505 bytes: &[u8],
506 ) -> Result<Vec<Message, QL>, Error> {
507 let (bytes, decoded_len) = C::decode_frame(bytes)?;
508 if self.buf.len() + decoded_len > BUFL {
509 return Err(Error::BufferFull);
510 }
511 self.buf.extend(bytes);
512
513 let mut output = Vec::<Message, QL>::new();
514 let mut cobs_index: usize = 0;
515
516 if !&self.buf.contains(&COBS_SENTINEL) {
517 return Ok(output);
518 }
519 loop {
520 if self.buf[cobs_index] == COBS_SENTINEL {
521 match Message::try_from_cobs(&mut self.buf[0..cobs_index]) {
522 Ok(command) => {
523 self.buf = Vec::from_slice(&self.buf[cobs_index + 1..])
524 .map_err(|_| Error::BufferLengthNotSufficient)?; cobs_index = 0;
526 if output.len() < QL {
527 output
528 .push(command)
529 .map_err(|_| Error::CannotAppendCommand)?;
530 } else {
531 return Err(Error::MessageQueueFull);
532 }
533 if self.buf.len() == 0 {
534 break;
535 } else {
536 continue;
537 }
538 }
539 Err(_) => return Err(Error::MalformedMessage),
540 }
541 }
542
543 if cobs_index + 1 == self.buf.len() {
544 break;
545 }
546
547 cobs_index += 1;
548 }
549 Ok(output)
550 }
551
552 pub fn ltrim(&mut self, length: usize) -> Result<(), Error> {
553 if self.buf.len() < length {
554 return Err(Error::BufferLengthNotSufficient);
555 }
556
557 self.buf = match Vec::from_slice(&self.buf[length..]) {
558 Ok(b) => b,
559 Err(_) => return Err(Error::BufferLengthNotSufficient),
560 };
561 Ok(())
562 }
563
564 pub fn reset(&mut self) {
565 self.buf.clear();
566 }
567
568 pub fn is_empty(&self) -> bool {
569 self.buf.is_empty()
570 }
571}
572
573impl<const BUFL: usize, const QL: usize> Default for MessageReader<BUFL, QL> {
574 fn default() -> Self {
575 Self::new()
576 }
577}
578
579#[cfg(test)]
580mod tests {
581 use super::*;
582 use rand::{thread_rng, Rng};
583
584 #[test]
585 fn test_msg_len() {
586 assert_eq!(
587 20,
588 Message::Report {
589 region: 0x01,
590 spreading_factor: 7,
591 sn: 12345678u32,
592 version_data: Vec::<u8, 9>::from_slice(&[
593 0x01, 0x00, 0x01, 0x00, 0x04, 0x40, 0x6e, 0xd3, 0x01,
594 ])
595 .unwrap(), receive_queue_size: 1,
597 transmit_queue_size: 3,
598 network: u16::from_be_bytes([0xaa, 0xcc])
599 }
600 .len()
601 );
602 assert_eq!(1, Message::ReportRequest.len());
603 assert_eq!(
604 5,
605 Message::Configure {
606 region: 0x1,
607 spreading_factor: 7,
608 network: u16::from_be_bytes([0xaa, 0xcc])
609 }
610 .len()
611 );
612 assert_eq!(
613 3,
614 Message::SendData {
615 data: Vec::<u8, 255>::from_slice(&[0xff, 0xee]).unwrap()
616 }
617 .len()
618 );
619 assert_eq!(
620 5,
621 Message::ReceiveData {
622 data: Vec::<u8, 255>::from_slice(&[0xde, 0xad, 0xbe, 0xef]).unwrap()
623 }
624 .len()
625 );
626 }
627
628 #[test]
629 fn test_process_with_no_bytes_is_empty() {
630 let mut cr = MessageReader::<MAX_MESSAGE_LENGTH, DEFAULT_MAX_MESSAGE_QUEUE_LENGTH>::new();
631 assert_eq!(
632 cr.process_bytes::<codec::UsbCodec>(&[][..]).unwrap().len(),
633 0
634 );
635 }
636
637 #[test]
638 fn test_process_with_no_full_message_is_empty() {
639 let mut cr = MessageReader::<MAX_MESSAGE_LENGTH, DEFAULT_MAX_MESSAGE_QUEUE_LENGTH>::new();
640 assert_eq!(
641 cr.process_bytes::<codec::UsbCodec>(&[0x01, 0x02][..])
642 .unwrap()
643 .len(),
644 0
645 );
646 }
647
648 #[test]
649 fn test_single_message_decoding() {
650 let encoded = &[0x06, 0xc2, 0xff, 0x07, 0xaa, 0xcc, 0x00];
651 let mut cr = MessageReader::<MAX_MESSAGE_LENGTH, DEFAULT_MAX_MESSAGE_QUEUE_LENGTH>::new();
652 let messages = cr.process_bytes::<codec::UsbCodec>(&encoded[..]).unwrap();
653
654 let expected_msg_0 = Message::Configure {
655 region: 255u8,
656 spreading_factor: 7,
657 network: u16::from_be_bytes([0xaa, 0xcc]),
658 };
659 assert_eq!(messages.len(), 1);
660 assert_eq!(messages[0], expected_msg_0);
661 }
662
663 #[test]
664 fn test_multiple() {
665 let mut encoded_buffer = [128; 32];
666 let mut start = 0;
667 for msg in vec![vec![0xc0, 0xff, 0xee], vec![0xc1, 0xde, 0xad, 0xbe, 0xef]] {
668 println!("start index is = {}", start);
669 let written = cobs::encode(&msg, &mut encoded_buffer[start..]);
670 println!("encoded_buffer -> {:02x?}", encoded_buffer);
671 encoded_buffer[start + written] = 0x00;
672 println!(
673 "start = {}, written = {}\nencoded_buffer -> {:02x?}",
674 start,
675 written + 1,
676 encoded_buffer
677 );
678 start = start + written + 1;
679 }
680
681 let mut cr = MessageReader::<MAX_MESSAGE_LENGTH, 2>::new();
682 let messages = cr
683 .process_bytes::<codec::UsbCodec>(&encoded_buffer[..])
684 .unwrap();
685 assert_eq!(messages.len(), 2);
686 assert_eq!(
687 messages[0],
688 Message::SendData {
689 data: Vec::<u8, 255>::from_slice(&[0xff, 0xee]).unwrap()
690 }
691 );
692 assert_eq!(
693 messages[1],
694 Message::ReceiveData {
695 data: Vec::<u8, 255>::from_slice(&[0xde, 0xad, 0xbe, 0xef]).unwrap()
696 }
697 );
698 }
699
700 #[test]
702 fn test_more_than_queue_capacity() {
703 let mut encoded_buffer = [128; 32];
704 let mut start = 0;
705 for msg in vec![
706 vec![0xc0, 0xff, 0xee],
707 vec![0xc0, 0xff, 0xee],
708 vec![0xc0, 0xff, 0xee],
709 vec![0xc0, 0xff, 0xee],
710 vec![0xc0, 0xff, 0xee],
711 ] {
712 println!("start index is = {}", start);
713 let written = cobs::encode(&msg, &mut encoded_buffer[start..]);
714 println!("encoded_buffer -> {:02x?}", encoded_buffer);
715 encoded_buffer[start + written] = 0x00;
716 println!(
717 "start = {}, written = {}\nencoded_buffer -> {:02x?}",
718 start,
719 written + 1,
720 encoded_buffer
721 );
722 start = start + written + 1;
723 }
724 let mut cr = MessageReader::<MAX_MESSAGE_LENGTH, DEFAULT_MAX_MESSAGE_QUEUE_LENGTH>::new();
725 let err = cr.process_bytes::<codec::UsbCodec>(&encoded_buffer[..]);
726 assert_eq!(err, Err(Error::MessageQueueFull));
727 }
728
729 #[test]
730 fn test_single_message_encoding_as_cobs_encoded_usb_frames() {
731 let expected = &[0x06, 0xc2, 0xff, 0x07, 0xaa, 0xcc, 0x00];
732 let msg = Message::Configure {
733 region: 255u8,
734 spreading_factor: 7,
735 network: u16::from_be_bytes([0xaa, 0xcc]),
736 };
737 let frames = msg.as_frames::<codec::UsbCodec>().unwrap();
738
739 assert_eq!(frames.len(), 1);
740 let result = &frames[0];
741 println!("encoded = {:02x?}", &result);
742 assert_eq!(result, expected);
743 }
744
745 #[test]
746 fn test_max_len_data_message_encoding() {
747 let mut arr = [0u8; crate::MAX_LORA_PAYLOAD_LENGTH];
748 thread_rng().try_fill(&mut arr[..]).unwrap();
749
750 let msg = Message::SendData {
751 data: Vec::<u8, { crate::MAX_LORA_PAYLOAD_LENGTH }>::from_slice(&arr).unwrap(),
752 };
753
754 let frames = msg.as_frames::<codec::UsbCodec>().unwrap();
756 assert_eq!(frames.len(), 2);
757
758 let last_frame = &frames.last().unwrap();
760 assert_eq!(last_frame.last().unwrap(), &COBS_SENTINEL);
761 }
762
763 #[test]
764 fn test_ltrim_ok() {
765 let mut cr = MessageReader::<MAX_MESSAGE_LENGTH, DEFAULT_MAX_MESSAGE_QUEUE_LENGTH>::new();
766 let buf = b"%DISCONNECT%";
767 cr.process_bytes::<codec::UsbCodec>(buf.as_ref()).unwrap();
768 let res = cr.ltrim(buf.len());
769 assert_eq!(Ok(()), res);
770 }
771
772 #[test]
773 fn test_ltrim_err() {
774 let mut cr = MessageReader::<MAX_MESSAGE_LENGTH, DEFAULT_MAX_MESSAGE_QUEUE_LENGTH>::new();
775 let buf = b"%DISCONNECT%";
776 cr.process_bytes::<codec::UsbCodec>(buf.as_ref()).unwrap();
777 let err = cr.ltrim(buf.len() + 1);
778 assert_eq!(err, Err(Error::BufferLengthNotSufficient));
779 }
780
781 #[test]
782 fn test_single_message_encoding_as_cobs_encoded_frames_for_ble() {
783 let expected = &[0x06, 0xc2, 0xff, 0x0c, 0xaa, 0xcc, 0x00];
784 let msg = Message::Configure {
785 region: 255u8,
786 spreading_factor: 12,
787 network: u16::from_be_bytes([0xaa, 0xcc]),
788 };
789 let hex_frames = msg.as_frames::<codec::Rn4870Codec>().unwrap();
790
791 assert_eq!(hex_frames.len(), 1);
792 let hex_frame = &hex_frames[0];
793 let mut decoded = Vec::<u8, 7>::new();
794 decoded.resize_default(expected.len()).unwrap();
795 base16::decode_slice(&hex_frame.clone()[1..hex_frame.len() - 1], &mut decoded).unwrap();
796 assert_eq!(decoded, expected);
797 }
798
799 #[test]
800 fn test_message_reader_process_bytes_hex() {
801 let msg = Message::Configure {
802 region: 255u8,
803 spreading_factor: 7,
804 network: u16::from_be_bytes([0xaa, 0xcc]),
805 };
806 let hex_frames = msg.as_frames::<codec::Rn4870Codec>().unwrap();
807
808 assert_eq!(hex_frames.len(), 1);
809 let hex_frame = hex_frames[0].clone();
810 let mut cr = MessageReader::<MAX_MESSAGE_LENGTH, DEFAULT_MAX_MESSAGE_QUEUE_LENGTH>::new();
811 let messages = cr
812 .process_bytes::<codec::Rn4870Codec>(&hex_frame[1..hex_frame.len() - 1])
813 .unwrap();
814 assert_eq!(messages.len(), 1);
815 assert_eq!(messages[0], msg);
816 }
817
818 #[test]
819 fn test_max_message_length_as_cobs_encoded_frames_for_ble() {
820 let mut arr = [0u8; crate::MAX_LORA_PAYLOAD_LENGTH];
821 thread_rng().try_fill(&mut arr[..]).unwrap();
822
823 let msg = Message::SendData {
824 data: Vec::<u8, { crate::MAX_LORA_PAYLOAD_LENGTH }>::from_slice(&arr).unwrap(),
825 };
826
827 let frames = msg.as_frames::<codec::Rn4870Codec>().unwrap();
829 assert_eq!(frames.len(), 5);
830 }
831
832 #[test]
833 fn test_status_code_encoding() {
834 let msg = Message::Status {
835 code: StatusCode::ErrBusyLoraTransmitting,
836 };
837 let encoded = msg.encode().unwrap();
838 let mut mr = MessageReader::<MAX_MESSAGE_LENGTH, DEFAULT_MAX_MESSAGE_QUEUE_LENGTH>::new();
839 let messages = mr.process_bytes::<codec::UsbCodec>(&encoded[..]).unwrap();
840 assert_eq!(messages.len(), 1);
841 assert_eq!(messages[0], msg);
842 }
843
844 #[test]
845 fn test_encode_to_slice_status() {
846 let mut result = [0u8; 20];
847 let msg = Message::Status {
848 code: StatusCode::ErrBusyLoraTransmitting,
849 };
850 let result_len = msg.encode_to_slice(&mut result[..]).unwrap();
851 assert_eq!(result[0..result_len], msg.encode().unwrap()[..]);
852 }
853
854 #[test]
855 fn test_encode_to_slice_receive_data() {
856 let mut result = [0u8; 68];
857 let msg = Message::ReceiveData {
858 data: Vec::<u8, 255>::from_slice([0xab].repeat(64).as_slice()).unwrap(),
859 };
860 let result_len = msg.encode_to_slice(&mut result[..]).unwrap();
861 assert_eq!(result[0..result_len], msg.encode().unwrap()[..]);
862 }
863
864 #[test]
865 fn test_encode_to_slice_report() {
866 let mut result = [0u8; 68];
867 let msg = Message::Report {
868 sn: 0xa1a2a3a4,
869 version_data: Vec::<u8, 9>::from_slice(&[
870 0x01, 0x00, 0x01, 0x00, 0x04, 0x40, 0x6e, 0xd3, 0x01,
871 ])
872 .unwrap(), region: 13,
874 spreading_factor: 7,
875 receive_queue_size: 17, transmit_queue_size: 25,
877 network: u16::from_be_bytes([0xaa, 0xcc]),
878 };
879 let result_len = msg.encode_to_slice(&mut result[..]).unwrap();
880 println!("{:02x?}", &result[0..result_len]);
881 assert_eq!(result[0..result_len], msg.encode().unwrap()[..]);
882 }
883
884 #[test]
885 fn test_message_parse_status() {
886 let msg = "status@".parse::<Message>().unwrap();
887 assert_eq!(msg, Message::ReportRequest);
888 }
889
890 #[test]
891 fn test_message_parse_send_data() {
892 let msg = "send@0xAABB".parse::<Message>().unwrap();
893 assert_eq!(
894 msg,
895 Message::SendData {
896 data: Vec::<u8, { crate::MAX_LORA_PAYLOAD_LENGTH }>::from_slice(&[0xaa, 0xbb])
897 .unwrap()
898 }
899 );
900
901 let msg = "send@ccdd".parse::<Message>().unwrap();
902 assert_eq!(
903 msg,
904 Message::SendData {
905 data: Vec::<u8, { crate::MAX_LORA_PAYLOAD_LENGTH }>::from_slice(&[0xcc, 0xdd])
906 .unwrap()
907 }
908 );
909 }
910
911 #[test]
912 fn test_message_parse_config() {
913 let msg = "config@1|7|aacc".parse::<Message>().unwrap();
914 assert_eq!(
915 msg,
916 Message::Configure {
917 region: 1,
918 spreading_factor: 7,
919 network: u16::from_be_bytes([0xaa, 0xcc])
920 }
921 );
922 }
923
924 #[test]
925 fn test_message_parse_config_invalid_sf() {
926 let err = "config@1|6|aacc".parse::<Message>();
927 assert_eq!(err, Err(ParseMessageError::InvalidMessage));
928
929 let err = "config@1|13|ccaa".parse::<Message>();
930 assert_eq!(err, Err(ParseMessageError::InvalidMessage));
931 }
932
933 #[test]
934 #[should_panic(expected = "MissingConfigNetwork")]
935 fn test_message_parse_config_missing_network() {
936 "config@1|12".parse::<Message>().unwrap();
937 }
938
939 #[test]
940 fn test_message_parse_ts() {
941 let msg = "ts@1629896485".parse::<Message>().unwrap();
942 assert_eq!(
943 msg,
944 Message::SetTimestamp {
945 timestamp: 1629896485u64
946 }
947 );
948 }
949
950 #[test]
951 fn test_calculate_cobs_overhead_for_255() {
952 let max_message_length = calculate_cobs_overhead(255);
953 assert_eq!(max_message_length, 260);
954 }
955
956 #[test]
957 fn test_calculate_cobs_overhead_for_2048() {
958 let max_message_length = calculate_cobs_overhead(2048);
959 assert_eq!(max_message_length, 2060);
960 }
961
962 #[test]
963 fn test_calculate_cobs_overhead_for_4096() {
964 let max_message_length = calculate_cobs_overhead(4096);
965 assert_eq!(max_message_length, 4116);
966 }
967}