#[cfg(feature = "std")]
use std::fmt::Display;
use deku::prelude::*;
use crate::{network::Addressee, physical::Channel, types::VarInt};
#[cfg(feature = "_wizzilab")]
mod interface_final;
#[cfg(feature = "_wizzilab")]
pub use interface_final::{InterfaceFinalStatus, InterfaceFinalStatusCode, InterfaceTxStatus};
#[derive(DekuRead, DekuWrite, Debug, Clone, Copy, PartialEq)]
#[deku(bits = 8, type = "u8")]
pub enum InterfaceType {
#[deku(id = "0x00")]
Host,
#[deku(id = "0x01")]
Serial,
#[deku(id = "0x02")]
LoRaWanABP,
#[deku(id = "0x03")]
LoRaWanOTAA,
#[deku(id = "0xD7")]
Dash7,
#[deku(id_pat = "_")]
Unknown,
}
impl TryFrom<u8> for InterfaceType {
type Error = DekuError;
fn try_from(value: u8) -> Result<Self, Self::Error> {
use bitvec::view::BitView;
Ok(Self::read(value.view_bits(), ())?.1)
}
}
impl Into<u8> for InterfaceType {
fn into(self) -> u8 {
self.deku_id().unwrap()
}
}
#[derive(DekuRead, DekuWrite, Default, Debug, Clone, PartialEq)]
#[deku(bits = 3, type = "u8")]
pub enum ResponseMode {
#[default]
#[deku(id = "0")]
No,
#[deku(id = "1")]
All,
#[deku(id = "2")]
Any,
#[deku(id = "4")]
NoRepeat,
#[deku(id = "5")]
OnError,
#[deku(id = "6")]
Preferred,
}
#[derive(DekuRead, DekuWrite, Default, Debug, Clone, PartialEq)]
#[deku(bits = 3, type = "u8")]
pub enum RetryMode {
#[default]
#[deku(id = "0")]
No,
#[deku(id = "1")]
OneshotRetry,
#[deku(id = "2")]
FifoFast,
#[deku(id = "3")]
FifoSlow,
#[deku(id = "4")]
SingleFast,
#[deku(id = "5")]
SingleSlow,
#[deku(id = "6")]
OneshotSticky,
#[deku(id = "7")]
Rfu,
}
#[derive(DekuRead, DekuWrite, Default, Debug, Clone, PartialEq)]
pub struct QoS {
#[deku(bits = 1)]
pub stop_on_error: bool,
#[deku(bits = 1)]
pub record: bool,
pub retry_mode: RetryMode,
pub response_mode: ResponseMode,
}
#[derive(DekuRead, DekuWrite, Debug, Clone, PartialEq)]
#[deku(ctx = "interface_id: InterfaceType, length: u32", id = "interface_id")]
pub enum InterfaceStatus {
#[deku(id = "InterfaceType::Host")]
Host,
#[deku(id = "InterfaceType::Serial")]
Serial,
#[deku(id = "InterfaceType::Dash7")]
Dash7(Dash7InterfaceStatus),
#[deku(id_pat = "_")]
Other(#[deku(count = "length")] Vec<u8>),
}
#[cfg(feature = "std")]
impl Display for InterfaceStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Dash7(status) => status.fmt(f),
Self::Other(status) => f.write_str(&format!("OtherInterfaceStatus{{ {:?} }}", status)),
_ => f.write_str(&format!(
"{}InterfaceStatus{{}}",
self.deku_id()
.map(|i| format!("{:?}", i))
.unwrap_or("Unknown".to_string())
)),
}
}
}
#[derive(DekuRead, DekuWrite, Debug, Clone, PartialEq)]
pub struct Dash7InterfaceStatus {
pub channel: Channel,
pub rx_level: u8,
pub link_budget: u8,
pub target_rx_level: u8,
#[deku(bits = 1)]
pub nls: bool,
#[deku(bits = 1)]
pub missed: bool,
#[deku(bits = 1)]
pub retry: bool,
#[deku(bits = 1)]
pub unicast: bool,
#[deku(pad_bits_before = "4")]
pub fifo_token: u8,
pub sequence_number: u8,
pub response_timeout: VarInt,
pub addressee: Addressee,
}
#[cfg(feature = "std")]
impl Display for Dash7InterfaceStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("Dash7InterfaceStatus { ")?;
f.write_str(&format!("channel: {:?}, ", self.channel))?;
f.write_str(&format!("rx_level: {:?}, ", self.rx_level))?;
f.write_str(&format!("link_budget: {:?}, ", self.link_budget))?;
f.write_str(&format!("target_rx_level: {:?}, ", self.target_rx_level))?;
f.write_str(&format!("nls: {:?}, ", self.nls))?;
f.write_str(&format!("missed: {:?}, ", self.missed))?;
f.write_str(&format!("retry: {:?}, ", self.retry))?;
f.write_str(&format!("unicast: {:?}, ", self.unicast))?;
f.write_str(&format!("fifo_token: {:?}, ", self.fifo_token))?;
f.write_str(&format!("sequence_number: {:?}, ", self.sequence_number))?;
f.write_str(&format!(
"response_timeout: {:?}, ",
Into::<u32>::into(self.response_timeout)
))?;
f.write_str(&format!("addressee: {:?}, ", self.addressee))?;
f.write_str(" }")?;
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::test_tools::test_item;
use hex_literal::hex;
#[test]
fn test_qos() {
test_item(QoS::default(), &[0]);
test_item(
QoS {
retry_mode: RetryMode::No,
response_mode: ResponseMode::Any,
record: true,
stop_on_error: true,
},
&[0b11000010],
);
test_item(
QoS {
retry_mode: RetryMode::No,
response_mode: ResponseMode::NoRepeat,
record: false,
stop_on_error: false,
},
&hex!("04"),
)
}
}