simplify error handling

This commit is contained in:
Denis-Cosmin Nutiu 2024-02-26 19:44:08 +02:00
parent 7174ddef17
commit fa4cc738e0
2 changed files with 44 additions and 56 deletions

View file

@ -1,16 +1,15 @@
#![no_std] #![no_std]
use bme680::{Bme680, Error, I2CAddress, IIRFilterSize, OversamplingSetting, PowerMode, SettingsBuilder}; use bme680::{Bme680, Bme680Error, I2CAddress, IIRFilterSize, OversamplingSetting, PowerMode, SettingsBuilder};
use core::result;
use core::time::Duration; use core::time::Duration;
use embedded_hal::delay::DelayNs; use embedded_hal::delay::DelayNs;
use linux_embedded_hal as hal; use linux_embedded_hal as hal;
use linux_embedded_hal::{Delay, I2CError}; use linux_embedded_hal::{Delay};
use log::info; use log::info;
// Please export RUST_LOG=info in order to see logs in the console. // Please export RUST_LOG=info in order to see logs in the console.
fn main() -> result::Result<(), Error<I2CError>> fn main() -> Result<(), Bme680Error>
{ {
env_logger::init(); env_logger::init();

View file

@ -77,13 +77,13 @@ use crate::hal::delay::DelayNs;
use crate::hal::i2c::I2c; use crate::hal::i2c::I2c;
use core::time::Duration; use core::time::Duration;
use core::{marker::PhantomData, result}; use core::{marker::PhantomData};
use embedded_hal as hal; use embedded_hal as hal;
use embedded_hal::i2c::ErrorType;
use log::{debug, error, info}; use log::{debug, error, info};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::Bme680Error::{I2CRead, I2CWrite};
/// BME680 General config /// BME680 General config
pub const BME680_POLL_PERIOD_MS: u8 = 10; pub const BME680_POLL_PERIOD_MS: u8 = 10;
@ -150,12 +150,12 @@ const BME680_REG_BUFFER_LENGTH: usize = 6;
/// All possible errors in this crate /// All possible errors in this crate
#[derive(Debug)] #[derive(Debug)]
pub enum Error<E> { pub enum Bme680Error {
/// ///
/// aka BME680_E_COM_FAIL /// aka BME680_E_COM_FAIL
/// ///
I2CWrite(E), I2CWrite,
I2CRead(E), I2CRead,
Delay, Delay,
/// ///
/// aka BME680_E_DEV_NOT_FOUND /// aka BME680_E_DEV_NOT_FOUND
@ -179,9 +179,6 @@ pub enum Error<E> {
BoundaryCheckFailure(&'static str), BoundaryCheckFailure(&'static str),
} }
/// Abbreviates `std::result::Result` type
pub type Result<T, E> = result::Result<T, Error<E>>;
/// ///
/// Power mode settings /// Power mode settings
/// ///
@ -192,7 +189,6 @@ pub enum PowerMode {
} }
impl PowerMode { impl PowerMode {
// TODO replace with TryFrom once stabilized
fn from(power_mode: u8) -> Self { fn from(power_mode: u8) -> Self {
match power_mode { match power_mode {
BME680_SLEEP_MODE => PowerMode::SleepMode, BME680_SLEEP_MODE => PowerMode::SleepMode,
@ -243,7 +239,7 @@ impl Default for I2CAddress {
} }
} }
/// Calibration data used during initalization /// Calibration data used during initialization
#[derive(Debug, Default, Copy)] #[derive(Debug, Default, Copy)]
#[repr(C)] #[repr(C)]
pub struct CalibrationData { pub struct CalibrationData {
@ -358,17 +354,17 @@ impl I2CUtil {
i2c: &mut I2C, i2c: &mut I2C,
dev_id: u8, dev_id: u8,
reg_addr: u8, reg_addr: u8,
) -> Result<u8, <I2C as ErrorType>::Error> ) -> Result<u8, Bme680Error>
where where
I2C: I2c I2C: I2c
{ {
let mut buf = [0; 1]; let mut buf = [0; 1];
i2c.write(dev_id, &[reg_addr]).map_err(Error::I2CWrite)?; i2c.write(dev_id, &[reg_addr]).map_err(|_e| { I2CWrite })?;
match i2c.read(dev_id, &mut buf) { match i2c.read(dev_id, &mut buf) {
Ok(()) => Ok(buf[0]), Ok(()) => Ok(buf[0]),
Err(e) => Err(Error::I2CRead(e)), Err(_e) => Err(I2CRead),
} }
} }
@ -377,15 +373,15 @@ impl I2CUtil {
dev_id: u8, dev_id: u8,
reg_addr: u8, reg_addr: u8,
buf: &mut [u8], buf: &mut [u8],
) -> Result<(), <I2C as ErrorType>::Error> ) -> Result<(), Bme680Error>
where where
I2C: I2c, I2C: I2c,
{ {
i2c.write(dev_id, &[reg_addr]).map_err(Error::I2CWrite)?; i2c.write(dev_id, &[reg_addr]).map_err(|_e| { Bme680Error::I2CWrite })?;
match i2c.read(dev_id, buf) { match i2c.read(dev_id, buf) {
Ok(()) => Ok(()), Ok(()) => Ok(()),
Err(e) => Err(Error::I2CRead(e)), Err(_e) => Err(I2CRead),
} }
} }
} }
@ -410,22 +406,22 @@ fn boundary_check<I2C>(
value_name: &'static str, value_name: &'static str,
min: u8, min: u8,
max: u8, max: u8,
) -> Result<u8, <I2C as ErrorType>::Error> ) -> Result<u8, Bme680Error<>>
where where
I2C: I2c, I2C: I2c,
{ {
let value = value.ok_or(Error::BoundaryCheckFailure(value_name))?; let value = value.ok_or(Bme680Error::BoundaryCheckFailure(value_name))?;
if value < min { if value < min {
const MIN: &str = "Boundary check failure, value exceeds maximum"; const MIN: &str = "Boundary check failure, value exceeds maximum";
error!("{}, value name: {}", MIN, value_name); error!("{}, value name: {}", MIN, value_name);
return Err(Error::BoundaryCheckFailure(MIN)); return Err(Bme680Error::BoundaryCheckFailure(MIN));
} }
if value > max { if value > max {
const MAX: &str = "Boundary check, value exceeds minimum"; const MAX: &str = "Boundary check, value exceeds minimum";
error!("{}, value name: {}", MAX, value_name); error!("{}, value name: {}", MAX, value_name);
return Err(Error::BoundaryCheckFailure(MAX)); return Err(Bme680Error::BoundaryCheckFailure(MAX));
} }
Ok(value) Ok(value)
} }
@ -439,11 +435,10 @@ impl<I2C, D> Bme680<I2C, D>
i2c: &mut I2C, i2c: &mut I2C,
delay: &mut D, delay: &mut D,
dev_id: I2CAddress, dev_id: I2CAddress,
) -> Result<(), <I2C as ErrorType>::Error> { ) -> Result<(), Bme680Error> {
let tmp_buff: [u8; 2] = [BME680_SOFT_RESET_ADDR, BME680_SOFT_RESET_CMD]; let tmp_buff: [u8; 2] = [BME680_SOFT_RESET_ADDR, BME680_SOFT_RESET_CMD];
i2c.write(dev_id.addr(), &tmp_buff) i2c.write(dev_id.addr(), &tmp_buff).map_err(|_e| { Bme680Error::I2CWrite })?;
.map_err(Error::I2CWrite)?;
delay.delay_ms(BME680_RESET_PERIOD as u32); delay.delay_ms(BME680_RESET_PERIOD as u32);
Ok(()) Ok(())
@ -453,7 +448,7 @@ impl<I2C, D> Bme680<I2C, D>
mut i2c: I2C, mut i2c: I2C,
delay: &mut D, delay: &mut D,
dev_id: I2CAddress, dev_id: I2CAddress,
) -> Result<Bme680<I2C, D>, <I2C as ErrorType>::Error> { ) -> Result<Bme680<I2C, D>, Bme680Error> {
Bme680::soft_reset(&mut i2c, delay, dev_id)?; Bme680::soft_reset(&mut i2c, delay, dev_id)?;
debug!("Reading chip id"); debug!("Reading chip id");
@ -478,16 +473,16 @@ impl<I2C, D> Bme680<I2C, D>
Ok(dev) Ok(dev)
} else { } else {
error!("Device does not match chip id {}", BME680_CHIP_ID); error!("Device does not match chip id {}", BME680_CHIP_ID);
Err(Error::DeviceNotFound) Err(Bme680Error::DeviceNotFound)
} }
} }
fn bme680_set_regs( fn bme680_set_regs(
&mut self, &mut self,
reg: &[(u8, u8)], reg: &[(u8, u8)],
) -> Result<(), <I2C as ErrorType>::Error> { ) -> Result<(), Bme680Error> {
if reg.is_empty() || reg.len() > (BME680_TMP_BUFFER_LENGTH / 2) as usize { if reg.is_empty() || reg.len() > (BME680_TMP_BUFFER_LENGTH / 2) as usize {
return Err(Error::InvalidLength); return Err(Bme680Error::InvalidLength);
} }
for (reg_addr, reg_data) in reg { for (reg_addr, reg_data) in reg {
@ -498,7 +493,7 @@ impl<I2C, D> Bme680<I2C, D>
); );
self.i2c self.i2c
.write(self.dev_id.addr(), &tmp_buff) .write(self.dev_id.addr(), &tmp_buff)
.map_err(Error::I2CWrite)?; .map_err(|_e| { I2CWrite })?;
} }
Ok(()) Ok(())
@ -509,7 +504,7 @@ impl<I2C, D> Bme680<I2C, D>
&mut self, &mut self,
delay: &mut D, delay: &mut D,
settings: Settings, settings: Settings,
) -> Result<(), <I2C as ErrorType>::Error> { ) -> Result<(), Bme680Error> {
let (sensor_settings, desired_settings) = settings; let (sensor_settings, desired_settings) = settings;
let tph_sett = sensor_settings.tph_sett; let tph_sett = sensor_settings.tph_sett;
let gas_sett = sensor_settings.gas_sett; let gas_sett = sensor_settings.gas_sett;
@ -636,7 +631,7 @@ impl<I2C, D> Bme680<I2C, D>
pub fn get_sensor_settings( pub fn get_sensor_settings(
&mut self, &mut self,
desired_settings: DesiredSensorSettings, desired_settings: DesiredSensorSettings,
) -> Result<SensorSettings, <I2C as ErrorType>::Error> { ) -> Result<SensorSettings, Bme680Error> {
let reg_addr: u8 = 0x70u8; let reg_addr: u8 = 0x70u8;
let mut data_array: [u8; BME680_REG_BUFFER_LENGTH] = [0; BME680_REG_BUFFER_LENGTH]; let mut data_array: [u8; BME680_REG_BUFFER_LENGTH] = [0; BME680_REG_BUFFER_LENGTH];
let mut sensor_settings: SensorSettings = Default::default(); let mut sensor_settings: SensorSettings = Default::default();
@ -692,7 +687,7 @@ impl<I2C, D> Bme680<I2C, D>
&mut self, &mut self,
delay: &mut D, delay: &mut D,
target_power_mode: PowerMode, target_power_mode: PowerMode,
) -> Result<(), <I2C as ErrorType>::Error> { ) -> Result<(), Bme680Error> {
let mut tmp_pow_mode: u8; let mut tmp_pow_mode: u8;
let mut current_power_mode: PowerMode; let mut current_power_mode: PowerMode;
@ -714,7 +709,6 @@ impl<I2C, D> Bme680<I2C, D>
delay delay
.delay_ms(BME680_POLL_PERIOD_MS as u32); .delay_ms(BME680_POLL_PERIOD_MS as u32);
} else { } else {
// TODO do while in Rust?
break; break;
} }
} }
@ -731,7 +725,7 @@ impl<I2C, D> Bme680<I2C, D>
/// Retrieve current sensor power mode via registers /// Retrieve current sensor power mode via registers
pub fn get_sensor_mode( pub fn get_sensor_mode(
&mut self, &mut self,
) -> Result<PowerMode, <I2C as ErrorType>::Error> { ) -> Result<PowerMode, Bme680Error> {
let regs = let regs =
I2CUtil::read_byte(&mut self.i2c, self.dev_id.addr(), BME680_CONF_T_P_MODE_ADDR)?; I2CUtil::read_byte(&mut self.i2c, self.dev_id.addr(), BME680_CONF_T_P_MODE_ADDR)?;
let mode = regs & BME680_MODE_MSK; let mode = regs & BME680_MODE_MSK;
@ -740,8 +734,6 @@ impl<I2C, D> Bme680<I2C, D>
pub fn bme680_set_profile_dur(&mut self, tph_sett: TphSett, duration: Duration) { pub fn bme680_set_profile_dur(&mut self, tph_sett: TphSett, duration: Duration) {
let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8]; let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8];
// TODO check if the following unwrap_ors do not change behaviour
// TODO replace once https://github.com/rust-lang/rust/pull/50167 has been merged
const MILLIS_PER_SEC: u64 = 1_000; const MILLIS_PER_SEC: u64 = 1_000;
const NANOS_PER_MILLI: u64 = 1_000_000; const NANOS_PER_MILLI: u64 = 1_000_000;
let millis = (duration.as_secs() as u64 * MILLIS_PER_SEC) let millis = (duration.as_secs() as u64 * MILLIS_PER_SEC)
@ -770,9 +762,8 @@ impl<I2C, D> Bme680<I2C, D>
pub fn get_profile_dur( pub fn get_profile_dur(
&self, &self,
sensor_settings: &SensorSettings, sensor_settings: &SensorSettings,
) -> Result<Duration, <I2C as ErrorType>::Error> { ) -> Result<Duration, Bme680Error> {
let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8]; let os_to_meas_cycles: [u8; 6] = [0u8, 1u8, 2u8, 4u8, 8u8, 16u8];
// TODO check if the following unwrap_ors do not change behaviour
let mut meas_cycles = os_to_meas_cycles[sensor_settings let mut meas_cycles = os_to_meas_cycles[sensor_settings
.tph_sett .tph_sett
.os_temp .os_temp
@ -806,7 +797,7 @@ impl<I2C, D> Bme680<I2C, D>
fn get_calib_data<I2CX>( fn get_calib_data<I2CX>(
i2c: &mut I2CX, i2c: &mut I2CX,
dev_id: I2CAddress, dev_id: I2CAddress,
) -> Result<CalibrationData, <I2C as ErrorType>::Error> ) -> Result<CalibrationData, Bme680Error>
where where
I2CX: I2c, I2CX: I2c,
{ {
@ -820,7 +811,7 @@ impl<I2C, D> Bme680<I2C, D>
dev_id.addr(), dev_id.addr(),
BME680_COEFF_ADDR1, BME680_COEFF_ADDR1,
&mut coeff_array[0..(BME680_COEFF_ADDR1_LEN - 1)], &mut coeff_array[0..(BME680_COEFF_ADDR1_LEN - 1)],
).unwrap(); ).map_err(|_e| { I2CRead })?;
I2CUtil::read_bytes::<I2CX>( I2CUtil::read_bytes::<I2CX>(
i2c, i2c,
@ -828,7 +819,7 @@ impl<I2C, D> Bme680<I2C, D>
BME680_COEFF_ADDR2, BME680_COEFF_ADDR2,
&mut coeff_array &mut coeff_array
[BME680_COEFF_ADDR1_LEN..(BME680_COEFF_ADDR1_LEN + BME680_COEFF_ADDR2_LEN - 1)], [BME680_COEFF_ADDR1_LEN..(BME680_COEFF_ADDR1_LEN + BME680_COEFF_ADDR2_LEN - 1)],
).unwrap(); ).map_err(|_e| { I2CRead })?;
calib.par_t1 = ((coeff_array[34usize] as i32) << 8i32 | coeff_array[33usize] as i32) as u16; calib.par_t1 = ((coeff_array[34usize] as i32) << 8i32 | coeff_array[33usize] as i32) as u16;
calib.par_t2 = ((coeff_array[2usize] as i32) << 8i32 | coeff_array[1usize] as i32) as i16; calib.par_t2 = ((coeff_array[2usize] as i32) << 8i32 | coeff_array[1usize] as i32) as i16;
@ -858,17 +849,16 @@ impl<I2C, D> Bme680<I2C, D>
calib.par_gh3 = coeff_array[38usize] as i8; calib.par_gh3 = coeff_array[38usize] as i8;
calib.res_heat_range = calib.res_heat_range =
(I2CUtil::read_byte::<I2CX>(i2c, dev_id.addr(), BME680_ADDR_RES_HEAT_RANGE_ADDR).unwrap() (I2CUtil::read_byte::<I2CX>(i2c, dev_id.addr(), BME680_ADDR_RES_HEAT_RANGE_ADDR)
& 0x30) .map_err(|_e| { I2CRead })? & 0x30) / 16;
/ 16;
calib.res_heat_val = calib.res_heat_val =
I2CUtil::read_byte::<I2CX>(i2c, dev_id.addr(), BME680_ADDR_RES_HEAT_VAL_ADDR).unwrap() as i8; I2CUtil::read_byte::<I2CX>(i2c, dev_id.addr(), BME680_ADDR_RES_HEAT_VAL_ADDR)
.map_err(|_e| { I2CRead })? as i8;
calib.range_sw_err = calib.range_sw_err =
(I2CUtil::read_byte::<I2CX>(i2c, dev_id.addr(), BME680_ADDR_RANGE_SW_ERR_ADDR).unwrap() (I2CUtil::read_byte::<I2CX>(i2c, dev_id.addr(), BME680_ADDR_RANGE_SW_ERR_ADDR)
& BME680_RSERROR_MSK) .map_err(|_e| { I2CRead })? & BME680_RSERROR_MSK) / 16;
/ 16;
Ok(calib) Ok(calib)
} }
@ -876,12 +866,11 @@ impl<I2C, D> Bme680<I2C, D>
fn set_gas_config( fn set_gas_config(
&mut self, &mut self,
gas_sett: GasSett, gas_sett: GasSett,
) -> Result<(), <I2C as ErrorType>::Error> { ) -> Result<(), Bme680Error> {
if self.power_mode != PowerMode::ForcedMode { if self.power_mode != PowerMode::ForcedMode {
return Err(Error::DefinePwrMode); return Err(Bme680Error::DefinePwrMode);
} }
// TODO check whether unwrap_or changes behaviour
let reg: [(u8, u8); 2] = [ let reg: [(u8, u8); 2] = [
( (
BME680_RES_HEAT0_ADDR, BME680_RES_HEAT0_ADDR,
@ -901,7 +890,7 @@ impl<I2C, D> Bme680<I2C, D>
self.bme680_set_regs(&reg) self.bme680_set_regs(&reg)
} }
fn get_gas_config(&mut self) -> Result<GasSett, <I2C as ErrorType>::Error> { fn get_gas_config(&mut self) -> Result<GasSett, Bme680Error> {
let heatr_temp = Some(I2CUtil::read_byte( let heatr_temp = Some(I2CUtil::read_byte(
&mut self.i2c, &mut self.i2c,
self.dev_id.addr(), self.dev_id.addr(),
@ -927,7 +916,7 @@ impl<I2C, D> Bme680<I2C, D>
pub fn get_sensor_data( pub fn get_sensor_data(
&mut self, &mut self,
delay: &mut D, delay: &mut D,
) -> Result<(FieldData, FieldDataCondition), <I2C as ErrorType>::Error> { ) -> Result<(FieldData, FieldDataCondition), Bme680Error> {
let mut buff: [u8; BME680_FIELD_LENGTH] = [0; BME680_FIELD_LENGTH]; let mut buff: [u8; BME680_FIELD_LENGTH] = [0; BME680_FIELD_LENGTH];
debug!("Buf {:?}, len: {}", buff, buff.len()); debug!("Buf {:?}, len: {}", buff, buff.len());