SolarEnergy/central_backend/src/energy/energy_actor.rs

332 lines
8.9 KiB
Rust
Raw Normal View History

2024-06-29 09:45:39 +00:00
use crate::constants;
2024-08-27 20:32:22 +00:00
use crate::devices::device::{
Device, DeviceGeneralInfo, DeviceId, DeviceInfo, DeviceRelay, DeviceRelayID,
};
2024-07-01 19:10:45 +00:00
use crate::devices::devices_list::DevicesList;
2024-06-29 09:45:39 +00:00
use crate::energy::consumption;
use crate::energy::consumption::EnergyConsumption;
2024-09-09 19:05:52 +00:00
use crate::utils::time_utils::time_secs;
2024-06-29 09:45:39 +00:00
use actix::prelude::*;
2024-07-02 20:55:51 +00:00
use openssl::x509::X509Req;
2024-09-09 19:05:52 +00:00
use std::collections::HashMap;
#[derive(Default)]
struct DeviceState {
last_ping: u64,
}
impl DeviceState {
fn is_online(&self) -> bool {
(time_secs() - self.last_ping) < constants::DEVICE_MAX_PING_TIME
}
}
#[derive(Default)]
struct RelayState {
enabled: bool,
since: usize,
}
2024-06-29 09:45:39 +00:00
pub struct EnergyActor {
curr_consumption: EnergyConsumption,
2024-07-01 19:10:45 +00:00
devices: DevicesList,
2024-09-09 19:05:52 +00:00
devices_state: HashMap<DeviceId, DeviceState>,
relays_state: HashMap<DeviceRelayID, RelayState>,
2024-06-29 09:45:39 +00:00
}
impl EnergyActor {
pub async fn new() -> anyhow::Result<Self> {
Ok(Self {
curr_consumption: consumption::get_curr_consumption().await?,
2024-07-01 19:10:45 +00:00
devices: DevicesList::load()?,
2024-09-09 19:05:52 +00:00
devices_state: Default::default(),
relays_state: Default::default(),
2024-06-29 09:45:39 +00:00
})
}
2024-09-09 19:05:52 +00:00
fn device_state(&mut self, dev_id: &DeviceId) -> &mut DeviceState {
if !self.devices_state.contains_key(dev_id) {
self.devices_state
.insert(dev_id.clone(), Default::default());
}
self.devices_state.get_mut(dev_id).unwrap()
}
2024-06-29 09:45:39 +00:00
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<Self>;
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<EnergyActor>;
/// Get current consumption
#[derive(Message)]
#[rtype(result = "EnergyConsumption")]
pub struct GetCurrConsumption;
impl Handler<GetCurrConsumption> for EnergyActor {
type Result = EnergyConsumption;
fn handle(&mut self, _msg: GetCurrConsumption, _ctx: &mut Context<Self>) -> Self::Result {
self.curr_consumption
}
}
2024-07-01 19:10:45 +00:00
/// Get current consumption
#[derive(Message)]
#[rtype(result = "bool")]
2024-07-01 20:24:03 +00:00
pub struct CheckDeviceExists(pub DeviceId);
2024-07-01 19:10:45 +00:00
impl Handler<CheckDeviceExists> for EnergyActor {
type Result = bool;
fn handle(&mut self, msg: CheckDeviceExists, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.exists(&msg.0)
}
}
2024-07-02 20:55:51 +00:00
/// Enroll device
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct EnrollDevice(pub DeviceId, pub DeviceInfo, pub X509Req);
impl Handler<EnrollDevice> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: EnrollDevice, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.enroll(&msg.0, &msg.1, &msg.2)
}
}
2024-07-03 19:32:32 +00:00
/// Validate a device
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct ValidateDevice(pub DeviceId);
impl Handler<ValidateDevice> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: ValidateDevice, _ctx: &mut Context<Self>) -> Self::Result {
log::info!("Requested to validate device {:?}...", &msg.0);
self.devices.validate(&msg.0)?;
Ok(())
}
}
2024-07-22 20:19:48 +00:00
/// Update a device general information
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct UpdateDeviceGeneralInfo(pub DeviceId, pub DeviceGeneralInfo);
impl Handler<UpdateDeviceGeneralInfo> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: UpdateDeviceGeneralInfo, _ctx: &mut Context<Self>) -> Self::Result {
log::info!(
"Requested to update device general info {:?}... {:#?}",
&msg.0,
&msg.1
);
self.devices.update_general_info(&msg.0, msg.1)?;
Ok(())
}
}
2024-07-03 19:10:15 +00:00
/// Delete a device
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct DeleteDevice(pub DeviceId);
impl Handler<DeleteDevice> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: DeleteDevice, _ctx: &mut Context<Self>) -> 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<Device>")]
pub struct GetDeviceLists;
impl Handler<GetDeviceLists> for EnergyActor {
type Result = Vec<Device>;
fn handle(&mut self, _msg: GetDeviceLists, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.full_list()
}
}
/// Get the information about a single device
#[derive(Message)]
#[rtype(result = "Option<Device>")]
pub struct GetSingleDevice(pub DeviceId);
impl Handler<GetSingleDevice> for EnergyActor {
type Result = Option<Device>;
fn handle(&mut self, msg: GetSingleDevice, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.get_single(&msg.0)
}
}
/// Get the full list of relays
#[derive(Message)]
#[rtype(result = "Vec<DeviceRelay>")]
pub struct GetRelaysList;
impl Handler<GetRelaysList> for EnergyActor {
type Result = Vec<DeviceRelay>;
fn handle(&mut self, _msg: GetRelaysList, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.relays_list()
}
}
2024-08-27 20:32:22 +00:00
/// Create a new device relay
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct CreateDeviceRelay(pub DeviceId, pub DeviceRelay);
impl Handler<CreateDeviceRelay> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: CreateDeviceRelay, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.relay_create(&msg.0, msg.1)
}
}
/// Get the information about a single relay
#[derive(Message)]
#[rtype(result = "Option<DeviceRelay>")]
pub struct GetSingleRelay(pub DeviceRelayID);
impl Handler<GetSingleRelay> for EnergyActor {
type Result = Option<DeviceRelay>;
fn handle(&mut self, msg: GetSingleRelay, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.relay_get_single(msg.0)
}
}
2024-08-31 18:00:40 +00:00
2024-08-31 18:26:16 +00:00
/// Update a device relay
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct UpdateDeviceRelay(pub DeviceRelay);
impl Handler<UpdateDeviceRelay> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: UpdateDeviceRelay, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.relay_update(msg.0)
}
}
2024-08-31 18:00:40 +00:00
/// Delete a device relay
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct DeleteDeviceRelay(pub DeviceRelayID);
impl Handler<DeleteDeviceRelay> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: DeleteDeviceRelay, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.relay_delete(msg.0)
}
}
2024-09-04 20:43:23 +00:00
#[derive(serde::Serialize)]
pub struct RelaySyncStatus {
enabled: bool,
}
/// Synchronize a device
#[derive(Message)]
#[rtype(result = "anyhow::Result<Vec<RelaySyncStatus>>")]
pub struct SynchronizeDevice(pub DeviceId, pub DeviceInfo);
impl Handler<SynchronizeDevice> for EnergyActor {
type Result = anyhow::Result<Vec<RelaySyncStatus>>;
fn handle(&mut self, msg: SynchronizeDevice, _ctx: &mut Context<Self>) -> Self::Result {
2024-09-09 19:05:52 +00:00
let s = self.device_state(&msg.0);
s.last_ping = time_secs();
2024-09-04 20:43:23 +00:00
// TODO : implement real code
let mut v = vec![];
for i in 0..msg.1.max_relays {
v.push(RelaySyncStatus {
enabled: i % 2 == 0,
});
}
Ok(v)
}
}
2024-09-09 19:05:52 +00:00
#[derive(serde::Serialize)]
pub struct ResDevState {
id: DeviceId,
last_ping: u64,
online: bool,
}
/// Get the state of devices
#[derive(Message)]
#[rtype(result = "Vec<ResDevState>")]
pub struct GetDevicesState;
impl Handler<GetDevicesState> for EnergyActor {
type Result = Vec<ResDevState>;
fn handle(&mut self, _msg: GetDevicesState, _ctx: &mut Context<Self>) -> Self::Result {
self.devices
.full_list()
.into_iter()
.map(|d| {
let s = self.device_state(&d.id);
ResDevState {
id: d.id,
last_ping: time_secs() - s.last_ping,
online: s.is_online(),
}
})
.collect()
}
}