#[cfg(feature = "serde")]
use super::SerializeUbxPacketFields;
#[cfg(feature = "serde")]
use crate::serde::ser::SerializeMap;
#[allow(unused_imports, reason = "It is only unused in some feature sets")]
use crate::FieldIter;
use crate::{error::ParserError, UbxPacketMeta};
use ublox_derive::ubx_packet_recv;
#[ubx_packet_recv]
#[ubx(class = 0x0a, id = 0x36, max_payload_len = 248)] struct MonComms {
version: u8,
n_ports: u8,
tx_errors: u8,
reserved0: u8,
prot_ids: [u8; 4],
#[ubx(map_type = MonCommsPortIter, may_fail,
from = MonCommsPortIter::new,
is_valid = MonCommsPortIter::is_valid)]
ports: [u8; 0],
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub enum PortId {
I2c,
Uart1,
Uart2,
Usb,
Spi,
Unknown(u16),
}
impl From<u16> for PortId {
fn from(value: u16) -> Self {
match value {
0 => PortId::I2c,
1 => PortId::Uart1,
2 => PortId::Uart2,
3 => PortId::Usb,
5 => PortId::Spi,
other => PortId::Unknown(other),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct MonCommsPort {
pub port_id: PortId,
pub tx_pending: u16,
pub tx_bytes: u32,
pub tx_usage: u8,
pub tx_peak_usage: u8,
pub rx_pending: u16,
pub rx_bytes: u32,
pub rx_usage: u8,
pub rx_peak_usage: u8,
pub overrun_errs: u16,
pub msgs: [u16; 4],
pub skipped: u32,
}
#[derive(Debug, Clone)]
pub struct MonCommsPortIter<'a> {
data: &'a [u8],
offset: usize,
}
impl<'a> MonCommsPortIter<'a> {
fn new(data: &'a [u8]) -> Self {
Self { data, offset: 0 }
}
#[allow(
dead_code,
reason = "Used by ubx_packet_recv macro for validation, but may appear unused in some feature configurations"
)]
fn is_valid(payload: &[u8]) -> bool {
payload.len().is_multiple_of(40)
}
}
impl core::iter::Iterator for MonCommsPortIter<'_> {
type Item = MonCommsPort;
fn next(&mut self) -> Option<Self::Item> {
let chunk = self.data.get(self.offset..self.offset + 40)?;
let port = MonCommsPort {
port_id: PortId::from(u16::from_le_bytes(chunk[0..2].try_into().ok()?)),
tx_pending: u16::from_le_bytes(chunk[2..4].try_into().ok()?),
tx_bytes: u32::from_le_bytes(chunk[4..8].try_into().ok()?),
tx_usage: chunk[8],
tx_peak_usage: chunk[9],
rx_pending: u16::from_le_bytes(chunk[10..12].try_into().ok()?),
rx_bytes: u32::from_le_bytes(chunk[12..16].try_into().ok()?),
rx_usage: chunk[16],
rx_peak_usage: chunk[17],
overrun_errs: u16::from_le_bytes(chunk[18..20].try_into().ok()?),
msgs: [
u16::from_le_bytes(chunk[20..22].try_into().ok()?),
u16::from_le_bytes(chunk[22..24].try_into().ok()?),
u16::from_le_bytes(chunk[24..26].try_into().ok()?),
u16::from_le_bytes(chunk[26..28].try_into().ok()?),
],
skipped: u32::from_le_bytes(chunk[36..40].try_into().ok()?),
};
self.offset += 40;
Some(port)
}
}