use embedded_hal::delay::DelayNs;
use embedded_hal::i2c::I2c;
pub use hs3003::Error as Hs3003Error;
use hs3003::{Hs3003, Measurement};
use crate::{addresses, Error, Result};
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ThermoMeasurement {
pub temperature: f32,
pub humidity: f32,
}
impl ThermoMeasurement {
pub const fn new(temperature: f32, humidity: f32) -> Self {
Self {
temperature,
humidity,
}
}
pub fn is_valid(&self) -> bool {
self.temperature > -40.0
&& self.temperature < 125.0
&& self.humidity >= 0.0
&& self.humidity <= 100.0
}
}
impl From<Measurement> for ThermoMeasurement {
fn from(m: Measurement) -> Self {
Self {
temperature: m.temperature,
humidity: m.humidity,
}
}
}
pub struct Thermo<I2C> {
sensor: Hs3003<I2C>,
}
impl<I2C, E> Thermo<I2C>
where
I2C: I2c<Error = E>,
{
pub fn new(i2c: I2C) -> Self {
Self {
sensor: Hs3003::new(i2c),
}
}
pub fn discover(i2c: &mut I2C) -> Result<u8, E> {
let addresses = [addresses::THERMO];
for &addr in &addresses {
if i2c.write(addr, &[]).is_ok() {
return Ok(addr);
}
}
i2c.write(addresses[0], &[])
.map(|_| addresses[0])
.map_err(Error::I2c)
}
pub fn address(&self) -> u8 {
addresses::THERMO
}
pub fn read<D: DelayNs>(&mut self, delay: &mut D) -> Result<ThermoMeasurement, E> {
match self.sensor.read(delay) {
Ok(measurement) => Ok(measurement.into()),
Err(hs3003::Error::I2c(e)) => Err(Error::I2c(e)),
}
}
pub fn temperature<D: DelayNs>(&mut self, delay: &mut D) -> Result<f32, E> {
Ok(self.read(delay)?.temperature)
}
pub fn humidity<D: DelayNs>(&mut self, delay: &mut D) -> Result<f32, E> {
Ok(self.read(delay)?.humidity)
}
pub fn release(self) -> Hs3003<I2C> {
self.sensor
}
pub fn inner(&mut self) -> &mut Hs3003<I2C> {
&mut self.sensor
}
}