diff --git a/src/actuators.rs b/src/actuators.rs index bfc9007..87b79c0 100644 --- a/src/actuators.rs +++ b/src/actuators.rs @@ -26,6 +26,19 @@ pub fn switch_water_pump( .switch(program_state.config.relay_settings.water_pump_pin, state) } +pub fn get_light_state(program_state: &mut ProgramState) -> GenericResult { + let pin = program_state.config.relay_settings.light_pin; + program_state.relay.get_state(pin) +} +pub fn get_water_pump_state(program_state: &mut ProgramState) -> GenericResult { + let pin = program_state.config.relay_settings.water_pump_pin; + program_state.relay.get_state(pin) +} +pub fn get_fan_state(program_state: &mut ProgramState) -> GenericResult { + let pin = program_state.config.relay_settings.fan_pin; + program_state.relay.get_state(pin) +} + pub fn pump_water(water_mass_g: u16, program_state: &mut ProgramState) -> GenericResult<()> { let duration_ms = water_mass_g as f32 / program_state diff --git a/src/io.rs b/src/io.rs index 7ff39b2..cc75faa 100644 --- a/src/io.rs +++ b/src/io.rs @@ -75,6 +75,15 @@ impl Relay { Ok(()) } + pub fn get_state(&mut self, pin: u8) -> GenericResult { + let pin = self.get_output_pin(pin)?; + if pin.is_set_high() { + Ok(RelaySwitchState::Off) + } else { + Ok(RelaySwitchState::On) + } + } + fn get_output_pin(&mut self, pin: u8) -> GenericResult<&mut OutputPin> { Ok(self .relay_pins diff --git a/src/server.rs b/src/server.rs index 864de83..bf284c5 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,15 +1,17 @@ use axum::{ extract::{Path, State}, http::StatusCode, - response::{Html, IntoResponse}, + response::IntoResponse, routing::get, - Router, + Json, Router, }; +use serde::{Deserialize, Serialize}; use crate::{ actuators, error::{lock_err, GenericResult}, io::RelaySwitchState, + sensors, state::ProgramStateShared, }; @@ -21,11 +23,27 @@ pub async fn run_server(program_state: ProgramStateShared) { fn setup_router(program_state: ProgramStateShared) -> Router { Router::new() - .route("/", get(handler)) + .route("/info", get(info_handler)) .route("/switch/:device/:state", get(switch_handler)) + .route("/pump/:quantity", get(pump_handler)) .with_state(program_state) } +async fn pump_handler( + Path(quantity): Path, + State(program_state): State, +) -> impl IntoResponse { + let exec = || -> GenericResult<()> { + let mut program_state = program_state.lock().map_err(lock_err)?; + actuators::pump_water(quantity, &mut program_state)?; + Ok(()) + }; + match exec() { + Ok(_) => StatusCode::OK, + Err(_) => StatusCode::INTERNAL_SERVER_ERROR, + } +} + async fn switch_handler( Path((device, state)): Path<(String, RelaySwitchState)>, State(program_state): State, @@ -46,6 +64,31 @@ async fn switch_handler( } } -async fn handler() -> Html<&'static str> { - Html("hi") +#[derive(Serialize, Deserialize)] +struct Info { + temperature: f32, + soil_moisture: f32, + fan_state: RelaySwitchState, + light_state: RelaySwitchState, + pump_state: RelaySwitchState, +} + +async fn info_handler( + State(program_state): State, +) -> Result, String> { + let mut program_state = program_state.lock().map_err(lock_err)?; + let temperature = sensors::get_temperature(&program_state.config).map_err(|e| e.to_string())?; + let soil_moisture = + sensors::get_soil_moisture(&program_state.config).map_err(|e| e.to_string())?; + let fan_state = actuators::get_fan_state(&mut program_state).map_err(|e| e.to_string())?; + let light_state = actuators::get_light_state(&mut program_state).map_err(|e| e.to_string())?; + let pump_state = + actuators::get_water_pump_state(&mut program_state).map_err(|e| e.to_string())?; + Ok(Json(Info { + temperature, + soil_moisture, + fan_state, + light_state, + pump_state, + })) }