Create energy actor
This commit is contained in:
parent
49a3e3a669
commit
d4a81f5fdf
52
central_backend/Cargo.lock
generated
52
central_backend/Cargo.lock
generated
@ -2,6 +2,31 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "actix"
|
||||||
|
version = "0.13.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "de7fa236829ba0841304542f7614c42b80fca007455315c45c785ccfa873a85b"
|
||||||
|
dependencies = [
|
||||||
|
"actix-macros",
|
||||||
|
"actix-rt",
|
||||||
|
"actix_derive",
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"bytes",
|
||||||
|
"crossbeam-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"parking_lot",
|
||||||
|
"pin-project-lite",
|
||||||
|
"smallvec",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-codec"
|
name = "actix-codec"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@ -205,6 +230,17 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "actix_derive"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c7db3d5a9718568e4cf4a537cfd7070e6e6ff7481510d0237fb529ac850f6d3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.22.0"
|
version = "0.22.0"
|
||||||
@ -443,6 +479,7 @@ dependencies = [
|
|||||||
name = "central_backend"
|
name = "central_backend"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"actix",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"asn1",
|
"asn1",
|
||||||
@ -565,6 +602,21 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
@ -20,4 +20,5 @@ futures = "0.3.30"
|
|||||||
serde = { version = "1.0.203", features = ["derive"] }
|
serde = { version = "1.0.203", features = ["derive"] }
|
||||||
reqwest = "0.12.5"
|
reqwest = "0.12.5"
|
||||||
serde_json = "1.0.118"
|
serde_json = "1.0.118"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
actix = "0.13.5"
|
7
central_backend/src/constants.rs
Normal file
7
central_backend/src/constants.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// Energy refresh operations interval
|
||||||
|
pub const ENERGY_REFRESH_INTERVAL: Duration = Duration::from_secs(30);
|
||||||
|
|
||||||
|
/// Fallback value to use if production cannot be fetched
|
||||||
|
pub const FALLBACK_PRODUCTION_VALUE: i32 = 5000;
|
64
central_backend/src/energy/energy_actor.rs
Normal file
64
central_backend/src/energy/energy_actor.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use crate::constants;
|
||||||
|
use crate::energy::consumption;
|
||||||
|
use crate::energy::consumption::EnergyConsumption;
|
||||||
|
use actix::prelude::*;
|
||||||
|
|
||||||
|
pub struct EnergyActor {
|
||||||
|
curr_consumption: EnergyConsumption,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnergyActor {
|
||||||
|
pub async fn new() -> anyhow::Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
curr_consumption: consumption::get_curr_consumption().await?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,2 @@
|
|||||||
pub mod consumption;
|
pub mod consumption;
|
||||||
|
pub mod energy_actor;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
pub mod app_config;
|
pub mod app_config;
|
||||||
|
pub mod constants;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod energy;
|
pub mod energy;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
use actix::Actor;
|
||||||
use central_backend::app_config::AppConfig;
|
use central_backend::app_config::AppConfig;
|
||||||
use central_backend::crypto::pki;
|
use central_backend::crypto::pki;
|
||||||
|
use central_backend::energy::energy_actor::EnergyActor;
|
||||||
use central_backend::server::{secure_server, unsecure_server};
|
use central_backend::server::{secure_server, unsecure_server};
|
||||||
use central_backend::utils::files_utils::create_directory_if_missing;
|
use central_backend::utils::files_utils::create_directory_if_missing;
|
||||||
use futures::future;
|
use futures::future;
|
||||||
@ -22,7 +24,13 @@ async fn main() -> std::io::Result<()> {
|
|||||||
|
|
||||||
pki::refresh_crls().expect("Failed to initialize Root CA!");
|
pki::refresh_crls().expect("Failed to initialize Root CA!");
|
||||||
|
|
||||||
let s1 = secure_server();
|
// Initialize energy actor
|
||||||
|
let actor = EnergyActor::new()
|
||||||
|
.await
|
||||||
|
.expect("Failed to initialize energy actor!")
|
||||||
|
.start();
|
||||||
|
|
||||||
|
let s1 = secure_server(actor);
|
||||||
let s2 = unsecure_server();
|
let s2 = unsecure_server();
|
||||||
future::try_join(s1, s2)
|
future::try_join(s1, s2)
|
||||||
.await
|
.await
|
||||||
|
@ -85,6 +85,12 @@ impl From<actix_web::Error> for HttpErr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<actix::MailboxError> for HttpErr {
|
||||||
|
fn from(value: actix::MailboxError) -> Self {
|
||||||
|
HttpErr::Err(std::io::Error::new(ErrorKind::Other, value.to_string()).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<HttpResponse> for HttpErr {
|
impl From<HttpResponse> for HttpErr {
|
||||||
fn from(value: HttpResponse) -> Self {
|
fn from(value: HttpResponse) -> Self {
|
||||||
HttpErr::HTTPResponse(value)
|
HttpErr::HTTPResponse(value)
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use crate::energy::consumption;
|
use crate::energy::{consumption, energy_actor};
|
||||||
use crate::server::custom_error::HttpResult;
|
use crate::server::custom_error::HttpResult;
|
||||||
|
use crate::server::WebEnergyActor;
|
||||||
use actix_web::HttpResponse;
|
use actix_web::HttpResponse;
|
||||||
|
|
||||||
#[derive(serde::Serialize)]
|
#[derive(serde::Serialize)]
|
||||||
struct CurrConsumption {
|
struct Consumption {
|
||||||
consumption: i32,
|
consumption: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11,5 +12,12 @@ struct CurrConsumption {
|
|||||||
pub async fn curr_consumption() -> HttpResult {
|
pub async fn curr_consumption() -> HttpResult {
|
||||||
let consumption = consumption::get_curr_consumption().await?;
|
let consumption = consumption::get_curr_consumption().await?;
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(CurrConsumption { consumption }))
|
Ok(HttpResponse::Ok().json(Consumption { consumption }))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get cached energy consumption
|
||||||
|
pub async fn cached_consumption(energy_actor: WebEnergyActor) -> HttpResult {
|
||||||
|
let consumption = energy_actor.send(energy_actor::GetCurrConsumption).await?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json(Consumption { consumption }))
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,15 @@ use openssl::ssl::{SslAcceptor, SslMethod};
|
|||||||
|
|
||||||
use crate::app_config::AppConfig;
|
use crate::app_config::AppConfig;
|
||||||
use crate::crypto::pki;
|
use crate::crypto::pki;
|
||||||
|
use crate::energy::energy_actor::EnergyActorAddr;
|
||||||
|
|
||||||
pub mod custom_error;
|
pub mod custom_error;
|
||||||
pub mod energy_controller;
|
pub mod energy_controller;
|
||||||
pub mod pki_controller;
|
pub mod pki_controller;
|
||||||
pub mod server_controller;
|
pub mod server_controller;
|
||||||
|
|
||||||
|
pub type WebEnergyActor = web::Data<EnergyActorAddr>;
|
||||||
|
|
||||||
/// Start unsecure (HTTP) server
|
/// Start unsecure (HTTP) server
|
||||||
pub async fn unsecure_server() -> anyhow::Result<()> {
|
pub async fn unsecure_server() -> anyhow::Result<()> {
|
||||||
log::info!(
|
log::info!(
|
||||||
@ -31,7 +34,7 @@ pub async fn unsecure_server() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Start secure (HTTPS) server
|
/// Start secure (HTTPS) server
|
||||||
pub async fn secure_server() -> anyhow::Result<()> {
|
pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()> {
|
||||||
let web_ca = pki::CertData::load_web_ca()?;
|
let web_ca = pki::CertData::load_web_ca()?;
|
||||||
let server_cert = pki::CertData::load_server()?;
|
let server_cert = pki::CertData::load_server()?;
|
||||||
|
|
||||||
@ -45,14 +48,19 @@ pub async fn secure_server() -> anyhow::Result<()> {
|
|||||||
AppConfig::get().listen_address,
|
AppConfig::get().listen_address,
|
||||||
AppConfig::get().secure_origin()
|
AppConfig::get().secure_origin()
|
||||||
);
|
);
|
||||||
HttpServer::new(|| {
|
HttpServer::new(move || {
|
||||||
App::new()
|
App::new()
|
||||||
|
.app_data(web::Data::new(energy_actor.clone()))
|
||||||
.wrap(Logger::default())
|
.wrap(Logger::default())
|
||||||
.route("/", web::get().to(server_controller::secure_home))
|
.route("/", web::get().to(server_controller::secure_home))
|
||||||
.route(
|
.route(
|
||||||
"/api/energy/curr_consumption",
|
"/api/energy/curr_consumption",
|
||||||
web::get().to(energy_controller::curr_consumption),
|
web::get().to(energy_controller::curr_consumption),
|
||||||
)
|
)
|
||||||
|
.route(
|
||||||
|
"/api/energy/cached_consumption",
|
||||||
|
web::get().to(energy_controller::cached_consumption),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.bind_openssl(&AppConfig::get().listen_address, builder)?
|
.bind_openssl(&AppConfig::get().listen_address, builder)?
|
||||||
.run()
|
.run()
|
||||||
|
Loading…
Reference in New Issue
Block a user