Can set device desired version

This commit is contained in:
2024-10-05 16:26:07 +02:00
parent 2f971c0055
commit 2feb3f6490
9 changed files with 107 additions and 3 deletions

View File

@ -9,7 +9,7 @@ use std::collections::{HashMap, HashSet};
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct DeviceInfo {
/// Device reference
reference: String,
pub reference: String,
/// Device firmware / software version
version: semver::Version,
/// Maximum number of relay that the device can support
@ -62,6 +62,9 @@ pub struct Device {
///
/// There cannot be more than [info.max_relays] relays
pub relays: Vec<DeviceRelay>,
/// Desired version, ie. the version of the software we would to seen run on the device
#[serde(skip_serializing_if = "Option::is_none")]
pub desired_version: Option<semver::Version>,
}
/// Structure that contains information about the minimal expected execution

View File

@ -84,6 +84,7 @@ impl DevicesList {
validated: false,
enabled: false,
relays: vec![],
desired_version: None,
};
// First, write CSR
@ -186,6 +187,24 @@ impl DevicesList {
Ok(())
}
/// Set a device desired version
pub fn set_desired_version(
&mut self,
id: &DeviceId,
version: Option<semver::Version>,
) -> anyhow::Result<()> {
let dev = self
.0
.get_mut(id)
.ok_or(DevicesListError::UpdateDeviceFailedDeviceNotFound)?;
dev.desired_version = version;
self.persist_dev_config(id)?;
Ok(())
}
/// Get single certificate information
fn get_cert(&self, id: &DeviceId) -> anyhow::Result<X509> {
let dev = self

View File

@ -195,6 +195,27 @@ impl Handler<UpdateDeviceGeneralInfo> for EnergyActor {
}
}
/// Set device desired version
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]
pub struct SetDesiredVersion(pub DeviceId, pub Option<semver::Version>);
impl Handler<SetDesiredVersion> for EnergyActor {
type Result = anyhow::Result<()>;
fn handle(&mut self, msg: SetDesiredVersion, _ctx: &mut Context<Self>) -> Self::Result {
log::info!(
"Requested to update device desired version {:?} => {:#?}",
&msg.0,
&msg.1
);
self.devices.set_desired_version(&msg.0, msg.1)?;
Ok(())
}
}
/// Delete a device
#[derive(Message)]
#[rtype(result = "anyhow::Result<()>")]

View File

@ -189,11 +189,13 @@ pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()>
"/web_api/ota/{platform}/{version}",
web::post().to(ota_controller::upload_firmware),
)
// TODO : upload a new software update
// TODO : list ota software update per platform
// TODO : download a OTA file
// TODO : delete an OTA file
// TODO : deploy an update to a device
.route(
"/web_api/ota/set_desired_version",
web::post().to(ota_controller::set_desired_version),
)
// Logging controller API
.route(
"/web_api/logging/logs",

View File

@ -1,7 +1,10 @@
use crate::constants;
use crate::devices::device::DeviceId;
use crate::energy::energy_actor;
use crate::ota::ota_manager;
use crate::ota::ota_update::OTAPlatform;
use crate::server::custom_error::HttpResult;
use crate::server::WebEnergyActor;
use actix_multipart::form::tempfile::TempFile;
use actix_multipart::form::MultipartForm;
use actix_web::{web, HttpResponse};
@ -49,3 +52,48 @@ pub async fn upload_firmware(
Ok(HttpResponse::Accepted().body("OTA update successfully saved."))
}
#[derive(serde::Deserialize)]
pub struct SetDesiredDeviceVersion {
devices: Option<Vec<DeviceId>>,
platform: Option<OTAPlatform>,
version: semver::Version,
}
pub async fn set_desired_version(
actor: WebEnergyActor,
body: web::Json<SetDesiredDeviceVersion>,
) -> HttpResult {
if body.devices.is_none() && body.platform.is_none() {
return Ok(
HttpResponse::BadRequest().json("Must specify one filter to select target devices!")
);
}
let devices = actor.send(energy_actor::GetDeviceLists).await?;
for d in devices {
// Filter per platform
if let Some(p) = body.platform {
if d.info.reference != p.to_string() {
continue;
}
}
// Filter per device
if let Some(ids) = &body.devices {
if !ids.contains(&d.id) {
continue;
}
}
actor
.send(energy_actor::SetDesiredVersion(
d.id,
Some(body.version.clone()),
))
.await??;
}
Ok(HttpResponse::Ok().finish())
}