Add the route to delete a relay

This commit is contained in:
Pierre HUBERT 2024-08-31 20:00:40 +02:00
parent 871d5109bf
commit f35aac04f6
5 changed files with 81 additions and 4 deletions

View File

@ -106,9 +106,9 @@ pub struct DeviceRelay {
/// Optional minimal runtime requirements for this relay /// Optional minimal runtime requirements for this relay
daily_runtime: Option<DailyMinRuntime>, daily_runtime: Option<DailyMinRuntime>,
/// Specify relay that must be turned on before this relay can be started /// Specify relay that must be turned on before this relay can be started
depends_on: Vec<DeviceRelayID>, pub depends_on: Vec<DeviceRelayID>,
/// Specify relays that must be turned off before this relay can be started /// Specify relays that must be turned off before this relay can be started
conflicts_with: Vec<DeviceRelayID>, pub conflicts_with: Vec<DeviceRelayID>,
} }
impl DeviceRelay { impl DeviceRelay {

View File

@ -23,6 +23,8 @@ pub enum DevicesListError {
DeviceNotFound, DeviceNotFound,
#[error("Requested device is not validated")] #[error("Requested device is not validated")]
DeviceNotValidated, DeviceNotValidated,
#[error("Failed to delete relay: {0}")]
DeleteRelayFailed(&'static str),
} }
pub struct DevicesList(HashMap<DeviceId, Device>); pub struct DevicesList(HashMap<DeviceId, Device>);
@ -221,4 +223,48 @@ impl DevicesList {
pub fn relay_get_single(&self, relay_id: DeviceRelayID) -> Option<DeviceRelay> { pub fn relay_get_single(&self, relay_id: DeviceRelayID) -> Option<DeviceRelay> {
self.relays_list().into_iter().find(|i| i.id == relay_id) self.relays_list().into_iter().find(|i| i.id == relay_id)
} }
/// Get the device hosting a relay
pub fn relay_get_device(&self, relay_id: DeviceRelayID) -> Option<Device> {
self.0
.iter()
.find(|r| r.1.relays.iter().any(|r| r.id == relay_id))
.map(|d| d.1.clone())
}
/// Get all the relays that depends directly on a relay
pub fn relay_get_direct_dependencies(&self, relay_id: DeviceRelayID) -> Vec<DeviceRelay> {
self.relays_list()
.into_iter()
.filter(|d| d.depends_on.contains(&relay_id))
.collect()
}
/// Delete a relay
pub fn relay_delete(&mut self, relay_id: DeviceRelayID) -> anyhow::Result<()> {
if !self.relay_get_direct_dependencies(relay_id).is_empty() {
return Err(DevicesListError::DeleteRelayFailed(
"At least one other relay depend on this relay!",
)
.into());
}
// Delete the relay
let device = self
.relay_get_device(relay_id)
.ok_or(DevicesListError::DeleteRelayFailed(
"Relay does not exists!",
))?;
let dev = self
.0
.get_mut(&device.id)
.ok_or(DevicesListError::UpdateDeviceFailedDeviceNotFound)?;
dev.relays.retain(|r| r.id != relay_id);
self.persist_dev_config(&device.id)?;
Ok(())
}
} }

View File

@ -212,3 +212,16 @@ impl Handler<GetSingleRelay> for EnergyActor {
self.devices.relay_get_single(msg.0) self.devices.relay_get_single(msg.0)
} }
} }
/// Delete a device relay
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct DeleteDeviceRelay(pub DeviceRelayID);
impl Handler<DeleteDeviceRelay> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: DeleteDeviceRelay, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.relay_delete(msg.0)
}
}

View File

@ -169,6 +169,10 @@ pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()>
"/web_api/relay/create", "/web_api/relay/create",
web::post().to(relays_controller::create), web::post().to(relays_controller::create),
) )
.route(
"/web_api/relay/{id}",
web::delete().to(relays_controller::delete),
)
// Devices API // Devices API
.route( .route(
"/devices_api/utils/time", "/devices_api/utils/time",

View File

@ -1,4 +1,4 @@
use crate::devices::device::{DeviceId, DeviceRelay}; use crate::devices::device::{DeviceId, DeviceRelay, DeviceRelayID};
use crate::energy::energy_actor; use crate::energy::energy_actor;
use crate::server::custom_error::HttpResult; use crate::server::custom_error::HttpResult;
use crate::server::WebEnergyActor; use crate::server::WebEnergyActor;
@ -48,7 +48,7 @@ pub async fn create(actor: WebEnergyActor, req: web::Json<CreateDeviceRelayReque
return Ok(HttpResponse::BadRequest().json("A relay with the same ID already exists!")); return Ok(HttpResponse::BadRequest().json("A relay with the same ID already exists!"));
} }
// Create the device // Create the device relay
actor actor
.send(energy_actor::CreateDeviceRelay( .send(energy_actor::CreateDeviceRelay(
req.device_id.clone(), req.device_id.clone(),
@ -58,3 +58,17 @@ pub async fn create(actor: WebEnergyActor, req: web::Json<CreateDeviceRelayReque
Ok(HttpResponse::Accepted().finish()) Ok(HttpResponse::Accepted().finish())
} }
#[derive(serde::Deserialize)]
pub struct RelayIDInPath {
id: DeviceRelayID,
}
/// Delete an existing relay
pub async fn delete(actor: WebEnergyActor, path: web::Path<RelayIDInPath>) -> HttpResult {
actor
.send(energy_actor::DeleteDeviceRelay(path.id))
.await??;
Ok(HttpResponse::Accepted().finish())
}