use crate::decode::time::decode_time;
use crate::decode::{DecodeError, check_length};
use std::convert::TryInto;
use std::fmt::{self, Display, Formatter};
use std::ops::Range;
use std::time::SystemTime;
pub(crate) fn decode_range(value: &[u8]) -> Result<Range<u32>, DecodeError> {
check_length(value.len(), 8)?;
let last_index = u32::from_le_bytes(value[0..4].try_into().unwrap());
let count = u32::from_le_bytes(value[4..8].try_into().unwrap());
let end = last_index + 1;
let start = end - count;
Ok(start..end)
}
#[derive(Clone, Debug, PartialEq)]
pub struct HistoryRecord {
pub index: u32,
pub time: SystemTime,
pub temperature_min: f32,
pub temperature_max: f32,
pub humidity_min: u8,
pub humidity_max: u8,
}
impl HistoryRecord {
pub(crate) fn decode(value: &[u8]) -> Result<HistoryRecord, DecodeError> {
check_length(value.len(), 14)?;
let index = u32::from_le_bytes(value[0..4].try_into().unwrap());
let time = decode_time(&value[4..8])?;
let temperature_max = decode_history_temperature(value[8..10].try_into().unwrap());
let temperature_min = decode_history_temperature(value[11..13].try_into().unwrap());
let humidity_max = value[10];
let humidity_min = value[13];
Ok(HistoryRecord {
index,
time,
temperature_min,
temperature_max,
humidity_min,
humidity_max,
})
}
}
impl Display for HistoryRecord {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(
f,
"{}/{:?} Temperature: {:.2}–{:.2}ºC Humidity: {:?}–{:?}%",
self.index,
self.time,
self.temperature_min,
self.temperature_max,
self.humidity_min,
self.humidity_max
)
}
}
fn decode_history_temperature(bytes: [u8; 2]) -> f32 {
i16::from_le_bytes(bytes) as f32 / 10.0
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn decode_too_short() {
assert_eq!(
HistoryRecord::decode(&[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
]),
Err(DecodeError::WrongLength {
length: 13,
expected_length: 14
})
);
}
#[test]
fn decode_too_long() {
assert_eq!(
HistoryRecord::decode(&[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f,
]),
Err(DecodeError::WrongLength {
length: 15,
expected_length: 14
})
);
}
#[test]
fn decode_valid() {
assert_eq!(
HistoryRecord::decode(&[
0x49, 0x01, 0x00, 0x00, 0x40, 0x0c, 0x55, 0x5e, 0xdd, 0x00, 0x43, 0xd5, 0x00, 0x3c
])
.unwrap(),
HistoryRecord {
index: 329,
time: SystemTime::UNIX_EPOCH + Duration::from_secs(1582632000),
temperature_min: 21.3,
temperature_max: 22.1,
humidity_min: 60,
humidity_max: 67,
}
);
}
}