islabtech_upw_sensor_v1/measurements/mod.rs
1use chrono;
2use serde::{self, Deserialize, Serialize};
3use std::fmt::{Debug, Display};
4
5mod serde_impl;
6
7/// conductivity in µS/cm
8///
9/// Construct instances with the [`From<f64>`] trait passing the conductivity in µS/cm:
10///
11/// ### Example
12/// ```rust
13/// use islabtech_upw_sensor_v1::measurements::Conductivity;
14/// let conductivity: Conductivity = 1.23.into();
15/// assert_eq!(conductivity, Conductivity::from_us_per_cm(1.23));
16/// println!("conductivity: {} µS/cm", conductivity.as_us_per_cm());
17/// ```
18#[derive(Copy, Clone, Serialize, Deserialize, PartialEq, PartialOrd)]
19pub struct Conductivity(f64);
20
21impl Conductivity {
22 pub fn from_us_per_cm(value: f64) -> Conductivity {
23 value.into()
24 }
25 pub fn as_us_per_cm(&self) -> f64 {
26 return self.0;
27 }
28}
29impl From<f64> for Conductivity {
30 fn from(value: f64) -> Self {
31 Conductivity(value)
32 }
33}
34impl Display for Conductivity {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 write!(f, "{} µS/cm", self.0)
37 }
38}
39impl Debug for Conductivity {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 write!(f, "{}", self)
42 }
43}
44
45/// temperature in °C
46///
47/// Construct instances with the [`From<f64>`] trait passing the temperature in °C:
48///
49/// ### Example
50/// ```rust
51/// use islabtech_upw_sensor_v1::measurements::Temperature;
52/// let temperature: Temperature = 12.34.into();
53/// assert_eq!(temperature, Temperature::from_celsius(12.34));
54/// ```
55#[derive(Copy, Clone, Serialize, Deserialize, PartialEq, PartialOrd)]
56pub struct Temperature(f64);
57
58impl Temperature {
59 pub fn from_celsius(value: f64) -> Temperature {
60 value.into()
61 }
62 pub fn as_celsius(&self) -> f64 {
63 return self.0;
64 }
65 pub fn as_kelvin(&self) -> f64 {
66 return self.0 + 273.15;
67 }
68}
69impl From<f64> for Temperature {
70 fn from(value: f64) -> Self {
71 Temperature(value)
72 }
73}
74impl Display for Temperature {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 write!(f, "{} °C", self.0)
77 }
78}
79impl Debug for Temperature {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 write!(f, "{}", self)
82 }
83}
84
85/// measurement point
86///
87/// Both conductivity and temperature can be a successful or failed measurement, hence the `Option` types.
88/// There is a success-guaranteed counterpart of this type [`SuccessfulMeasurement`].
89///
90/// call [`crate::Device::latest_measurement()`] to fetch the latest measurement
91///
92/// ### Example
93/// ```rust
94/// use islabtech_upw_sensor_v1::measurements::Measurement;
95/// Measurement {
96/// timestamp: chrono::DateTime::from_timestamp(1716821872, 123456).unwrap(),
97/// conductivity: Some(1.23.into()), // µS/cm
98/// temperature: None, // `None` because temperature out of range or broken temperature sensor
99/// };
100/// ```
101#[derive(Debug, Clone, PartialEq, PartialOrd)]
102pub struct Measurement {
103 pub timestamp: chrono::DateTime<chrono::Utc>,
104 pub conductivity: Option<Conductivity>,
105 pub temperature: Option<Temperature>,
106}
107
108/// successful measurement point
109///
110/// call [`crate::Device::latest_successful_measurement()`] to fetch the latest successful measurement
111///
112/// ### Example
113/// ```rust
114/// use islabtech_upw_sensor_v1::measurements::SuccessfulMeasurement;
115/// SuccessfulMeasurement {
116/// timestamp: chrono::DateTime::from_timestamp(1716821872, 123456).unwrap(),
117/// conductivity: 1.23.into(), // µS/cm
118/// temperature: 12.34.into(), // °C
119/// };
120/// ```
121#[derive(Debug, Clone, PartialEq, PartialOrd)]
122pub struct SuccessfulMeasurement {
123 pub timestamp: chrono::DateTime<chrono::Utc>,
124 pub conductivity: Conductivity,
125 pub temperature: Temperature,
126}