downlink_logfile #21
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -613,6 +613,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"mio",
|
"mio",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
|
"once_cell",
|
||||||
"satrs",
|
"satrs",
|
||||||
"satrs-mib",
|
"satrs-mib",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -21,6 +21,7 @@ serde_json = "1"
|
|||||||
mio = "0.8"
|
mio = "0.8"
|
||||||
homedir = "0.2"
|
homedir = "0.2"
|
||||||
socket2 = "0.5"
|
socket2 = "0.5"
|
||||||
|
once_cell = "1.19"
|
||||||
|
|
||||||
[dependencies.satrs]
|
[dependencies.satrs]
|
||||||
version = "0.2.0-rc.5"
|
version = "0.2.0-rc.5"
|
||||||
|
@ -96,6 +96,16 @@ def create_cmd_definition_tree() -> CmdTreeNode:
|
|||||||
CmdTreeNode("custom_params", "Custom Camera Parameters as specified from file")
|
CmdTreeNode("custom_params", "Custom Camera Parameters as specified from file")
|
||||||
)
|
)
|
||||||
action_node.add_child(cam_node)
|
action_node.add_child(cam_node)
|
||||||
|
|
||||||
|
controller_node = CmdTreeNode("controller", "Main OBSW Controller")
|
||||||
|
controller_node.add_child(
|
||||||
|
CmdTreeNode("downlink_logs", "Downlink Logs via toGround folder")
|
||||||
|
)
|
||||||
|
controller_node.add_child(
|
||||||
|
CmdTreeNode("downlink_last_img", "Downlink last image via toGroundLP folder")
|
||||||
|
)
|
||||||
|
action_node.add_child(controller_node)
|
||||||
|
|
||||||
root_node.add_child(action_node)
|
root_node.add_child(action_node)
|
||||||
|
|
||||||
return root_node
|
return root_node
|
||||||
@ -157,7 +167,18 @@ def pack_pus_telecommands(q: DefaultPusQueueHelper, cmd_path: str):
|
|||||||
service=8, subservice=128, apid=EXPERIMENT_APID, app_data=data
|
service=8, subservice=128, apid=EXPERIMENT_APID, app_data=data
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if cmd_path_list[1] == "controller":
|
||||||
|
assert len(cmd_path_list) >= 3
|
||||||
|
data = bytearray()
|
||||||
|
if cmd_path_list[2] == "downlink_logs":
|
||||||
|
data.extend(make_action_cmd_header(UniqueId.Controller, 2))
|
||||||
|
if cmd_path_list[2] == "downlink_last_img":
|
||||||
|
data.extend(make_action_cmd_header(UniqueId.Controller, 3))
|
||||||
|
return q.add_pus_tc(
|
||||||
|
PusTelecommand(
|
||||||
|
service=8, subservice=128, apid=EXPERIMENT_APID, app_data=data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def handle_set_mode_cmd(
|
def handle_set_mode_cmd(
|
||||||
q: DefaultPusQueueHelper, target_str: str, mode_str: str, apid: int, unique_id: int
|
q: DefaultPusQueueHelper, target_str: str, mode_str: str, apid: int, unique_id: int
|
||||||
|
@ -9,7 +9,9 @@ use std::path::{Path, PathBuf};
|
|||||||
|
|
||||||
pub const STOP_FILE_NAME: &str = "stop-experiment";
|
pub const STOP_FILE_NAME: &str = "stop-experiment";
|
||||||
pub const CONFIG_FILE_NAME: &str = "exp278.toml";
|
pub const CONFIG_FILE_NAME: &str = "exp278.toml";
|
||||||
pub const HOME_FOLDER_EXPERIMENT: &str = "/home/exp278";
|
pub const HOME_FOLDER_EXPERIMENT: &str = "/home/exp278"; // also where IMS-100 images are placed
|
||||||
|
pub const TO_GROUND_FOLDER_EXPERIMENT: &str = "/home/exp278/toGround";
|
||||||
|
pub const TO_GROUND_LP_FOLDER_EXPERIMENT: &str = "/home/exp278/toGroundLP";
|
||||||
pub const LOG_FOLDER: &str = "logs";
|
pub const LOG_FOLDER: &str = "logs";
|
||||||
|
|
||||||
pub const OBSW_SERVER_ADDR: Ipv4Addr = Ipv4Addr::UNSPECIFIED;
|
pub const OBSW_SERVER_ADDR: Ipv4Addr = Ipv4Addr::UNSPECIFIED;
|
||||||
@ -291,3 +293,15 @@ pub mod tasks {
|
|||||||
pub const STOP_CHECK_FREQUENCY_MS: u64 = 400;
|
pub const STOP_CHECK_FREQUENCY_MS: u64 = 400;
|
||||||
pub const STOP_CHECK_FREQUENCY: Duration = Duration::from_millis(STOP_CHECK_FREQUENCY_MS);
|
pub const STOP_CHECK_FREQUENCY: Duration = Duration::from_millis(STOP_CHECK_FREQUENCY_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_low_priority_ground_dir() {
|
||||||
|
log::info!("Creating low priority to ground directory");
|
||||||
|
if !Path::new(TO_GROUND_LP_FOLDER_EXPERIMENT).exists()
|
||||||
|
&& std::fs::create_dir_all(TO_GROUND_LP_FOLDER_EXPERIMENT).is_err()
|
||||||
|
{
|
||||||
|
log::error!(
|
||||||
|
"Failed to create low priority to ground directory '{}'",
|
||||||
|
TO_GROUND_LP_FOLDER_EXPERIMENT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
|
use crate::logger::LOGFILE_PATH;
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
|
use ops_sat_rs::config::{
|
||||||
|
action_err::INVALID_ACTION_ID, HOME_FOLDER_EXPERIMENT, HOME_PATH, STOP_FILE_NAME,
|
||||||
|
TO_GROUND_FOLDER_EXPERIMENT,
|
||||||
|
};
|
||||||
|
use satrs::action::ActionRequestVariant;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
action::ActionRequest,
|
action::ActionRequest,
|
||||||
pus::action::{ActionReplyPus, ActionReplyVariant},
|
pus::action::{ActionReplyPus, ActionReplyVariant},
|
||||||
@ -10,14 +16,14 @@ use std::{
|
|||||||
sync::{atomic::AtomicBool, mpsc, Arc},
|
sync::{atomic::AtomicBool, mpsc, Arc},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ops_sat_rs::config::{action_err::INVALID_ACTION_ID, HOME_PATH, STOP_FILE_NAME};
|
|
||||||
|
|
||||||
use crate::requests::CompositeRequest;
|
use crate::requests::CompositeRequest;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, TryFromPrimitive)]
|
#[derive(Debug, Clone, Copy, TryFromPrimitive)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum ActionId {
|
pub enum ActionId {
|
||||||
StopExperiment = 1,
|
StopExperiment = 1,
|
||||||
|
DownlinkLogfile = 2,
|
||||||
|
DownlinkImages = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ExperimentController {
|
pub struct ExperimentController {
|
||||||
@ -96,7 +102,45 @@ impl ExperimentController {
|
|||||||
ActionReplyVariant::Completed,
|
ActionReplyVariant::Completed,
|
||||||
));
|
));
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
log::error!("sending action reply failed");
|
log::error!("Sending action reply failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ActionId::DownlinkLogfile => {
|
||||||
|
log::info!("Copying logfile into downlink folder");
|
||||||
|
if let Some(logfile_path) = LOGFILE_PATH.get() {
|
||||||
|
if let Ok(logfile_path) = <PathBuf as Clone>::clone(logfile_path)
|
||||||
|
.into_os_string()
|
||||||
|
.into_string()
|
||||||
|
{
|
||||||
|
if std::fs::copy(logfile_path.as_str(), TO_GROUND_FOLDER_EXPERIMENT)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
log::error!("Copying logfile into downlink path failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::error!("Downlink path emtpy")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// downlink images, default will be the last image, otherwise specified counting down (2 = second to last image, etc.)
|
||||||
|
ActionId::DownlinkImages => {
|
||||||
|
log::info!("Copying images into low priority downlink folder");
|
||||||
|
if let Ok(image_path) = match action_req.variant {
|
||||||
|
ActionRequestVariant::VecData(data) => {
|
||||||
|
let index = data[0];
|
||||||
|
get_latest_image(index as usize)
|
||||||
|
}
|
||||||
|
_ => get_latest_image(0),
|
||||||
|
} {
|
||||||
|
if let Ok(image_path) = <PathBuf as Clone>::clone(&image_path)
|
||||||
|
.into_os_string()
|
||||||
|
.into_string()
|
||||||
|
{
|
||||||
|
if std::fs::copy(image_path, TO_GROUND_FOLDER_EXPERIMENT).is_err() {
|
||||||
|
log::error!("Copying logfile into downlink path failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,3 +170,35 @@ impl ExperimentController {
|
|||||||
check_at_path(self.home_path_stop_file.as_path());
|
check_at_path(self.home_path_stop_file.as_path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO no idea if this works in any way shape or form
|
||||||
|
pub fn get_latest_image(index: usize) -> Result<PathBuf, std::io::Error> {
|
||||||
|
// Get the most recently modified file
|
||||||
|
let mut png_files = std::fs::read_dir(HOME_FOLDER_EXPERIMENT)?
|
||||||
|
.flatten()
|
||||||
|
.filter(|f| match f.metadata() {
|
||||||
|
Ok(metadata) => metadata.is_file(),
|
||||||
|
Err(_) => false,
|
||||||
|
})
|
||||||
|
.filter(|f| match f.file_name().into_string() {
|
||||||
|
Ok(name) => name.ends_with(".png"),
|
||||||
|
Err(_) => false,
|
||||||
|
})
|
||||||
|
.collect::<Vec<std::fs::DirEntry>>();
|
||||||
|
png_files.sort_by_key(|x| match x.metadata() {
|
||||||
|
Ok(metadata) => {
|
||||||
|
if let Ok(time) = metadata.modified() {
|
||||||
|
time
|
||||||
|
} else {
|
||||||
|
std::time::SystemTime::UNIX_EPOCH
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => std::time::SystemTime::UNIX_EPOCH,
|
||||||
|
});
|
||||||
|
|
||||||
|
png_files.reverse();
|
||||||
|
if let Some(png) = png_files.into_iter().nth(index) {
|
||||||
|
return Ok(png.path());
|
||||||
|
}
|
||||||
|
Err(std::io::Error::other("No latest image found"))
|
||||||
|
}
|
||||||
|
@ -291,7 +291,7 @@ impl IMS100BatchHandler {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
let output = self.take_picture(param)?;
|
let output = self.take_picture(param)?;
|
||||||
debug!("Sending action reply!");
|
info!("Sending action reply!");
|
||||||
send_data_reply(self.id, output.stdout, &self.stamp_helper, &self.tm_tx)?;
|
send_data_reply(self.id, output.stdout, &self.stamp_helper, &self.tm_tx)?;
|
||||||
self.action_reply_tx
|
self.action_reply_tx
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(
|
||||||
|
@ -1,13 +1,25 @@
|
|||||||
|
use once_cell::sync::OnceCell;
|
||||||
|
use ops_sat_rs::config::LOG_FOLDER;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use ops_sat_rs::config::LOG_FOLDER;
|
pub static LOGFILE_PATH: OnceCell<PathBuf> = OnceCell::new();
|
||||||
|
|
||||||
pub fn setup_logger() -> Result<(), fern::InitError> {
|
pub fn setup_logger() -> Result<(), fern::InitError> {
|
||||||
if !Path::new(LOG_FOLDER).exists() && std::fs::create_dir_all(LOG_FOLDER).is_err() {
|
if !Path::new(LOG_FOLDER).exists() && std::fs::create_dir_all(LOG_FOLDER).is_err() {
|
||||||
eprintln!("Failed to create log folder '{}'", LOG_FOLDER);
|
eprintln!("Failed to create log folder '{}'", LOG_FOLDER);
|
||||||
}
|
}
|
||||||
let mut path_buf = PathBuf::from(LOG_FOLDER);
|
let mut path_buf = PathBuf::from(LOG_FOLDER);
|
||||||
path_buf.push("output.log");
|
path_buf.push(
|
||||||
|
format!(
|
||||||
|
"output_{}.log",
|
||||||
|
humantime::format_rfc3339_seconds(std::time::SystemTime::now()).to_string()
|
||||||
|
)
|
||||||
|
.replace(":", "_"),
|
||||||
|
);
|
||||||
|
println!("Creating logfile {:?}", path_buf);
|
||||||
|
LOGFILE_PATH
|
||||||
|
.set(path_buf.clone())
|
||||||
|
.expect("Error setting global logfile path");
|
||||||
fern::Dispatch::new()
|
fern::Dispatch::new()
|
||||||
.format(move |out, message, record| {
|
.format(move |out, message, record| {
|
||||||
out.finish(format_args!(
|
out.finish(format_args!(
|
||||||
|
@ -5,10 +5,11 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use log::info;
|
use log::{debug, info};
|
||||||
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},
|
||||||
|
create_low_priority_ground_dir,
|
||||||
pool::create_sched_tc_pool,
|
pool::create_sched_tc_pool,
|
||||||
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},
|
||||||
VALID_PACKET_ID_LIST, VERSION,
|
VALID_PACKET_ID_LIST, VERSION,
|
||||||
@ -55,9 +56,10 @@ fn main() {
|
|||||||
setup_logger().expect("setting up logging with fern failed");
|
setup_logger().expect("setting up logging with fern failed");
|
||||||
let version_str = VERSION.unwrap_or("?");
|
let version_str = VERSION.unwrap_or("?");
|
||||||
println!("OPS-SAT Rust Experiment OBSW v{}", version_str);
|
println!("OPS-SAT Rust Experiment OBSW v{}", version_str);
|
||||||
lkoester marked this conversation as resolved
Outdated
|
|||||||
|
create_low_priority_ground_dir();
|
||||||
|
|
||||||
let app_cfg = create_app_config();
|
let app_cfg = create_app_config();
|
||||||
println!("App Configuration: {:?}", app_cfg);
|
info!("App Configuration: {:?}", app_cfg);
|
||||||
lkoester marked this conversation as resolved
Outdated
muellerr
commented
I'd transform this to INFO. debug is usually not visible, and this is valuable information, as long as it's not too noisy. I'd transform this to INFO. debug is usually not visible, and this is valuable information, as long as it's not too noisy.
|
|||||||
|
|
||||||
let stop_signal = Arc::new(AtomicBool::new(false));
|
let stop_signal = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user
I'd leave this a println. There are corner cases where logger output ca nbe invisible, and I always want to see this line at the very least.