OBSW-Client Example #11
19
.idea/runConfigurations/Run_obsw_client_example.xml
Normal file
19
.idea/runConfigurations/Run_obsw_client_example.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Run obsw client example" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||||
|
<option name="command" value="run --package fsrc-example --bin client" />
|
||||||
|
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||||
|
<option name="channel" value="DEFAULT" />
|
||||||
|
<option name="requiredFeatures" value="true" />
|
||||||
|
<option name="allFeatures" value="false" />
|
||||||
|
<option name="emulateTerminal" value="false" />
|
||||||
|
<option name="withSudo" value="false" />
|
||||||
|
<option name="buildTarget" value="REMOTE" />
|
||||||
|
<option name="backtrace" value="SHORT" />
|
||||||
|
<envs />
|
||||||
|
<option name="isRedirectInput" value="false" />
|
||||||
|
<option name="redirectInputPath" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
19
.idea/runConfigurations/Run_obsw_example.xml
Normal file
19
.idea/runConfigurations/Run_obsw_example.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Run obsw example" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||||
|
<option name="command" value="run --package fsrc-example --bin obsw" />
|
||||||
|
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||||
|
<option name="channel" value="DEFAULT" />
|
||||||
|
<option name="requiredFeatures" value="true" />
|
||||||
|
<option name="allFeatures" value="false" />
|
||||||
|
<option name="emulateTerminal" value="false" />
|
||||||
|
<option name="withSudo" value="false" />
|
||||||
|
<option name="buildTarget" value="REMOTE" />
|
||||||
|
<option name="backtrace" value="SHORT" />
|
||||||
|
<envs />
|
||||||
|
<option name="isRedirectInput" value="false" />
|
||||||
|
<option name="redirectInputPath" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -235,6 +235,7 @@ dependencies = [
|
|||||||
name = "fsrc-example"
|
name = "fsrc-example"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"fsrc-core",
|
||||||
"spacepackets",
|
"spacepackets",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,20 +1,24 @@
|
|||||||
use crate::hal::host::udp_server::ReceiveResult::{IoError, ReceiverError};
|
use crate::hal::host::udp_server::ReceiveResult::{IoError, ReceiverError};
|
||||||
use crate::tmtc::ReceivesTc;
|
use crate::tmtc::ReceivesTc;
|
||||||
|
use std::boxed::Box;
|
||||||
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
||||||
|
use std::vec;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
pub struct UdpTmtcServer<E> {
|
pub struct UdpTcServer<E> {
|
||||||
socket: UdpSocket,
|
pub socket: UdpSocket,
|
||||||
recv_buf: Vec<u8>,
|
recv_buf: Vec<u8>,
|
||||||
|
sender_addr: Option<SocketAddr>,
|
||||||
tc_receiver: Box<dyn ReceivesTc<Error = E>>,
|
tc_receiver: Box<dyn ReceivesTc<Error = E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum ReceiveResult<E> {
|
pub enum ReceiveResult<E> {
|
||||||
IoError(std::io::Error),
|
IoError(std::io::Error),
|
||||||
ReceiverError(E),
|
ReceiverError(E),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> UdpTmtcServer<E> {
|
impl<E> UdpTcServer<E> {
|
||||||
pub fn new<A: ToSocketAddrs>(
|
pub fn new<A: ToSocketAddrs>(
|
||||||
addr: A,
|
addr: A,
|
||||||
max_recv_size: usize,
|
max_recv_size: usize,
|
||||||
@ -22,7 +26,8 @@ impl<E> UdpTmtcServer<E> {
|
|||||||
) -> Result<Self, std::io::Error> {
|
) -> Result<Self, std::io::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
socket: UdpSocket::bind(addr)?,
|
socket: UdpSocket::bind(addr)?,
|
||||||
recv_buf: Vec::with_capacity(max_recv_size),
|
recv_buf: vec![0; max_recv_size],
|
||||||
|
sender_addr: None,
|
||||||
tc_receiver,
|
tc_receiver,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -32,6 +37,7 @@ impl<E> UdpTmtcServer<E> {
|
|||||||
.socket
|
.socket
|
||||||
.recv_from(&mut self.recv_buf)
|
.recv_from(&mut self.recv_buf)
|
||||||
.map_err(|e| IoError(e))?;
|
.map_err(|e| IoError(e))?;
|
||||||
|
self.sender_addr = Some(res.1);
|
||||||
self.tc_receiver
|
self.tc_receiver
|
||||||
.pass_tc(&self.recv_buf[0..res.0])
|
.pass_tc(&self.recv_buf[0..res.0])
|
||||||
.map_err(|e| ReceiverError(e))?;
|
.map_err(|e| ReceiverError(e))?;
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#[cfg(feature = "use_std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod host;
|
pub mod host;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
//!
|
//!
|
||||||
//! The routing components consist of two core components:
|
//! The routing components consist of two core components:
|
||||||
//! 1. [CcsdsDistributor] component which dispatches received packets to a user-provided handler
|
//! 1. [CcsdsDistributor] component which dispatches received packets to a user-provided handler
|
||||||
//! 2. [ApidPacketHandler] trait which should be implemented by the user-provided packet handler.
|
//! 2. [CcsdsPacketHandler] trait which should be implemented by the user-provided packet handler.
|
||||||
//!
|
//!
|
||||||
//! The [CcsdsDistributor] implements the [ReceivesCcsdsTc] and [ReceivesTc] trait which allows to
|
//! The [CcsdsDistributor] implements the [ReceivesCcsdsTc] and [ReceivesTc] trait which allows to
|
||||||
//! pass raw or CCSDS packets to it. Upon receiving a packet, it performs the following steps:
|
//! pass raw or CCSDS packets to it. Upon receiving a packet, it performs the following steps:
|
||||||
@ -11,14 +11,14 @@
|
|||||||
//! respective CCSDS space packet header field. If that process fails, a [PacketError] is
|
//! respective CCSDS space packet header field. If that process fails, a [PacketError] is
|
||||||
//! returned to the user
|
//! returned to the user
|
||||||
//! 2. If a valid APID is found and matches one of the APIDs provided by
|
//! 2. If a valid APID is found and matches one of the APIDs provided by
|
||||||
//! [ApidPacketHandler::valid_apids], it will pass the packet to the user provided
|
//! [CcsdsPacketHandler::valid_apids], it will pass the packet to the user provided
|
||||||
//! [ApidPacketHandler::handle_known_apid] function. If no valid APID is found, the packet
|
//! [CcsdsPacketHandler::handle_known_apid] function. If no valid APID is found, the packet
|
||||||
//! will be passed to the [ApidPacketHandler::handle_unknown_apid] function.
|
//! will be passed to the [CcsdsPacketHandler::handle_unknown_apid] function.
|
||||||
//!
|
//!
|
||||||
//! # Example
|
//! # Example
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use fsrc_core::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor};
|
//! use fsrc_core::tmtc::ccsds_distrib::{CcsdsPacketHandler, CcsdsDistributor};
|
||||||
//! use fsrc_core::tmtc::ReceivesTc;
|
//! use fsrc_core::tmtc::ReceivesTc;
|
||||||
//! use spacepackets::{CcsdsPacket, SpHeader};
|
//! use spacepackets::{CcsdsPacket, SpHeader};
|
||||||
//! use spacepackets::tc::PusTc;
|
//! use spacepackets::tc::PusTc;
|
||||||
@ -33,7 +33,7 @@
|
|||||||
//! fn mutable_foo(&mut self) {}
|
//! fn mutable_foo(&mut self) {}
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! impl ApidPacketHandler for ConcreteApidHandler {
|
//! impl CcsdsPacketHandler for ConcreteApidHandler {
|
||||||
//! type Error = ();
|
//! type Error = ();
|
||||||
//! fn valid_apids(&self) -> &'static [u16] { &[0x002] }
|
//! fn valid_apids(&self) -> &'static [u16] { &[0x002] }
|
||||||
//! fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
//! fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
||||||
@ -86,7 +86,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
use crate::tmtc::{ReceivesCcsdsTc, ReceivesTc};
|
use crate::tmtc::{ReceivesCcsdsTc, ReceivesTc};
|
||||||
use downcast_rs::Downcast;
|
use downcast_rs::Downcast;
|
||||||
use spacepackets::{CcsdsPacket, PacketError, SpHeader};
|
use spacepackets::{CcsdsPacket, PacketError, SizeMissmatch, SpHeader};
|
||||||
|
|
||||||
/// Generic trait for a handler or dispatcher object handling CCSDS packets.
|
/// Generic trait for a handler or dispatcher object handling CCSDS packets.
|
||||||
///
|
///
|
||||||
@ -98,7 +98,7 @@ use spacepackets::{CcsdsPacket, PacketError, SpHeader};
|
|||||||
/// This trait automatically implements the [downcast_rs::Downcast] to allow a more convenient API
|
/// This trait automatically implements the [downcast_rs::Downcast] to allow a more convenient API
|
||||||
/// to cast trait objects back to their concrete type after the handler was passed to the
|
/// to cast trait objects back to their concrete type after the handler was passed to the
|
||||||
/// distributor.
|
/// distributor.
|
||||||
pub trait ApidPacketHandler: Downcast {
|
pub trait CcsdsPacketHandler: Downcast {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
fn valid_apids(&self) -> &'static [u16];
|
fn valid_apids(&self) -> &'static [u16];
|
||||||
@ -111,14 +111,14 @@ pub trait ApidPacketHandler: Downcast {
|
|||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
downcast_rs::impl_downcast!(ApidPacketHandler assoc Error);
|
downcast_rs::impl_downcast!(CcsdsPacketHandler assoc Error);
|
||||||
|
|
||||||
/// The CCSDS distributor dispatches received CCSDS packets to a user provided packet handler.
|
/// The CCSDS distributor dispatches received CCSDS packets to a user provided packet handler.
|
||||||
pub struct CcsdsDistributor<E> {
|
pub struct CcsdsDistributor<E> {
|
||||||
/// User provided APID handler stored as a generic trait object.
|
/// User provided APID handler stored as a generic trait object.
|
||||||
/// It can be cast back to the original concrete type using the [Self::apid_handler_ref] or
|
/// It can be cast back to the original concrete type using the [Self::apid_handler_ref] or
|
||||||
/// the [Self::apid_handler_mut] method.
|
/// the [Self::apid_handler_mut] method.
|
||||||
pub apid_handler: Box<dyn ApidPacketHandler<Error = E>>,
|
pub apid_handler: Box<dyn CcsdsPacketHandler<Error = E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
@ -139,26 +139,34 @@ impl<E: 'static> ReceivesTc for CcsdsDistributor<E> {
|
|||||||
type Error = CcsdsError<E>;
|
type Error = CcsdsError<E>;
|
||||||
|
|
||||||
fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> {
|
||||||
|
if tc_raw.len() < 7 {
|
||||||
|
return Err(CcsdsError::PacketError(
|
||||||
|
PacketError::FromBytesSliceTooSmall(SizeMissmatch {
|
||||||
|
found: tc_raw.len(),
|
||||||
|
expected: 7,
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
}
|
||||||
let sp_header = SpHeader::from_raw_slice(tc_raw).map_err(|e| CcsdsError::PacketError(e))?;
|
let sp_header = SpHeader::from_raw_slice(tc_raw).map_err(|e| CcsdsError::PacketError(e))?;
|
||||||
self.dispatch_ccsds(&sp_header, tc_raw)
|
self.dispatch_ccsds(&sp_header, tc_raw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: 'static> CcsdsDistributor<E> {
|
impl<E: 'static> CcsdsDistributor<E> {
|
||||||
pub fn new(apid_handler: Box<dyn ApidPacketHandler<Error = E>>) -> Self {
|
pub fn new(apid_handler: Box<dyn CcsdsPacketHandler<Error = E>>) -> Self {
|
||||||
CcsdsDistributor { apid_handler }
|
CcsdsDistributor { apid_handler }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function can be used to retrieve a reference to the concrete instance of the APID
|
/// This function can be used to retrieve a reference to the concrete instance of the APID
|
||||||
/// handler after it was passed to the distributor. See the
|
/// handler after it was passed to the distributor. See the
|
||||||
/// [module documentation][crate::tmtc::ccsds_distrib] for an fsrc-example.
|
/// [module documentation][crate::tmtc::ccsds_distrib] for an fsrc-example.
|
||||||
pub fn apid_handler_ref<T: ApidPacketHandler<Error = E>>(&self) -> Option<&T> {
|
pub fn apid_handler_ref<T: CcsdsPacketHandler<Error = E>>(&self) -> Option<&T> {
|
||||||
self.apid_handler.downcast_ref::<T>()
|
self.apid_handler.downcast_ref::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function can be used to retrieve a mutable reference to the concrete instance of the
|
/// This function can be used to retrieve a mutable reference to the concrete instance of the
|
||||||
/// APID handler after it was passed to the distributor.
|
/// APID handler after it was passed to the distributor.
|
||||||
pub fn apid_handler_mut<T: ApidPacketHandler<Error = E>>(&mut self) -> Option<&mut T> {
|
pub fn apid_handler_mut<T: CcsdsPacketHandler<Error = E>>(&mut self) -> Option<&mut T> {
|
||||||
self.apid_handler.downcast_mut::<T>()
|
self.apid_handler.downcast_mut::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +190,7 @@ impl<E: 'static> CcsdsDistributor<E> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) mod tests {
|
pub(crate) mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor};
|
use crate::tmtc::ccsds_distrib::{CcsdsDistributor, CcsdsPacketHandler};
|
||||||
use spacepackets::tc::PusTc;
|
use spacepackets::tc::PusTc;
|
||||||
use spacepackets::CcsdsPacket;
|
use spacepackets::CcsdsPacket;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
@ -207,7 +215,7 @@ pub(crate) mod tests {
|
|||||||
pub unknown_packet_queue: VecDeque<(u16, Vec<u8>)>,
|
pub unknown_packet_queue: VecDeque<(u16, Vec<u8>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApidPacketHandler for BasicApidHandlerSharedQueue {
|
impl CcsdsPacketHandler for BasicApidHandlerSharedQueue {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
fn valid_apids(&self) -> &'static [u16] {
|
fn valid_apids(&self) -> &'static [u16] {
|
||||||
&[0x000, 0x002]
|
&[0x000, 0x002]
|
||||||
@ -242,7 +250,7 @@ pub(crate) mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApidPacketHandler for BasicApidHandlerOwnedQueue {
|
impl CcsdsPacketHandler for BasicApidHandlerOwnedQueue {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn valid_apids(&self) -> &'static [u16] {
|
fn valid_apids(&self) -> &'static [u16] {
|
||||||
|
@ -12,6 +12,9 @@ use spacepackets::SpHeader;
|
|||||||
pub mod ccsds_distrib;
|
pub mod ccsds_distrib;
|
||||||
pub mod pus_distrib;
|
pub mod pus_distrib;
|
||||||
|
|
||||||
|
pub use ccsds_distrib::{CcsdsDistributor, CcsdsError, CcsdsPacketHandler};
|
||||||
|
pub use pus_distrib::{PusDistributor, PusServiceProvider};
|
||||||
|
|
||||||
const _RAW_PACKET_ERROR: &str = "raw-tmtc";
|
const _RAW_PACKET_ERROR: &str = "raw-tmtc";
|
||||||
const _CCSDS_ERROR: &str = "ccsds-tmtc";
|
const _CCSDS_ERROR: &str = "ccsds-tmtc";
|
||||||
const _PUS_ERROR: &str = "pus-tmtc";
|
const _PUS_ERROR: &str = "pus-tmtc";
|
||||||
|
@ -137,7 +137,8 @@ mod tests {
|
|||||||
use crate::tmtc::ccsds_distrib::tests::{
|
use crate::tmtc::ccsds_distrib::tests::{
|
||||||
generate_ping_tc, BasicApidHandlerOwnedQueue, BasicApidHandlerSharedQueue,
|
generate_ping_tc, BasicApidHandlerOwnedQueue, BasicApidHandlerSharedQueue,
|
||||||
};
|
};
|
||||||
use crate::tmtc::ccsds_distrib::{ApidPacketHandler, CcsdsDistributor};
|
use crate::tmtc::ccsds_distrib::{CcsdsDistributor, CcsdsPacketHandler};
|
||||||
|
use alloc::vec::Vec;
|
||||||
use spacepackets::ecss::PusError;
|
use spacepackets::ecss::PusError;
|
||||||
use spacepackets::tc::PusTc;
|
use spacepackets::tc::PusTc;
|
||||||
use spacepackets::CcsdsPacket;
|
use spacepackets::CcsdsPacket;
|
||||||
@ -235,11 +236,11 @@ mod tests {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApidPacketHandler for ApidHandlerOwned {
|
impl CcsdsPacketHandler for ApidHandlerOwned {
|
||||||
apid_handler_impl!();
|
apid_handler_impl!();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApidPacketHandler for ApidHandlerShared {
|
impl CcsdsPacketHandler for ApidHandlerShared {
|
||||||
apid_handler_impl!();
|
apid_handler_impl!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
use fsrc_core::pool::{LocalPool, PoolCfg, StoreAddr, StoreError};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use fsrc_core::pool::{LocalPool, PoolCfg, StoreAddr, StoreError};
|
|
||||||
|
|
||||||
|
|
||||||
struct PoolAccessDummy<'a> {
|
struct PoolAccessDummy<'a> {
|
||||||
pool: &'a mut LocalPool,
|
pool: &'a mut LocalPool,
|
||||||
|
@ -6,3 +6,6 @@ authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
|||||||
|
|
||||||
[dependencies.spacepackets]
|
[dependencies.spacepackets]
|
||||||
path = "../spacepackets"
|
path = "../spacepackets"
|
||||||
|
|
||||||
|
[dependencies.fsrc-core]
|
||||||
|
path = "../fsrc-core"
|
||||||
|
@ -8,7 +8,7 @@ fn main() {
|
|||||||
let addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
let addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
||||||
let mut sph = SpHeader::tc(0x02, 0, 0).unwrap();
|
let mut sph = SpHeader::tc(0x02, 0, 0).unwrap();
|
||||||
let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true);
|
let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true);
|
||||||
let client = UdpSocket::bind("127.0.0.1:7300").expect("Connecting to UDP server failed");
|
let client = UdpSocket::bind("127.0.0.1:7302").expect("Connecting to UDP server failed");
|
||||||
let size = pus_tc.write_to(&mut buf).expect("Creating PUS TC failed");
|
let size = pus_tc.write_to(&mut buf).expect("Creating PUS TC failed");
|
||||||
client
|
client
|
||||||
.send_to(&buf[0..size], &addr)
|
.send_to(&buf[0..size], &addr)
|
||||||
|
@ -1,15 +1,96 @@
|
|||||||
|
use fsrc_core::hal::host::udp_server::{ReceiveResult, UdpTcServer};
|
||||||
|
use fsrc_core::tmtc::{
|
||||||
|
CcsdsDistributor, CcsdsError, CcsdsPacketHandler, PusDistributor, PusServiceProvider,
|
||||||
|
ReceivesCcsdsTc,
|
||||||
|
};
|
||||||
use fsrc_example::{OBSW_SERVER_ADDR, SERVER_PORT};
|
use fsrc_example::{OBSW_SERVER_ADDR, SERVER_PORT};
|
||||||
use std::net::{IpAddr, SocketAddr, UdpSocket};
|
use spacepackets::tc::PusTc;
|
||||||
|
use spacepackets::{CcsdsPacket, SpHeader};
|
||||||
|
use std::net::{IpAddr, SocketAddr};
|
||||||
|
|
||||||
|
const PUS_APID: u16 = 0x02;
|
||||||
|
|
||||||
|
struct PusReceiver {}
|
||||||
|
|
||||||
|
struct CcsdsReceiver {
|
||||||
|
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 detected");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PusServiceProvider for PusReceiver {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn handle_pus_tc_packet(
|
||||||
|
&mut self,
|
||||||
|
service: u8,
|
||||||
|
_header: &SpHeader,
|
||||||
|
pus_tc: &PusTc,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
if service == 17 {
|
||||||
|
println!("Received PUS ping command");
|
||||||
|
let raw_data = pus_tc.raw().expect("Could not retrieve raw data");
|
||||||
|
println!("Raw data: 0x{raw_data:x?}");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut recv_buf = [0; 1024];
|
|
||||||
let addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
let addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
||||||
let socket = UdpSocket::bind(&addr).expect("Error opening UDP socket");
|
let pus_receiver = PusReceiver {};
|
||||||
|
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 mut udp_tmtc_server = UdpTcServer::new(addr, 2048, Box::new(ccsds_distributor))
|
||||||
|
.expect("Creating UDP TMTC server failed");
|
||||||
loop {
|
loop {
|
||||||
let (num_bytes, src) = socket.recv_from(&mut recv_buf).expect("UDP Receive error");
|
let res = udp_tmtc_server.recv_tc();
|
||||||
println!(
|
match res {
|
||||||
"Received TM with len {num_bytes} from {src}: {:x?}",
|
Ok(_) => (),
|
||||||
&recv_buf[0..num_bytes]
|
Err(e) => match e {
|
||||||
);
|
ReceiveResult::ReceiverError(e) => match e {
|
||||||
|
CcsdsError::PacketError(e) => {
|
||||||
|
println!("Got packet error: {e:?}");
|
||||||
|
}
|
||||||
|
CcsdsError::CustomError(_) => {
|
||||||
|
println!("Unknown receiver error")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ReceiveResult::IoError(e) => {
|
||||||
|
println!("IO error {e}");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 35073a45a536051e3852696c501d7afa1b36a808
|
Subproject commit 42d3487c1934cfecf9b2d599c2f81fde52a61cc3
|
Loading…
Reference in New Issue
Block a user