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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! # BME280 Environmental Sensor Driver
//!
//! This module provides an interface to the BME280 environmental sensor. It
//! allows for reading temperature, humidity, and pressure using the I2C
//! communication protocol.

use bme280::i2c::BME280 as ExternalBME280_i2c;
// use embedded_hal_bus::spi::ExclusiveDevice;
// Import the necessary modules from `esp-hal`
use esp_hal::{delay::Delay, i2c::I2C};

use super::{
    HumiditySensor,
    I2cPeriph,
    PeripheralError,
    PressureSensor,
    TemperatureSensor,
    UnifiedData,
};

/// A sensor instance for the BME280 that provides access to temperature,
/// humidity, and pressure readings.
pub struct Bme280Sensor {
    /// The internal BME280 driver from the `bme280` crate used over I2C.
    pub inner: ExternalBME280_i2c<I2C<'static, esp_hal::peripherals::I2C0>>,
    /// A delay provider for timing-dependent operations.
    pub delay: Delay,
}

impl I2cPeriph for Bme280Sensor {
    type Returnable = Self;
    /// Creates a new instance of the BME280 sensor using the provided I2C bus.
    ///
    /// # Arguments
    /// * `bus` - The I2C bus to use for communication with the sensor.
    /// * `delay` - A delay provider for timing-dependent operations.
    ///
    /// # Returns
    /// Returns an `Ok(Bme280Sensor)` if the sensor is successfully
    /// initialized, or `Err(PeripheralError::InitializationFailed)` if the
    /// sensor cannot be initialized.
    fn create_on_i2c(
        bus: I2C<'static, esp_hal::peripherals::I2C0>,
        mut delay: Delay,
    ) -> Result<Self::Returnable, PeripheralError> {
        let mut sensor = ExternalBME280_i2c::new_primary(bus);
        match sensor.init(&mut delay) {
            Ok(_) => {}
            Err(_) => return Err(PeripheralError::InitializationFailed),
        }
        Ok(Bme280Sensor {
            inner: sensor,
            delay: delay,
        })
    }
}

impl TemperatureSensor for Bme280Sensor {
    /// Reads the current temperature from the BME280 sensor.
    ///
    /// # Returns
    /// Returns an `Ok(f32)` representing the temperature in degrees Celsius if
    /// the read is successful, or `Err(PeripheralError::ReadError)` if the
    /// temperature cannot be read.
    fn get_temperature(&mut self) -> Result<f32, PeripheralError> {
        match self.inner.measure(&mut self.delay) {
            Ok(measurement) => Ok(measurement.temperature),
            Err(_) => Err(PeripheralError::ReadError),
        }
    }
}

impl HumiditySensor for Bme280Sensor {
    /// Reads the current relative humidity from the BME280 sensor.
    ///
    /// # Returns
    /// Returns an `Ok(f32)` representing the relative humidity in percentage if
    /// the read is successful, or `Err(PeripheralError::ReadError)` if the
    /// humidity cannot be read.
    fn get_humidity(&mut self) -> Result<f32, PeripheralError> {
        match self.inner.measure(&mut self.delay) {
            Ok(measurement) => Ok(measurement.humidity),
            Err(_) => Err(PeripheralError::ReadError),
        }
    }
}

impl PressureSensor for Bme280Sensor {
    /// Reads the current atmospheric pressure from the BME280 sensor.
    ///
    /// # Returns
    /// Returns an `Ok(f32)` representing the pressure in hPa (hectopascals) if
    /// the read is successful, or `Err(PeripheralError::ReadError)` if the
    /// pressure cannot be read.
    fn get_pressure(&mut self) -> Result<f32, PeripheralError> {
        match self.inner.measure(&mut self.delay) {
            Ok(measurement) => Ok(measurement.pressure),
            Err(_) => Err(PeripheralError::ReadError),
        }
    }
}

impl UnifiedData for Bme280Sensor {
    type Output = (f32, f32, f32);
    /// Reads the current relative humidity, temperature and pressure from the
    /// BME280 sensor.
    ///
    /// # Returns
    /// Returns an `Ok((f32, f32, f32))` representing the relative
    /// humidity(percentage), temperature(celsious) and pressure(hPa) if the
    /// read is successful, or `Err(PeripheralError::ReadError)` if the data
    /// from sensor cannot be read.
    fn read(&mut self, _delay: Delay) -> Result<Self::Output, PeripheralError> {
        match self.inner.measure(&mut self.delay) {
            Ok(measurement) => Ok((
                measurement.temperature,
                measurement.humidity,
                measurement.pressure,
            )),
            Err(_) => Err(PeripheralError::ReadError),
        }
    }
}

// TO BE IMPROVED SECTION:
// 1) SPI implementation is blocked due to embedded_hal versions incompatibility
// Skeleton is ready and code should be buldable, but the `OutputPin` type
// incompatibility makes it impossible to implement now and save the whole other
// library pub struct Bme280SensorSpi<CS> {
//     /// The internal BME280 driver from the `bme280` crate used over I2C.
//     pub inner: ExternalBME280_spi<
//         ExclusiveDevice<Spi<'static, esp_hal::peripherals::SPI2,
// FullDuplexMode>, CS, Delay>,     >,
//     /// A delay provider for timing-dependent operations.
//     pub delay: Delay,
// }

// impl<CS: OutputPin<Error = core::convert::Infallible>> Bme280SensorSpi<CS> {
//     pub fn create_on_spi(
//         bus: Spi<'static, esp_hal::peripherals::SPI2, FullDuplexMode>,
//         cs: CS,
//         mut delay: Delay,
//     ) -> Self {
//         let formatted_bus = ExclusiveDevice::new(bus, cs, delay);
//         let mut sensor = ExternalBME280_spi::new(formatted_bus).unwrap();
//         match sensor.init(&mut delay) {
//             Ok(_) => {}
//             Err(_) => return Err(PeripheralError::InitializationFailed),
//         }
//         Ok(Bme280SensorSpi {
//             inner: sensor,
//             delay: delay,
//         })
//     }
// }