use crate::constants; use crate::devices::device::{Device, DeviceId, DeviceRelayID}; use crate::energy::consumption::EnergyConsumption; use crate::utils::time_utils::time_secs; use prettytable::{row, Table}; use std::collections::HashMap; #[derive(Default)] pub struct DeviceState { pub last_ping: u64, } impl DeviceState { pub fn record_ping(&mut self) { self.last_ping = time_secs(); } pub fn is_online(&self) -> bool { (time_secs() - self.last_ping) < constants::DEVICE_MAX_PING_TIME } } #[derive(Default, Clone)] pub struct RelayState { on: bool, since: usize, } #[derive(Default)] pub struct EnergyEngine { devices_state: HashMap, relays_state: HashMap, } impl EnergyEngine { pub fn device_state(&mut self, dev_id: &DeviceId) -> &mut DeviceState { self.devices_state.entry(dev_id.clone()).or_default(); self.devices_state.get_mut(dev_id).unwrap() } pub fn relay_state(&mut self, relay_id: DeviceRelayID) -> &mut RelayState { self.relays_state.entry(relay_id).or_default(); self.relays_state.get_mut(&relay_id).unwrap() } fn print_summary(&mut self, curr_consumption: EnergyConsumption, devices: &[Device]) { log::info!("Current consumption: {curr_consumption}"); let mut table = Table::new(); table.add_row(row!["Device", "Relay", "On", "Since"]); for d in devices { for r in &d.relays { let status = self.relay_state(r.id); table.add_row(row![d.name, r.name, status.on.to_string(), status.since]); } } table.printstd(); } pub fn refresh(&mut self, curr_consumption: EnergyConsumption, devices: &[Device]) { // TODO : force creation of missing relays state let new_relays_state = self.relays_state.clone(); // TODO Forcefully turn off relays that belongs to offline devices // TODO Forcefully turn off relays with dependency conflicts // TODO Virtually turn off all relays that can be stopped // TODO Turn on relays based on priority / dependencies // TODO Turn on relays with running constraints // TODO Commit changes for (id, new_state) in &new_relays_state { let curr_state = self.relay_state(*id); if curr_state.on != new_state.on { curr_state.on = new_state.on; curr_state.since = time_secs() as usize; } log::info!("Changing state of {id:?}"); } self.print_summary(curr_consumption, devices); } }