take image metadata generation #30
@ -30,7 +30,7 @@ use derive_new::new;
|
|||||||
use log::info;
|
use log::info;
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
use ops_sat_rs::config::cam_error::{self, CameraError};
|
use ops_sat_rs::config::cam_error::{self, CameraError};
|
||||||
use ops_sat_rs::config::{GENERIC_FAILED, HOME_PATH};
|
use ops_sat_rs::config::GENERIC_FAILED;
|
||||||
use ops_sat_rs::TimeStampHelper;
|
use ops_sat_rs::TimeStampHelper;
|
||||||
use satrs::action::{ActionRequest, ActionRequestVariant};
|
use satrs::action::{ActionRequest, ActionRequestVariant};
|
||||||
use satrs::hk::HkRequest;
|
use satrs::hk::HkRequest;
|
||||||
@ -41,6 +41,7 @@ use satrs::res_code::ResultU16;
|
|||||||
use satrs::tmtc::PacketAsVec;
|
use satrs::tmtc::PacketAsVec;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Output};
|
use std::process::{Command, Output};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
@ -103,7 +104,7 @@ pub enum ActionId {
|
|||||||
|
|
||||||
// TODO what happens if limits are exceded
|
// TODO what happens if limits are exceded
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, new)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, new)]
|
||||||
pub struct CameraPictureParameters {
|
pub struct CameraPictureParameters {
|
||||||
pub R: u8,
|
pub R: u8,
|
||||||
pub G: u8,
|
pub G: u8,
|
||||||
@ -158,7 +159,8 @@ impl TakeImageExecutor for Ims100ImageExecutor {
|
|||||||
|
|
||||||
pub struct Ims100BatchHandler<ImgExecutor: TakeImageExecutor = Ims100ImageExecutor> {
|
pub struct Ims100BatchHandler<ImgExecutor: TakeImageExecutor = Ims100ImageExecutor> {
|
||||||
id: UniqueApidTargetId,
|
id: UniqueApidTargetId,
|
||||||
image_executor: ImgExecutor,
|
pub image_executor: ImgExecutor,
|
||||||
|
pub home_path: PathBuf,
|
||||||
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
||||||
tm_tx: mpsc::Sender<PacketAsVec>,
|
tm_tx: mpsc::Sender<PacketAsVec>,
|
||||||
action_reply_tx: mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
action_reply_tx: mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
||||||
@ -169,6 +171,7 @@ impl<ImgExecutor: TakeImageExecutor> Ims100BatchHandler<ImgExecutor> {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
id: UniqueApidTargetId,
|
id: UniqueApidTargetId,
|
||||||
image_executor: ImgExecutor,
|
image_executor: ImgExecutor,
|
||||||
|
home_path: &Path,
|
||||||
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
||||||
tm_tx: mpsc::Sender<PacketAsVec>,
|
tm_tx: mpsc::Sender<PacketAsVec>,
|
||||||
action_reply_tx: mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
action_reply_tx: mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
||||||
@ -177,6 +180,7 @@ impl<ImgExecutor: TakeImageExecutor> Ims100BatchHandler<ImgExecutor> {
|
|||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
image_executor,
|
image_executor,
|
||||||
|
home_path: home_path.to_path_buf(),
|
||||||
composite_request_rx,
|
composite_request_rx,
|
||||||
tm_tx,
|
tm_tx,
|
||||||
action_reply_tx,
|
action_reply_tx,
|
||||||
@ -322,7 +326,7 @@ impl<ImgExecutor: TakeImageExecutor> Ims100BatchHandler<ImgExecutor> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let unix_timestamp = unix_timestamp.unwrap().as_millis();
|
let unix_timestamp = unix_timestamp.unwrap().as_millis();
|
||||||
let mut metadata_path = HOME_PATH.get().unwrap().clone();
|
let mut metadata_path = self.home_path.clone();
|
||||||
metadata_path.push(format!("img_msec_{}.txt", unix_timestamp));
|
metadata_path.push(format!("img_msec_{}.txt", unix_timestamp));
|
||||||
let mut file = std::fs::File::create(metadata_path)?;
|
let mut file = std::fs::File::create(metadata_path)?;
|
||||||
writeln!(file, "time: {}", humantime::format_rfc3339_seconds(now))?;
|
writeln!(file, "time: {}", humantime::format_rfc3339_seconds(now))?;
|
||||||
@ -397,6 +401,7 @@ impl<ImgExecutor: TakeImageExecutor> Ims100BatchHandler<ImgExecutor> {
|
|||||||
impl Ims100BatchHandler {
|
impl Ims100BatchHandler {
|
||||||
pub fn new_with_default_img_executor(
|
pub fn new_with_default_img_executor(
|
||||||
id: UniqueApidTargetId,
|
id: UniqueApidTargetId,
|
||||||
|
home_path: &Path,
|
||||||
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
||||||
tm_tx: mpsc::Sender<PacketAsVec>,
|
tm_tx: mpsc::Sender<PacketAsVec>,
|
||||||
action_reply_tx: mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
action_reply_tx: mpsc::Sender<GenericMessage<ActionReplyPus>>,
|
||||||
@ -405,6 +410,7 @@ impl Ims100BatchHandler {
|
|||||||
Self::new(
|
Self::new(
|
||||||
id,
|
id,
|
||||||
Ims100ImageExecutor::default(),
|
Ims100ImageExecutor::default(),
|
||||||
|
home_path,
|
||||||
composite_request_rx,
|
composite_request_rx,
|
||||||
tm_tx,
|
tm_tx,
|
||||||
action_reply_tx,
|
action_reply_tx,
|
||||||
@ -420,7 +426,6 @@ mod tests {
|
|||||||
};
|
};
|
||||||
use crate::requests::CompositeRequest;
|
use crate::requests::CompositeRequest;
|
||||||
use ops_sat_rs::config::components::CAMERA_HANDLER;
|
use ops_sat_rs::config::components::CAMERA_HANDLER;
|
||||||
use ops_sat_rs::config::HOME_PATH;
|
|
||||||
use ops_sat_rs::TimeStampHelper;
|
use ops_sat_rs::TimeStampHelper;
|
||||||
use satrs::action::{ActionRequest, ActionRequestVariant};
|
use satrs::action::{ActionRequest, ActionRequestVariant};
|
||||||
use satrs::pus::action::{ActionReplyPus, ActionReplyVariant};
|
use satrs::pus::action::{ActionReplyPus, ActionReplyVariant};
|
||||||
@ -429,9 +434,11 @@ mod tests {
|
|||||||
use satrs::ComponentId;
|
use satrs::ComponentId;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufRead, BufReader};
|
||||||
use std::os::unix::process::ExitStatusExt;
|
use std::os::unix::process::ExitStatusExt;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use tempfile::tempdir;
|
use tempfile::{tempdir, TempDir};
|
||||||
|
|
||||||
use super::{build_take_image_command, TakeImageExecutor};
|
use super::{build_take_image_command, TakeImageExecutor};
|
||||||
|
|
||||||
@ -465,6 +472,7 @@ mod tests {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct Ims100Testbench {
|
struct Ims100Testbench {
|
||||||
pub handler: Ims100BatchHandler<Ims100TestImageExecutor>,
|
pub handler: Ims100BatchHandler<Ims100TestImageExecutor>,
|
||||||
|
pub tmp_home_dir: TempDir,
|
||||||
pub composite_req_tx: mpsc::Sender<GenericMessage<CompositeRequest>>,
|
pub composite_req_tx: mpsc::Sender<GenericMessage<CompositeRequest>>,
|
||||||
pub tm_receiver: mpsc::Receiver<PacketAsVec>,
|
pub tm_receiver: mpsc::Receiver<PacketAsVec>,
|
||||||
pub action_reply_rx: mpsc::Receiver<GenericMessage<ActionReplyPus>>,
|
pub action_reply_rx: mpsc::Receiver<GenericMessage<ActionReplyPus>>,
|
||||||
@ -472,11 +480,7 @@ mod tests {
|
|||||||
|
|
||||||
impl Default for Ims100Testbench {
|
impl Default for Ims100Testbench {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
// TODO: Set home path which is used inside the batch handler for creating metadata.
|
let tmp_home_dir = tempdir().expect("errror creating temp directory");
|
||||||
let temp_dir = tempdir().expect("errror creating temp directory");
|
|
||||||
HOME_PATH
|
|
||||||
.set(temp_dir.path().to_path_buf())
|
|
||||||
.expect("error setting test home path");
|
|
||||||
let (composite_request_tx, composite_request_rx) = mpsc::channel();
|
let (composite_request_tx, composite_request_rx) = mpsc::channel();
|
||||||
let (tm_tx, tm_rx) = mpsc::channel();
|
let (tm_tx, tm_rx) = mpsc::channel();
|
||||||
let (action_reply_tx, action_reply_rx) = mpsc::channel();
|
let (action_reply_tx, action_reply_rx) = mpsc::channel();
|
||||||
@ -484,13 +488,17 @@ mod tests {
|
|||||||
let cam_handler = Ims100BatchHandler::new(
|
let cam_handler = Ims100BatchHandler::new(
|
||||||
CAMERA_HANDLER,
|
CAMERA_HANDLER,
|
||||||
Ims100TestImageExecutor::default(),
|
Ims100TestImageExecutor::default(),
|
||||||
|
tmp_home_dir.path(),
|
||||||
composite_request_rx,
|
composite_request_rx,
|
||||||
tm_tx,
|
tm_tx,
|
||||||
action_reply_tx,
|
action_reply_tx,
|
||||||
time_helper,
|
time_helper,
|
||||||
);
|
);
|
||||||
|
// Even though we set the temporary home directory into HOME_PATH, we still need to
|
||||||
|
// cache the TempDir, so it is not dropped.
|
||||||
Ims100Testbench {
|
Ims100Testbench {
|
||||||
handler: cam_handler,
|
handler: cam_handler,
|
||||||
|
tmp_home_dir,
|
||||||
composite_req_tx: composite_request_tx,
|
composite_req_tx: composite_request_tx,
|
||||||
tm_receiver: tm_rx,
|
tm_receiver: tm_rx,
|
||||||
action_reply_rx,
|
action_reply_rx,
|
||||||
@ -528,7 +536,6 @@ mod tests {
|
|||||||
testbench
|
testbench
|
||||||
.handler
|
.handler
|
||||||
.handle_action_request(&MessageMetadata::new(request_id, REQUESTOR_ID), &req);
|
.handle_action_request(&MessageMetadata::new(request_id, REQUESTOR_ID), &req);
|
||||||
// TODO: Verify execution and generated metadata file.
|
|
||||||
let action_reply = testbench
|
let action_reply = testbench
|
||||||
.action_reply_rx
|
.action_reply_rx
|
||||||
.try_recv()
|
.try_recv()
|
||||||
@ -539,6 +546,55 @@ mod tests {
|
|||||||
));
|
));
|
||||||
assert_eq!(action_reply.request_id(), request_id);
|
assert_eq!(action_reply.request_id(), request_id);
|
||||||
assert_eq!(action_reply.sender_id(), REQUESTOR_ID);
|
assert_eq!(action_reply.sender_id(), REQUESTOR_ID);
|
||||||
|
let mut image_executor = testbench
|
||||||
|
.handler
|
||||||
|
.image_executor
|
||||||
|
.called_with_params
|
||||||
|
.borrow_mut();
|
||||||
|
let called_params = image_executor.pop_front().expect("expected called params");
|
||||||
|
assert_eq!(called_params, DEFAULT_SINGLE_FLATSAT_CAM_PARAMS);
|
||||||
|
let mut detected_metadata_file = false;
|
||||||
|
for dir_entry_result in std::fs::read_dir(&testbench.handler.home_path)
|
||||||
|
.unwrap_or_else(|_| panic!("can not read {:?}", testbench.handler.home_path.as_path()))
|
||||||
|
{
|
||||||
|
if let Ok(dir_entry) = &dir_entry_result {
|
||||||
|
if let Ok(file_type) = dir_entry.file_type() {
|
||||||
|
if file_type.is_file() {
|
||||||
|
let path_name = dir_entry.file_name();
|
||||||
|
let path_name_str = path_name.to_string_lossy();
|
||||||
|
if path_name_str.contains("img_msec_") {
|
||||||
|
let file = File::open(dir_entry.path()).expect("file not found");
|
||||||
|
let buf_reader = BufReader::new(file);
|
||||||
|
for (idx, line) in buf_reader.lines().enumerate() {
|
||||||
|
let line = line.expect("line is not proper string");
|
||||||
|
if idx == 0 {
|
||||||
|
assert!(line.contains("time:"));
|
||||||
|
// Tricky to check, would have to mock this.. I think it's okay
|
||||||
|
// for now.
|
||||||
|
}
|
||||||
|
if idx == 1 {
|
||||||
|
assert!(line.contains("cmd params:"));
|
||||||
|
assert!(line.contains(&format!(
|
||||||
|
"{:?}",
|
||||||
|
&DEFAULT_SINGLE_FLATSAT_CAM_PARAMS
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
if idx == 2 {
|
||||||
|
assert!(line.contains("cmd:"));
|
||||||
|
let cmd = build_take_image_command(
|
||||||
|
&DEFAULT_SINGLE_FLATSAT_CAM_PARAMS,
|
||||||
|
);
|
||||||
|
let cmd_str = format!("{:?}", cmd);
|
||||||
|
assert!(line.contains(&cmd_str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detected_metadata_file = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(detected_metadata_file, "no metadata file was generated");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -7,15 +7,13 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
#[cfg(not(feature = "host"))]
|
|
||||||
use ops_sat_rs::config::HOME_PATH;
|
|
||||||
use ops_sat_rs::config::{
|
use ops_sat_rs::config::{
|
||||||
cfg_file::create_app_config,
|
cfg_file::create_app_config,
|
||||||
components::{CONTROLLER_ID, TCP_SERVER, TCP_SPP_CLIENT, UDP_SERVER},
|
components::{CONTROLLER_ID, TCP_SERVER, TCP_SPP_CLIENT, UDP_SERVER},
|
||||||
pool::create_sched_tc_pool,
|
pool::create_sched_tc_pool,
|
||||||
set_up_ground_dir, set_up_home_path, set_up_low_prio_ground_dir,
|
set_up_ground_dir, set_up_home_path, set_up_low_prio_ground_dir,
|
||||||
tasks::{FREQ_MS_CAMERA_HANDLING, FREQ_MS_CTRL, FREQ_MS_PUS_STACK, STOP_CHECK_FREQUENCY},
|
tasks::{FREQ_MS_CAMERA_HANDLING, FREQ_MS_CTRL, FREQ_MS_PUS_STACK, STOP_CHECK_FREQUENCY},
|
||||||
STOP_FILE_NAME, VALID_PACKET_ID_LIST, VERSION,
|
HOME_PATH, STOP_FILE_NAME, VALID_PACKET_ID_LIST, VERSION,
|
||||||
};
|
};
|
||||||
use ops_sat_rs::config::{components::CAMERA_HANDLER, tasks::FREQ_MS_EVENT_HANDLING};
|
use ops_sat_rs::config::{components::CAMERA_HANDLER, tasks::FREQ_MS_EVENT_HANDLING};
|
||||||
use ops_sat_rs::config::{tasks::FREQ_MS_UDP_TMTC, OBSW_SERVER_ADDR, SERVER_PORT};
|
use ops_sat_rs::config::{tasks::FREQ_MS_UDP_TMTC, OBSW_SERVER_ADDR, SERVER_PORT};
|
||||||
@ -227,6 +225,7 @@ fn main() {
|
|||||||
let timestamp_helper = TimeStampHelper::default();
|
let timestamp_helper = TimeStampHelper::default();
|
||||||
let mut camera_handler: Ims100BatchHandler = Ims100BatchHandler::new_with_default_img_executor(
|
let mut camera_handler: Ims100BatchHandler = Ims100BatchHandler::new_with_default_img_executor(
|
||||||
CAMERA_HANDLER,
|
CAMERA_HANDLER,
|
||||||
|
HOME_PATH.get().unwrap(),
|
||||||
camera_composite_rx,
|
camera_composite_rx,
|
||||||
tm_funnel_tx.clone(),
|
tm_funnel_tx.clone(),
|
||||||
pus_action_reply_tx.clone(),
|
pus_action_reply_tx.clone(),
|
||||||
|
Loading…
Reference in New Issue
Block a user