Take relays consumption in account
This commit is contained in:
		@@ -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>,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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(
 | 
				
			||||||
            log::info!("Performing energy refresh operation");
 | 
					            Duration::from_secs(AppConfig::get().refresh_interval),
 | 
				
			||||||
            if let Err(e) = futures::executor::block_on(act.refresh()) {
 | 
					            |act, _ctx| {
 | 
				
			||||||
                log::error!("Energy refresh failed! {e}")
 | 
					                log::info!("Performing energy refresh operation");
 | 
				
			||||||
            }
 | 
					                if let Err(e) = futures::executor::block_on(act.refresh()) {
 | 
				
			||||||
        });
 | 
					                    log::error!("Energy refresh failed! {e}")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn stopped(&mut self, _ctx: &mut Self::Context) {
 | 
					    fn stopped(&mut self, _ctx: &mut Self::Context) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user