//! Routes for legacy API present in versions <= 2.0.0 of the firmware.
use crate::api::into_legacy_response::LegacyResponse;
use crate::api::into_legacy_response::{LegacyResult, Null};
+use crate::app::bmc_application::NodeInfo;
use crate::app::bmc_application::{BmcApplication, UsbConfig};
use crate::app::bmc_info::{
get_fs_stat, get_ipv4_address, get_mac_address, get_net_interfaces, get_storage_info,
use crate::serial_service::{legacy_serial_get_handler, legacy_serial_set_handler};
use crate::streaming_data_service::data_transfer::DataTransfer;
use crate::streaming_data_service::StreamingDataService;
-use crate::utils;
use actix_files::file_extension_to_mime;
use actix_multipart::Multipart;
use actix_web::guard::{fn_guard, GuardContext};
}]
}
}
-
-#[derive(Debug, serde::Deserialize)]
-struct SetNodeInfos {
- node_info: Vec<SetNodeInfo>,
-}
-
-#[derive(Debug, Clone, serde::Deserialize)]
-pub struct SetNodeInfo {
- pub node: u8,
- pub name: Option<String>,
- pub module_name: Option<String>,
- pub uart_baud: Option<u32>,
-}
-
async fn set_node_aux_info(
bmc: web::Data<BmcApplication>,
- payload: web::Json<SetNodeInfos>,
+ payload: web::Json<HashMap<NodeId, NodeInfo>>,
) -> impl Responder {
- for info in &payload.node_info {
- bmc.set_node_info(info.clone()).await?;
- }
-
+ bmc.set_node_info(payload.into_inner()).await?;
Ok::<Null, LegacyResponse>(Null)
}
-async fn get_node_aux_info(bmc: &BmcApplication) -> impl Into<LegacyResponse> {
- let Some(current_time) = utils::get_timestamp_unix() else {
- anyhow::bail!("Current time before Unix epoch");
- };
-
- let infos = bmc.get_node_infos().await;
-
- let mut output = json!(
- {
- "node_info": []
- }
- );
-
- let array = output["node_info"].as_array_mut().expect("key mismatch");
-
- for (i, n) in infos.data.iter().enumerate() {
- let insert_idx = array.len();
- let key = (i + 1).to_string();
- let uptime = match n.power_on_time {
- Some(powered_on) => current_time - powered_on,
- None => 0,
- };
-
- let node_info = json!(
- {
- key: {
- "name": n.name,
- "module_name": n.module_name,
- "uptime": uptime,
- "uart_baud": n.uart_baud,
- }
- }
- );
-
- array.insert(insert_idx, node_info);
- }
-
- Ok(output)
+async fn get_node_aux_info(bmc: &BmcApplication) -> LegacyResult<serde_json::Value> {
+ let infos = bmc.get_node_infos().await?;
+ Ok(serde_json::to_value(infos)?)
}
async fn set_node_to_msd(bmc: &BmcApplication, query: Query) -> LegacyResult<()> {
msg.unwrap_or("transfer canceled".to_string()),
)
}
+
+#[cfg(test)]
+mod test {
+
+ use super::*;
+
+ #[actix_web::test]
+ async fn test_node_info() {
+ let json = serde_json::json! {
+ {
+ "Node1": {
+ "module_name": "Raspberry Pi CM4"
+ },
+ "Node3": {
+ "name": "New jeston"
+ }
+ }
+ };
+ let _: HashMap<NodeId, NodeInfo> = serde_json::from_value(json).unwrap();
+ }
+}
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-use crate::api::legacy::SetNodeInfo;
use crate::hal::helpers::bit_iterator;
use crate::hal::PowerController;
use crate::hal::{NodeId, PinController, UsbMode, UsbRoute};
use crate::persistency::app_persistency::ApplicationPersistency;
use crate::persistency::app_persistency::PersistencyBuilder;
use crate::usb_boot::NodeDrivers;
-use crate::utils::get_timestamp_unix;
+use crate::utils::{self, get_timestamp_unix};
use crate::{
app::usb_gadget::append_msd_config_to_usb_gadget,
app::usb_gadget::remove_msd_function_from_usb_gadget,
use log::info;
use log::{debug, trace};
use serde::{Deserialize, Serialize};
+use std::collections::HashMap;
use std::path::PathBuf;
use std::process::Command;
use std::time::Duration;
use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite};
+pub type NodeInfos = [NodeInfo; 4];
+
/// Stores which slots are actually used. This information is used to determine
/// for instance, which nodes need to be powered on, when such command is given
pub const ACTIVATED_NODES_KEY: &str = "activated_nodes";
Flashing(NodeId, UsbRoute),
}
-#[derive(Debug, serde::Serialize, serde::Deserialize)]
-pub struct NodeInfos {
- pub data: Vec<NodeInfo>,
-}
-
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
pub struct NodeInfo {
- pub name: String,
- pub module_name: String,
+ pub name: Option<String>,
+ pub module_name: Option<String>,
pub power_on_time: Option<u64>,
- pub uart_baud: u32,
-}
-
-impl Default for NodeInfos {
- fn default() -> Self {
- Self {
- data: vec![NodeInfo::new(); 4],
- }
- }
-}
-
-impl NodeInfo {
- fn new() -> Self {
- Self {
- uart_baud: 115_200,
- ..Default::default()
- }
- }
+ pub uart_baud: Option<u32>,
}
pub struct BmcApplication {
for (idx, new_state) in bit_iterator(node_states, mask) {
let current_state = activated_nodes & (1 << idx);
let current_time = get_timestamp_unix();
- let node_info = &mut node_infos.data[idx];
+ let node_info = &mut node_infos[idx];
if new_state != current_state {
if new_state == 1 {
Ok(())
}
- pub async fn set_node_info(&self, info: SetNodeInfo) -> anyhow::Result<()> {
- ensure!(info.node >= 1 && info.node <= 4);
+ pub async fn set_node_info(&self, new_info: HashMap<NodeId, NodeInfo>) -> anyhow::Result<()> {
+ let mut stored_nodes = self.app_db.get::<NodeInfos>(NODE_INFO_KEY).await;
- let node_idx = info.node - 1;
- let mut node_infos = self.app_db.get::<NodeInfos>(NODE_INFO_KEY).await;
- let node_info = &mut node_infos.data[usize::from(node_idx)];
+ for (i, info) in &mut new_info.into_iter().map(|(k, v)| (k as usize, v)) {
+ let store_node = &mut stored_nodes[i];
- if let Some(name) = info.name {
- node_info.name = name;
- }
+ if let Some(name) = info.name {
+ store_node.name = Some(name);
+ }
- if let Some(module_name) = info.module_name {
- node_info.module_name = module_name;
- }
+ if let Some(module_name) = info.module_name {
+ store_node.module_name = Some(module_name);
+ }
- if let Some(uart_baud) = info.uart_baud {
- node_info.uart_baud = uart_baud;
+ if let Some(uart_baud) = info.uart_baud {
+ store_node.uart_baud = Some(uart_baud);
+ }
}
self.app_db
- .set::<NodeInfos>(NODE_INFO_KEY, node_infos)
+ .set::<NodeInfos>(NODE_INFO_KEY, stored_nodes)
.await;
Ok(())
}
- pub async fn get_node_infos(&self) -> NodeInfos {
- self.app_db.get::<NodeInfos>(NODE_INFO_KEY).await
+ pub async fn get_node_infos(&self) -> anyhow::Result<NodeInfos> {
+ let Some(current_time) = utils::get_timestamp_unix() else {
+ anyhow::bail!("Current time before Unix epoch");
+ };
+
+ let mut node_infos = self.app_db.get::<NodeInfos>(NODE_INFO_KEY).await;
+ node_infos.iter_mut().for_each(|info| {
+ if let Some(time) = &mut info.power_on_time {
+ *time = current_time - *time;
+ }
+ });
+
+ Ok(node_infos)
}
}