use crate::packets::CrsfPacket;
use crate::packets::PacketType;
use crate::CrsfParsingError;
use heapless::Vec;
#[derive(Clone, Debug, PartialEq)]
pub struct Temp {
pub temp_source_id: u8,
temperatures: Vec<i16, 20>,
}
impl Temp {
pub fn new(temp_source_id: u8, temperatures: &[i16]) -> Result<Self, CrsfParsingError> {
if temperatures.len() > 20 {
return Err(CrsfParsingError::InvalidPayloadLength);
}
let mut temps = Vec::new();
temps
.extend_from_slice(temperatures)
.map_err(|_| CrsfParsingError::InvalidPayloadLength)?;
Ok(Self {
temp_source_id,
temperatures: temps,
})
}
pub fn temperatures(&self) -> &[i16] {
&self.temperatures
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for Temp {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(
fmt,
"Temp {{ temp_source_id: {}, temperatures: {} }}",
self.temp_source_id,
self.temperatures(),
)
}
}
impl CrsfPacket for Temp {
const PACKET_TYPE: PacketType = PacketType::Temp;
const MIN_PAYLOAD_SIZE: usize = 3;
fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, CrsfParsingError> {
let required_len = 1 + self.temperatures.len() * 2;
if buffer.len() < required_len {
return Err(CrsfParsingError::BufferOverflow);
}
buffer[0] = self.temp_source_id;
let mut i = 1;
for &temp in self.temperatures() {
let bytes = temp.to_be_bytes();
buffer[i..i + 2].copy_from_slice(&bytes);
i += 2;
}
Ok(i)
}
fn from_bytes(data: &[u8]) -> Result<Self, CrsfParsingError> {
if data.len() < Self::MIN_PAYLOAD_SIZE {
return Err(CrsfParsingError::InvalidPayloadLength);
}
let temp_source_id = data[0];
let temperatures: Vec<i16, 20> = data[1..]
.chunks_exact(2)
.map(|chunk| {
let bytes = [chunk[0], chunk[1]];
i16::from_be_bytes(bytes)
})
.collect();
Ok(Self {
temp_source_id,
temperatures,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_temp_to_bytes() {
let temperatures = [250, -50];
let temp = Temp::new(1, &temperatures).unwrap();
let mut buffer = [0u8; 60];
let len = temp.to_bytes(&mut buffer).unwrap();
let expected_bytes: [u8; 5] = [
1, 0x00, 0xfa, 0xff, 0xce, ];
assert_eq!(len, 5);
assert_eq!(&buffer[..len], &expected_bytes);
}
#[test]
fn test_temp_from_bytes() {
let data: [u8; 5] = [
1, 0x00, 0xfa, 0xff, 0xce, ];
let temp = Temp::from_bytes(&data).unwrap();
let expected_temperatures = [250, -50];
assert_eq!(temp.temp_source_id, 1);
assert_eq!(temp.temperatures(), &expected_temperatures);
}
#[test]
fn test_temp_round_trip() {
let temperatures = [1234, -5678];
let temp = Temp::new(2, &temperatures).unwrap();
let mut buffer = [0u8; 60];
let len = temp.to_bytes(&mut buffer).unwrap();
let round_trip_temp = Temp::from_bytes(&buffer[..len]).unwrap();
assert_eq!(temp, round_trip_temp);
}
#[test]
fn test_edge_cases() {
let temperatures = [0, 32767, -32768];
let temp = Temp::new(3, &temperatures).unwrap();
let mut buffer = [0u8; 60];
let len = temp.to_bytes(&mut buffer).unwrap();
let round_trip_temp = Temp::from_bytes(&buffer[..len]).unwrap();
assert_eq!(temp, round_trip_temp);
}
}