use crate::constants; use crate::devices::device::{Device, DeviceId, DeviceInfo}; use crate::devices::devices_list::DevicesList; use crate::energy::consumption; use crate::energy::consumption::EnergyConsumption; use actix::prelude::*; use openssl::x509::X509Req; pub struct EnergyActor { curr_consumption: EnergyConsumption, devices: DevicesList, } impl EnergyActor { pub async fn new() -> anyhow::Result { Ok(Self { curr_consumption: consumption::get_curr_consumption().await?, devices: DevicesList::load()?, }) } async fn refresh(&mut self) -> anyhow::Result<()> { // Refresh energy self.curr_consumption = consumption::get_curr_consumption() .await .unwrap_or_else(|e| { log::error!( "Failed to fetch latest consumption value, will use fallback value! {e}" ); constants::FALLBACK_PRODUCTION_VALUE }); Ok(()) } } impl Actor for EnergyActor { type Context = Context; fn started(&mut self, ctx: &mut Self::Context) { log::info!("Energy actor successfully started!"); ctx.run_interval(constants::ENERGY_REFRESH_INTERVAL, |act, _ctx| { 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) { log::info!("Energy actor successfully stopped!"); } } pub type EnergyActorAddr = Addr; /// Get current consumption #[derive(Message)] #[rtype(result = "EnergyConsumption")] pub struct GetCurrConsumption; impl Handler for EnergyActor { type Result = EnergyConsumption; fn handle(&mut self, _msg: GetCurrConsumption, _ctx: &mut Context) -> Self::Result { self.curr_consumption } } /// Get current consumption #[derive(Message)] #[rtype(result = "bool")] pub struct CheckDeviceExists(pub DeviceId); impl Handler for EnergyActor { type Result = bool; fn handle(&mut self, msg: CheckDeviceExists, _ctx: &mut Context) -> Self::Result { self.devices.exists(&msg.0) } } /// Enroll device #[derive(Message)] #[rtype(result = "anyhow::Result<()>")] pub struct EnrollDevice(pub DeviceId, pub DeviceInfo, pub X509Req); impl Handler for EnergyActor { type Result = anyhow::Result<()>; fn handle(&mut self, msg: EnrollDevice, _ctx: &mut Context) -> Self::Result { self.devices.enroll(&msg.0, &msg.1, &msg.2) } } /// Delete a device #[derive(Message)] #[rtype(result = "anyhow::Result<()>")] pub struct DeleteDevice(pub DeviceId); impl Handler for EnergyActor { type Result = anyhow::Result<()>; fn handle(&mut self, msg: DeleteDevice, _ctx: &mut Context) -> Self::Result { log::info!("Requested to delete device {:?}...", &msg.0); self.devices.delete(&msg.0)?; // TODO : delete energy related information Ok(()) } } /// Get the list of devices #[derive(Message)] #[rtype(result = "Vec")] pub struct GetDeviceLists; impl Handler for EnergyActor { type Result = Vec; fn handle(&mut self, _msg: GetDeviceLists, _ctx: &mut Context) -> Self::Result { self.devices.full_list() } }