that gets the job done
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit

This commit is contained in:
Robin Müller 2024-04-03 18:04:32 +02:00
parent 68908f53d4
commit cba4a29396
Signed by: muellerr
GPG Key ID: A649FB78196E3849
12 changed files with 290 additions and 174 deletions

View File

@ -17,6 +17,8 @@ zerocopy = "0.6"
csv = "1"
num_enum = "0.7"
thiserror = "1"
lazy_static = "1"
strum = { version = "0.26", features = ["derive"] }
derive-new = "0.5"
serde = { version = "1", features = ["derive"] }
serde_json = "1"

View File

@ -36,8 +36,15 @@ class EventU32:
)
class RequestTargetId(enum.IntEnum):
ACS = 1
class Apid(enum.IntEnum):
SCHED = 1
GENERIC_PUS = 2
ACS = 3
CFDP = 4
class AcsId(enum.IntEnum):
MGM_0 = 0
class AcsHkIds(enum.IntEnum):

View File

@ -1,23 +1,35 @@
import datetime
import struct
import logging
from spacepackets.ccsds import CdsShortTimestamp
from spacepackets.ecss import PusTelecommand
from tmtccmd.config import CmdTreeNode
from tmtccmd.pus.tc.s200_fsfw_mode import Mode
from tmtccmd.tmtc import DefaultPusQueueHelper
from tmtccmd.pus.s11_tc_sched import create_time_tagged_cmd
from tmtccmd.pus.tc.s3_fsfw_hk import create_request_one_hk_command
from tmtccmd.pus.s200_fsfw_mode import Subservice as ModeSubservice
from common import (
EXAMPLE_PUS_APID,
make_addressable_id,
RequestTargetId,
AcsHkIds,
)
from common import EXAMPLE_PUS_APID, AcsId, Apid
_LOGGER = logging.getLogger(__name__)
def create_set_mode_cmd(
apid: int, unique_id: int, mode: int, submode: int
) -> PusTelecommand:
app_data = bytearray()
app_data.extend(struct.pack("!I", unique_id))
app_data.extend(struct.pack("!I", mode))
app_data.extend(struct.pack("!H", submode))
return PusTelecommand(
service=200,
subservice=ModeSubservice.TC_MODE_COMMAND,
apid=apid,
app_data=app_data,
)
def create_cmd_definition_tree() -> CmdTreeNode:
root_node = CmdTreeNode.root_node()
@ -95,12 +107,33 @@ def pack_pus_telecommands(q: DefaultPusQueueHelper, cmd_path: str):
)
if cmd_path_list[0] == "acs":
assert len(cmd_path_list) >= 2
if cmd_path_list[1] == "mgm":
if cmd_path_list[1] == "mgms":
assert len(cmd_path_list) >= 3
if cmd_path_list[2] == "one_shot_hk":
q.add_log_cmd("Sending HK one shot request")
q.add_pus_tc(
create_request_one_hk_command(
make_addressable_id(RequestTargetId.ACS, AcsHkIds.MGM_SET)
if cmd_path_list[2] == "hk":
if cmd_path_list[3] == "one_shot_hk":
q.add_log_cmd("Sending HK one shot request")
# TODO: Fix
# q.add_pus_tc(
# create_request_one_hk_command(
# make_addressable_id(Apid.ACS, AcsId.MGM_SET)
# )
# )
if cmd_path_list[2] == "mode":
if cmd_path_list[3] == "set_mode":
handle_set_mode_cmd(
q, "MGM 0", cmd_path_list[4], Apid.ACS, AcsId.MGM_0
)
)
def handle_set_mode_cmd(
q: DefaultPusQueueHelper, target_str: str, mode_str: str, apid: int, unique_id: int
):
if mode_str == "off":
q.add_log_cmd(f"Sending Mode OFF to {target_str}")
q.add_pus_tc(create_set_mode_cmd(apid, unique_id, Mode.OFF, 0))
elif mode_str == "on":
q.add_log_cmd(f"Sending Mode ON to {target_str}")
q.add_pus_tc(create_set_mode_cmd(apid, unique_id, Mode.ON, 0))
elif mode_str == "normal":
q.add_log_cmd(f"Sending Mode NORMAL to {target_str}")
q.add_pus_tc(create_set_mode_cmd(apid, unique_id, Mode.NORMAL, 0))

View File

@ -1,7 +1,9 @@
use satrs::encoding::ccsds::PacketIdValidator;
use satrs::pus::ReceivesEcssPusTc;
use satrs::spacepackets::{CcsdsPacket, SpHeader};
use satrs::spacepackets::{CcsdsPacket, PacketId, SpHeader};
use satrs::tmtc::{CcsdsPacketHandler, ReceivesCcsdsTc};
use satrs_example::config::components::Apid;
use satrs_example::config::PACKET_ID_VALIDATOR;
#[derive(Clone)]
pub struct CcsdsReceiver<
@ -11,6 +13,16 @@ pub struct CcsdsReceiver<
pub tc_source: TcSource,
}
impl<
TcSource: ReceivesCcsdsTc<Error = E> + ReceivesEcssPusTc<Error = E> + Clone + 'static,
E: 'static,
> PacketIdValidator for CcsdsReceiver<TcSource, E>
{
fn validate(&self, packet_id: u16) -> bool {
PACKET_ID_VALIDATOR.contains(&PacketId::from(packet_id))
}
}
impl<
TcSource: ReceivesCcsdsTc<Error = E> + ReceivesEcssPusTc<Error = E> + Clone + 'static,
E: 'static,
@ -18,16 +30,7 @@ impl<
{
type Error = E;
fn valid_apids(&self) -> &'static [u16] {
&[
Apid::GenericPus as u16,
Apid::Acs as u16,
Apid::Sched as u16,
Apid::EventTm as u16,
]
}
fn handle_known_apid(
fn handle_packet_with_valid_apid(
&mut self,
sp_header: &SpHeader,
tc_raw: &[u8],
@ -39,7 +42,7 @@ impl<
Ok(())
}
fn handle_unknown_apid(
fn handle_packet_with_unknown_apid(
&mut self,
sp_header: &SpHeader,
_tc_raw: &[u8],

View File

@ -1,7 +1,12 @@
use satrs::res_code::ResultU16;
use lazy_static::lazy_static;
use satrs::{
res_code::ResultU16,
spacepackets::{PacketId, PacketType},
};
use satrs_mib::res_code::ResultU16Info;
use satrs_mib::resultcode;
use std::net::Ipv4Addr;
use std::{collections::HashSet, net::Ipv4Addr};
use strum::IntoEnumIterator;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use satrs::{
@ -36,6 +41,16 @@ pub const SERVER_PORT: u16 = 7301;
pub const TEST_EVENT: EventU32TypedSev<SeverityInfo> =
EventU32TypedSev::<SeverityInfo>::const_new(0, 0);
lazy_static! {
pub static ref PACKET_ID_VALIDATOR: HashSet<PacketId> = {
let mut set = HashSet::new();
for id in components::Apid::iter() {
set.insert(PacketId::const_new(PacketType::Tc, true, id as u16));
}
set
};
}
pub mod tmtc_err {
use super::*;
@ -102,26 +117,25 @@ pub mod mode_err {
pub mod components {
use satrs::request::UniqueApidTargetId;
use strum::EnumIter;
#[derive(Copy, Clone, PartialEq, Eq)]
#[derive(Copy, Clone, PartialEq, Eq, EnumIter)]
pub enum Apid {
VerificationTm = 1,
Sched = 2,
EventTm = 3,
HkTm = 4,
GenericPus = 5,
Acs = 6,
Cfdp = 7,
Sched = 1,
GenericPus = 2,
Acs = 3,
Cfdp = 4,
}
// Component IDs for components with the PUS APID.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum PusId {
PusRouting = 0,
PusTest = 1,
PusAction = 2,
PusMode = 3,
PusHk = 4,
PusEventManagement = 0,
PusRouting = 1,
PusTest = 2,
PusAction = 3,
PusMode = 4,
PusHk = 5,
}
#[derive(Copy, Clone, PartialEq, Eq)]
@ -132,7 +146,7 @@ pub mod components {
pub const PUS_ACTION_SERVICE: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusAction as u32);
pub const PUS_EVENT_MANAGEMENT: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::EventTm as u16, 0);
UniqueApidTargetId::new(Apid::GenericPus as u16, 0);
pub const PUS_ROUTING_SERVICE: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusRouting as u32);
pub const PUS_TEST_SERVICE: UniqueApidTargetId =

View File

@ -3,8 +3,10 @@ use std::sync::mpsc::{self};
use crate::pus::create_verification_reporter;
use satrs::event_man::{EventMessageU32, EventRoutingError};
use satrs::params::WritableToBeBytes;
use satrs::pus::event::EventTmHookProvider;
use satrs::pus::verification::VerificationReporter;
use satrs::pus::EcssTmSenderCore;
use satrs::request::UniqueApidTargetId;
use satrs::{
event_man::{
EventManagerWithBoundedMpsc, EventSendProvider, EventU32SenderMpscBounded,
@ -18,11 +20,22 @@ use satrs::{
},
spacepackets::time::cds::CdsTime,
};
use satrs_example::config::components;
use satrs_example::config::components::PUS_EVENT_MANAGEMENT;
use crate::update_time;
// This helper sets the APID of the event sender for the PUS telemetry.
#[derive(Default)]
pub struct EventApidSetter {
pub next_apid: u16,
}
impl EventTmHookProvider for EventApidSetter {
fn modify_tm(&self, tm: &mut satrs::spacepackets::ecss::tm::PusTmCreator) {
tm.set_apid(self.next_apid);
}
}
/// The PUS event handler subscribes for all events and converts them into ECSS PUS 5 event
/// packets. It also handles the verification completion of PUS event service requests.
pub struct PusEventHandler<TmSender: EcssTmSenderCore> {
@ -33,6 +46,7 @@ pub struct PusEventHandler<TmSender: EcssTmSenderCore> {
time_provider: CdsTime,
timestamp: [u8; 7],
verif_handler: VerificationReporter,
event_apid_setter: EventApidSetter,
}
impl<TmSender: EcssTmSenderCore> PusEventHandler<TmSender> {
@ -47,12 +61,7 @@ impl<TmSender: EcssTmSenderCore> PusEventHandler<TmSender> {
// All events sent to the manager are routed to the PUS event manager, which generates PUS event
// telemetry for each event.
let event_reporter = EventReporter::new(
PUS_EVENT_MANAGEMENT.raw(),
components::Apid::EventTm as u16,
128,
)
.unwrap();
let event_reporter = EventReporter::new(PUS_EVENT_MANAGEMENT.raw(), 0, 0, 128).unwrap();
let pus_event_dispatcher =
DefaultPusEventU32Dispatcher::new_with_default_backend(event_reporter);
let pus_event_man_send_provider = EventU32SenderMpscBounded::new(
@ -72,6 +81,7 @@ impl<TmSender: EcssTmSenderCore> PusEventHandler<TmSender> {
timestamp: [0; 7],
verif_handler,
tm_sender,
event_apid_setter: EventApidSetter::default(),
}
}
@ -113,6 +123,7 @@ impl<TmSender: EcssTmSenderCore> PusEventHandler<TmSender> {
let param_vec = event_msg.params().map_or(Vec::new(), |param| {
param.to_vec().expect("failed to convert params to vec")
});
self.event_apid_setter.next_apid = UniqueApidTargetId::from(event_msg.sender_id()).apid;
self.pus_event_dispatcher
.generate_pus_event_tm_generic(
&self.tm_sender,

View File

@ -23,7 +23,7 @@ use satrs_example::config::pool::{create_sched_tc_pool, create_static_pools};
use satrs_example::config::tasks::{
FREQ_MS_AOCS, FREQ_MS_EVENT_HANDLING, FREQ_MS_PUS_STACK, FREQ_MS_UDP_TMTC,
};
use satrs_example::config::{OBSW_SERVER_ADDR, SERVER_PORT};
use satrs_example::config::{OBSW_SERVER_ADDR, PACKET_ID_VALIDATOR, SERVER_PORT};
use tmtc::PusTcSourceProviderDynamic;
use udp::DynamicUdpTmHandler;
@ -191,6 +191,7 @@ fn static_tmtc_pool_main() {
tcp_server_cfg,
sync_tm_tcp_source.clone(),
tcp_ccsds_distributor,
PACKET_ID_VALIDATOR.clone(),
)
.expect("tcp server creation failed");
@ -415,6 +416,7 @@ fn dyn_tmtc_pool_main() {
tcp_server_cfg,
sync_tm_tcp_source.clone(),
tcp_ccsds_distributor,
PACKET_ID_VALIDATOR.clone(),
)
.expect("tcp server creation failed");

View File

@ -1,5 +1,5 @@
use std::{
collections::VecDeque,
collections::{HashSet, VecDeque},
sync::{Arc, Mutex},
};
@ -10,17 +10,9 @@ use satrs::{
spacepackets::PacketId,
tmtc::{CcsdsDistributor, CcsdsError, ReceivesCcsdsTc, TmPacketSourceCore},
};
use satrs_example::config::components;
use crate::ccsds::CcsdsReceiver;
pub const PACKET_ID_LOOKUP: &[PacketId] = &[
PacketId::const_tc(true, components::Apid::GenericPus as u16),
PacketId::const_tc(true, components::Apid::EventTm as u16),
PacketId::const_tc(true, components::Apid::Acs as u16),
PacketId::const_tc(true, components::Apid::Sched as u16),
];
#[derive(Default, Clone)]
pub struct SyncTcpTmSource {
tm_queue: Arc<Mutex<VecDeque<Vec<u8>>>>,
@ -82,6 +74,7 @@ pub type TcpServerType<TcSource, MpscErrorType> = TcpSpacepacketsServer<
CcsdsError<MpscErrorType>,
SyncTcpTmSource,
CcsdsDistributor<CcsdsReceiver<TcSource, MpscErrorType>, MpscErrorType>,
HashSet<PacketId>,
>;
pub struct TcpTask<
@ -108,14 +101,10 @@ impl<
cfg: ServerConfig,
tm_source: SyncTcpTmSource,
tc_receiver: CcsdsDistributor<CcsdsReceiver<TcSource, MpscErrorType>, MpscErrorType>,
packet_id_lookup: HashSet<PacketId>,
) -> Result<Self, std::io::Error> {
Ok(Self {
server: TcpSpacepacketsServer::new(
cfg,
tm_source,
tc_receiver,
Box::new(PACKET_ID_LOOKUP),
)?,
server: TcpSpacepacketsServer::new(cfg, tm_source, tc_receiver, packet_id_lookup)?,
})
}

View File

@ -2,60 +2,71 @@
use alloc::vec::Vec;
#[cfg(feature = "alloc")]
use hashbrown::HashSet;
#[cfg(feature = "std")]
use std::collections::HashSet as StdHashSet;
use spacepackets::PacketId;
use crate::tmtc::ReceivesTcCore;
pub trait PacketIdLookup {
pub trait PacketIdValidator {
fn validate(&self, packet_id: u16) -> bool;
}
#[cfg(feature = "alloc")]
impl PacketIdLookup for Vec<u16> {
impl PacketIdValidator for Vec<u16> {
fn validate(&self, packet_id: u16) -> bool {
self.contains(&packet_id)
}
}
#[cfg(feature = "alloc")]
impl PacketIdLookup for HashSet<u16> {
impl PacketIdValidator for HashSet<u16> {
fn validate(&self, packet_id: u16) -> bool {
self.contains(&packet_id)
}
}
impl PacketIdLookup for [u16] {
impl PacketIdValidator for [u16] {
fn validate(&self, packet_id: u16) -> bool {
self.binary_search(&packet_id).is_ok()
}
}
impl PacketIdLookup for &[u16] {
impl PacketIdValidator for &[u16] {
fn validate(&self, packet_id: u16) -> bool {
self.binary_search(&packet_id).is_ok()
}
}
#[cfg(feature = "alloc")]
impl PacketIdLookup for Vec<PacketId> {
fn validate(&self, packet_id: u16) -> bool {
self.contains(&PacketId::from(packet_id))
}
}
#[cfg(feature = "alloc")]
impl PacketIdLookup for HashSet<PacketId> {
impl PacketIdValidator for Vec<PacketId> {
fn validate(&self, packet_id: u16) -> bool {
self.contains(&PacketId::from(packet_id))
}
}
impl PacketIdLookup for [PacketId] {
#[cfg(feature = "alloc")]
impl PacketIdValidator for HashSet<PacketId> {
fn validate(&self, packet_id: u16) -> bool {
self.contains(&PacketId::from(packet_id))
}
}
#[cfg(feature = "std")]
impl PacketIdValidator for StdHashSet<PacketId> {
fn validate(&self, packet_id: u16) -> bool {
self.contains(&PacketId::from(packet_id))
}
}
impl PacketIdValidator for [PacketId] {
fn validate(&self, packet_id: u16) -> bool {
self.binary_search(&PacketId::from(packet_id)).is_ok()
}
}
impl PacketIdLookup for &[PacketId] {
impl PacketIdValidator for &[PacketId] {
fn validate(&self, packet_id: u16) -> bool {
self.binary_search(&PacketId::from(packet_id)).is_ok()
}
@ -75,7 +86,7 @@ impl PacketIdLookup for &[PacketId] {
/// error will be returned.
pub fn parse_buffer_for_ccsds_space_packets<E>(
buf: &mut [u8],
packet_id_lookup: &(impl PacketIdLookup + ?Sized),
packet_id_validator: &(impl PacketIdValidator + ?Sized),
tc_receiver: &mut (impl ReceivesTcCore<Error = E> + ?Sized),
next_write_idx: &mut usize,
) -> Result<u32, E> {
@ -88,7 +99,7 @@ pub fn parse_buffer_for_ccsds_space_packets<E>(
break;
}
let packet_id = u16::from_be_bytes(buf[current_idx..current_idx + 2].try_into().unwrap());
if packet_id_lookup.validate(packet_id) {
if packet_id_validator.validate(packet_id) {
let length_field =
u16::from_be_bytes(buf[current_idx + 4..current_idx + 6].try_into().unwrap());
let packet_size = length_field + 7;

View File

@ -4,10 +4,8 @@ use std::{
net::{SocketAddr, TcpListener, TcpStream},
};
use alloc::boxed::Box;
use crate::{
encoding::{ccsds::PacketIdLookup, parse_buffer_for_ccsds_space_packets},
encoding::{ccsds::PacketIdValidator, parse_buffer_for_ccsds_space_packets},
tmtc::{ReceivesTc, TmPacketSource},
};
@ -16,17 +14,19 @@ use super::tcp_server::{
};
/// Concrete [TcpTcParser] implementation for the [TcpSpacepacketsServer].
pub struct SpacepacketsTcParser {
packet_id_lookup: Box<dyn PacketIdLookup + Send>,
pub struct SpacepacketsTcParser<PacketIdChecker: PacketIdValidator> {
packet_id_lookup: PacketIdChecker,
}
impl SpacepacketsTcParser {
pub fn new(packet_id_lookup: Box<dyn PacketIdLookup + Send>) -> Self {
impl<PacketIdChecker: PacketIdValidator> SpacepacketsTcParser<PacketIdChecker> {
pub fn new(packet_id_lookup: PacketIdChecker) -> Self {
Self { packet_id_lookup }
}
}
impl<TmError, TcError: 'static> TcpTcParser<TmError, TcError> for SpacepacketsTcParser {
impl<TmError, TcError: 'static, PacketIdChecker: PacketIdValidator> TcpTcParser<TmError, TcError>
for SpacepacketsTcParser<PacketIdChecker>
{
fn handle_tc_parsing(
&mut self,
tc_buffer: &mut [u8],
@ -38,7 +38,7 @@ impl<TmError, TcError: 'static> TcpTcParser<TmError, TcError> for SpacepacketsTc
// Reader vec full, need to parse for packets.
conn_result.num_received_tcs += parse_buffer_for_ccsds_space_packets(
&mut tc_buffer[..current_write_idx],
self.packet_id_lookup.as_ref(),
&self.packet_id_lookup,
tc_receiver.upcast_mut(),
next_write_idx,
)
@ -95,6 +95,7 @@ pub struct TcpSpacepacketsServer<
TcError: 'static,
TmSource: TmPacketSource<Error = TmError>,
TcReceiver: ReceivesTc<Error = TcError>,
PacketIdChecker: PacketIdValidator,
> {
generic_server: TcpTmtcGenericServer<
TmError,
@ -102,7 +103,7 @@ pub struct TcpSpacepacketsServer<
TmSource,
TcReceiver,
SpacepacketsTmSender,
SpacepacketsTcParser,
SpacepacketsTcParser<PacketIdChecker>,
>,
}
@ -111,7 +112,8 @@ impl<
TcError: 'static,
TmSource: TmPacketSource<Error = TmError>,
TcReceiver: ReceivesTc<Error = TcError>,
> TcpSpacepacketsServer<TmError, TcError, TmSource, TcReceiver>
PacketIdChecker: PacketIdValidator,
> TcpSpacepacketsServer<TmError, TcError, TmSource, TcReceiver, PacketIdChecker>
{
///
/// ## Parameter
@ -127,12 +129,12 @@ impl<
cfg: ServerConfig,
tm_source: TmSource,
tc_receiver: TcReceiver,
packet_id_lookup: Box<dyn PacketIdLookup + Send>,
packet_id_checker: PacketIdChecker,
) -> Result<Self, std::io::Error> {
Ok(Self {
generic_server: TcpTmtcGenericServer::new(
cfg,
SpacepacketsTcParser::new(packet_id_lookup),
SpacepacketsTcParser::new(packet_id_checker),
SpacepacketsTmSender::default(),
tm_source,
tc_receiver,
@ -170,7 +172,7 @@ mod tests {
thread,
};
use alloc::{boxed::Box, sync::Arc};
use alloc::sync::Arc;
use hashbrown::HashSet;
use spacepackets::{
ecss::{tc::PusTcCreator, WritablePusPacket},
@ -194,12 +196,12 @@ mod tests {
tc_receiver: SyncTcCacher,
tm_source: SyncTmSource,
packet_id_lookup: HashSet<PacketId>,
) -> TcpSpacepacketsServer<(), (), SyncTmSource, SyncTcCacher> {
) -> TcpSpacepacketsServer<(), (), SyncTmSource, SyncTcCacher, HashSet<PacketId>> {
TcpSpacepacketsServer::new(
ServerConfig::new(*addr, Duration::from_millis(2), 1024, 1024),
tm_source,
tc_receiver,
Box::new(packet_id_lookup),
packet_id_lookup,
)
.expect("TCP server generation failed")
}

View File

@ -6,8 +6,10 @@ use spacepackets::ByteConversionError;
use spacepackets::{SpHeader, MAX_APID};
use crate::pus::EcssTmSenderCore;
#[cfg(feature = "alloc")]
pub use alloc_mod::EventReporter;
pub use alloc_mod::*;
pub use spacepackets::ecss::event::*;
pub struct EventReportCreator {
@ -16,102 +18,98 @@ pub struct EventReportCreator {
}
impl EventReportCreator {
pub fn new(apid: u16) -> Option<Self> {
pub fn new(apid: u16, dest_id: u16) -> Option<Self> {
if apid > MAX_APID {
return None;
}
Some(Self {
// msg_count: 0,
dest_id: 0,
apid,
})
Some(Self { dest_id, apid })
}
pub fn event_info<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&'src_data [u8]>,
params: Option<&'src_data [u8]>,
src_data_buf: &'src_data mut [u8],
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
self.generate_and_send_generic_tm(
src_data_buf,
Subservice::TmInfoReport,
time_stamp,
event_id,
aux_data,
params,
src_data_buf,
)
}
pub fn event_low_severity<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&'src_data [u8]>,
params: Option<&'src_data [u8]>,
src_data_buf: &'src_data mut [u8],
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
self.generate_and_send_generic_tm(
src_data_buf,
Subservice::TmLowSeverityReport,
time_stamp,
event_id,
aux_data,
params,
src_data_buf,
)
}
pub fn event_medium_severity<'time, 'src_data>(
&self,
buf: &'src_data mut [u8],
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&'src_data [u8]>,
params: Option<&'src_data [u8]>,
buf: &'src_data mut [u8],
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
self.generate_and_send_generic_tm(
buf,
Subservice::TmMediumSeverityReport,
time_stamp,
event_id,
aux_data,
params,
buf,
)
}
pub fn event_high_severity<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&'src_data [u8]>,
params: Option<&'src_data [u8]>,
src_data_buf: &'src_data mut [u8],
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
self.generate_and_send_generic_tm(
src_data_buf,
Subservice::TmHighSeverityReport,
time_stamp,
event_id,
aux_data,
params,
src_data_buf,
)
}
fn generate_and_send_generic_tm<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
subservice: Subservice,
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&'src_data [u8]>,
params: Option<&'src_data [u8]>,
src_data_buf: &'src_data mut [u8],
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
self.generate_generic_event_tm(src_data_buf, subservice, time_stamp, event_id, aux_data)
self.generate_generic_event_tm(subservice, time_stamp, event_id, params, src_data_buf)
}
fn generate_generic_event_tm<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
subservice: Subservice,
time_stamp: &'time [u8],
event_id: impl EcssEnumeration,
aux_data: Option<&'src_data [u8]>,
params: Option<&'src_data [u8]>,
src_data_buf: &'src_data mut [u8],
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
let mut src_data_len = event_id.size();
if let Some(aux_data) = aux_data {
if let Some(aux_data) = params {
src_data_len += aux_data.len();
}
source_buffer_large_enough(src_data_buf.len(), src_data_len)?;
@ -121,7 +119,7 @@ impl EventReportCreator {
let mut current_idx = 0;
event_id.write_to_be_bytes(&mut src_data_buf[0..event_id.size()])?;
current_idx += event_id.size();
if let Some(aux_data) = aux_data {
if let Some(aux_data) = params {
src_data_buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data);
current_idx += aux_data.len();
}
@ -142,25 +140,56 @@ mod alloc_mod {
use alloc::vec::Vec;
use core::cell::RefCell;
pub struct EventReporter {
pub trait EventTmHookProvider {
fn modify_tm(&self, tm: &mut PusTmCreator);
}
#[derive(Default)]
pub struct DummyEventHook {}
impl EventTmHookProvider for DummyEventHook {
fn modify_tm(&self, _tm: &mut PusTmCreator) {}
}
pub struct EventReporter<EventTmHook: EventTmHookProvider = DummyEventHook> {
id: ComponentId,
// Use interior mutability pattern here. This is just an intermediate buffer to the PUS event packet
// generation.
source_data_buf: RefCell<Vec<u8>>,
pub report_creator: EventReportCreator,
pub tm_hook: EventTmHook,
}
impl EventReporter {
impl EventReporter<DummyEventHook> {
pub fn new(
id: ComponentId,
apid: u16,
default_apid: u16,
default_dest_id: u16,
max_event_id_and_aux_data_size: usize,
) -> Option<Self> {
let reporter = EventReportCreator::new(apid)?;
let reporter = EventReportCreator::new(default_apid, default_dest_id)?;
Some(Self {
id,
source_data_buf: RefCell::new(vec![0; max_event_id_and_aux_data_size]),
report_creator: reporter,
tm_hook: DummyEventHook::default(),
})
}
}
impl<EventTmHook: EventTmHookProvider> EventReporter<EventTmHook> {
pub fn new_with_hook(
id: ComponentId,
default_apid: u16,
default_dest_id: u16,
max_event_id_and_aux_data_size: usize,
tm_hook: EventTmHook,
) -> Option<Self> {
let reporter = EventReportCreator::new(default_apid, default_dest_id)?;
Some(Self {
id,
source_data_buf: RefCell::new(vec![0; max_event_id_and_aux_data_size]),
report_creator: reporter,
tm_hook,
})
}
@ -169,13 +198,14 @@ mod alloc_mod {
sender: &(impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
params: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
let mut mut_buf = self.source_data_buf.borrow_mut();
let tm_creator = self
let mut tm_creator = self
.report_creator
.event_info(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
.event_info(time_stamp, event_id, params, mut_buf.as_mut_slice())
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.id, tm_creator.into())?;
Ok(())
}
@ -185,13 +215,14 @@ mod alloc_mod {
sender: &(impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
params: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
let mut mut_buf = self.source_data_buf.borrow_mut();
let tm_creator = self
let mut tm_creator = self
.report_creator
.event_low_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
.event_low_severity(time_stamp, event_id, params, mut_buf.as_mut_slice())
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.id, tm_creator.into())?;
Ok(())
}
@ -201,13 +232,14 @@ mod alloc_mod {
sender: &(impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
params: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
let mut mut_buf = self.source_data_buf.borrow_mut();
let tm_creator = self
let mut tm_creator = self
.report_creator
.event_medium_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
.event_medium_severity(time_stamp, event_id, params, mut_buf.as_mut_slice())
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.id, tm_creator.into())?;
Ok(())
}
@ -217,13 +249,14 @@ mod alloc_mod {
sender: &(impl EcssTmSenderCore + ?Sized),
time_stamp: &[u8],
event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>,
params: Option<&[u8]>,
) -> Result<(), EcssTmtcError> {
let mut mut_buf = self.source_data_buf.borrow_mut();
let tm_creator = self
let mut tm_creator = self
.report_creator
.event_high_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
.event_high_severity(time_stamp, event_id, params, mut_buf.as_mut_slice())
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.id, tm_creator.into())?;
Ok(())
}
@ -346,6 +379,7 @@ mod tests {
let reporter = EventReporter::new(
TEST_COMPONENT_ID_0.id(),
EXAMPLE_APID,
0,
max_event_aux_data_buf,
);
assert!(reporter.is_some());
@ -440,7 +474,7 @@ mod tests {
fn insufficient_buffer() {
let mut sender = TestSender::default();
for i in 0..3 {
let reporter = EventReporter::new(0, EXAMPLE_APID, i);
let reporter = EventReporter::new(0, EXAMPLE_APID, 0, i);
assert!(reporter.is_some());
let mut reporter = reporter.unwrap();
check_buf_too_small(&mut reporter, &mut sender, i);

View File

@ -81,7 +81,10 @@
//! let mutable_handler_ref = ccsds_distributor.packet_handler_mut();
//! mutable_handler_ref.mutable_foo();
//! ```
use crate::tmtc::{ReceivesCcsdsTc, ReceivesTcCore};
use crate::{
encoding::ccsds::PacketIdValidator,
tmtc::{ReceivesCcsdsTc, ReceivesTcCore},
};
use core::fmt::{Display, Formatter};
use spacepackets::{ByteConversionError, CcsdsPacket, SpHeader};
#[cfg(feature = "std")]
@ -93,14 +96,16 @@ use std::error::Error;
/// instance of this handler to the [CcsdsDistributor]. The distributor will use the trait
/// interface to dispatch received packets to the user based on the Application Process Identifier
/// (APID) field of the CCSDS packet.
pub trait CcsdsPacketHandler {
pub trait CcsdsPacketHandler: PacketIdValidator {
type Error;
// TODO: Rework this to return a boolean based on u16 input..
fn valid_apids(&self) -> &'static [u16];
fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8])
-> Result<(), Self::Error>;
fn handle_unknown_apid(
fn handle_packet_with_valid_apid(
&mut self,
sp_header: &SpHeader,
tc_raw: &[u8],
) -> Result<(), Self::Error>;
fn handle_packet_with_unknown_apid(
&mut self,
sp_header: &SpHeader,
tc_raw: &[u8],
@ -184,18 +189,16 @@ impl<PacketHandler: CcsdsPacketHandler<Error = E>, E: 'static> CcsdsDistributor<
}
fn dispatch_ccsds(&mut self, sp_header: &SpHeader, tc_raw: &[u8]) -> Result<(), CcsdsError<E>> {
let apid = sp_header.apid();
let valid_apids = self.packet_handler.valid_apids();
for &valid_apid in valid_apids {
if valid_apid == apid {
return self
.packet_handler
.handle_known_apid(sp_header, tc_raw)
.map_err(|e| CcsdsError::CustomError(e));
}
//let valid_apids = self.packet_handler.valid_apids();
let valid_apid = self.packet_handler().validate(sp_header.packet_id().raw());
if valid_apid {
return self
.packet_handler
.handle_packet_with_valid_apid(sp_header, tc_raw)
.map_err(|e| CcsdsError::CustomError(e));
}
self.packet_handler
.handle_unknown_apid(sp_header, tc_raw)
.handle_packet_with_unknown_apid(sp_header, tc_raw)
.map_err(|e| CcsdsError::CustomError(e))
}
}
@ -242,13 +245,16 @@ pub(crate) mod tests {
pub unknown_packet_queue: VecDeque<(u16, Vec<u8>)>,
}
impl PacketIdValidator for BasicApidHandlerSharedQueue {
fn validate(&self, packet_id: u16) -> bool {
&[0x000, 0x002].contains(&packet_id)
}
}
impl CcsdsPacketHandler for BasicApidHandlerSharedQueue {
type Error = ();
fn valid_apids(&self) -> &'static [u16] {
&[0x000, 0x002]
}
fn handle_known_apid(
fn handle_packet_with_valid_apid(
&mut self,
sp_header: &SpHeader,
tc_raw: &[u8],
@ -262,7 +268,7 @@ pub(crate) mod tests {
Ok(())
}
fn handle_unknown_apid(
fn handle_packet_with_unknown_apid(
&mut self,
sp_header: &SpHeader,
tc_raw: &[u8],
@ -277,14 +283,16 @@ pub(crate) mod tests {
}
}
impl PacketIdValidator for BasicApidHandlerOwnedQueue {
fn validate(&self, packet_id: u16) -> bool {
&[0x000, 0x002].contains(&packet_id)
}
}
impl CcsdsPacketHandler for BasicApidHandlerOwnedQueue {
type Error = ();
fn valid_apids(&self) -> &'static [u16] {
&[0x000, 0x002]
}
fn handle_known_apid(
fn handle_packet_with_valid_apid(
&mut self,
sp_header: &SpHeader,
tc_raw: &[u8],
@ -295,7 +303,7 @@ pub(crate) mod tests {
Ok(())
}
fn handle_unknown_apid(
fn handle_packet_with_unknown_apid(
&mut self,
sp_header: &SpHeader,
tc_raw: &[u8],