Can create a relay
This commit is contained in:
		@@ -13,7 +13,7 @@ pub struct DeviceInfo {
 | 
			
		||||
    /// Device firmware / software version
 | 
			
		||||
    version: semver::Version,
 | 
			
		||||
    /// Maximum number of relay that the device can support
 | 
			
		||||
    max_relays: usize,
 | 
			
		||||
    pub max_relays: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DeviceInfo {
 | 
			
		||||
@@ -90,7 +90,7 @@ impl Default for DeviceRelayID {
 | 
			
		||||
pub struct DeviceRelay {
 | 
			
		||||
    /// Device relay id. Should be unique across the whole application
 | 
			
		||||
    #[serde(default)]
 | 
			
		||||
    id: DeviceRelayID,
 | 
			
		||||
    pub id: DeviceRelayID,
 | 
			
		||||
    /// Human-readable name for the relay
 | 
			
		||||
    name: String,
 | 
			
		||||
    /// 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)) {
 | 
			
		||||
            return Some("A specified dependent relay does not exists!");
 | 
			
		||||
@@ -212,12 +212,12 @@ impl DeviceRelay {
 | 
			
		||||
        clone.insert(self.id);
 | 
			
		||||
 | 
			
		||||
        for d in &self.depends_on {
 | 
			
		||||
            if visited.contains(&d) {
 | 
			
		||||
            if visited.contains(d) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if list
 | 
			
		||||
                .get(&d)
 | 
			
		||||
                .get(d)
 | 
			
		||||
                .expect("Missing a relay!")
 | 
			
		||||
                .check_for_loop_in_dependencies(&clone, list)
 | 
			
		||||
            {
 | 
			
		||||
@@ -235,7 +235,7 @@ impl DeviceRelay {
 | 
			
		||||
        list: &HashMap<DeviceRelayID, &Self>,
 | 
			
		||||
    ) {
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
use crate::app_config::AppConfig;
 | 
			
		||||
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 openssl::x509::{X509Req, X509};
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
@@ -194,10 +196,29 @@ impl DevicesList {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get the full list of relays
 | 
			
		||||
    pub fn relays_list(&mut self) -> Vec<DeviceRelay> {
 | 
			
		||||
    pub fn relays_list(&self) -> Vec<DeviceRelay> {
 | 
			
		||||
        self.0
 | 
			
		||||
            .iter()
 | 
			
		||||
            .flat_map(|(_id, d)| d.relays.clone())
 | 
			
		||||
            .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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
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::energy::consumption;
 | 
			
		||||
use crate::energy::consumption::EnergyConsumption;
 | 
			
		||||
@@ -184,3 +186,29 @@ impl Handler<GetRelaysList> for EnergyActor {
 | 
			
		||||
        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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -166,7 +166,7 @@ pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()>
 | 
			
		||||
                web::get().to(relays_controller::get_list),
 | 
			
		||||
            )
 | 
			
		||||
            .route(
 | 
			
		||||
                "/web_api/relays/create",
 | 
			
		||||
                "/web_api/relay/create",
 | 
			
		||||
                web::post().to(relays_controller::create),
 | 
			
		||||
            )
 | 
			
		||||
            // Devices API
 | 
			
		||||
 
 | 
			
		||||
@@ -19,5 +19,33 @@ pub struct CreateDeviceRelayRequest {
 | 
			
		||||
 | 
			
		||||
/// Create a new relay
 | 
			
		||||
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())
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ export class RelayApi {
 | 
			
		||||
      uri: "/relay/create",
 | 
			
		||||
      jsonData: {
 | 
			
		||||
        ...relay,
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        device_id: device.id,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user