use super::{write_preamble, Error as PktError, Identifier, MacAddress, SerializablePacket};
use serde::{Deserialize, Serialize};
use std::{
error::Error as stdError,
fmt,
io::{Cursor, Write},
};
#[derive(Debug, Clone)]
pub struct Packet {
pub random_token: u16,
pub gateway_mac: MacAddress,
pub data: Option<TxPkNack>,
}
impl Packet {
pub fn has_error(&self) -> bool {
self.data.is_some()
}
pub fn get_error(&self) -> Option<Error> {
if let Some(txpk_ack) = &self.data {
Some(txpk_ack.txpk_ack.error)
} else {
None
}
}
}
impl SerializablePacket for Packet {
fn serialize(&self, buffer: &mut [u8]) -> std::result::Result<u64, PktError> {
let mut w = Cursor::new(buffer);
write_preamble(&mut w, self.random_token)?;
w.write_all(&[Identifier::TxAck as u8])?;
w.write_all(&self.gateway_mac.bytes())?;
if let Some(data) = &self.data {
w.write_all(&serde_json::to_string(&data)?.as_bytes())?;
}
Ok(w.position())
}
}
impl From<Packet> for super::Packet {
fn from(packet: Packet) -> super::Packet {
super::Packet::Up(super::Up::TxAck(packet))
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
#[allow(non_camel_case_types)]
pub enum Error {
NONE,
TOO_LATE,
TOO_EARLY,
COLLISION_PACKET,
COLLISION_BEACON,
TX_FREQ,
TX_POWER,
GPS_UNLOCKED,
SEND_LBT,
SEND_FAIL,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::NONE => write!(f, "TxAck::Error::NONE"),
Error::TOO_LATE => write!(f, "TxAck::Error::TOO_LATE"),
Error::TOO_EARLY => write!(f, "TxAck::Error::TOO_EARLY"),
Error::COLLISION_PACKET => write!(f, "TxAck::Error::COLLISION_PACKET"),
Error::COLLISION_BEACON => write!(f, "TxAck::Error::COLLISION_BEACON"),
Error::TX_FREQ => write!(f, "TxAck::Error::TX_FREQ, Transmit frequency is rejected"),
Error::TX_POWER => write!(f, "TxAck::Error::TX_POWER"),
Error::GPS_UNLOCKED => write!(f, "TxAck::Error::GPS_UNLOCKED"),
Error::SEND_LBT => write!(f, "TxAck::Error::SEND_LBT"),
Error::SEND_FAIL => write!(f, "TxAck::Error::SEND_FAIL"),
}
}
}
impl stdError for Error {
fn source(&self) -> Option<&(dyn stdError + 'static)> {
Some(self)
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TxPkNack {
txpk_ack: SubTxPkAck,
}
impl TxPkNack {
pub fn new(error: Error) -> TxPkNack {
TxPkNack {
txpk_ack: SubTxPkAck { error },
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
struct SubTxPkAck {
pub error: Error,
}