SolarEnergy/central_backend/src/energy/consumption.rs

74 lines
2.1 KiB
Rust

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),
}
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<EnergyConsumption> {
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 { origin } => {
let url = format!("{origin}/solar_api/v1/GetPowerFlowRealtimeData.fcgi");
let response = reqwest::get(url).await?.json::<FroniusResponse>().await?;
Ok(response.body.data.site.grid_production as i32)
}
}
}