use crate::devices::device::DeviceRelayID; use crate::energy::engine::RelayForcedState; use crate::energy::{consumption, energy_actor, relay_state_history}; use crate::server::WebEnergyActor; use crate::server::custom_error::HttpResult; use actix_web::{HttpResponse, web}; #[derive(serde::Deserialize)] pub struct LegacyStateRelay { id: DeviceRelayID, } /// Legacy relay state #[derive(serde::Serialize)] pub struct LegacyState { /// Indicates if relay is on or off is_on: bool, /// Relay name name: String, /// Duration since last change of state r#for: usize, /// Current grid consumption prod: i32, /// Total uptime since last reset total_uptime: usize, /// Required uptime during a day /// /// Will be 0 if there is no daily requirements required_uptime: usize, } /// Get the state of a relay, adapted for old system components pub async fn legacy_state( energy_actor: WebEnergyActor, path: web::Path, ) -> HttpResult { let Some(relay) = energy_actor .send(energy_actor::GetSingleRelay(path.id)) .await? else { return Ok(HttpResponse::NotFound().body("Relay not found!")); }; let all_states = energy_actor.send(energy_actor::GetAllRelaysState).await?; let Some(state) = all_states.into_iter().find(|r| r.id == path.id) else { return Ok(HttpResponse::InternalServerError().body("Relay status unavailable!")); }; let production = energy_actor.send(energy_actor::GetCurrConsumption).await?; let total_uptime = relay_state_history::relay_total_runtime_adjusted(&relay); Ok(HttpResponse::Ok().json(LegacyState { name: relay.name, is_on: state.on, r#for: state.r#for.min(3600 * 24 * 7), prod: production, total_uptime, required_uptime: relay.daily_runtime.map(|r| r.min_runtime).unwrap_or(0), })) } #[derive(serde::Serialize)] pub struct FullRelayState { /// Indicates if the relay (or its parent device) is enabled or not enabled: bool, /// Indicates if relay is on or off is_on: bool, /// Relay name name: String, /// Relay priority (0 = lowest) priority: usize, /// Duration since last change of state r#for: usize, /// Total uptime since last reset total_uptime: usize, /// Required uptime during a day (in seconds) daily_requirement: Option, /// Forced relay state relay_forced_state: RelayForcedState, } #[derive(serde::Serialize)] pub struct RelaysFullState { /// Current global consumption, if successful curr_consumption: Option, /// Cached consumption cached_consumption: i32, /// Total relays consumptions relays_consumption: usize, /// Individual relays state relays: Vec, } pub async fn relays_full_state(energy_actor: WebEnergyActor) -> HttpResult { let cached_consumption = energy_actor.send(energy_actor::GetCurrConsumption).await?; let relays_consumption = energy_actor.send(energy_actor::RelaysConsumption).await?; let curr_consumption = consumption::get_curr_consumption().await.ok(); let mut relays = energy_actor.send(energy_actor::GetRelaysList).await?; relays.sort_by_key(|r| -(r.priority as i64)); let relays_state = energy_actor.send(energy_actor::GetAllRelaysState).await?; Ok(HttpResponse::Ok().json(RelaysFullState { curr_consumption, cached_consumption, relays_consumption, relays: relays .into_iter() .map(|r| { let state = relays_state.iter().find(|s| s.id == r.id); FullRelayState { enabled: r.enabled, is_on: state.map(|s| s.on).unwrap_or(false), name: r.name, priority: r.priority, r#for: state.map(|s| s.r#for).unwrap_or(0), total_uptime: 0, daily_requirement: r.daily_runtime.map(|r| r.min_runtime), relay_forced_state: state.map(|s| s.forced_state.clone()).unwrap_or_default(), } }) .collect(), })) }