that gets the job done
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit
This commit is contained in:
parent
68908f53d4
commit
cba4a29396
@ -17,6 +17,8 @@ zerocopy = "0.6"
|
|||||||
csv = "1"
|
csv = "1"
|
||||||
num_enum = "0.7"
|
num_enum = "0.7"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
|
lazy_static = "1"
|
||||||
|
strum = { version = "0.26", features = ["derive"] }
|
||||||
derive-new = "0.5"
|
derive-new = "0.5"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
@ -36,8 +36,15 @@ class EventU32:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class RequestTargetId(enum.IntEnum):
|
class Apid(enum.IntEnum):
|
||||||
ACS = 1
|
SCHED = 1
|
||||||
|
GENERIC_PUS = 2
|
||||||
|
ACS = 3
|
||||||
|
CFDP = 4
|
||||||
|
|
||||||
|
|
||||||
|
class AcsId(enum.IntEnum):
|
||||||
|
MGM_0 = 0
|
||||||
|
|
||||||
|
|
||||||
class AcsHkIds(enum.IntEnum):
|
class AcsHkIds(enum.IntEnum):
|
||||||
|
@ -1,23 +1,35 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
import struct
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from spacepackets.ccsds import CdsShortTimestamp
|
from spacepackets.ccsds import CdsShortTimestamp
|
||||||
from spacepackets.ecss import PusTelecommand
|
from spacepackets.ecss import PusTelecommand
|
||||||
from tmtccmd.config import CmdTreeNode
|
from tmtccmd.config import CmdTreeNode
|
||||||
|
from tmtccmd.pus.tc.s200_fsfw_mode import Mode
|
||||||
from tmtccmd.tmtc import DefaultPusQueueHelper
|
from tmtccmd.tmtc import DefaultPusQueueHelper
|
||||||
from tmtccmd.pus.s11_tc_sched import create_time_tagged_cmd
|
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 (
|
from common import EXAMPLE_PUS_APID, AcsId, Apid
|
||||||
EXAMPLE_PUS_APID,
|
|
||||||
make_addressable_id,
|
|
||||||
RequestTargetId,
|
|
||||||
AcsHkIds,
|
|
||||||
)
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_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:
|
def create_cmd_definition_tree() -> CmdTreeNode:
|
||||||
|
|
||||||
root_node = CmdTreeNode.root_node()
|
root_node = CmdTreeNode.root_node()
|
||||||
@ -95,12 +107,33 @@ def pack_pus_telecommands(q: DefaultPusQueueHelper, cmd_path: str):
|
|||||||
)
|
)
|
||||||
if cmd_path_list[0] == "acs":
|
if cmd_path_list[0] == "acs":
|
||||||
assert len(cmd_path_list) >= 2
|
assert len(cmd_path_list) >= 2
|
||||||
if cmd_path_list[1] == "mgm":
|
if cmd_path_list[1] == "mgms":
|
||||||
assert len(cmd_path_list) >= 3
|
assert len(cmd_path_list) >= 3
|
||||||
if cmd_path_list[2] == "one_shot_hk":
|
if cmd_path_list[2] == "hk":
|
||||||
q.add_log_cmd("Sending HK one shot request")
|
if cmd_path_list[3] == "one_shot_hk":
|
||||||
q.add_pus_tc(
|
q.add_log_cmd("Sending HK one shot request")
|
||||||
create_request_one_hk_command(
|
# TODO: Fix
|
||||||
make_addressable_id(RequestTargetId.ACS, AcsHkIds.MGM_SET)
|
# 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))
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
use satrs::encoding::ccsds::PacketIdValidator;
|
||||||
use satrs::pus::ReceivesEcssPusTc;
|
use satrs::pus::ReceivesEcssPusTc;
|
||||||
use satrs::spacepackets::{CcsdsPacket, SpHeader};
|
use satrs::spacepackets::{CcsdsPacket, PacketId, SpHeader};
|
||||||
use satrs::tmtc::{CcsdsPacketHandler, ReceivesCcsdsTc};
|
use satrs::tmtc::{CcsdsPacketHandler, ReceivesCcsdsTc};
|
||||||
use satrs_example::config::components::Apid;
|
use satrs_example::config::components::Apid;
|
||||||
|
use satrs_example::config::PACKET_ID_VALIDATOR;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CcsdsReceiver<
|
pub struct CcsdsReceiver<
|
||||||
@ -11,6 +13,16 @@ pub struct CcsdsReceiver<
|
|||||||
pub tc_source: TcSource,
|
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<
|
impl<
|
||||||
TcSource: ReceivesCcsdsTc<Error = E> + ReceivesEcssPusTc<Error = E> + Clone + 'static,
|
TcSource: ReceivesCcsdsTc<Error = E> + ReceivesEcssPusTc<Error = E> + Clone + 'static,
|
||||||
E: 'static,
|
E: 'static,
|
||||||
@ -18,16 +30,7 @@ impl<
|
|||||||
{
|
{
|
||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
fn valid_apids(&self) -> &'static [u16] {
|
fn handle_packet_with_valid_apid(
|
||||||
&[
|
|
||||||
Apid::GenericPus as u16,
|
|
||||||
Apid::Acs as u16,
|
|
||||||
Apid::Sched as u16,
|
|
||||||
Apid::EventTm as u16,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_known_apid(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
sp_header: &SpHeader,
|
sp_header: &SpHeader,
|
||||||
tc_raw: &[u8],
|
tc_raw: &[u8],
|
||||||
@ -39,7 +42,7 @@ impl<
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_unknown_apid(
|
fn handle_packet_with_unknown_apid(
|
||||||
&mut self,
|
&mut self,
|
||||||
sp_header: &SpHeader,
|
sp_header: &SpHeader,
|
||||||
_tc_raw: &[u8],
|
_tc_raw: &[u8],
|
||||||
|
@ -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::res_code::ResultU16Info;
|
||||||
use satrs_mib::resultcode;
|
use satrs_mib::resultcode;
|
||||||
use std::net::Ipv4Addr;
|
use std::{collections::HashSet, net::Ipv4Addr};
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
use satrs::{
|
use satrs::{
|
||||||
@ -36,6 +41,16 @@ pub const SERVER_PORT: u16 = 7301;
|
|||||||
pub const TEST_EVENT: EventU32TypedSev<SeverityInfo> =
|
pub const TEST_EVENT: EventU32TypedSev<SeverityInfo> =
|
||||||
EventU32TypedSev::<SeverityInfo>::const_new(0, 0);
|
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 {
|
pub mod tmtc_err {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -102,26 +117,25 @@ pub mod mode_err {
|
|||||||
|
|
||||||
pub mod components {
|
pub mod components {
|
||||||
use satrs::request::UniqueApidTargetId;
|
use satrs::request::UniqueApidTargetId;
|
||||||
|
use strum::EnumIter;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq, EnumIter)]
|
||||||
pub enum Apid {
|
pub enum Apid {
|
||||||
VerificationTm = 1,
|
Sched = 1,
|
||||||
Sched = 2,
|
GenericPus = 2,
|
||||||
EventTm = 3,
|
Acs = 3,
|
||||||
HkTm = 4,
|
Cfdp = 4,
|
||||||
GenericPus = 5,
|
|
||||||
Acs = 6,
|
|
||||||
Cfdp = 7,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Component IDs for components with the PUS APID.
|
// Component IDs for components with the PUS APID.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum PusId {
|
pub enum PusId {
|
||||||
PusRouting = 0,
|
PusEventManagement = 0,
|
||||||
PusTest = 1,
|
PusRouting = 1,
|
||||||
PusAction = 2,
|
PusTest = 2,
|
||||||
PusMode = 3,
|
PusAction = 3,
|
||||||
PusHk = 4,
|
PusMode = 4,
|
||||||
|
PusHk = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
@ -132,7 +146,7 @@ pub mod components {
|
|||||||
pub const PUS_ACTION_SERVICE: UniqueApidTargetId =
|
pub const PUS_ACTION_SERVICE: UniqueApidTargetId =
|
||||||
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusAction as u32);
|
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusAction as u32);
|
||||||
pub const PUS_EVENT_MANAGEMENT: UniqueApidTargetId =
|
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 =
|
pub const PUS_ROUTING_SERVICE: UniqueApidTargetId =
|
||||||
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusRouting as u32);
|
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusRouting as u32);
|
||||||
pub const PUS_TEST_SERVICE: UniqueApidTargetId =
|
pub const PUS_TEST_SERVICE: UniqueApidTargetId =
|
||||||
|
@ -3,8 +3,10 @@ use std::sync::mpsc::{self};
|
|||||||
use crate::pus::create_verification_reporter;
|
use crate::pus::create_verification_reporter;
|
||||||
use satrs::event_man::{EventMessageU32, EventRoutingError};
|
use satrs::event_man::{EventMessageU32, EventRoutingError};
|
||||||
use satrs::params::WritableToBeBytes;
|
use satrs::params::WritableToBeBytes;
|
||||||
|
use satrs::pus::event::EventTmHookProvider;
|
||||||
use satrs::pus::verification::VerificationReporter;
|
use satrs::pus::verification::VerificationReporter;
|
||||||
use satrs::pus::EcssTmSenderCore;
|
use satrs::pus::EcssTmSenderCore;
|
||||||
|
use satrs::request::UniqueApidTargetId;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
event_man::{
|
event_man::{
|
||||||
EventManagerWithBoundedMpsc, EventSendProvider, EventU32SenderMpscBounded,
|
EventManagerWithBoundedMpsc, EventSendProvider, EventU32SenderMpscBounded,
|
||||||
@ -18,11 +20,22 @@ use satrs::{
|
|||||||
},
|
},
|
||||||
spacepackets::time::cds::CdsTime,
|
spacepackets::time::cds::CdsTime,
|
||||||
};
|
};
|
||||||
use satrs_example::config::components;
|
|
||||||
use satrs_example::config::components::PUS_EVENT_MANAGEMENT;
|
use satrs_example::config::components::PUS_EVENT_MANAGEMENT;
|
||||||
|
|
||||||
use crate::update_time;
|
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
|
/// 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.
|
/// packets. It also handles the verification completion of PUS event service requests.
|
||||||
pub struct PusEventHandler<TmSender: EcssTmSenderCore> {
|
pub struct PusEventHandler<TmSender: EcssTmSenderCore> {
|
||||||
@ -33,6 +46,7 @@ pub struct PusEventHandler<TmSender: EcssTmSenderCore> {
|
|||||||
time_provider: CdsTime,
|
time_provider: CdsTime,
|
||||||
timestamp: [u8; 7],
|
timestamp: [u8; 7],
|
||||||
verif_handler: VerificationReporter,
|
verif_handler: VerificationReporter,
|
||||||
|
event_apid_setter: EventApidSetter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TmSender: EcssTmSenderCore> PusEventHandler<TmSender> {
|
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
|
// All events sent to the manager are routed to the PUS event manager, which generates PUS event
|
||||||
// telemetry for each event.
|
// telemetry for each event.
|
||||||
let event_reporter = EventReporter::new(
|
let event_reporter = EventReporter::new(PUS_EVENT_MANAGEMENT.raw(), 0, 0, 128).unwrap();
|
||||||
PUS_EVENT_MANAGEMENT.raw(),
|
|
||||||
components::Apid::EventTm as u16,
|
|
||||||
128,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let pus_event_dispatcher =
|
let pus_event_dispatcher =
|
||||||
DefaultPusEventU32Dispatcher::new_with_default_backend(event_reporter);
|
DefaultPusEventU32Dispatcher::new_with_default_backend(event_reporter);
|
||||||
let pus_event_man_send_provider = EventU32SenderMpscBounded::new(
|
let pus_event_man_send_provider = EventU32SenderMpscBounded::new(
|
||||||
@ -72,6 +81,7 @@ impl<TmSender: EcssTmSenderCore> PusEventHandler<TmSender> {
|
|||||||
timestamp: [0; 7],
|
timestamp: [0; 7],
|
||||||
verif_handler,
|
verif_handler,
|
||||||
tm_sender,
|
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| {
|
let param_vec = event_msg.params().map_or(Vec::new(), |param| {
|
||||||
param.to_vec().expect("failed to convert params to vec")
|
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
|
self.pus_event_dispatcher
|
||||||
.generate_pus_event_tm_generic(
|
.generate_pus_event_tm_generic(
|
||||||
&self.tm_sender,
|
&self.tm_sender,
|
||||||
|
@ -23,7 +23,7 @@ use satrs_example::config::pool::{create_sched_tc_pool, create_static_pools};
|
|||||||
use satrs_example::config::tasks::{
|
use satrs_example::config::tasks::{
|
||||||
FREQ_MS_AOCS, FREQ_MS_EVENT_HANDLING, FREQ_MS_PUS_STACK, FREQ_MS_UDP_TMTC,
|
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 tmtc::PusTcSourceProviderDynamic;
|
||||||
use udp::DynamicUdpTmHandler;
|
use udp::DynamicUdpTmHandler;
|
||||||
|
|
||||||
@ -191,6 +191,7 @@ fn static_tmtc_pool_main() {
|
|||||||
tcp_server_cfg,
|
tcp_server_cfg,
|
||||||
sync_tm_tcp_source.clone(),
|
sync_tm_tcp_source.clone(),
|
||||||
tcp_ccsds_distributor,
|
tcp_ccsds_distributor,
|
||||||
|
PACKET_ID_VALIDATOR.clone(),
|
||||||
)
|
)
|
||||||
.expect("tcp server creation failed");
|
.expect("tcp server creation failed");
|
||||||
|
|
||||||
@ -415,6 +416,7 @@ fn dyn_tmtc_pool_main() {
|
|||||||
tcp_server_cfg,
|
tcp_server_cfg,
|
||||||
sync_tm_tcp_source.clone(),
|
sync_tm_tcp_source.clone(),
|
||||||
tcp_ccsds_distributor,
|
tcp_ccsds_distributor,
|
||||||
|
PACKET_ID_VALIDATOR.clone(),
|
||||||
)
|
)
|
||||||
.expect("tcp server creation failed");
|
.expect("tcp server creation failed");
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::{HashSet, VecDeque},
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -10,17 +10,9 @@ use satrs::{
|
|||||||
spacepackets::PacketId,
|
spacepackets::PacketId,
|
||||||
tmtc::{CcsdsDistributor, CcsdsError, ReceivesCcsdsTc, TmPacketSourceCore},
|
tmtc::{CcsdsDistributor, CcsdsError, ReceivesCcsdsTc, TmPacketSourceCore},
|
||||||
};
|
};
|
||||||
use satrs_example::config::components;
|
|
||||||
|
|
||||||
use crate::ccsds::CcsdsReceiver;
|
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)]
|
#[derive(Default, Clone)]
|
||||||
pub struct SyncTcpTmSource {
|
pub struct SyncTcpTmSource {
|
||||||
tm_queue: Arc<Mutex<VecDeque<Vec<u8>>>>,
|
tm_queue: Arc<Mutex<VecDeque<Vec<u8>>>>,
|
||||||
@ -82,6 +74,7 @@ pub type TcpServerType<TcSource, MpscErrorType> = TcpSpacepacketsServer<
|
|||||||
CcsdsError<MpscErrorType>,
|
CcsdsError<MpscErrorType>,
|
||||||
SyncTcpTmSource,
|
SyncTcpTmSource,
|
||||||
CcsdsDistributor<CcsdsReceiver<TcSource, MpscErrorType>, MpscErrorType>,
|
CcsdsDistributor<CcsdsReceiver<TcSource, MpscErrorType>, MpscErrorType>,
|
||||||
|
HashSet<PacketId>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
pub struct TcpTask<
|
pub struct TcpTask<
|
||||||
@ -108,14 +101,10 @@ impl<
|
|||||||
cfg: ServerConfig,
|
cfg: ServerConfig,
|
||||||
tm_source: SyncTcpTmSource,
|
tm_source: SyncTcpTmSource,
|
||||||
tc_receiver: CcsdsDistributor<CcsdsReceiver<TcSource, MpscErrorType>, MpscErrorType>,
|
tc_receiver: CcsdsDistributor<CcsdsReceiver<TcSource, MpscErrorType>, MpscErrorType>,
|
||||||
|
packet_id_lookup: HashSet<PacketId>,
|
||||||
) -> Result<Self, std::io::Error> {
|
) -> Result<Self, std::io::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
server: TcpSpacepacketsServer::new(
|
server: TcpSpacepacketsServer::new(cfg, tm_source, tc_receiver, packet_id_lookup)?,
|
||||||
cfg,
|
|
||||||
tm_source,
|
|
||||||
tc_receiver,
|
|
||||||
Box::new(PACKET_ID_LOOKUP),
|
|
||||||
)?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,60 +2,71 @@
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::collections::HashSet as StdHashSet;
|
||||||
|
|
||||||
use spacepackets::PacketId;
|
use spacepackets::PacketId;
|
||||||
|
|
||||||
use crate::tmtc::ReceivesTcCore;
|
use crate::tmtc::ReceivesTcCore;
|
||||||
|
|
||||||
pub trait PacketIdLookup {
|
pub trait PacketIdValidator {
|
||||||
fn validate(&self, packet_id: u16) -> bool;
|
fn validate(&self, packet_id: u16) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl PacketIdLookup for Vec<u16> {
|
impl PacketIdValidator for Vec<u16> {
|
||||||
fn validate(&self, packet_id: u16) -> bool {
|
fn validate(&self, packet_id: u16) -> bool {
|
||||||
self.contains(&packet_id)
|
self.contains(&packet_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl PacketIdLookup for HashSet<u16> {
|
impl PacketIdValidator for HashSet<u16> {
|
||||||
fn validate(&self, packet_id: u16) -> bool {
|
fn validate(&self, packet_id: u16) -> bool {
|
||||||
self.contains(&packet_id)
|
self.contains(&packet_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketIdLookup for [u16] {
|
impl PacketIdValidator for [u16] {
|
||||||
fn validate(&self, packet_id: u16) -> bool {
|
fn validate(&self, packet_id: u16) -> bool {
|
||||||
self.binary_search(&packet_id).is_ok()
|
self.binary_search(&packet_id).is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketIdLookup for &[u16] {
|
impl PacketIdValidator for &[u16] {
|
||||||
fn validate(&self, packet_id: u16) -> bool {
|
fn validate(&self, packet_id: u16) -> bool {
|
||||||
self.binary_search(&packet_id).is_ok()
|
self.binary_search(&packet_id).is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl PacketIdLookup for Vec<PacketId> {
|
impl PacketIdValidator for Vec<PacketId> {
|
||||||
fn validate(&self, packet_id: u16) -> bool {
|
|
||||||
self.contains(&PacketId::from(packet_id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
impl PacketIdLookup for HashSet<PacketId> {
|
|
||||||
fn validate(&self, packet_id: u16) -> bool {
|
fn validate(&self, packet_id: u16) -> bool {
|
||||||
self.contains(&PacketId::from(packet_id))
|
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 {
|
fn validate(&self, packet_id: u16) -> bool {
|
||||||
self.binary_search(&PacketId::from(packet_id)).is_ok()
|
self.binary_search(&PacketId::from(packet_id)).is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketIdLookup for &[PacketId] {
|
impl PacketIdValidator for &[PacketId] {
|
||||||
fn validate(&self, packet_id: u16) -> bool {
|
fn validate(&self, packet_id: u16) -> bool {
|
||||||
self.binary_search(&PacketId::from(packet_id)).is_ok()
|
self.binary_search(&PacketId::from(packet_id)).is_ok()
|
||||||
}
|
}
|
||||||
@ -75,7 +86,7 @@ impl PacketIdLookup for &[PacketId] {
|
|||||||
/// error will be returned.
|
/// error will be returned.
|
||||||
pub fn parse_buffer_for_ccsds_space_packets<E>(
|
pub fn parse_buffer_for_ccsds_space_packets<E>(
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
packet_id_lookup: &(impl PacketIdLookup + ?Sized),
|
packet_id_validator: &(impl PacketIdValidator + ?Sized),
|
||||||
tc_receiver: &mut (impl ReceivesTcCore<Error = E> + ?Sized),
|
tc_receiver: &mut (impl ReceivesTcCore<Error = E> + ?Sized),
|
||||||
next_write_idx: &mut usize,
|
next_write_idx: &mut usize,
|
||||||
) -> Result<u32, E> {
|
) -> Result<u32, E> {
|
||||||
@ -88,7 +99,7 @@ pub fn parse_buffer_for_ccsds_space_packets<E>(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let packet_id = u16::from_be_bytes(buf[current_idx..current_idx + 2].try_into().unwrap());
|
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 =
|
let length_field =
|
||||||
u16::from_be_bytes(buf[current_idx + 4..current_idx + 6].try_into().unwrap());
|
u16::from_be_bytes(buf[current_idx + 4..current_idx + 6].try_into().unwrap());
|
||||||
let packet_size = length_field + 7;
|
let packet_size = length_field + 7;
|
||||||
|
@ -4,10 +4,8 @@ use std::{
|
|||||||
net::{SocketAddr, TcpListener, TcpStream},
|
net::{SocketAddr, TcpListener, TcpStream},
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
encoding::{ccsds::PacketIdLookup, parse_buffer_for_ccsds_space_packets},
|
encoding::{ccsds::PacketIdValidator, parse_buffer_for_ccsds_space_packets},
|
||||||
tmtc::{ReceivesTc, TmPacketSource},
|
tmtc::{ReceivesTc, TmPacketSource},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,17 +14,19 @@ use super::tcp_server::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Concrete [TcpTcParser] implementation for the [TcpSpacepacketsServer].
|
/// Concrete [TcpTcParser] implementation for the [TcpSpacepacketsServer].
|
||||||
pub struct SpacepacketsTcParser {
|
pub struct SpacepacketsTcParser<PacketIdChecker: PacketIdValidator> {
|
||||||
packet_id_lookup: Box<dyn PacketIdLookup + Send>,
|
packet_id_lookup: PacketIdChecker,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpacepacketsTcParser {
|
impl<PacketIdChecker: PacketIdValidator> SpacepacketsTcParser<PacketIdChecker> {
|
||||||
pub fn new(packet_id_lookup: Box<dyn PacketIdLookup + Send>) -> Self {
|
pub fn new(packet_id_lookup: PacketIdChecker) -> Self {
|
||||||
Self { packet_id_lookup }
|
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(
|
fn handle_tc_parsing(
|
||||||
&mut self,
|
&mut self,
|
||||||
tc_buffer: &mut [u8],
|
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.
|
// Reader vec full, need to parse for packets.
|
||||||
conn_result.num_received_tcs += parse_buffer_for_ccsds_space_packets(
|
conn_result.num_received_tcs += parse_buffer_for_ccsds_space_packets(
|
||||||
&mut tc_buffer[..current_write_idx],
|
&mut tc_buffer[..current_write_idx],
|
||||||
self.packet_id_lookup.as_ref(),
|
&self.packet_id_lookup,
|
||||||
tc_receiver.upcast_mut(),
|
tc_receiver.upcast_mut(),
|
||||||
next_write_idx,
|
next_write_idx,
|
||||||
)
|
)
|
||||||
@ -95,6 +95,7 @@ pub struct TcpSpacepacketsServer<
|
|||||||
TcError: 'static,
|
TcError: 'static,
|
||||||
TmSource: TmPacketSource<Error = TmError>,
|
TmSource: TmPacketSource<Error = TmError>,
|
||||||
TcReceiver: ReceivesTc<Error = TcError>,
|
TcReceiver: ReceivesTc<Error = TcError>,
|
||||||
|
PacketIdChecker: PacketIdValidator,
|
||||||
> {
|
> {
|
||||||
generic_server: TcpTmtcGenericServer<
|
generic_server: TcpTmtcGenericServer<
|
||||||
TmError,
|
TmError,
|
||||||
@ -102,7 +103,7 @@ pub struct TcpSpacepacketsServer<
|
|||||||
TmSource,
|
TmSource,
|
||||||
TcReceiver,
|
TcReceiver,
|
||||||
SpacepacketsTmSender,
|
SpacepacketsTmSender,
|
||||||
SpacepacketsTcParser,
|
SpacepacketsTcParser<PacketIdChecker>,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +112,8 @@ impl<
|
|||||||
TcError: 'static,
|
TcError: 'static,
|
||||||
TmSource: TmPacketSource<Error = TmError>,
|
TmSource: TmPacketSource<Error = TmError>,
|
||||||
TcReceiver: ReceivesTc<Error = TcError>,
|
TcReceiver: ReceivesTc<Error = TcError>,
|
||||||
> TcpSpacepacketsServer<TmError, TcError, TmSource, TcReceiver>
|
PacketIdChecker: PacketIdValidator,
|
||||||
|
> TcpSpacepacketsServer<TmError, TcError, TmSource, TcReceiver, PacketIdChecker>
|
||||||
{
|
{
|
||||||
///
|
///
|
||||||
/// ## Parameter
|
/// ## Parameter
|
||||||
@ -127,12 +129,12 @@ impl<
|
|||||||
cfg: ServerConfig,
|
cfg: ServerConfig,
|
||||||
tm_source: TmSource,
|
tm_source: TmSource,
|
||||||
tc_receiver: TcReceiver,
|
tc_receiver: TcReceiver,
|
||||||
packet_id_lookup: Box<dyn PacketIdLookup + Send>,
|
packet_id_checker: PacketIdChecker,
|
||||||
) -> Result<Self, std::io::Error> {
|
) -> Result<Self, std::io::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
generic_server: TcpTmtcGenericServer::new(
|
generic_server: TcpTmtcGenericServer::new(
|
||||||
cfg,
|
cfg,
|
||||||
SpacepacketsTcParser::new(packet_id_lookup),
|
SpacepacketsTcParser::new(packet_id_checker),
|
||||||
SpacepacketsTmSender::default(),
|
SpacepacketsTmSender::default(),
|
||||||
tm_source,
|
tm_source,
|
||||||
tc_receiver,
|
tc_receiver,
|
||||||
@ -170,7 +172,7 @@ mod tests {
|
|||||||
thread,
|
thread,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::{boxed::Box, sync::Arc};
|
use alloc::sync::Arc;
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use spacepackets::{
|
use spacepackets::{
|
||||||
ecss::{tc::PusTcCreator, WritablePusPacket},
|
ecss::{tc::PusTcCreator, WritablePusPacket},
|
||||||
@ -194,12 +196,12 @@ mod tests {
|
|||||||
tc_receiver: SyncTcCacher,
|
tc_receiver: SyncTcCacher,
|
||||||
tm_source: SyncTmSource,
|
tm_source: SyncTmSource,
|
||||||
packet_id_lookup: HashSet<PacketId>,
|
packet_id_lookup: HashSet<PacketId>,
|
||||||
) -> TcpSpacepacketsServer<(), (), SyncTmSource, SyncTcCacher> {
|
) -> TcpSpacepacketsServer<(), (), SyncTmSource, SyncTcCacher, HashSet<PacketId>> {
|
||||||
TcpSpacepacketsServer::new(
|
TcpSpacepacketsServer::new(
|
||||||
ServerConfig::new(*addr, Duration::from_millis(2), 1024, 1024),
|
ServerConfig::new(*addr, Duration::from_millis(2), 1024, 1024),
|
||||||
tm_source,
|
tm_source,
|
||||||
tc_receiver,
|
tc_receiver,
|
||||||
Box::new(packet_id_lookup),
|
packet_id_lookup,
|
||||||
)
|
)
|
||||||
.expect("TCP server generation failed")
|
.expect("TCP server generation failed")
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,10 @@ use spacepackets::ByteConversionError;
|
|||||||
use spacepackets::{SpHeader, MAX_APID};
|
use spacepackets::{SpHeader, MAX_APID};
|
||||||
|
|
||||||
use crate::pus::EcssTmSenderCore;
|
use crate::pus::EcssTmSenderCore;
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub use alloc_mod::EventReporter;
|
pub use alloc_mod::*;
|
||||||
|
|
||||||
pub use spacepackets::ecss::event::*;
|
pub use spacepackets::ecss::event::*;
|
||||||
|
|
||||||
pub struct EventReportCreator {
|
pub struct EventReportCreator {
|
||||||
@ -16,102 +18,98 @@ pub struct EventReportCreator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EventReportCreator {
|
impl EventReportCreator {
|
||||||
pub fn new(apid: u16) -> Option<Self> {
|
pub fn new(apid: u16, dest_id: u16) -> Option<Self> {
|
||||||
if apid > MAX_APID {
|
if apid > MAX_APID {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(Self {
|
Some(Self { dest_id, apid })
|
||||||
// msg_count: 0,
|
|
||||||
dest_id: 0,
|
|
||||||
apid,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_info<'time, 'src_data>(
|
pub fn event_info<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
event_id: impl EcssEnumeration,
|
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> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
self.generate_and_send_generic_tm(
|
self.generate_and_send_generic_tm(
|
||||||
src_data_buf,
|
|
||||||
Subservice::TmInfoReport,
|
Subservice::TmInfoReport,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
event_id,
|
event_id,
|
||||||
aux_data,
|
params,
|
||||||
|
src_data_buf,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_low_severity<'time, 'src_data>(
|
pub fn event_low_severity<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
event_id: impl EcssEnumeration,
|
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> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
self.generate_and_send_generic_tm(
|
self.generate_and_send_generic_tm(
|
||||||
src_data_buf,
|
|
||||||
Subservice::TmLowSeverityReport,
|
Subservice::TmLowSeverityReport,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
event_id,
|
event_id,
|
||||||
aux_data,
|
params,
|
||||||
|
src_data_buf,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_medium_severity<'time, 'src_data>(
|
pub fn event_medium_severity<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
buf: &'src_data mut [u8],
|
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
event_id: impl EcssEnumeration,
|
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> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
self.generate_and_send_generic_tm(
|
self.generate_and_send_generic_tm(
|
||||||
buf,
|
|
||||||
Subservice::TmMediumSeverityReport,
|
Subservice::TmMediumSeverityReport,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
event_id,
|
event_id,
|
||||||
aux_data,
|
params,
|
||||||
|
buf,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_high_severity<'time, 'src_data>(
|
pub fn event_high_severity<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
event_id: impl EcssEnumeration,
|
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> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
self.generate_and_send_generic_tm(
|
self.generate_and_send_generic_tm(
|
||||||
src_data_buf,
|
|
||||||
Subservice::TmHighSeverityReport,
|
Subservice::TmHighSeverityReport,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
event_id,
|
event_id,
|
||||||
aux_data,
|
params,
|
||||||
|
src_data_buf,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_and_send_generic_tm<'time, 'src_data>(
|
fn generate_and_send_generic_tm<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
|
||||||
subservice: Subservice,
|
subservice: Subservice,
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
event_id: impl EcssEnumeration,
|
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> {
|
) -> 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>(
|
fn generate_generic_event_tm<'time, 'src_data>(
|
||||||
&self,
|
&self,
|
||||||
src_data_buf: &'src_data mut [u8],
|
|
||||||
subservice: Subservice,
|
subservice: Subservice,
|
||||||
time_stamp: &'time [u8],
|
time_stamp: &'time [u8],
|
||||||
event_id: impl EcssEnumeration,
|
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> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
let mut src_data_len = event_id.size();
|
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();
|
src_data_len += aux_data.len();
|
||||||
}
|
}
|
||||||
source_buffer_large_enough(src_data_buf.len(), src_data_len)?;
|
source_buffer_large_enough(src_data_buf.len(), src_data_len)?;
|
||||||
@ -121,7 +119,7 @@ impl EventReportCreator {
|
|||||||
let mut current_idx = 0;
|
let mut current_idx = 0;
|
||||||
event_id.write_to_be_bytes(&mut src_data_buf[0..event_id.size()])?;
|
event_id.write_to_be_bytes(&mut src_data_buf[0..event_id.size()])?;
|
||||||
current_idx += 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);
|
src_data_buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data);
|
||||||
current_idx += aux_data.len();
|
current_idx += aux_data.len();
|
||||||
}
|
}
|
||||||
@ -142,25 +140,56 @@ mod alloc_mod {
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::cell::RefCell;
|
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,
|
id: ComponentId,
|
||||||
// Use interior mutability pattern here. This is just an intermediate buffer to the PUS event packet
|
// Use interior mutability pattern here. This is just an intermediate buffer to the PUS event packet
|
||||||
// generation.
|
// generation.
|
||||||
source_data_buf: RefCell<Vec<u8>>,
|
source_data_buf: RefCell<Vec<u8>>,
|
||||||
pub report_creator: EventReportCreator,
|
pub report_creator: EventReportCreator,
|
||||||
|
pub tm_hook: EventTmHook,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventReporter {
|
impl EventReporter<DummyEventHook> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
id: ComponentId,
|
id: ComponentId,
|
||||||
apid: u16,
|
default_apid: u16,
|
||||||
|
default_dest_id: u16,
|
||||||
max_event_id_and_aux_data_size: usize,
|
max_event_id_and_aux_data_size: usize,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
let reporter = EventReportCreator::new(apid)?;
|
let reporter = EventReportCreator::new(default_apid, default_dest_id)?;
|
||||||
Some(Self {
|
Some(Self {
|
||||||
id,
|
id,
|
||||||
source_data_buf: RefCell::new(vec![0; max_event_id_and_aux_data_size]),
|
source_data_buf: RefCell::new(vec![0; max_event_id_and_aux_data_size]),
|
||||||
report_creator: reporter,
|
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),
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
params: Option<&[u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<(), EcssTmtcError> {
|
||||||
let mut mut_buf = self.source_data_buf.borrow_mut();
|
let mut mut_buf = self.source_data_buf.borrow_mut();
|
||||||
let tm_creator = self
|
let mut tm_creator = self
|
||||||
.report_creator
|
.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)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.id, tm_creator.into())?;
|
sender.send_tm(self.id, tm_creator.into())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -185,13 +215,14 @@ mod alloc_mod {
|
|||||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
params: Option<&[u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<(), EcssTmtcError> {
|
||||||
let mut mut_buf = self.source_data_buf.borrow_mut();
|
let mut mut_buf = self.source_data_buf.borrow_mut();
|
||||||
let tm_creator = self
|
let mut tm_creator = self
|
||||||
.report_creator
|
.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)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.id, tm_creator.into())?;
|
sender.send_tm(self.id, tm_creator.into())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -201,13 +232,14 @@ mod alloc_mod {
|
|||||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
params: Option<&[u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<(), EcssTmtcError> {
|
||||||
let mut mut_buf = self.source_data_buf.borrow_mut();
|
let mut mut_buf = self.source_data_buf.borrow_mut();
|
||||||
let tm_creator = self
|
let mut tm_creator = self
|
||||||
.report_creator
|
.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)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.id, tm_creator.into())?;
|
sender.send_tm(self.id, tm_creator.into())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -217,13 +249,14 @@ mod alloc_mod {
|
|||||||
sender: &(impl EcssTmSenderCore + ?Sized),
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
params: Option<&[u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<(), EcssTmtcError> {
|
||||||
let mut mut_buf = self.source_data_buf.borrow_mut();
|
let mut mut_buf = self.source_data_buf.borrow_mut();
|
||||||
let tm_creator = self
|
let mut tm_creator = self
|
||||||
.report_creator
|
.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)?;
|
.map_err(PusError::ByteConversion)?;
|
||||||
|
self.tm_hook.modify_tm(&mut tm_creator);
|
||||||
sender.send_tm(self.id, tm_creator.into())?;
|
sender.send_tm(self.id, tm_creator.into())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -346,6 +379,7 @@ mod tests {
|
|||||||
let reporter = EventReporter::new(
|
let reporter = EventReporter::new(
|
||||||
TEST_COMPONENT_ID_0.id(),
|
TEST_COMPONENT_ID_0.id(),
|
||||||
EXAMPLE_APID,
|
EXAMPLE_APID,
|
||||||
|
0,
|
||||||
max_event_aux_data_buf,
|
max_event_aux_data_buf,
|
||||||
);
|
);
|
||||||
assert!(reporter.is_some());
|
assert!(reporter.is_some());
|
||||||
@ -440,7 +474,7 @@ mod tests {
|
|||||||
fn insufficient_buffer() {
|
fn insufficient_buffer() {
|
||||||
let mut sender = TestSender::default();
|
let mut sender = TestSender::default();
|
||||||
for i in 0..3 {
|
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());
|
assert!(reporter.is_some());
|
||||||
let mut reporter = reporter.unwrap();
|
let mut reporter = reporter.unwrap();
|
||||||
check_buf_too_small(&mut reporter, &mut sender, i);
|
check_buf_too_small(&mut reporter, &mut sender, i);
|
||||||
|
@ -81,7 +81,10 @@
|
|||||||
//! let mutable_handler_ref = ccsds_distributor.packet_handler_mut();
|
//! let mutable_handler_ref = ccsds_distributor.packet_handler_mut();
|
||||||
//! mutable_handler_ref.mutable_foo();
|
//! mutable_handler_ref.mutable_foo();
|
||||||
//! ```
|
//! ```
|
||||||
use crate::tmtc::{ReceivesCcsdsTc, ReceivesTcCore};
|
use crate::{
|
||||||
|
encoding::ccsds::PacketIdValidator,
|
||||||
|
tmtc::{ReceivesCcsdsTc, ReceivesTcCore},
|
||||||
|
};
|
||||||
use core::fmt::{Display, Formatter};
|
use core::fmt::{Display, Formatter};
|
||||||
use spacepackets::{ByteConversionError, CcsdsPacket, SpHeader};
|
use spacepackets::{ByteConversionError, CcsdsPacket, SpHeader};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -93,14 +96,16 @@ use std::error::Error;
|
|||||||
/// instance of this handler to the [CcsdsDistributor]. The distributor will use the trait
|
/// 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
|
/// interface to dispatch received packets to the user based on the Application Process Identifier
|
||||||
/// (APID) field of the CCSDS packet.
|
/// (APID) field of the CCSDS packet.
|
||||||
pub trait CcsdsPacketHandler {
|
pub trait CcsdsPacketHandler: PacketIdValidator {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
// TODO: Rework this to return a boolean based on u16 input..
|
fn handle_packet_with_valid_apid(
|
||||||
fn valid_apids(&self) -> &'static [u16];
|
&mut self,
|
||||||
fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8])
|
sp_header: &SpHeader,
|
||||||
-> Result<(), Self::Error>;
|
tc_raw: &[u8],
|
||||||
fn handle_unknown_apid(
|
) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
|
fn handle_packet_with_unknown_apid(
|
||||||
&mut self,
|
&mut self,
|
||||||
sp_header: &SpHeader,
|
sp_header: &SpHeader,
|
||||||
tc_raw: &[u8],
|
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>> {
|
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();
|
||||||
let valid_apids = self.packet_handler.valid_apids();
|
let valid_apid = self.packet_handler().validate(sp_header.packet_id().raw());
|
||||||
for &valid_apid in valid_apids {
|
if valid_apid {
|
||||||
if valid_apid == apid {
|
return self
|
||||||
return self
|
.packet_handler
|
||||||
.packet_handler
|
.handle_packet_with_valid_apid(sp_header, tc_raw)
|
||||||
.handle_known_apid(sp_header, tc_raw)
|
.map_err(|e| CcsdsError::CustomError(e));
|
||||||
.map_err(|e| CcsdsError::CustomError(e));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.packet_handler
|
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))
|
.map_err(|e| CcsdsError::CustomError(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,13 +245,16 @@ pub(crate) mod tests {
|
|||||||
pub unknown_packet_queue: VecDeque<(u16, Vec<u8>)>,
|
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 {
|
impl CcsdsPacketHandler for BasicApidHandlerSharedQueue {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
fn valid_apids(&self) -> &'static [u16] {
|
|
||||||
&[0x000, 0x002]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_known_apid(
|
fn handle_packet_with_valid_apid(
|
||||||
&mut self,
|
&mut self,
|
||||||
sp_header: &SpHeader,
|
sp_header: &SpHeader,
|
||||||
tc_raw: &[u8],
|
tc_raw: &[u8],
|
||||||
@ -262,7 +268,7 @@ pub(crate) mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_unknown_apid(
|
fn handle_packet_with_unknown_apid(
|
||||||
&mut self,
|
&mut self,
|
||||||
sp_header: &SpHeader,
|
sp_header: &SpHeader,
|
||||||
tc_raw: &[u8],
|
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 {
|
impl CcsdsPacketHandler for BasicApidHandlerOwnedQueue {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn valid_apids(&self) -> &'static [u16] {
|
fn handle_packet_with_valid_apid(
|
||||||
&[0x000, 0x002]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_known_apid(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
sp_header: &SpHeader,
|
sp_header: &SpHeader,
|
||||||
tc_raw: &[u8],
|
tc_raw: &[u8],
|
||||||
@ -295,7 +303,7 @@ pub(crate) mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_unknown_apid(
|
fn handle_packet_with_unknown_apid(
|
||||||
&mut self,
|
&mut self,
|
||||||
sp_header: &SpHeader,
|
sp_header: &SpHeader,
|
||||||
tc_raw: &[u8],
|
tc_raw: &[u8],
|
||||||
|
Loading…
Reference in New Issue
Block a user