Can create a relay

This commit is contained in:
Pierre HUBERT 2024-08-27 22:32:22 +02:00
parent f46a7dbc94
commit 87fb3360fb
6 changed files with 89 additions and 11 deletions

View File

@ -13,7 +13,7 @@ pub struct DeviceInfo {
/// Device firmware / software version /// Device firmware / software version
version: semver::Version, version: semver::Version,
/// Maximum number of relay that the device can support /// Maximum number of relay that the device can support
max_relays: usize, pub max_relays: usize,
} }
impl DeviceInfo { impl DeviceInfo {
@ -90,7 +90,7 @@ impl Default for DeviceRelayID {
pub struct DeviceRelay { pub struct DeviceRelay {
/// Device relay id. Should be unique across the whole application /// Device relay id. Should be unique across the whole application
#[serde(default)] #[serde(default)]
id: DeviceRelayID, pub id: DeviceRelayID,
/// Human-readable name for the relay /// Human-readable name for the relay
name: String, name: String,
/// Whether this relay can be turned on or not /// Whether this relay can be turned on or not
@ -165,7 +165,7 @@ impl DeviceRelay {
} }
} }
let mut relays_map = list.iter().map(|r| (r.id, r)).collect::<HashMap<_, _>>(); let relays_map = list.iter().map(|r| (r.id, r)).collect::<HashMap<_, _>>();
if self.depends_on.iter().any(|d| !relays_map.contains_key(d)) { if self.depends_on.iter().any(|d| !relays_map.contains_key(d)) {
return Some("A specified dependent relay does not exists!"); return Some("A specified dependent relay does not exists!");
@ -212,12 +212,12 @@ impl DeviceRelay {
clone.insert(self.id); clone.insert(self.id);
for d in &self.depends_on { for d in &self.depends_on {
if visited.contains(&d) { if visited.contains(d) {
return true; return true;
} }
if list if list
.get(&d) .get(d)
.expect("Missing a relay!") .expect("Missing a relay!")
.check_for_loop_in_dependencies(&clone, list) .check_for_loop_in_dependencies(&clone, list)
{ {
@ -235,7 +235,7 @@ impl DeviceRelay {
list: &HashMap<DeviceRelayID, &Self>, list: &HashMap<DeviceRelayID, &Self>,
) { ) {
for d in &self.depends_on { for d in &self.depends_on {
let dependency = list.get(&d).expect("Missing a relay!"); let dependency = list.get(d).expect("Missing a relay!");
deps_out.insert(dependency.id); deps_out.insert(dependency.id);

View File

@ -1,6 +1,8 @@
use crate::app_config::AppConfig; use crate::app_config::AppConfig;
use crate::crypto::pki; use crate::crypto::pki;
use crate::devices::device::{Device, DeviceGeneralInfo, DeviceId, DeviceInfo, DeviceRelay}; use crate::devices::device::{
Device, DeviceGeneralInfo, DeviceId, DeviceInfo, DeviceRelay, DeviceRelayID,
};
use crate::utils::time_utils::time_secs; use crate::utils::time_utils::time_secs;
use openssl::x509::{X509Req, X509}; use openssl::x509::{X509Req, X509};
use std::collections::HashMap; use std::collections::HashMap;
@ -194,10 +196,29 @@ impl DevicesList {
} }
/// Get the full list of relays /// Get the full list of relays
pub fn relays_list(&mut self) -> Vec<DeviceRelay> { pub fn relays_list(&self) -> Vec<DeviceRelay> {
self.0 self.0
.iter() .iter()
.flat_map(|(_id, d)| d.relays.clone()) .flat_map(|(_id, d)| d.relays.clone())
.collect() .collect()
} }
/// Create a new relay
pub fn relay_create(&mut self, dev_id: &DeviceId, relay: DeviceRelay) -> anyhow::Result<()> {
let dev = self
.0
.get_mut(dev_id)
.ok_or(DevicesListError::DeviceNotFound)?;
dev.relays.push(relay);
self.persist_dev_config(dev_id)?;
Ok(())
}
/// Get a single relay
pub fn relay_get_single(&self, relay_id: DeviceRelayID) -> Option<DeviceRelay> {
self.relays_list().into_iter().find(|i| i.id == relay_id)
}
} }

View File

@ -1,5 +1,7 @@
use crate::constants; use crate::constants;
use crate::devices::device::{Device, DeviceGeneralInfo, DeviceId, DeviceInfo, DeviceRelay}; use crate::devices::device::{
Device, DeviceGeneralInfo, DeviceId, DeviceInfo, DeviceRelay, DeviceRelayID,
};
use crate::devices::devices_list::DevicesList; use crate::devices::devices_list::DevicesList;
use crate::energy::consumption; use crate::energy::consumption;
use crate::energy::consumption::EnergyConsumption; use crate::energy::consumption::EnergyConsumption;
@ -184,3 +186,29 @@ impl Handler<GetRelaysList> for EnergyActor {
self.devices.relays_list() self.devices.relays_list()
} }
} }
/// Create a new device relay
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct CreateDeviceRelay(pub DeviceId, pub DeviceRelay);
impl Handler<CreateDeviceRelay> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: CreateDeviceRelay, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.relay_create(&msg.0, msg.1)
}
}
/// Get the information about a single relay
#[derive(Message)]
#[rtype(result = "Option<DeviceRelay>")]
pub struct GetSingleRelay(pub DeviceRelayID);
impl Handler<GetSingleRelay> for EnergyActor {
type Result = Option<DeviceRelay>;
fn handle(&mut self, msg: GetSingleRelay, _ctx: &mut Context<Self>) -> Self::Result {
self.devices.relay_get_single(msg.0)
}
}

View File

@ -166,7 +166,7 @@ pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()>
web::get().to(relays_controller::get_list), web::get().to(relays_controller::get_list),
) )
.route( .route(
"/web_api/relays/create", "/web_api/relay/create",
web::post().to(relays_controller::create), web::post().to(relays_controller::create),
) )
// Devices API // Devices API

View File

@ -19,5 +19,33 @@ pub struct CreateDeviceRelayRequest {
/// Create a new relay /// Create a new relay
pub async fn create(actor: WebEnergyActor, req: web::Json<CreateDeviceRelayRequest>) -> HttpResult { pub async fn create(actor: WebEnergyActor, req: web::Json<CreateDeviceRelayRequest>) -> HttpResult {
todo!() let list = actor.send(energy_actor::GetRelaysList).await?;
if let Some(e) = req.relay.error(&list) {
log::error!("Invalid relay create query: {e}");
return Ok(HttpResponse::BadRequest().json(e));
}
let Some(device) = actor
.send(energy_actor::GetSingleDevice(req.device_id.clone()))
.await?
else {
log::error!("Invalid relay create query: specified device does not exists!");
return Ok(HttpResponse::NotFound().json("Linked device not found!"));
};
if device.relays.len() >= device.info.max_relays {
log::error!("Invalid relay create query: too many relay for the target device!");
return Ok(HttpResponse::BadRequest().json("Too many relays for the target device!"));
}
// Create the device
actor
.send(energy_actor::CreateDeviceRelay(
req.device_id.clone(),
req.relay.clone(),
))
.await??;
Ok(HttpResponse::Accepted().finish())
} }

View File

@ -23,6 +23,7 @@ export class RelayApi {
uri: "/relay/create", uri: "/relay/create",
jsonData: { jsonData: {
...relay, ...relay,
id: undefined,
device_id: device.id, device_id: device.id,
}, },
}); });