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.
|
||||
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]]
|
||||
name = "actix-codec"
|
||||
version = "0.5.2"
|
||||
@ -205,6 +230,17 @@ dependencies = [
|
||||
"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]]
|
||||
name = "addr2line"
|
||||
version = "0.22.0"
|
||||
@ -443,6 +479,7 @@ dependencies = [
|
||||
name = "central_backend"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"actix",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"asn1",
|
||||
@ -565,6 +602,21 @@ dependencies = [
|
||||
"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]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
|
@ -21,3 +21,4 @@ serde = { version = "1.0.203", features = ["derive"] }
|
||||
reqwest = "0.12.5"
|
||||
serde_json = "1.0.118"
|
||||
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 energy_actor;
|
||||
|
@ -1,4 +1,5 @@
|
||||
pub mod app_config;
|
||||
pub mod constants;
|
||||
pub mod crypto;
|
||||
pub mod energy;
|
||||
pub mod server;
|
||||
|
@ -1,5 +1,7 @@
|
||||
use actix::Actor;
|
||||
use central_backend::app_config::AppConfig;
|
||||
use central_backend::crypto::pki;
|
||||
use central_backend::energy::energy_actor::EnergyActor;
|
||||
use central_backend::server::{secure_server, unsecure_server};
|
||||
use central_backend::utils::files_utils::create_directory_if_missing;
|
||||
use futures::future;
|
||||
@ -22,7 +24,13 @@ async fn main() -> std::io::Result<()> {
|
||||
|
||||
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();
|
||||
future::try_join(s1, s2)
|
||||
.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 {
|
||||
fn from(value: HttpResponse) -> Self {
|
||||
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::WebEnergyActor;
|
||||
use actix_web::HttpResponse;
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct CurrConsumption {
|
||||
struct Consumption {
|
||||
consumption: i32,
|
||||
}
|
||||
|
||||
@ -11,5 +12,12 @@ struct CurrConsumption {
|
||||
pub async fn curr_consumption() -> HttpResult {
|
||||
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::crypto::pki;
|
||||
use crate::energy::energy_actor::EnergyActorAddr;
|
||||
|
||||
pub mod custom_error;
|
||||
pub mod energy_controller;
|
||||
pub mod pki_controller;
|
||||
pub mod server_controller;
|
||||
|
||||
pub type WebEnergyActor = web::Data<EnergyActorAddr>;
|
||||
|
||||
/// Start unsecure (HTTP) server
|
||||
pub async fn unsecure_server() -> anyhow::Result<()> {
|
||||
log::info!(
|
||||
@ -31,7 +34,7 @@ pub async fn unsecure_server() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
/// 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 server_cert = pki::CertData::load_server()?;
|
||||
|
||||
@ -45,14 +48,19 @@ pub async fn secure_server() -> anyhow::Result<()> {
|
||||
AppConfig::get().listen_address,
|
||||
AppConfig::get().secure_origin()
|
||||
);
|
||||
HttpServer::new(|| {
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::Data::new(energy_actor.clone()))
|
||||
.wrap(Logger::default())
|
||||
.route("/", web::get().to(server_controller::secure_home))
|
||||
.route(
|
||||
"/api/energy/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)?
|
||||
.run()
|
||||
|
Loading…
Reference in New Issue
Block a user