1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Temperature(i32);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Humidity(i32);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Measurement {
pub temperature: Temperature,
pub humidity: Humidity,
}
impl Temperature {
pub(crate) 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(crate) 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);
}
}