Store last ping of devices

This commit is contained in:
Pierre HUBERT 2024-09-09 21:05:52 +02:00
parent 6bdebe6932
commit 7cac6aeb35
4 changed files with 80 additions and 0 deletions

View File

@ -6,6 +6,9 @@ pub const SESSION_COOKIE_NAME: &str = "X-session-cookie";
/// Energy refresh operations interval
pub const ENERGY_REFRESH_INTERVAL: Duration = Duration::from_secs(30);
/// Maximum time after a ping during which a device is considered "up"
pub const DEVICE_MAX_PING_TIME: u64 = 30;
/// Fallback value to use if production cannot be fetched
pub const FALLBACK_PRODUCTION_VALUE: i32 = 5000;

View File

@ -5,12 +5,33 @@ use crate::devices::device::{
use crate::devices::devices_list::DevicesList;
use crate::energy::consumption;
use crate::energy::consumption::EnergyConsumption;
use crate::utils::time_utils::time_secs;
use actix::prelude::*;
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 {
curr_consumption: EnergyConsumption,
devices: DevicesList,
devices_state: HashMap<DeviceId, DeviceState>,
relays_state: HashMap<DeviceRelayID, RelayState>,
}
impl EnergyActor {
@ -18,9 +39,20 @@ impl EnergyActor {
Ok(Self {
curr_consumption: consumption::get_curr_consumption().await?,
devices: DevicesList::load()?,
devices_state: Default::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<()> {
// Refresh energy
self.curr_consumption = consumption::get_curr_consumption()
@ -253,6 +285,9 @@ impl Handler<SynchronizeDevice> for EnergyActor {
type Result = anyhow::Result<Vec<RelaySyncStatus>>;
fn handle(&mut self, msg: SynchronizeDevice, _ctx: &mut Context<Self>) -> Self::Result {
let s = self.device_state(&msg.0);
s.last_ping = time_secs();
// TODO : implement real code
let mut v = vec![];
for i in 0..msg.1.max_relays {
@ -263,3 +298,34 @@ impl Handler<SynchronizeDevice> for EnergyActor {
Ok(v)
}
}
#[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()
}
}

View File

@ -144,6 +144,10 @@ pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()>
"/web_api/devices/list_validated",
web::get().to(devices_controller::list_validated),
)
.route(
"/web_api/devices/state",
web::get().to(devices_controller::devices_state),
)
.route(
"/web_api/device/{id}",
web::get().to(devices_controller::get_single),

View File

@ -28,6 +28,13 @@ pub async fn list_validated(actor: WebEnergyActor) -> HttpResult {
Ok(HttpResponse::Ok().json(list))
}
/// Get the state of devices
pub async fn devices_state(actor: WebEnergyActor) -> HttpResult {
let states = actor.send(energy_actor::GetDevicesState).await?;
Ok(HttpResponse::Ok().json(states))
}
#[derive(serde::Deserialize)]
pub struct DeviceInPath {
id: DeviceId,