1#![no_std]
2
3use heapless::String;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum ReadingStatus {
7 Ok,
8 SensorReadFailed,
9 NotConnected,
10 Stale,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq)]
14pub struct EnvironmentReading {
15 pub temperature_c: Option<f32>,
16 pub humidity_pct: Option<f32>,
17 pub heat_index_c: Option<f32>,
18 pub status: ReadingStatus,
19}
20
21impl EnvironmentReading {
22 pub const fn failed() -> Self {
23 Self {
24 temperature_c: None,
25 humidity_pct: None,
26 heat_index_c: None,
27 status: ReadingStatus::SensorReadFailed,
28 }
29 }
30 pub const fn new(temperature_c: f32, humidity_pct: f32, heat_index_c: Option<f32>) -> Self {
31 Self {
32 temperature_c: Some(temperature_c),
33 humidity_pct: Some(humidity_pct),
34 heat_index_c,
35 status: ReadingStatus::Ok,
36 }
37 }
38}
39
40#[derive(Debug, Clone, PartialEq)]
41pub struct DeviceStatus<const N: usize> {
42 pub device_id: String<N>,
43 pub uptime_ms: u64,
44 pub wifi_rssi: Option<i32>,
45 pub ip: String<32>,
46}
47
48pub trait Sensor {
49 type Reading;
50 type Error;
51 fn read(&mut self) -> Result<Self::Reading, Self::Error>;
52}
53
54pub trait TextDisplay {
55 type Error;
56 fn clear(&mut self) -> Result<(), Self::Error>;
57 fn write_line(&mut self, row: u8, text: &str) -> Result<(), Self::Error>;
58}
59
60pub trait StatusDisplay: TextDisplay {
61 fn show_environment(&mut self, reading: &EnvironmentReading) -> Result<(), Self::Error> {
62 self.clear()?;
63 match reading.status {
64 ReadingStatus::Ok => {
65 self.write_line(0, "sensor ok")?;
66 self.write_line(1, "temp/humidity valid")
68 }
69 _ => self.write_line(0, "sensor failed"),
70 }
71 }
72}
73
74impl<T: TextDisplay> StatusDisplay for T {}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 #[test]
80 fn environment_reading_ok() {
81 let r = EnvironmentReading::new(22.0, 44.0, Some(21.8));
82 assert_eq!(r.status, ReadingStatus::Ok);
83 assert_eq!(r.temperature_c, Some(22.0));
84 }
85}