#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Temperature(i32);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Humidity(i32);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Measurement {
pub temperature: Temperature,
pub humidity: Humidity,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct RawMeasurement {
pub temperature: u16,
pub humidity: u16,
}
impl From<RawMeasurement> for Measurement {
fn from(other: RawMeasurement) -> Self {
Self {
temperature: Temperature::from_raw(other.temperature),
humidity: Humidity::from_raw(other.humidity),
}
}
}
impl Temperature {
pub fn from_raw(raw: u16) -> Self {
Self(convert_temperature(raw))
}
pub fn as_millidegrees_celsius(&self) -> i32 {
self.0
}
pub fn as_degrees_celsius(&self) -> f32 {
self.0 as f32 / 1000.0
}
}
impl Humidity {
pub fn from_raw(raw: u16) -> Self {
Self(convert_humidity(raw))
}
pub fn as_millipercent(&self) -> i32 {
self.0
}
pub fn as_percent(&self) -> f32 {
self.0 as f32 / 1000.0
}
}
#[inline]
fn convert_temperature(temp_raw: u16) -> i32 {
(((temp_raw as u32) * 21875) >> 13) as i32 - 45000
}
#[inline]
fn convert_humidity(humi_raw: u16) -> i32 {
(((humi_raw as u32) * 12500) >> 13) as i32
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_convert_temperature() {
let test_data = [
(0x0000, -45000),
(((0b0110_0100 as u16) << 8) | 0b1000_1011, 23730),
];
for td in &test_data {
assert_eq!(convert_temperature(td.0), td.1);
}
}
#[test]
fn test_convert_humidity() {
let test_data = [
(0x0000, 0),
(((0b1010_0001 as u16) << 8) | 0b0011_0011, 62968),
];
for td in &test_data {
assert_eq!(convert_humidity(td.0), td.1);
}
}
#[test]
fn measurement_conversion() {
let temperature = convert_temperature(((0b0110_0100 as u16) << 8) | 0b1000_1011);
let humidity = convert_humidity(((0b1010_0001 as u16) << 8) | 0b0011_0011);
assert_eq!(temperature, 23730);
assert_eq!(humidity, 62968);
}
#[test]
fn temperature() {
let temp = Temperature(24123);
assert_eq!(temp.as_millidegrees_celsius(), 24123);
assert_eq!(temp.as_degrees_celsius(), 24.123);
}
#[test]
fn humidity() {
let humi = Humidity(65432);
assert_eq!(humi.as_millipercent(), 65432);
assert_eq!(humi.as_percent(), 65.432);
}
#[test]
fn measurement_from_into() {
let raw = RawMeasurement {
temperature: ((0b0110_0100 as u16) << 8) | 0b1000_1011,
humidity: ((0b1010_0001 as u16) << 8) | 0b0011_0011,
};
let measurement1 = Measurement::from(raw);
assert_eq!(measurement1.temperature.0, 23730);
assert_eq!(measurement1.humidity.0, 62968);
let measurement2: Measurement = raw.into();
assert_eq!(measurement2.temperature.0, 23730);
assert_eq!(measurement2.humidity.0, 62968);
assert_eq!(measurement1, measurement2);
}
}