Refactor energy management
This commit is contained in:
parent
36ba4efd9f
commit
c74ed0cfbb
148
central_backend/Cargo.lock
generated
148
central_backend/Cargo.lock
generated
@ -626,6 +626,7 @@ dependencies = [
|
|||||||
"mime_guess",
|
"mime_guess",
|
||||||
"openssl",
|
"openssl",
|
||||||
"openssl-sys",
|
"openssl-sys",
|
||||||
|
"prettytable-rs",
|
||||||
"rand",
|
"rand",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rust-embed",
|
"rust-embed",
|
||||||
@ -798,6 +799,27 @@ dependencies = [
|
|||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "csv"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
|
||||||
|
dependencies = [
|
||||||
|
"csv-core",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "csv-core"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctr"
|
name = "ctr"
|
||||||
version = "0.9.2"
|
version = "0.9.2"
|
||||||
@ -840,6 +862,33 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-next"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"dirs-sys-next",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys-next"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encode_unicode"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.34"
|
version = "0.8.34"
|
||||||
@ -1118,6 +1167,12 @@ version = "0.3.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hkdf"
|
name = "hkdf"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
@ -1336,6 +1391,17 @@ version = "2.9.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.4.0",
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
@ -1422,6 +1488,16 @@ version = "0.2.155"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libredox"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
@ -1498,7 +1574,7 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
|
checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi",
|
"hermit-abi 0.3.9",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"wasi",
|
"wasi",
|
||||||
@ -1731,6 +1807,20 @@ dependencies = [
|
|||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prettytable-rs"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a"
|
||||||
|
dependencies = [
|
||||||
|
"csv",
|
||||||
|
"encode_unicode",
|
||||||
|
"is-terminal",
|
||||||
|
"lazy_static",
|
||||||
|
"term",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.86"
|
version = "1.0.86"
|
||||||
@ -1788,6 +1878,17 @@ dependencies = [
|
|||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libredox",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.10.6"
|
version = "1.10.6"
|
||||||
@ -1983,6 +2084,12 @@ dependencies = [
|
|||||||
"untrusted",
|
"untrusted",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
@ -2226,6 +2333,17 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "term"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-next",
|
||||||
|
"rustversion",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.63"
|
version = "1.0.63"
|
||||||
@ -2466,6 +2584,12 @@ dependencies = [
|
|||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "universal-hash"
|
name = "universal-hash"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@ -2622,6 +2746,22 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
@ -2631,6 +2771,12 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
|
@ -35,3 +35,4 @@ tokio_schedule = "0.3.2"
|
|||||||
mime_guess = "2.0.5"
|
mime_guess = "2.0.5"
|
||||||
rust-embed = "8.5.0"
|
rust-embed = "8.5.0"
|
||||||
jsonwebtoken = { version = "9.3.0", features = ["use_pem"] }
|
jsonwebtoken = { version = "9.3.0", features = ["use_pem"] }
|
||||||
|
prettytable-rs = "0.10.0"
|
@ -5,33 +5,15 @@ use crate::devices::device::{
|
|||||||
use crate::devices::devices_list::DevicesList;
|
use crate::devices::devices_list::DevicesList;
|
||||||
use crate::energy::consumption;
|
use crate::energy::consumption;
|
||||||
use crate::energy::consumption::EnergyConsumption;
|
use crate::energy::consumption::EnergyConsumption;
|
||||||
|
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::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,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EnergyActor {
|
pub struct EnergyActor {
|
||||||
curr_consumption: EnergyConsumption,
|
curr_consumption: EnergyConsumption,
|
||||||
devices: DevicesList,
|
devices: DevicesList,
|
||||||
devices_state: HashMap<DeviceId, DeviceState>,
|
engine: EnergyEngine,
|
||||||
relays_state: HashMap<DeviceRelayID, RelayState>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnergyActor {
|
impl EnergyActor {
|
||||||
@ -39,20 +21,10 @@ impl EnergyActor {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
curr_consumption: consumption::get_curr_consumption().await?,
|
curr_consumption: consumption::get_curr_consumption().await?,
|
||||||
devices: DevicesList::load()?,
|
devices: DevicesList::load()?,
|
||||||
devices_state: Default::default(),
|
engine: EnergyEngine::default(),
|
||||||
relays_state: Default::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn refresh(&mut self) -> anyhow::Result<()> {
|
async fn refresh(&mut self) -> anyhow::Result<()> {
|
||||||
// Refresh energy
|
// Refresh energy
|
||||||
self.curr_consumption = consumption::get_curr_consumption()
|
self.curr_consumption = consumption::get_curr_consumption()
|
||||||
@ -64,6 +36,9 @@ impl EnergyActor {
|
|||||||
constants::FALLBACK_PRODUCTION_VALUE
|
constants::FALLBACK_PRODUCTION_VALUE
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.engine
|
||||||
|
.refresh(self.curr_consumption, &self.devices.full_list());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,8 +260,7 @@ impl Handler<SynchronizeDevice> for EnergyActor {
|
|||||||
type Result = anyhow::Result<Vec<RelaySyncStatus>>;
|
type Result = anyhow::Result<Vec<RelaySyncStatus>>;
|
||||||
|
|
||||||
fn handle(&mut self, msg: SynchronizeDevice, _ctx: &mut Context<Self>) -> Self::Result {
|
fn handle(&mut self, msg: SynchronizeDevice, _ctx: &mut Context<Self>) -> Self::Result {
|
||||||
let s = self.device_state(&msg.0);
|
self.engine.device_state(&msg.0).record_ping();
|
||||||
s.last_ping = time_secs();
|
|
||||||
|
|
||||||
// TODO : implement real code
|
// TODO : implement real code
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
@ -319,7 +293,7 @@ impl Handler<GetDevicesState> for EnergyActor {
|
|||||||
.full_list()
|
.full_list()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|d| {
|
.map(|d| {
|
||||||
let s = self.device_state(&d.id);
|
let s = self.engine.device_state(&d.id);
|
||||||
ResDevState {
|
ResDevState {
|
||||||
id: d.id,
|
id: d.id,
|
||||||
last_ping: time_secs() - s.last_ping,
|
last_ping: time_secs() - s.last_ping,
|
||||||
|
83
central_backend/src/energy/engine.rs
Normal file
83
central_backend/src/energy/engine.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
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)]
|
||||||
|
struct RelayState {
|
||||||
|
on: bool,
|
||||||
|
since: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct EnergyEngine {
|
||||||
|
devices_state: HashMap<DeviceId, DeviceState>,
|
||||||
|
relays_state: HashMap<DeviceRelayID, RelayState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnergyEngine {
|
||||||
|
pub 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()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn relay_state(&mut self, relay_id: DeviceRelayID) -> &mut RelayState {
|
||||||
|
if !self.relays_state.contains_key(&relay_id) {
|
||||||
|
self.relays_state.insert(relay_id, Default::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]) {
|
||||||
|
let new_relays_state = self.relays_state.clone();
|
||||||
|
|
||||||
|
// Forcefully turn off relays that belongs to offline devices
|
||||||
|
|
||||||
|
// Forcefully turn off relays with dependency conflicts
|
||||||
|
|
||||||
|
// Virtually turn off all relays that can be stopped
|
||||||
|
|
||||||
|
// Turn on relays based on priority / dependencies
|
||||||
|
|
||||||
|
// Turn on relays with running constraints
|
||||||
|
|
||||||
|
// Commit changes
|
||||||
|
self.print_summary(curr_consumption, devices); // TODO :replace
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
pub mod consumption;
|
pub mod consumption;
|
||||||
pub mod energy_actor;
|
pub mod energy_actor;
|
||||||
|
pub mod engine;
|
||||||
|
Loading…
Reference in New Issue
Block a user