Compare commits

...

3 Commits

Author SHA1 Message Date
Nareshkumar Rao 34d9ff6811 wip 7 months ago
Nareshkumar Rao 69c873d9f5 wip 7 months ago
Nareshkumar Rao efbe1a54fd wip 7 months ago
  1. 24
      growpi.toml
  2. 16
      src/actuators.rs
  3. 32
      src/cli_mode.rs
  4. 38
      src/config.rs
  5. 6
      src/io.rs

24
growpi.toml

@ -0,0 +1,24 @@
[board_settings]
logic_level = 3.299999952316284
[relay_settings]
light_pin = 0
fan_pin = 1
water_pump_pin = 2
relay_gpio_pins = [17, 27, 22, -1]
[soil_moisture_settings]
pin = 1
voltage_100 = 1.4170000553131104
voltage_nominal = 2.822999954223633
moisture_nominal = 0.4099999964237213
[thermistor_settings]
pin = 0
voltage_divider_resistance = 9700.0
nominal_resistance = 10000.0
nominal_temperature = 298.1499938964844
thermal_constant = 3950.0
[water_pump_settings]
milliseconds_to_grams = 0.06914

16
src/actuators.rs

@ -1,3 +1,5 @@
use std::{thread, time::Duration};
use crate::{ use crate::{
config::*, config::*,
error::GenericResult, error::GenericResult,
@ -27,3 +29,17 @@ pub fn switch_water_pump(
) -> GenericResult<()> { ) -> GenericResult<()> {
relay.switch(config.relay_settings.water_pump_pin, state, config) relay.switch(config.relay_settings.water_pump_pin, state, config)
} }
pub fn pump_water(
water_mass_g: u16,
relay: &mut Relay,
config: &Configuration,
) -> GenericResult<()> {
let duration_ms = water_mass_g as f32 / config.water_pump_settings.grams_per_millisecond;
let duration_ms = duration_ms.round() as u64;
let duration = Duration::from_millis(duration_ms);
switch_water_pump(relay, RelaySwitchState::On, config)?;
thread::sleep(duration);
switch_water_pump(relay, RelaySwitchState::Off, config)?;
Ok(())
}

32
src/cli_mode.rs

@ -3,6 +3,7 @@ use std::{thread, time::Duration};
use rustyline::{config::Configurer, error::ReadlineError, history::FileHistory}; use rustyline::{config::Configurer, error::ReadlineError, history::FileHistory};
use crate::{ use crate::{
actuators,
config::Configuration, config::Configuration,
error::GenericResult, error::GenericResult,
io::{self, get_input_voltage}, io::{self, get_input_voltage},
@ -25,6 +26,7 @@ fn process_input(
"rel" => command_rel(&args, program_state, config)?, "rel" => command_rel(&args, program_state, config)?,
"soil" => command_soil(&args, config)?, "soil" => command_soil(&args, config)?,
"temp" => command_temp(&args, config)?, "temp" => command_temp(&args, config)?,
"pump" => command_pump(&args, program_state, config)?,
"exit" => return Ok(LoopFlags { exit: true }), "exit" => return Ok(LoopFlags { exit: true }),
_ => return Err("Unknown main command".into()), _ => return Err("Unknown main command".into()),
}; };
@ -32,6 +34,31 @@ fn process_input(
Ok(LoopFlags { exit: false }) Ok(LoopFlags { exit: false })
} }
fn command_pump(
args: &[&str],
program_state: &mut ProgramState,
config: &Configuration,
) -> GenericResult<()> {
let use_grams = args
.get(2)
.map(|arg| matches!(*arg, "grams"))
.unwrap_or(false);
if use_grams {
let grams: u16 = args.get(1).ok_or("No mass specified.")?.parse()?;
actuators::pump_water(grams, &mut program_state.relay, config)?;
return Ok(());
}
let duration_ms: u64 = args.get(1).ok_or("No duration specified.")?.parse()?;
let duration = Duration::from_millis(duration_ms);
actuators::switch_water_pump(&mut program_state.relay, io::RelaySwitchState::On, config)?;
thread::sleep(duration);
actuators::switch_water_pump(&mut program_state.relay, io::RelaySwitchState::Off, config)?;
Ok(())
}
fn command_temp(args: &[&str], config: &Configuration) -> GenericResult<()> { fn command_temp(args: &[&str], config: &Configuration) -> GenericResult<()> {
let show_loop = args let show_loop = args
.get(1) .get(1)
@ -160,7 +187,10 @@ fn init_state(config: &Configuration) -> GenericResult<ProgramState> {
pub fn run_cli() { pub fn run_cli() {
let mut rl = init_readline().unwrap(); let mut rl = init_readline().unwrap();
let config = Configuration::default();
let config =
Configuration::from_file(std::path::Path::new("./growpi.toml")).unwrap_or_default();
let mut program_state = init_state(&config).unwrap(); let mut program_state = init_state(&config).unwrap();
'cli_loop: loop { 'cli_loop: loop {

38
src/config.rs

@ -7,7 +7,7 @@ pub struct RelaySettings {
pub light_pin: u8, pub light_pin: u8,
pub fan_pin: u8, pub fan_pin: u8,
pub water_pump_pin: u8, pub water_pump_pin: u8,
pub relay_gpio_pins: Vec<Option<u8>>,
pub relay_gpio_pins: Vec<i16>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -27,6 +27,11 @@ pub struct SoilMoistureSettings {
pub moisture_nominal: f32, pub moisture_nominal: f32,
} }
#[derive(Serialize, Deserialize)]
pub struct WaterPumpSettings {
pub grams_per_millisecond: f32,
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct BoardSettings { pub struct BoardSettings {
pub logic_level: f32, pub logic_level: f32,
@ -38,25 +43,22 @@ pub struct Configuration {
pub relay_settings: RelaySettings, pub relay_settings: RelaySettings,
pub soil_moisture_settings: SoilMoistureSettings, pub soil_moisture_settings: SoilMoistureSettings,
pub thermistor_settings: ThermistorSettings, pub thermistor_settings: ThermistorSettings,
pub water_pump_settings: WaterPumpSettings,
} }
impl Configuration { impl Configuration {
fn from_file(path: &std::path::Path) -> GenericResult<Configuration> {
pub fn from_file(path: &std::path::Path) -> GenericResult<Configuration> {
let text = std::fs::read_to_string(path)?; let text = std::fs::read_to_string(path)?;
let config: Configuration = toml::from_str(text.as_str())?;
let config = toml::from_str(text.as_str())?;
Ok(config) Ok(config)
} }
fn save_to_file(path: &std::path::Path, config: &Configuration) -> GenericResult<()> {
let text = toml::to_string_pretty(config)?;
pub fn save_to_file(&self, path: &std::path::Path) -> GenericResult<()> {
let text = toml::to_string_pretty(self)?;
std::fs::write(path, text)?; std::fs::write(path, text)?;
Ok(()) Ok(())
} }
} }
const THERMISTOR_NOMINAL_RESISTANCE: f32 = 10_000.;
const THERMISTOR_NOMINAL_TEMPERATURE: f32 = 298.15;
const THERMISTOR_CONSTANT: f32 = 3950.;
impl Default for Configuration { impl Default for Configuration {
fn default() -> Self { fn default() -> Self {
Self { Self {
@ -65,7 +67,7 @@ impl Default for Configuration {
light_pin: 0, light_pin: 0,
fan_pin: 1, fan_pin: 1,
water_pump_pin: 2, water_pump_pin: 2,
relay_gpio_pins: [Some(17), Some(27), Some(22), None].to_vec(),
relay_gpio_pins: [17, 27, 22, -1].to_vec(),
}, },
soil_moisture_settings: SoilMoistureSettings { soil_moisture_settings: SoilMoistureSettings {
pin: 1, pin: 1,
@ -80,6 +82,22 @@ impl Default for Configuration {
nominal_temperature: 298.15, nominal_temperature: 298.15,
thermal_constant: 3950., thermal_constant: 3950.,
}, },
water_pump_settings: WaterPumpSettings {
grams_per_millisecond: 0.05281,
},
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_write_default() {
let config = Configuration::default();
config
.save_to_file(std::path::Path::new("./growpi.toml"))
.unwrap();
}
}

6
src/io.rs

@ -39,7 +39,11 @@ impl Relay {
.clone() .clone()
.into_iter() .into_iter()
.map(|pin| { .map(|pin| {
pin.and_then(|pin| {
match pin {
-1 => None,
_ => Some(pin as u8),
}
.and_then(|pin| {
let result = (|| -> GenericResult<OutputPin> { let result = (|| -> GenericResult<OutputPin> {
Ok(Gpio::new()?.get(pin)?.into_output()) Ok(Gpio::new()?.get(pin)?.into_output())
})(); })();

Loading…
Cancel
Save