Merge branch 'stop-logic' into add-action-service-controller-obj

This commit is contained in:
2024-04-10 15:02:45 +02:00
7 changed files with 176 additions and 66 deletions

View File

@ -1,5 +1,4 @@
use ops_sat_rs::config::components::Apid;
use ops_sat_rs::config::APID_VALIDATOR;
use ops_sat_rs::config::EXPERIMENT_APID;
use satrs::pus::ReceivesEcssPusTc;
use satrs::spacepackets::{CcsdsPacket, SpHeader};
use satrs::tmtc::{CcsdsPacketHandler, ReceivesCcsdsTc};
@ -19,7 +18,7 @@ impl<
> ValidatorU16Id for CcsdsReceiver<TcSource, E>
{
fn validate(&self, apid: u16) -> bool {
APID_VALIDATOR.contains(&apid)
apid == EXPERIMENT_APID
}
}
@ -35,11 +34,7 @@ impl<
sp_header: &SpHeader,
tc_raw: &[u8],
) -> Result<(), Self::Error> {
if sp_header.apid() == Apid::Cfdp as u16 {
} else {
return self.tc_source.pass_ccsds(sp_header, tc_raw);
}
Ok(())
return self.tc_source.pass_ccsds(sp_header, tc_raw);
}
fn handle_packet_with_unknown_apid(
@ -48,6 +43,7 @@ impl<
_tc_raw: &[u8],
) -> Result<(), Self::Error> {
log::warn!("unknown APID 0x{:x?} detected", sp_header.apid());
// TODO: Log event or something similar?
Ok(())
}
}

View File

@ -3,6 +3,8 @@ use satrs_mib::res_code::ResultU16Info;
use satrs_mib::resultcode;
use std::net::Ipv4Addr;
pub const STOP_FILE_NAME: &str = "stop-experiment";
pub const OBSW_SERVER_ADDR: Ipv4Addr = Ipv4Addr::UNSPECIFIED;
pub const SERVER_PORT: u16 = 7301;
pub const EXPERIMENT_ID: u32 = 278;
@ -96,4 +98,7 @@ pub mod tasks {
pub const FREQ_MS_EVENT_HANDLING: u64 = 400;
pub const FREQ_MS_AOCS: u64 = 500;
pub const FREQ_MS_PUS_STACK: u64 = 200;
pub const FREQ_MS_CTRL: u64 = 400;
pub const STOP_CHECK_FREQUENCY: u64 = 400;
}

View File

