Add the route to update a relay

This commit is contained in:
Pierre HUBERT 2024-08-31 20:26:16 +02:00
parent b0023a5167
commit bbe128e055
6 changed files with 88 additions and 15 deletions

View File

@ -92,11 +92,11 @@ pub struct DeviceRelay {
#[serde(default)] #[serde(default)]
pub id: DeviceRelayID, pub id: DeviceRelayID,
/// Human-readable name for the relay /// Human-readable name for the relay
name: String, pub name: String,
/// Whether this relay can be turned on or not /// Whether this relay can be turned on or not
enabled: bool, pub enabled: bool,
/// Relay priority when selecting relays to turn on. 0 = lowest priority /// Relay priority when selecting relays to turn on. 0 = lowest priority
priority: usize, pub priority: usize,
/// Estimated consumption of the electrical equipment triggered by the relay /// Estimated consumption of the electrical equipment triggered by the relay
consumption: usize, consumption: usize,
/// Minimal time this relay shall be left on before it can be turned off (in seconds) /// Minimal time this relay shall be left on before it can be turned off (in seconds)

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 update relay configuration: {0}")]
UpdateRelayFailed(&'static str),
#[error("Failed to delete relay: {0}")] #[error("Failed to delete relay: {0}")]
DeleteRelayFailed(&'static str), DeleteRelayFailed(&'static str),
} }
@ -224,12 +226,23 @@ impl DevicesList {
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 /// Get a mutable reference on a single relay
pub fn relay_get_device(&self, relay_id: DeviceRelayID) -> Option<Device> { pub fn relay_get_single_mut(&mut self, relay_id: DeviceRelayID) -> Option<&mut DeviceRelay> {
self.0 self.0
.iter() .iter_mut()
.find(|d| d.1.relays.iter().any(|r| r.id == relay_id))?
.1
.relays
.iter_mut()
.find(|r| r.id == relay_id)
}
/// Get the device hosting a relay
pub fn relay_get_device(&mut self, relay_id: DeviceRelayID) -> Option<&mut Device> {
self.0
.iter_mut()
.find(|r| r.1.relays.iter().any(|r| r.id == relay_id)) .find(|r| r.1.relays.iter().any(|r| r.id == relay_id))
.map(|d| d.1.clone()) .map(|d| d.1)
} }
/// Get all the relays that depends directly on a relay /// Get all the relays that depends directly on a relay
@ -240,6 +253,27 @@ impl DevicesList {
.collect() .collect()
} }
/// Update a relay configuration
pub fn relay_update(&mut self, relay: DeviceRelay) -> anyhow::Result<()> {
let device = self
.relay_get_device(relay.id)
.ok_or(DevicesListError::UpdateRelayFailed(
"Relay does not exists!",
))?;
let idx = device.relays.iter().position(|r| r.id == relay.id).ok_or(
DevicesListError::UpdateRelayFailed("Relay index not found!"),
)?;
// Update the relay configuration
device.relays[idx] = relay;
let device_id = device.id.clone();
self.persist_dev_config(&device_id)?;
Ok(())
}
/// Delete a relay /// Delete a relay
pub fn relay_delete(&mut self, relay_id: DeviceRelayID) -> anyhow::Result<()> { pub fn relay_delete(&mut self, relay_id: DeviceRelayID) -> anyhow::Result<()> {
if !self.relay_get_direct_dependencies(relay_id).is_empty() { if !self.relay_get_direct_dependencies(relay_id).is_empty() {
@ -256,14 +290,10 @@ impl DevicesList {
"Relay does not exists!", "Relay does not exists!",
))?; ))?;
let dev = self device.relays.retain(|r| r.id != relay_id);
.0
.get_mut(&device.id)
.ok_or(DevicesListError::UpdateDeviceFailedDeviceNotFound)?;
dev.relays.retain(|r| r.id != relay_id); let device_id = device.id.clone();
self.persist_dev_config(&device_id)?;
self.persist_dev_config(&device.id)?;
Ok(()) Ok(())
} }

View File

@ -213,6 +213,19 @@ impl Handler<GetSingleRelay> for EnergyActor {
} }
} }
/// Update a device relay
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct UpdateDeviceRelay(pub DeviceRelay);
impl Handler<UpdateDeviceRelay> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: UpdateDeviceRelay, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.relay_update(msg.0)
}
}
/// Delete a device relay /// Delete a device relay
#[derive(Message)] #[derive(Message)]
#[rtype(result = "anyhow::Result<()>")] #[rtype(result = "anyhow::Result<()>")]

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::put().to(relays_controller::update),
)
.route( .route(
"/web_api/relay/{id}", "/web_api/relay/{id}",
web::delete().to(relays_controller::delete), web::delete().to(relays_controller::delete),

View File

@ -64,6 +64,27 @@ pub struct RelayIDInPath {
id: DeviceRelayID, id: DeviceRelayID,
} }
/// Update a relay configuration
pub async fn update(
actor: WebEnergyActor,
mut req: web::Json<DeviceRelay>,
path: web::Path<RelayIDInPath>,
) -> HttpResult {
req.id = path.id;
let list = actor.send(energy_actor::GetRelaysList).await?;
if let Some(e) = req.error(&list) {
log::error!("Invalid relay update query: {e}");
return Ok(HttpResponse::BadRequest().json(e));
}
// Create the device relay
actor.send(energy_actor::UpdateDeviceRelay(req.0)).await??;
Ok(HttpResponse::Accepted().finish())
}
/// Delete an existing relay /// Delete an existing relay
pub async fn delete(actor: WebEnergyActor, path: web::Path<RelayIDInPath>) -> HttpResult { pub async fn delete(actor: WebEnergyActor, path: web::Path<RelayIDInPath>) -> HttpResult {
actor actor

View File

@ -35,6 +35,11 @@ export function DeviceRelays(p: {
setCurrRelay(undefined); setCurrRelay(undefined);
}; };
const updateRelay = async (r: DeviceRelay) => {
setDialogOpen(true);
setCurrRelay(r);
};
const deleteRelay = async (r: DeviceRelay) => { const deleteRelay = async (r: DeviceRelay) => {
if ( if (
!(await confirm("Do you really want to delete this relay configuration?")) !(await confirm("Do you really want to delete this relay configuration?"))
@ -95,7 +100,7 @@ export function DeviceRelays(p: {
secondaryAction={ secondaryAction={
<> <>
<Tooltip title="Edit the relay configuration"> <Tooltip title="Edit the relay configuration">
<IconButton> <IconButton onClick={() => updateRelay(r)}>
<EditIcon /> <EditIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>