use crate::app_config::{AppConfig, ConsumptionBackend}; use rand::{thread_rng, Rng}; use std::num::ParseIntError; use std::path::Path; #[derive(thiserror::Error, Debug)] pub enum ConsumptionError { #[error("The file that should contain the consumption does not exists!")] NonExistentFile, #[error("The file that should contain the consumption has an invalid content!")] FileInvalidContent(#[source] ParseIntError), #[error("Failed to execute cURL request!")] CurlReqFailed, } pub type EnergyConsumption = i32; #[derive(serde::Deserialize)] struct FroniusResponse { #[serde(rename = "Body")] body: FroniusResponseBody, } #[derive(serde::Deserialize)] struct FroniusResponseBody { #[serde(rename = "Data")] data: FroniusResponseBodyData, } #[derive(serde::Deserialize)] struct FroniusResponseBodyData { #[serde(rename = "Site")] site: FroniusResponseSite, } #[derive(serde::Deserialize)] struct FroniusResponseSite { #[serde(rename = "P_Grid")] grid_production: f64, } /// Get current electrical energy consumption pub async fn get_curr_consumption() -> anyhow::Result { let backend = AppConfig::get() .consumption_backend .as_ref() .unwrap_or(&ConsumptionBackend::Constant { value: 300 }); match backend { ConsumptionBackend::Constant { value } => Ok(*value), ConsumptionBackend::Random { min, max } => Ok(thread_rng().gen_range(*min..*max)), ConsumptionBackend::File { path } => { let path = Path::new(path); if !path.is_file() { return Err(ConsumptionError::NonExistentFile.into()); } let content = std::fs::read_to_string(path)?; Ok(content .trim() .parse() .map_err(ConsumptionError::FileInvalidContent)?) } ConsumptionBackend::Fronius { fronius_orig, curl } => { let url = format!("{fronius_orig}/solar_api/v1/GetPowerFlowRealtimeData.fcgi"); let response = match curl { false => reqwest::get(url).await?.json::().await?, true => { let res = std::process::Command::new("curl") .arg("--connect-timeout") .arg("1.5") .arg(url) .output()?; if !res.status.success() { return Err(ConsumptionError::CurlReqFailed.into()); } serde_json::from_slice::(&res.stdout)? } }; Ok(response.body.data.site.grid_production as i32) } } }