Store last ping of devices
This commit is contained in:
		| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user