@ -1,11 +1,13 @@
use std::{
collections::{HashSet, VecDeque},
sync::{Arc, Mutex},
sync::{atomic::AtomicBool, Arc, Mutex},
time::Duration,
};
use log::{info, warn};
use ops_sat_rs::config::tasks::STOP_CHECK_FREQUENCY;
use satrs::{
hal::std::tcp_server::{ServerConfig, TcpSpacepacketsServer},
hal::std::tcp_server::{HandledConnectionHandler, ServerConfig, TcpSpacepacketsServer},
pus::ReceivesEcssPusTc,
spacepackets::PacketId,
tmtc::{CcsdsDistributor, CcsdsError, ReceivesCcsdsTc, TmPacketSourceCore},
@ -69,12 +71,25 @@ impl TmPacketSourceCore for SyncTcpTmSource {
}
}
#[derive(Default)]
pub struct ConnectionFinishedHandler {}
impl HandledConnectionHandler for ConnectionFinishedHandler {
fn handled_connection(&mut self, info: satrs::hal::std::tcp_server::HandledConnectionInfo) {
info!(
"Served {} TMs and {} TCs for client {:?}",
info.num_sent_tms, info.num_received_tcs, info.addr
);
}
}
pub type TcpServerType<TcSource, MpscErrorType> = TcpSpacepacketsServer<
(),
CcsdsError<MpscErrorType>,
SyncTcpTmSource,
CcsdsDistributor<CcsdsReceiver<TcSource, MpscErrorType>, MpscErrorType>,
HashSet<PacketId>,
ConnectionFinishedHandler,
(),
CcsdsError<MpscErrorType>,
>;
pub struct TcpTask<
@ -102,25 +117,28 @@ impl<
tm_source: SyncTcpTmSource,
tc_receiver: CcsdsDistributor<CcsdsReceiver<TcSource, MpscErrorType>, MpscErrorType>,
packet_id_lookup: Vec<PacketId>,
stop_signal: Arc<AtomicBool>,
) -> Result<Self, std::io::Error> {
Ok(Self {
server: TcpSpacepacketsServer::new(cfg, tm_source, tc_receiver, packet_id_lookup)?,
server: TcpSpacepacketsServer::new(
cfg,
tm_source,
tc_receiver,
packet_id_lookup,
ConnectionFinishedHandler::default(),
Some(stop_signal),
)?,
})
}
pub fn periodic_operation(&mut self) {
loop {
let result = self.server.handle_next_connection();
match result {
Ok(conn_result) => {
info!(
"Served {} TMs and {} TCs for client {:?}",
conn_result.num_sent_tms, conn_result.num_received_tcs, conn_result.addr
);
}
Err(e) => {
warn!("TCP server error: {e:?}");
}
let result = self
.server
.handle_next_connection(Some(Duration::from_millis(STOP_CHECK_FREQUENCY)));
match result {
Ok(_conn_result) => (),
Err(e) => {
warn!("TCP server error: {e:?}");
}
}
}

View File

@ -1,12 +1,16 @@
use std::{
net::{IpAddr, SocketAddr},
sync::mpsc,
sync::{atomic::AtomicBool, mpsc, Arc},
thread,
time::Duration,
};
use log::info;
use ops_sat_rs::config::{components::CONTROLLER_ID, tasks::FREQ_MS_PUS_STACK, EXPERIMENT_APID};
use ops_sat_rs::config::{
components::CONTROLLER_ID,
tasks::{FREQ_MS_CTRL, FREQ_MS_PUS_STACK},
EXPERIMENT_APID, STOP_FILE_NAME,
};
use ops_sat_rs::config::{tasks::FREQ_MS_UDP_TMTC, OBSW_SERVER_ADDR, SERVER_PORT};
use satrs::{
hal::std::{tcp_server::ServerConfig, udp_server::UdpTcServer},
@ -38,10 +42,11 @@ mod requests;
mod tm_funnel;
mod tmtc;
#[allow(dead_code)]
fn main() {
setup_logger().expect("setting up logging with fern failed");
println!("OPS-SAT Rust experiment OBSW");
println!("OPS-SAT Rust Experiment OBSW");
let stop_signal = Arc::new(AtomicBool::new(false));
let (tc_source_tx, tc_source_rx) = mpsc::channel();
let (tm_funnel_tx, tm_funnel_rx) = mpsc::channel();
@ -143,53 +148,94 @@ fn main() {
sync_tm_tcp_source.clone(),
tcp_ccsds_distributor,
vec![PacketId::new_for_tc(true, EXPERIMENT_APID)],
// PACKET_ID_VALIDATOR.clone(),
stop_signal.clone(),
)
.expect("tcp server creation failed");
let mut tm_funnel = TmFunnelDynamic::new(sync_tm_tcp_source, tm_funnel_rx, tm_server_tx);
let mut tm_funnel = TmFunnelDynamic::new(
sync_tm_tcp_source,
tm_funnel_rx,
tm_server_tx,
stop_signal.clone(),
);
info!("Starting CTRL task");
let ctrl_stop_signal = stop_signal.clone();
let jh_ctrl_thread = thread::Builder::new()
.name("ops-sat ctrl".to_string())
.spawn(move || loop {
if std::path::Path::new(STOP_FILE_NAME).exists() {
log::warn!(
"Detected stop file name at {}. Initiating experiment shutdown",
STOP_FILE_NAME
);
ctrl_stop_signal.store(true, std::sync::atomic::Ordering::Relaxed);
break;
}
thread::sleep(Duration::from_millis(FREQ_MS_CTRL));
})
.unwrap();
info!("Starting TMTC and UDP task");
let tmtc_stop_signal = stop_signal.clone();
let jh_udp_tmtc = thread::Builder::new()
.name("TMTC and UDP".to_string())
.name("ops-sat tmtc-udp".to_string())
.spawn(move || {
info!("Running UDP server on port {SERVER_PORT}");
loop {
udp_tmtc_server.periodic_operation();
tmtc_task.periodic_operation();
if tmtc_stop_signal.load(std::sync::atomic::Ordering::Relaxed) {
break;
}
thread::sleep(Duration::from_millis(FREQ_MS_UDP_TMTC));
}
})
.unwrap();
let tcp_stop_signal = stop_signal.clone();
info!("Starting TCP task");
let jh_tcp = thread::Builder::new()
.name("TCP".to_string())
.name("ops-sat tcp".to_string())
.spawn(move || {
info!("Running TCP server on port {SERVER_PORT}");
loop {
tcp_server.periodic_operation();
if tcp_stop_signal.load(std::sync::atomic::Ordering::Relaxed) {
break;
}
}
})
.unwrap();
info!("Starting TM funnel task");
let funnel_stop_signal = stop_signal.clone();
let jh_tm_funnel = thread::Builder::new()
.name("TM Funnel".to_string())
.name("ops-sat tm-funnel".to_string())
.spawn(move || loop {
tm_funnel.operation();
if funnel_stop_signal.load(std::sync::atomic::Ordering::Relaxed) {
break;
}
})
.unwrap();
info!("Starting PUS handler thread");
let pus_stop_signal = stop_signal.clone();
let jh_pus_handler = thread::Builder::new()
.name("PUS".to_string())
.name("ops-sat pus".to_string())
.spawn(move || loop {
pus_stack.periodic_operation();
if pus_stop_signal.load(std::sync::atomic::Ordering::Relaxed) {
break;
}
thread::sleep(Duration::from_millis(FREQ_MS_PUS_STACK));
})
.unwrap();
jh_ctrl_thread
.join()
.expect("Joining Controller thread failed");
jh_udp_tmtc
.join()
.expect("Joining UDP TMTC server thread failed");

View File

@ -1,9 +1,9 @@
use std::{
collections::HashMap,
sync::mpsc::{self},
};
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use std::{collections::HashMap, sync::mpsc, time::Duration};
use log::info;
use ops_sat_rs::config::tasks::STOP_CHECK_FREQUENCY;
use satrs::pus::PusTmAsVec;
use satrs::{
seq_count::{CcsdsSimpleSeqCountProvider, SequenceCountProviderCore},
@ -78,6 +78,7 @@ pub struct TmFunnelDynamic {
common: TmFunnelCommon,
tm_funnel_rx: mpsc::Receiver<PusTmAsVec>,
tm_server_tx: mpsc::Sender<PusTmAsVec>,
stop_signal: Arc<AtomicBool>,
}
impl TmFunnelDynamic {
@ -85,25 +86,49 @@ impl TmFunnelDynamic {
sync_tm_tcp_source: SyncTcpTmSource,
tm_funnel_rx: mpsc::Receiver<PusTmAsVec>,
tm_server_tx: mpsc::Sender<PusTmAsVec>,
stop_signal: Arc<AtomicBool>,
) -> Self {
Self {
common: TmFunnelCommon::new(sync_tm_tcp_source),
tm_funnel_rx,
tm_server_tx,
stop_signal,
}
}
pub fn operation(&mut self) {
if let Ok(mut tm) = self.tm_funnel_rx.recv() {
// Read the TM, set sequence counter and message counter, and finally update
// the CRC.
let zero_copy_writer = PusTmZeroCopyWriter::new(&mut tm.packet, MIN_CDS_FIELD_LEN)
.expect("Creating TM zero copy writer failed");
self.common.apply_packet_processing(zero_copy_writer);
self.common.sync_tm_tcp_source.add_tm(&tm.packet);
self.tm_server_tx
.send(tm)
.expect("Sending TM to server failed");
loop {
match self
.tm_funnel_rx
.recv_timeout(Duration::from_millis(STOP_CHECK_FREQUENCY))
{
Ok(mut tm) => {
// Read the TM, set sequence counter and message counter, and finally update
// the CRC.
let zero_copy_writer =
PusTmZeroCopyWriter::new(&mut tm.packet, MIN_CDS_FIELD_LEN)
.expect("Creating TM zero copy writer failed");
self.common.apply_packet_processing(zero_copy_writer);
self.common.sync_tm_tcp_source.add_tm(&tm.packet);
self.tm_server_tx
.send(tm)
.expect("Sending TM to server failed");
if self.stop_signal.load(std::sync::atomic::Ordering::Relaxed) {
break;
}
}
Err(e) => match e {
mpsc::RecvTimeoutError::Timeout => {
if self.stop_signal.load(std::sync::atomic::Ordering::Relaxed) {
break;
}
}
mpsc::RecvTimeoutError::Disconnected => {
log::warn!("All TM funnel senders have disconnected");
break;
}
},
}
}
}
}