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)]
pub id: DeviceRelayID,
/// Human-readable name for the relay
name: String,
pub name: String,
/// 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
priority: usize,
pub priority: usize,
/// Estimated consumption of the electrical equipment triggered by the relay
consumption: usize,
/// 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,
#[error("Requested device is not validated")]
DeviceNotValidated,
#[error("Failed to update relay configuration: {0}")]
UpdateRelayFailed(&'static str),
#[error("Failed to delete relay: {0}")]
DeleteRelayFailed(&'static str),
}
@ -224,12 +226,23 @@ impl DevicesList {
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> {
/// Get a mutable reference on a single relay
pub fn relay_get_single_mut(&mut self, relay_id: DeviceRelayID) -> Option<&mut DeviceRelay> {
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))
.map(|d| d.1.clone())
.map(|d| d.1)
}
/// Get all the relays that depends directly on a relay
@ -240,6 +253,27 @@ impl DevicesList {
.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
pub fn relay_delete(&mut self, relay_id: DeviceRelayID) -> anyhow::Result<()> {
if !self.relay_get_direct_dependencies(relay_id).is_empty() {
@ -256,14 +290,10 @@ impl DevicesList {
"Relay does not exists!",
))?;
let dev = self
.0
.get_mut(&device.id)
.ok_or(DevicesListError::UpdateDeviceFailedDeviceNotFound)?;
device.relays.retain(|r| r.id != relay_id);
dev.relays.retain(|r| r.id != relay_id);
self.persist_dev_config(&device.id)?;
let device_id = device.id.clone();
self.persist_dev_config(&device_id)?;
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
#[derive(Message)]
#[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::post().to(relays_controller::create),
)
.route(
"/web_api/relay/{id}",
web::put().to(relays_controller::update),
)
.route(
"/web_api/relay/{id}",
web::delete().to(relays_controller::delete),

View File

@ -64,6 +64,27 @@ pub struct RelayIDInPath {
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
pub async fn delete(actor: WebEnergyActor, path: web::Path<RelayIDInPath>) -> HttpResult {
actor

View File

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