embedded_devices/
sensor.rs

1use paste::paste;
2use uom::si::f64::{
3    ElectricCharge, ElectricCurrent, ElectricPotential, Energy, Frequency, MassConcentration, Power, Pressure, Ratio,
4    ThermodynamicTemperature, Velocity,
5};
6
7/// This trait is implemented for any sensor specific measurement struct.
8pub trait Measurement: core::fmt::Debug {}
9
10/// A sensor supporting one-shot measurements.
11///
12/// If the hardware device itself doesn't support one-shot measurements but they can be
13/// meaningfully emulated by starting and stopping continuous measurements without drawbacks, it
14/// may also implement this trait. If the sensor requires a certain amount of time in continuous
15/// measurement mode to yield meaningful results, this trait should not be implemented.
16#[maybe_async_cfg::maybe(sync(feature = "sync"), async(feature = "async"))]
17#[allow(async_fn_in_trait)]
18pub trait OneshotSensor {
19    /// The error type which may occur on associated functions
20    type Error: core::fmt::Debug;
21    /// A type holding the measurements obtained by this sensor
22    type Measurement: self::Measurement;
23
24    /// Performs a one-shot measurement.
25    ///
26    /// If the device supports several measurement modes, this function attempts to switch to
27    /// oneshot mode on best effort. The mode in which the device is left after measurement is not
28    /// specified further, but if possible, a sleep mode or equivalent mode should be preferred.
29    async fn measure(&mut self) -> Result<Self::Measurement, Self::Error>;
30}
31
32/// A sensor supporting continuous measurement mode.
33///
34/// If the hardware device itself doesn't support continuous measurements but they can be
35/// meaningfully emulated by using a one-shot mode without drawbacks, it may also implement this
36/// trait.
37#[maybe_async_cfg::maybe(sync(feature = "sync"), async(feature = "async"))]
38#[allow(async_fn_in_trait)]
39pub trait ContinuousSensor {
40    /// The error type which may occur on associated functions
41    type Error: core::fmt::Debug;
42    /// A type holding the measurements obtained by this sensor
43    type Measurement: self::Measurement;
44
45    /// Starts continuous measurement.
46    ///
47    /// If the device supports several measurement modes, this function attempts to switch to
48    /// continuous mode on best effort.
49    async fn start_measuring(&mut self) -> Result<(), Self::Error>;
50
51    /// Stops continuous measurement.
52    ///
53    /// The mode in which the device is left afterwards is not specified further, but if possible,
54    /// a sleep mode or equivalent mode should be preferred.
55    async fn stop_measuring(&mut self) -> Result<(), Self::Error>;
56
57    /// Expected amount of time between measurements in microseconds. This may need to communicate
58    /// with the device to determine the interval based on device settings.
59    async fn measurement_interval_us(&mut self) -> Result<u32, Self::Error>;
60
61    /// Returns the most recent measurement. If the sensor cannot provide the measurement
62    /// current/last measurement at any time (e.g. the register is cleared after it is read), this
63    /// should return `None` when there is no new data available.
64    async fn current_measurement(&mut self) -> Result<Option<Self::Measurement>, Self::Error>;
65
66    /// Check if new measurements are available. If the device does not support checking for
67    /// availability of new measurements (e.g. via some form of data ready indicator), this method
68    /// should always return `true`.
69    async fn is_measurement_ready(&mut self) -> Result<bool, Self::Error>;
70
71    /// Wait indefinitely until new measurements are available and return them. If the device does
72    /// not support checking for new measurements (e.g. via some form of data ready indicator),
73    /// this method should wait for [`Self::measurement_interval_us`] and read the measurement
74    /// opportunistically.
75    async fn next_measurement(&mut self) -> Result<Self::Measurement, Self::Error>;
76}
77
78/// Macro to define a sensor trait and its corresponding measurement trait
79///
80/// # Arguments
81/// - `$sensor_name` - The name of the sensor (e.g., Temperature, Pressure)
82/// - `$measurement_type` - The Rust type for the measurement (e.g., ThermodynamicTemperature, Pressure)
83/// - `$measurement_desc` - A lowercase description of what is measured (e.g., "temperature", "pressure")
84macro_rules! define_sensor_measurement {
85    (
86        $sensor_name:ident,
87        $measurement_type:ty,
88        $measurement_desc:expr
89    ) => {
90        paste! {
91            #[doc = concat!("A sensor which measures ", $measurement_desc)]
92            pub trait [<$sensor_name Sensor>] {}
93
94            #[doc = concat!("A measurement result which may include a ", $measurement_desc, " measurement")]
95            pub trait [<$sensor_name Measurement>]: Measurement {
96                fn [<$sensor_name:snake>](&self) -> Option<$measurement_type>;
97            }
98        }
99    };
100}
101
102define_sensor_measurement!(Charge, ElectricCharge, "charge");
103define_sensor_measurement!(Co2Concentration, Ratio, "CO2 concentration");
104define_sensor_measurement!(Current, ElectricCurrent, "current");
105define_sensor_measurement!(Energy, Energy, "energy");
106define_sensor_measurement!(HchoConcentration, Ratio, "HCHO concentration");
107// define_sensor_measurement!(Illuminance, Illuminance, "illuminance");
108define_sensor_measurement!(NoxIndex, Ratio, "NOx index");
109define_sensor_measurement!(Pm10Concentration, MassConcentration, "PM10 concentration");
110define_sensor_measurement!(Pm1Concentration, MassConcentration, "PM1 concentration");
111define_sensor_measurement!(Pm2_5Concentration, MassConcentration, "PM2.5 concentration");
112define_sensor_measurement!(Pm4Concentration, MassConcentration, "PM4 concentration");
113define_sensor_measurement!(Power, Power, "power");
114define_sensor_measurement!(Pressure, Pressure, "pressure");
115define_sensor_measurement!(RelativeHumidity, Ratio, "relative humidity");
116define_sensor_measurement!(SoilMoisture, Ratio, "soil moisture");
117define_sensor_measurement!(Temperature, ThermodynamicTemperature, "temperature");
118define_sensor_measurement!(VocIndex, Ratio, "VOC index");
119define_sensor_measurement!(Voltage, ElectricPotential, "voltage");
120define_sensor_measurement!(WindSpeed, Velocity, "wind speed");
121define_sensor_measurement!(Frequency, Frequency, "frequency");