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");