Take relays consumption in account

This commit is contained in:
Pierre HUBERT 2024-09-16 22:27:43 +02:00
parent 79b2ad12d8
commit 20bc71851d
4 changed files with 81 additions and 14 deletions

View File

@ -76,6 +76,14 @@ pub struct AppConfig {
#[arg(short, long, env, default_value = "storage")] #[arg(short, long, env, default_value = "storage")]
storage: String, storage: String,
/// The minimal production that must be excluded when selecting relays to turn on
#[arg(short('m'), long, env, default_value_t = -500)]
pub production_margin: i32,
/// Energy refresh operations interval, in seconds
#[arg(short('i'), long, env, default_value_t = 30)]
pub refresh_interval: u64,
/// Consumption backend provider /// Consumption backend provider
#[clap(subcommand)] #[clap(subcommand)]
pub consumption_backend: Option<ConsumptionBackend>, pub consumption_backend: Option<ConsumptionBackend>,

View File

@ -1,11 +1,6 @@
use std::time::Duration;
/// Name of the cookie that contains session information /// Name of the cookie that contains session information
pub const SESSION_COOKIE_NAME: &str = "X-session-cookie"; pub const SESSION_COOKIE_NAME: &str = "X-session-cookie";
/// Energy refresh operations interval
pub const ENERGY_REFRESH_INTERVAL: Duration = Duration::from_secs(30);
/// Maximum time after a ping during which a device is considered "up" /// Maximum time after a ping during which a device is considered "up"
pub const DEVICE_MAX_PING_TIME: u64 = 30; pub const DEVICE_MAX_PING_TIME: u64 = 30;

View File

@ -1,3 +1,4 @@
use crate::app_config::AppConfig;
use crate::constants; use crate::constants;
use crate::devices::device::{ use crate::devices::device::{
Device, DeviceGeneralInfo, DeviceId, DeviceInfo, DeviceRelay, DeviceRelayID, Device, DeviceGeneralInfo, DeviceId, DeviceInfo, DeviceRelay, DeviceRelayID,
@ -9,6 +10,7 @@ use crate::energy::engine::EnergyEngine;
use crate::utils::time_utils::time_secs; use crate::utils::time_utils::time_secs;
use actix::prelude::*; use actix::prelude::*;
use openssl::x509::X509Req; use openssl::x509::X509Req;
use std::time::Duration;
pub struct EnergyActor { pub struct EnergyActor {
curr_consumption: EnergyConsumption, curr_consumption: EnergyConsumption,
@ -49,12 +51,15 @@ impl Actor for EnergyActor {
fn started(&mut self, ctx: &mut Self::Context) { fn started(&mut self, ctx: &mut Self::Context) {
log::info!("Energy actor successfully started!"); log::info!("Energy actor successfully started!");
ctx.run_interval(constants::ENERGY_REFRESH_INTERVAL, |act, _ctx| { ctx.run_interval(
Duration::from_secs(AppConfig::get().refresh_interval),
|act, _ctx| {
log::info!("Performing energy refresh operation"); log::info!("Performing energy refresh operation");
if let Err(e) = futures::executor::block_on(act.refresh()) { if let Err(e) = futures::executor::block_on(act.refresh()) {
log::error!("Energy refresh failed! {e}") log::error!("Energy refresh failed! {e}")
} }
}); },
);
} }
fn stopped(&mut self, _ctx: &mut Self::Context) { fn stopped(&mut self, _ctx: &mut Self::Context) {

View File

@ -1,5 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::app_config::AppConfig;
use prettytable::{row, Table}; use prettytable::{row, Table};
use crate::constants; use crate::constants;
@ -87,6 +88,20 @@ impl DeviceRelay {
} }
} }
fn sum_relays_consumption(state: &RelaysState, devices: &[Device]) -> usize {
let mut consumption = 0;
for d in devices {
for r in &d.relays {
if matches!(state.get(&r.id).map(|r| r.on), Some(true)) {
consumption += r.consumption;
}
}
}
consumption
}
impl EnergyEngine { impl EnergyEngine {
pub fn device_state(&mut self, dev_id: &DeviceId) -> &mut DeviceState { pub fn device_state(&mut self, dev_id: &DeviceId) -> &mut DeviceState {
self.devices_state.entry(dev_id.clone()).or_default(); self.devices_state.entry(dev_id.clone()).or_default();
@ -102,22 +117,60 @@ impl EnergyEngine {
log::info!("Current consumption: {curr_consumption}"); log::info!("Current consumption: {curr_consumption}");
let mut table = Table::new(); let mut table = Table::new();
table.add_row(row!["Device", "Relay", "On", "Since"]); table.add_row(row![
"Device",
"Relay",
"Consumption",
"Min downtime / uptime",
"On",
"Since",
"Online",
"Enabled device / relay"
]);
for d in devices { for d in devices {
let dev_online = self.device_state(&d.id).is_online();
for r in &d.relays { for r in &d.relays {
let status = self.relay_state(r.id); let status = self.relay_state(r.id);
table.add_row(row![ table.add_row(row![
d.name, d.name,
r.name, r.name,
r.consumption,
format!("{} / {}", r.minimal_downtime, r.minimal_uptime),
status.is_on().to_string(), status.is_on().to_string(),
status.since status.since,
match dev_online {
true => "Online",
false => "Offline",
},
format!(
"{} / {}",
match d.enabled {
true => "Enabled",
false => "Disabled",
},
match r.enabled {
true => "Enabled",
false => "Disabled",
}
)
]); ]);
} }
} }
table.printstd(); table.printstd();
} }
pub fn estimated_consumption_without_relays(
&self,
curr_consumption: EnergyConsumption,
devices: &[Device],
) -> EnergyConsumption {
curr_consumption - sum_relays_consumption(&self.relays_state, devices) as i32
}
pub fn refresh(&mut self, curr_consumption: EnergyConsumption, devices: &[Device]) { pub fn refresh(&mut self, curr_consumption: EnergyConsumption, devices: &[Device]) {
let base_production = self.estimated_consumption_without_relays(curr_consumption, devices);
log::info!("Estimated base production: {base_production}");
// Force creation of missing relays state // Force creation of missing relays state
for d in devices { for d in devices {
for r in &d.relays { for r in &d.relays {
@ -238,7 +291,13 @@ impl EnergyEngine {
continue; continue;
} }
// TODO : check consumption let new_consumption = base_production
+ sum_relays_consumption(&new_relays_state, devices) as EnergyConsumption;
if new_consumption + relay.consumption as i32 > AppConfig::get().production_margin {
continue;
}
log::info!("Turn on relay {}", relay.name); log::info!("Turn on relay {}", relay.name);
new_relays_state.get_mut(&relay.id).unwrap().on = true; new_relays_state.get_mut(&relay.id).unwrap().on = true;
changed = true; changed = true;