use embedded_hal::delay::DelayNs;
use hal::{Delay, I2CError, I2cdev};
use linux_embedded_hal as hal;
use log::{debug, error, info};
use clap::Parser;
use humantime::Duration as HumanDuration;
use simplelog::{LevelFilter, TermLogger};
use scd4x::{Error, Scd4x};
#[derive(Parser)]
#[command(name = "scd4x-util")]
pub struct Options {
#[arg(
short = 'd',
long = "i2c",
default_value = "/dev/i2c-1",
env = "SCD4x_I2C"
)]
i2c: String,
#[arg(long = "poll-delay", default_value = "100ms")]
pub poll_delay: HumanDuration,
#[arg(long = "allowed-errors", default_value = "3")]
pub allowed_errors: usize,
#[arg(long = "log-level", default_value = "info")]
level: LevelFilter,
}
fn main() -> Result<(), Error<I2CError>> {
let opts = Options::parse();
TermLogger::init(
opts.level,
simplelog::Config::default(),
simplelog::TerminalMode::Mixed,
simplelog::ColorChoice::Auto,
)
.unwrap();
debug!("Connecting to I2C device");
let i2c = match I2cdev::new(&opts.i2c) {
Ok(v) => v,
Err(e) => {
error!("Error opening I2C device '{}': {:?}", &opts.i2c, e);
std::process::exit(-1);
}
};
debug!("Connecting to sensor");
let mut sensor = Scd4x::new(i2c, Delay);
debug!("Initalising sensor");
#[cfg(feature = "scd41")]
sensor.wake_up();
sensor.stop_periodic_measurement()?;
sensor.reinit()?;
let serial = sensor.serial_number()?;
info!("Serial: {serial:#04x}");
debug!("Starting periodic measurement");
sensor.start_periodic_measurement()?;
debug!("Waiting for first measurement... (5 sec)");
loop {
hal::Delay.delay_ms(5000u32);
debug!("Waiting for data ready");
loop {
match sensor.data_ready_status() {
Ok(true) => break,
Ok(false) => std::thread::sleep(*opts.poll_delay),
Err(e) => {
error!("Failed to poll for data ready: {e:?}");
std::process::exit(-2);
}
}
}
debug!("Reading sensor data");
let data = match sensor.measurement() {
Ok(v) => v,
Err(e) => {
error!("Failed to read measurement: {e:?}");
std::process::exit(-3);
}
};
println!(
"CO2: {0}, Temperature: {1:#.2} °C, Humidity: {2:#.2} RH",
data.co2, data.temperature, data.humidity
);
}
}