rename subfolders, add more READMEs
This commit is contained in:
96
satrs-example/src/bin/client.rs
Normal file
96
satrs-example/src/bin/client.rs
Normal file
@ -0,0 +1,96 @@
|
||||
use fsrc_core::pus::verification::RequestId;
|
||||
use fsrc_example::{OBSW_SERVER_ADDR, SERVER_PORT};
|
||||
use spacepackets::ecss::PusPacket;
|
||||
use spacepackets::tc::PusTc;
|
||||
use spacepackets::tm::PusTm;
|
||||
use spacepackets::SpHeader;
|
||||
use std::net::{IpAddr, SocketAddr, UdpSocket};
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
let mut buf = [0; 32];
|
||||
let addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
||||
let mut sph = SpHeader::tc(0x02, 0, 0).unwrap();
|
||||
let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true);
|
||||
let client = UdpSocket::bind("127.0.0.1:7302").expect("Connecting to UDP server failed");
|
||||
let tc_req_id = RequestId::new(&pus_tc);
|
||||
println!(
|
||||
"Packing and sending PUS ping command TC[17,1] with request ID {}",
|
||||
tc_req_id
|
||||
);
|
||||
let size = pus_tc
|
||||
.write_to_bytes(&mut buf)
|
||||
.expect("Creating PUS TC failed");
|
||||
client
|
||||
.send_to(&buf[0..size], &addr)
|
||||
.expect(&*format!("Sending to {:?} failed", addr));
|
||||
client
|
||||
.set_read_timeout(Some(Duration::from_secs(2)))
|
||||
.expect("Setting read timeout failed");
|
||||
loop {
|
||||
let res = client.recv(&mut buf);
|
||||
match res {
|
||||
Ok(_len) => {
|
||||
let (pus_tm, size) = PusTm::from_bytes(&buf, 7).expect("Parsing PUS TM failed");
|
||||
if pus_tm.service() == 17 && pus_tm.subservice() == 2 {
|
||||
println!("Received PUS Ping Reply TM[17,2]")
|
||||
} else if pus_tm.service() == 1 {
|
||||
if pus_tm.source_data().is_none() {
|
||||
println!("Invalid verification TM, no source data");
|
||||
}
|
||||
let src_data = pus_tm.source_data().unwrap();
|
||||
if src_data.len() < 4 {
|
||||
println!("Invalid verification TM source data, less than 4 bytes")
|
||||
}
|
||||
let req_id = RequestId::from_bytes(src_data).unwrap();
|
||||
if pus_tm.subservice() == 1 {
|
||||
println!(
|
||||
"Received TM[1,1] acceptance success for request ID {}",
|
||||
req_id
|
||||
)
|
||||
} else if pus_tm.subservice() == 2 {
|
||||
println!(
|
||||
"Received TM[1,2] acceptance failure for request ID {}",
|
||||
req_id
|
||||
)
|
||||
} else if pus_tm.subservice() == 3 {
|
||||
println!("Received TM[1,3] start success for request ID {}", req_id)
|
||||
} else if pus_tm.subservice() == 4 {
|
||||
println!("Received TM[1,2] start failure for request ID {}", req_id)
|
||||
} else if pus_tm.subservice() == 5 {
|
||||
println!("Received TM[1,5] step success for request ID {}", req_id)
|
||||
} else if pus_tm.subservice() == 6 {
|
||||
println!("Received TM[1,6] step failure for request ID {}", req_id)
|
||||
} else if pus_tm.subservice() == 7 {
|
||||
println!(
|
||||
"Received TM[1,7] completion success for request ID {}",
|
||||
req_id
|
||||
)
|
||||
} else if pus_tm.subservice() == 8 {
|
||||
println!(
|
||||
"Received TM[1,8] completion failure for request ID {}",
|
||||
req_id
|
||||
);
|
||||
}
|
||||
} else {
|
||||
println!(
|
||||
"Received TM[{}, {}] with {} bytes",
|
||||
pus_tm.service(),
|
||||
pus_tm.subservice(),
|
||||
size
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(ref e)
|
||||
if e.kind() == std::io::ErrorKind::WouldBlock
|
||||
|| e.kind() == std::io::ErrorKind::TimedOut =>
|
||||
{
|
||||
println!("No reply received for 2 seconds");
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
println!("UDP receive error {:?}", res.unwrap_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
satrs-example/src/bin/obsw/ccsds.rs
Normal file
37
satrs-example/src/bin/obsw/ccsds.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use crate::tmtc::PUS_APID;
|
||||
use fsrc_core::tmtc::{CcsdsPacketHandler, PusDistributor, ReceivesCcsdsTc};
|
||||
use spacepackets::{CcsdsPacket, SpHeader};
|
||||
|
||||
pub struct CcsdsReceiver {
|
||||
pub pus_handler: PusDistributor<()>,
|
||||
}
|
||||
|
||||
impl CcsdsPacketHandler for CcsdsReceiver {
|
||||
type Error = ();
|
||||
|
||||
fn valid_apids(&self) -> &'static [u16] {
|
||||
&[PUS_APID]
|
||||
}
|
||||
|
||||
fn handle_known_apid(
|
||||
&mut self,
|
||||
sp_header: &SpHeader,
|
||||
tc_raw: &[u8],
|
||||
) -> Result<(), Self::Error> {
|
||||
if sp_header.apid() == PUS_APID {
|
||||
self.pus_handler
|
||||
.pass_ccsds(sp_header, tc_raw)
|
||||
.expect("Handling PUS packet failed");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_unknown_apid(
|
||||
&mut self,
|
||||
sp_header: &SpHeader,
|
||||
_tc_raw: &[u8],
|
||||
) -> Result<(), Self::Error> {
|
||||
println!("Unknown APID 0x{:x?} detected", sp_header.apid());
|
||||
Ok(())
|
||||
}
|
||||
}
|
178
satrs-example/src/bin/obsw/main.rs
Normal file
178
satrs-example/src/bin/obsw/main.rs
Normal file
@ -0,0 +1,178 @@
|
||||
mod ccsds;
|
||||
mod pus;
|
||||
mod tmtc;
|
||||
|
||||
use crate::tmtc::{core_tmtc_task, CoreTmtcArgs, TmStore, PUS_APID};
|
||||
use fsrc_core::event_man::{
|
||||
EventManagerWithMpscQueue, MpscEventReceiver, MpscEventU32SendProvider, SendEventProvider,
|
||||
};
|
||||
use fsrc_core::events::EventU32;
|
||||
use fsrc_core::hal::host::udp_server::UdpTcServer;
|
||||
use fsrc_core::pool::{LocalPool, PoolCfg, SharedPool, StoreAddr};
|
||||
use fsrc_core::pus::event_man::{
|
||||
DefaultPusMgmtBackendProvider, EventReporter, EventRequest, EventRequestWithToken,
|
||||
PusEventDispatcher,
|
||||
};
|
||||
use fsrc_core::pus::verification::{
|
||||
MpscVerifSender, VerificationReporterCfg, VerificationReporterWithSender,
|
||||
};
|
||||
use fsrc_core::pus::{EcssTmError, EcssTmSender};
|
||||
use fsrc_core::tmtc::CcsdsError;
|
||||
use fsrc_example::{OBSW_SERVER_ADDR, SERVER_PORT};
|
||||
use spacepackets::time::{CdsShortTimeProvider, TimeWriter};
|
||||
use spacepackets::tm::PusTm;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::{mpsc, Arc, Mutex, RwLock};
|
||||
use std::thread;
|
||||
|
||||
struct TmFunnel {
|
||||
tm_funnel_rx: mpsc::Receiver<StoreAddr>,
|
||||
tm_server_tx: mpsc::Sender<StoreAddr>,
|
||||
}
|
||||
|
||||
struct UdpTmtcServer {
|
||||
udp_tc_server: UdpTcServer<CcsdsError<()>>,
|
||||
tm_rx: mpsc::Receiver<StoreAddr>,
|
||||
tm_store: SharedPool,
|
||||
}
|
||||
|
||||
unsafe impl Send for UdpTmtcServer {}
|
||||
|
||||
struct EventTmSender {
|
||||
store_helper: TmStore,
|
||||
sender: mpsc::Sender<StoreAddr>,
|
||||
}
|
||||
|
||||
impl EventTmSender {
|
||||
fn new(store_helper: TmStore, sender: mpsc::Sender<StoreAddr>) -> Self {
|
||||
Self {
|
||||
store_helper,
|
||||
sender,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EcssTmSender for EventTmSender {
|
||||
type Error = mpsc::SendError<StoreAddr>;
|
||||
|
||||
fn send_tm(&mut self, tm: PusTm) -> Result<(), EcssTmError<Self::Error>> {
|
||||
let addr = self.store_helper.add_pus_tm(&tm);
|
||||
self.sender.send(addr).map_err(EcssTmError::SendError)
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
println!("Running OBSW example");
|
||||
let pool_cfg = PoolCfg::new(vec![(8, 32), (4, 64), (2, 128)]);
|
||||
let tm_pool = LocalPool::new(pool_cfg);
|
||||
let tm_store: SharedPool = Arc::new(RwLock::new(Box::new(tm_pool)));
|
||||
let tm_store_helper = TmStore {
|
||||
pool: tm_store.clone(),
|
||||
};
|
||||
let addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
||||
let (tm_funnel_tx, tm_funnel_rx) = channel();
|
||||
let (tm_server_tx, tm_server_rx) = channel();
|
||||
let sender = MpscVerifSender::new(tm_store.clone(), tm_funnel_tx.clone());
|
||||
let verif_cfg = VerificationReporterCfg::new(PUS_APID, 1, 2, 8).unwrap();
|
||||
let reporter_with_sender_0 = Arc::new(Mutex::new(VerificationReporterWithSender::new(
|
||||
verif_cfg,
|
||||
Box::new(sender),
|
||||
)));
|
||||
|
||||
// Create event handling components
|
||||
let (event_request_tx, event_request_rx) = channel::<EventRequestWithToken>();
|
||||
let (event_sender, event_man_rx) = channel();
|
||||
let event_recv = MpscEventReceiver::<EventU32>::new(event_man_rx);
|
||||
let mut event_man = EventManagerWithMpscQueue::new(Box::new(event_recv));
|
||||
let event_reporter = EventReporter::new(PUS_APID, 128).unwrap();
|
||||
let pus_tm_backend = DefaultPusMgmtBackendProvider::<EventU32>::default();
|
||||
let mut pus_event_dispatcher =
|
||||
PusEventDispatcher::new(event_reporter, Box::new(pus_tm_backend));
|
||||
let (pus_event_man_tx, pus_event_man_rx) = channel();
|
||||
let pus_event_man_send_provider = MpscEventU32SendProvider::new(1, pus_event_man_tx);
|
||||
let reporter1 = reporter_with_sender_0.clone();
|
||||
event_man.subscribe_all(pus_event_man_send_provider.id());
|
||||
|
||||
// Create clones here to allow move for thread 0
|
||||
let core_args = CoreTmtcArgs {
|
||||
tm_store: tm_store_helper.clone(),
|
||||
tm_sender: tm_funnel_tx.clone(),
|
||||
event_sender,
|
||||
event_request_tx,
|
||||
};
|
||||
|
||||
println!("Starting TMTC task");
|
||||
let jh0 = thread::spawn(move || {
|
||||
core_tmtc_task(core_args, tm_server_rx, addr, reporter_with_sender_0);
|
||||
});
|
||||
|
||||
println!("Starting TM funnel task");
|
||||
let jh1 = thread::spawn(move || {
|
||||
let tm_funnel = TmFunnel {
|
||||
tm_server_tx,
|
||||
tm_funnel_rx,
|
||||
};
|
||||
loop {
|
||||
if let Ok(addr) = tm_funnel.tm_funnel_rx.recv() {
|
||||
tm_funnel
|
||||
.tm_server_tx
|
||||
.send(addr)
|
||||
.expect("Sending TM to server failed");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
println!("Starting event handling task");
|
||||
let jh2 = thread::spawn(move || {
|
||||
let mut timestamp: [u8; 7] = [0; 7];
|
||||
let mut sender = EventTmSender::new(tm_store_helper, tm_funnel_tx);
|
||||
let mut time_provider = CdsShortTimeProvider::new(0, 0);
|
||||
let report_completion = |event_req: EventRequestWithToken, timestamp: &[u8]| {
|
||||
let mut reporter = reporter1
|
||||
.lock()
|
||||
.expect("Locking Verification reporter failed");
|
||||
reporter
|
||||
.completion_success(event_req.token, timestamp)
|
||||
.expect("Sending completion success failed");
|
||||
};
|
||||
loop {
|
||||
if let Ok(event_req) = event_request_rx.try_recv() {
|
||||
match event_req.request {
|
||||
EventRequest::Enable(event) => {
|
||||
pus_event_dispatcher
|
||||
.enable_tm_for_event(&event)
|
||||
.expect("Enabling TM failed");
|
||||
update_time(&mut time_provider, &mut timestamp);
|
||||
report_completion(event_req, ×tamp);
|
||||
}
|
||||
EventRequest::Disable(event) => {
|
||||
pus_event_dispatcher
|
||||
.disable_tm_for_event(&event)
|
||||
.expect("Disabling TM failed");
|
||||
update_time(&mut time_provider, &mut timestamp);
|
||||
report_completion(event_req, ×tamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Ok((event, _param)) = pus_event_man_rx.try_recv() {
|
||||
update_time(&mut time_provider, &mut timestamp);
|
||||
pus_event_dispatcher
|
||||
.generate_pus_event_tm_generic(&mut sender, ×tamp, event, None)
|
||||
.expect("Sending TM as event failed");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
jh0.join().expect("Joining UDP TMTC server thread failed");
|
||||
jh1.join().expect("Joining TM Funnel thread failed");
|
||||
jh2.join().expect("Joining Event Manager thread failed");
|
||||
}
|
||||
|
||||
pub fn update_time(time_provider: &mut CdsShortTimeProvider, timestamp: &mut [u8]) {
|
||||
time_provider
|
||||
.update_from_now()
|
||||
.expect("Could not get current time");
|
||||
time_provider
|
||||
.write_to_bytes(timestamp)
|
||||
.expect("Writing timestamp failed");
|
||||
}
|
188
satrs-example/src/bin/obsw/pus.rs
Normal file
188
satrs-example/src/bin/obsw/pus.rs
Normal file
@ -0,0 +1,188 @@
|
||||
use crate::tmtc::TmStore;
|
||||
use fsrc_core::events::EventU32;
|
||||
use fsrc_core::pool::StoreAddr;
|
||||
use fsrc_core::pus::event::Subservices;
|
||||
use fsrc_core::pus::event_man::{EventRequest, EventRequestWithToken};
|
||||
use fsrc_core::pus::verification::{
|
||||
FailParams, SharedStdVerifReporterWithSender, TcStateAccepted, VerificationToken,
|
||||
};
|
||||
use fsrc_core::tmtc::tm_helper::PusTmWithCdsShortHelper;
|
||||
use fsrc_core::tmtc::PusServiceProvider;
|
||||
use spacepackets::ecss::{EcssEnumU16, PusPacket};
|
||||
use spacepackets::tc::PusTc;
|
||||
use spacepackets::time::{CdsShortTimeProvider, TimeWriter};
|
||||
use spacepackets::SpHeader;
|
||||
use std::sync::mpsc;
|
||||
|
||||
pub struct PusReceiver {
|
||||
pub tm_helper: PusTmWithCdsShortHelper,
|
||||
pub tm_tx: mpsc::Sender<StoreAddr>,
|
||||
pub tm_store: TmStore,
|
||||
pub verif_reporter: SharedStdVerifReporterWithSender,
|
||||
event_request_tx: mpsc::Sender<EventRequestWithToken>,
|
||||
stamper: CdsShortTimeProvider,
|
||||
time_stamp: [u8; 7],
|
||||
}
|
||||
|
||||
impl PusReceiver {
|
||||
pub fn new(
|
||||
apid: u16,
|
||||
tm_tx: mpsc::Sender<StoreAddr>,
|
||||
tm_store: TmStore,
|
||||
verif_reporter: SharedStdVerifReporterWithSender,
|
||||
event_request_tx: mpsc::Sender<EventRequestWithToken>,
|
||||
) -> Self {
|
||||
Self {
|
||||
tm_helper: PusTmWithCdsShortHelper::new(apid),
|
||||
tm_tx,
|
||||
tm_store,
|
||||
verif_reporter,
|
||||
event_request_tx,
|
||||
stamper: CdsShortTimeProvider::default(),
|
||||
time_stamp: [0; 7],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PusServiceProvider for PusReceiver {
|
||||
type Error = ();
|
||||
|
||||
fn handle_pus_tc_packet(
|
||||
&mut self,
|
||||
service: u8,
|
||||
_header: &SpHeader,
|
||||
pus_tc: &PusTc,
|
||||
) -> Result<(), Self::Error> {
|
||||
let mut reporter = self
|
||||
.verif_reporter
|
||||
.lock()
|
||||
.expect("Locking Verification Reporter failed");
|
||||
let init_token = reporter.add_tc(pus_tc);
|
||||
self.stamper
|
||||
.update_from_now()
|
||||
.expect("Updating time for time stamp failed");
|
||||
self.stamper
|
||||
.write_to_bytes(&mut self.time_stamp)
|
||||
.expect("Writing time stamp failed");
|
||||
let accepted_token = reporter
|
||||
.acceptance_success(init_token, &self.time_stamp)
|
||||
.expect("Acceptance success failure");
|
||||
drop(reporter);
|
||||
if service == 17 {
|
||||
self.handle_test_service(pus_tc, accepted_token);
|
||||
} else if service == 5 {
|
||||
self.handle_event_service(pus_tc, accepted_token);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl PusReceiver {
|
||||
fn handle_test_service(&mut self, pus_tc: &PusTc, token: VerificationToken<TcStateAccepted>) {
|
||||
if pus_tc.subservice() == 1 {
|
||||
println!("Received PUS ping command TC[17,1]");
|
||||
println!("Sending ping reply PUS TM[17,2]");
|
||||
let ping_reply = self.tm_helper.create_pus_tm_timestamp_now(17, 2, None);
|
||||
let addr = self.tm_store.add_pus_tm(&ping_reply);
|
||||
let mut reporter = self
|
||||
.verif_reporter
|
||||
.lock()
|
||||
.expect("Error locking verification reporter");
|
||||
let start_token = reporter
|
||||
.start_success(token, &self.time_stamp)
|
||||
.expect("Error sending start success");
|
||||
self.tm_tx
|
||||
.send(addr)
|
||||
.expect("Sending TM to TM funnel failed");
|
||||
reporter
|
||||
.completion_success(start_token, &self.time_stamp)
|
||||
.expect("Error sending completion success");
|
||||
}
|
||||
}
|
||||
|
||||
fn update_time_stamp(&mut self) {
|
||||
self.stamper
|
||||
.update_from_now()
|
||||
.expect("Updating timestamp failed");
|
||||
self.stamper
|
||||
.write_to_bytes(&mut self.time_stamp)
|
||||
.expect("Writing timestamp failed");
|
||||
}
|
||||
|
||||
fn handle_event_service(&mut self, pus_tc: &PusTc, token: VerificationToken<TcStateAccepted>) {
|
||||
let send_start_failure = |verif_reporter: &mut SharedStdVerifReporterWithSender,
|
||||
timestamp: &[u8; 7],
|
||||
failure_code: EcssEnumU16,
|
||||
failure_data: Option<&[u8]>| {
|
||||
verif_reporter
|
||||
.lock()
|
||||
.expect("Locking verification reporter failed")
|
||||
.start_failure(
|
||||
token,
|
||||
FailParams::new(timestamp, &failure_code, failure_data),
|
||||
)
|
||||
.expect("Sending start failure TM failed");
|
||||
};
|
||||
let send_start_acceptance = |verif_reporter: &mut SharedStdVerifReporterWithSender,
|
||||
timestamp: &[u8; 7]| {
|
||||
verif_reporter
|
||||
.lock()
|
||||
.expect("Locking verification reporter failed")
|
||||
.start_success(token, timestamp)
|
||||
.expect("Sending start success TM failed")
|
||||
};
|
||||
if pus_tc.user_data().is_none() {
|
||||
self.update_time_stamp();
|
||||
send_start_failure(
|
||||
&mut self.verif_reporter,
|
||||
&self.time_stamp,
|
||||
EcssEnumU16::new(1),
|
||||
None,
|
||||
);
|
||||
return;
|
||||
}
|
||||
let app_data = pus_tc.user_data().unwrap();
|
||||
if app_data.len() < 4 {
|
||||
self.update_time_stamp();
|
||||
send_start_failure(
|
||||
&mut self.verif_reporter,
|
||||
&self.time_stamp,
|
||||
EcssEnumU16::new(1),
|
||||
None,
|
||||
);
|
||||
return;
|
||||
}
|
||||
let event_id = EventU32::from(u32::from_be_bytes(app_data.try_into().unwrap()));
|
||||
match PusPacket::subservice(pus_tc).try_into() {
|
||||
Ok(Subservices::TcEnableEventGeneration) => {
|
||||
self.update_time_stamp();
|
||||
let start_token = send_start_acceptance(&mut self.verif_reporter, &self.time_stamp);
|
||||
self.event_request_tx
|
||||
.send(EventRequestWithToken {
|
||||
request: EventRequest::Enable(event_id),
|
||||
token: start_token,
|
||||
})
|
||||
.expect("Sending event request failed");
|
||||
}
|
||||
Ok(Subservices::TcDisableEventGeneration) => {
|
||||
self.update_time_stamp();
|
||||
let start_token = send_start_acceptance(&mut self.verif_reporter, &self.time_stamp);
|
||||
self.event_request_tx
|
||||
.send(EventRequestWithToken {
|
||||
request: EventRequest::Disable(event_id),
|
||||
token: start_token,
|
||||
})
|
||||
.expect("Sending event request failed");
|
||||
}
|
||||
_ => {
|
||||
self.update_time_stamp();
|
||||
send_start_failure(
|
||||
&mut self.verif_reporter,
|
||||
&self.time_stamp,
|
||||
EcssEnumU16::new(2),
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
121
satrs-example/src/bin/obsw/tmtc.rs
Normal file
121
satrs-example/src/bin/obsw/tmtc.rs
Normal file
@ -0,0 +1,121 @@
|
||||
use fsrc_core::events::EventU32;
|
||||
use fsrc_core::hal::host::udp_server::{ReceiveResult, UdpTcServer};
|
||||
use fsrc_core::params::Params;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::ccsds::CcsdsReceiver;
|
||||
use crate::pus::PusReceiver;
|
||||
use crate::UdpTmtcServer;
|
||||
use fsrc_core::pool::{SharedPool, StoreAddr};
|
||||
use fsrc_core::pus::event_man::EventRequestWithToken;
|
||||
use fsrc_core::pus::verification::SharedStdVerifReporterWithSender;
|
||||
use fsrc_core::tmtc::{CcsdsDistributor, CcsdsError, PusDistributor};
|
||||
use spacepackets::tm::PusTm;
|
||||
|
||||
pub const PUS_APID: u16 = 0x02;
|
||||
|
||||
pub struct CoreTmtcArgs {
|
||||
pub tm_store: TmStore,
|
||||
pub tm_sender: Sender<StoreAddr>,
|
||||
pub event_sender: Sender<(EventU32, Option<Params>)>,
|
||||
pub event_request_tx: Sender<EventRequestWithToken>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TmStore {
|
||||
pub pool: SharedPool,
|
||||
}
|
||||
|
||||
impl TmStore {
|
||||
pub fn add_pus_tm(&mut self, pus_tm: &PusTm) -> StoreAddr {
|
||||
let mut pg = self.pool.write().expect("Error locking TM store");
|
||||
let (addr, buf) = pg.free_element(pus_tm.len_packed()).expect("Store error");
|
||||
pus_tm
|
||||
.write_to_bytes(buf)
|
||||
.expect("Writing PUS TM to store failed");
|
||||
addr
|
||||
}
|
||||
}
|
||||
|
||||
pub fn core_tmtc_task(
|
||||
args: CoreTmtcArgs,
|
||||
tm_server_rx: mpsc::Receiver<StoreAddr>,
|
||||
addr: SocketAddr,
|
||||
verif_reporter: SharedStdVerifReporterWithSender,
|
||||
) {
|
||||
let pus_receiver = PusReceiver::new(
|
||||
PUS_APID,
|
||||
args.tm_sender,
|
||||
args.tm_store.clone(),
|
||||
verif_reporter,
|
||||
args.event_request_tx,
|
||||
);
|
||||
let pus_distributor = PusDistributor::new(Box::new(pus_receiver));
|
||||
let ccsds_receiver = CcsdsReceiver {
|
||||
pus_handler: pus_distributor,
|
||||
};
|
||||
let ccsds_distributor = CcsdsDistributor::new(Box::new(ccsds_receiver));
|
||||
let udp_tc_server = UdpTcServer::new(addr, 2048, Box::new(ccsds_distributor))
|
||||
.expect("Creating UDP TMTC server failed");
|
||||
|
||||
let mut udp_tmtc_server = UdpTmtcServer {
|
||||
udp_tc_server,
|
||||
tm_rx: tm_server_rx,
|
||||
tm_store: args.tm_store.pool.clone(),
|
||||
};
|
||||
loop {
|
||||
core_tmtc_loop(&mut udp_tmtc_server);
|
||||
thread::sleep(Duration::from_millis(400));
|
||||
}
|
||||
}
|
||||
|
||||
fn core_tmtc_loop(udp_tmtc_server: &mut UdpTmtcServer) {
|
||||
while core_tc_handling(udp_tmtc_server) {}
|
||||
if let Some(recv_addr) = udp_tmtc_server.udp_tc_server.last_sender() {
|
||||
core_tm_handling(udp_tmtc_server, &recv_addr);
|
||||
}
|
||||
}
|
||||
|
||||
fn core_tc_handling(udp_tmtc_server: &mut UdpTmtcServer) -> bool {
|
||||
match udp_tmtc_server.udp_tc_server.try_recv_tc() {
|
||||
Ok(_) => true,
|
||||
Err(e) => match e {
|
||||
ReceiveResult::ReceiverError(e) => match e {
|
||||
CcsdsError::PacketError(e) => {
|
||||
println!("Got packet error: {e:?}");
|
||||
true
|
||||
}
|
||||
CcsdsError::CustomError(_) => {
|
||||
println!("Unknown receiver error");
|
||||
true
|
||||
}
|
||||
},
|
||||
ReceiveResult::IoError(e) => {
|
||||
println!("IO error {e}");
|
||||
false
|
||||
}
|
||||
ReceiveResult::NothingReceived => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn core_tm_handling(udp_tmtc_server: &mut UdpTmtcServer, recv_addr: &SocketAddr) {
|
||||
while let Ok(addr) = udp_tmtc_server.tm_rx.try_recv() {
|
||||
let mut store_lock = udp_tmtc_server
|
||||
.tm_store
|
||||
.write()
|
||||
.expect("Locking TM store failed");
|
||||
let pg = store_lock.read_with_guard(addr);
|
||||
let buf = pg.read().expect("Error reading TM pool data");
|
||||
println!("Sending TM");
|
||||
udp_tmtc_server
|
||||
.udp_tc_server
|
||||
.socket
|
||||
.send_to(buf, recv_addr)
|
||||
.expect("Sending TM failed");
|
||||
}
|
||||
}
|
55
satrs-example/src/bin/test.rs
Normal file
55
satrs-example/src/bin/test.rs
Normal file
@ -0,0 +1,55 @@
|
||||
#![allow(dead_code)]
|
||||
use crossbeam_channel::{bounded, Receiver, Sender};
|
||||
use std::thread;
|
||||
use zerocopy::{AsBytes, FromBytes, NetworkEndian, Unaligned, U16};
|
||||
|
||||
trait FieldDataProvider: Send {
|
||||
fn get_data(&self) -> &[u8];
|
||||
}
|
||||
|
||||
struct FixedFieldDataWrapper {
|
||||
data: [u8; 8],
|
||||
}
|
||||
|
||||
impl FixedFieldDataWrapper {
|
||||
pub fn from_two_u32(p0: u32, p1: u32) -> Self {
|
||||
let mut data = [0; 8];
|
||||
data[0..4].copy_from_slice(p0.to_be_bytes().as_slice());
|
||||
data[4..8].copy_from_slice(p1.to_be_bytes().as_slice());
|
||||
Self { data }
|
||||
}
|
||||
}
|
||||
|
||||
impl FieldDataProvider for FixedFieldDataWrapper {
|
||||
fn get_data(&self) -> &[u8] {
|
||||
self.data.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
type FieldDataTraitObj = Box<dyn FieldDataProvider>;
|
||||
|
||||
struct ExampleMgmSet {
|
||||
mgm_vec: [f32; 3],
|
||||
temperature: u16,
|
||||
}
|
||||
|
||||
#[derive(FromBytes, AsBytes, Unaligned)]
|
||||
#[repr(C)]
|
||||
struct ExampleMgmSetZc {
|
||||
mgm_vec: [u8; 12],
|
||||
temperatur: U16<NetworkEndian>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (s0, r0): (Sender<FieldDataTraitObj>, Receiver<FieldDataTraitObj>) = bounded(5);
|
||||
let data_wrapper = FixedFieldDataWrapper::from_two_u32(2, 3);
|
||||
s0.send(Box::new(data_wrapper)).unwrap();
|
||||
let jh0 = thread::spawn(move || {
|
||||
let data = r0.recv().unwrap();
|
||||
let raw = data.get_data();
|
||||
println!("Received data {:?}", raw);
|
||||
});
|
||||
let jh1 = thread::spawn(|| {});
|
||||
jh0.join().unwrap();
|
||||
jh1.join().unwrap();
|
||||
}
|
4
satrs-example/src/lib.rs
Normal file
4
satrs-example/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
pub const OBSW_SERVER_ADDR: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
|
||||
pub const SERVER_PORT: u16 = 7301;
|
Reference in New Issue
Block a user