Merge branch 'mueller_add_hk_in_example'

This commit is contained in:
Robin Müller 2022-12-21 10:25:26 +01:00
commit f109d59d56
16 changed files with 292 additions and 75 deletions

View File

@ -32,6 +32,7 @@ default-features = false
[dependencies.serde]
version = "1.0"
default-features = false
optional = true
[dependencies.spacepackets]
path = "../spacepackets"
@ -50,6 +51,7 @@ version = "1.0"
default = ["std"]
std = ["downcast-rs/std", "alloc", "bus", "postcard/use-std", "crossbeam-channel/std", "serde/std"]
alloc = ["serde/alloc"]
serde = ["dep:serde"]
heapless = []
doc-images = []

View File

@ -211,9 +211,9 @@ impl<E: 'static, Event: GenericEvent + Copy + 'static, AuxDataProvider: Clone +
/// Create an event manager where the sender table will be the [DefaultSenderTableProvider]
/// and the listener table will be the [DefaultListenerTableProvider].
pub fn new(event_receiver: Box<dyn EventReceiver<Event, AuxDataProvider>>) -> Self {
let listener_table = Box::new(DefaultListenerTableProvider::default());
let sender_table =
Box::new(DefaultSenderTableProvider::<E, Event, AuxDataProvider>::default());
let listener_table: Box<DefaultListenerTableProvider> = Box::default();
let sender_table: Box<DefaultSenderTableProvider<E, Event, AuxDataProvider>> =
Box::default();
Self::new_custom_tables(listener_table, sender_table, event_receiver)
}
}

View File

@ -136,17 +136,14 @@ impl<RAW: ToBeBytes, GID, UID> EventBase<RAW, GID, UID> {
impl EventBase<u32, u16, u16> {
#[inline]
fn raw(&self) -> u32 {
(((self.severity as u32) << 30) | ((self.group_id as u32) << 16) | self.unique_id as u32)
as u32
((self.severity as u32) << 30) | ((self.group_id as u32) << 16) | self.unique_id as u32
}
}
impl EventBase<u16, u8, u8> {
#[inline]
fn raw(&self) -> u16 {
(((self.severity as u16) << 14) as u16
| ((self.group_id as u16) << 8) as u16
| self.unique_id as u16) as u16
((self.severity as u16) << 14) | ((self.group_id as u16) << 8) | self.unique_id as u16
}
}

View File

@ -136,7 +136,7 @@ impl StoreAddr {
pub const INVALID_ADDR: u32 = 0xFFFFFFFF;
pub fn raw(&self) -> u32 {
((self.pool_idx as u32) << 16) as u32 | self.packet_idx as u32
((self.pool_idx as u32) << 16) | self.packet_idx as u32
}
}
@ -239,7 +239,7 @@ impl LocalPool {
fn validate_addr(&self, addr: &StoreAddr) -> Result<(), StoreError> {
let pool_idx = addr.pool_idx as usize;
if pool_idx as usize >= self.pool_cfg.cfg.len() {
if pool_idx >= self.pool_cfg.cfg.len() {
return Err(StoreError::InvalidStoreId(
StoreIdError::InvalidSubpool(addr.pool_idx),
Some(*addr),

8
satrs-core/src/pus/hk.rs Normal file
View File

@ -0,0 +1,8 @@
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Subservice {
TcEnableGeneration = 5,
TcDisableGeneration = 6,
TmHkPacket = 25,
TcGenerateOneShotHk = 27,
TcModifyCollectionInterval = 31,
}

View File

@ -12,6 +12,7 @@ use spacepackets::{ByteConversionError, SizeMissmatch};
pub mod event;
pub mod event_man;
pub mod hk;
pub mod verification;
/// Generic error type which is also able to wrap a user send error with the user supplied type E.

View File

@ -569,7 +569,7 @@ impl VerificationReporterBasic {
) -> Result<PusTm, EcssTmError<E>> {
let mut source_data_len = size_of::<u32>();
if let Some(step) = step {
source_data_len += step.byte_width() as usize;
source_data_len += step.byte_width();
}
source_buffer_large_enough(buf.len(), source_data_len)?;
let mut idx = 0;
@ -577,7 +577,7 @@ impl VerificationReporterBasic {
idx += RequestId::SIZE_AS_BYTES;
if let Some(step) = step {
// Size check was done beforehand
step.write_to_be_bytes(&mut buf[idx..idx + step.byte_width() as usize])
step.write_to_be_bytes(&mut buf[idx..idx + step.byte_width()])
.unwrap();
}
let mut sp_header = SpHeader::tm_unseg(self.apid(), 0, 0).unwrap();
@ -601,10 +601,9 @@ impl VerificationReporterBasic {
params: &'a FailParams,
) -> Result<PusTm, EcssTmError<E>> {
let mut idx = 0;
let mut source_data_len =
RequestId::SIZE_AS_BYTES + params.failure_code.byte_width() as usize;
let mut source_data_len = RequestId::SIZE_AS_BYTES + params.failure_code.byte_width();
if let Some(step) = step {
source_data_len += step.byte_width() as usize;
source_data_len += step.byte_width();
}
if let Some(failure_data) = params.failure_data {
source_data_len += failure_data.len();
@ -614,14 +613,14 @@ impl VerificationReporterBasic {
idx += RequestId::SIZE_AS_BYTES;
if let Some(step) = step {
// Size check done beforehand
step.write_to_be_bytes(&mut buf[idx..idx + step.byte_width() as usize])
step.write_to_be_bytes(&mut buf[idx..idx + step.byte_width()])
.unwrap();
idx += step.byte_width() as usize;
idx += step.byte_width();
}
params
.failure_code
.write_to_be_bytes(&mut buf[idx..idx + params.failure_code.byte_width() as usize])?;
idx += params.failure_code.byte_width() as usize;
.write_to_be_bytes(&mut buf[idx..idx + params.failure_code.byte_width()])?;
idx += params.failure_code.byte_width();
if let Some(failure_data) = params.failure_data {
buf[idx..idx + failure_data.len()].copy_from_slice(failure_data);
}
@ -709,8 +708,8 @@ mod allocmod {
source_data_buf: vec![
0;
RequestId::SIZE_AS_BYTES
+ cfg.step_field_width as usize
+ cfg.fail_code_field_width as usize
+ cfg.step_field_width
+ cfg.fail_code_field_width
+ cfg.max_fail_data_len
],
seq_counter: cfg.seq_counter.clone(),

View File

@ -5,10 +5,11 @@
//! directly dispatch received packets to packet listeners based on packet fields like the CCSDS
//! Application Process ID (APID) or the ECSS PUS service type. This allows for fast packet
//! routing without the overhead and complication of using message queues. However, it also requires
use crate::error::{FsrcErrorRaw, FsrcGroupIds};
use downcast_rs::{impl_downcast, Downcast};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use spacepackets::tc::PusTc;
use spacepackets::SpHeader;
use spacepackets::{ByteConversionError, SizeMissmatch, SpHeader};
#[cfg(feature = "alloc")]
pub mod ccsds_distrib;
@ -19,24 +20,27 @@ pub mod tm_helper;
pub use ccsds_distrib::{CcsdsDistributor, CcsdsError, CcsdsPacketHandler};
pub use pus_distrib::{PusDistributor, PusServiceProvider};
const _RAW_PACKET_ERROR: &str = "raw-tmtc";
const _CCSDS_ERROR: &str = "ccsds-tmtc";
const _PUS_ERROR: &str = "pus-tmtc";
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct AddressableId {
pub target_id: u32,
pub unique_id: u32,
}
// TODO: A macro for general and unknown errors would be nice
const _FROM_BYTES_SLICE_TOO_SMALL_ERROR: FsrcErrorRaw = FsrcErrorRaw::new(
FsrcGroupIds::Tmtc as u8,
0,
_RAW_PACKET_ERROR,
"FROM_BYTES_SLICE_TOO_SMALL_ERROR",
);
const _FROM_BYTES_ZEROCOPY_ERROR: FsrcErrorRaw = FsrcErrorRaw::new(
FsrcGroupIds::Tmtc as u8,
1,
_RAW_PACKET_ERROR,
"FROM_BYTES_ZEROCOPY_ERROR",
);
impl AddressableId {
pub fn from_raw_be(buf: &[u8]) -> Result<Self, ByteConversionError> {
if buf.len() < 8 {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
found: buf.len(),
expected: 8,
}));
}
Ok(Self {
target_id: u32::from_be_bytes(buf[0..4].try_into().unwrap()),
unique_id: u32::from_be_bytes(buf[4..8].try_into().unwrap()),
})
}
}
/// Generic trait for object which can receive any telecommands in form of a raw bytestream, with
/// no assumptions about the received protocol.

View File

@ -1,5 +1,7 @@
#!/usr/bin/env python3
"""Example client for the sat-rs example application"""
import enum
import struct
import sys
import time
from typing import Optional
@ -8,9 +10,9 @@ import tmtccmd
from spacepackets.ecss import PusTelemetry, PusTelecommand, PusVerificator
from spacepackets.ecss.pus_17_test import Service17Tm
from spacepackets.ecss.pus_1_verification import UnpackParams, Service1Tm
from spacepackets.util import UnsignedByteField
from tmtccmd import CcsdsTmtcBackend, TcHandlerBase, ProcedureParamsWrapper
from tmtccmd.tc.pus_3_fsfw_hk import generate_one_hk_command, make_sid
from tmtccmd.core.base import BackendRequest
from tmtccmd.pus import VerificationWrapper
from tmtccmd.tm import CcsdsTmHandler, SpecificApidHandlerBase
@ -85,6 +87,13 @@ class SatRsConfigHook(TmTcCfgHookBase):
info="PUS Service 17 Test",
op_code_entry=srv_17,
)
srv_3 = OpCodeEntry()
srv_3.add(HkOpCodes.GENERATE_ONE_SHOT, "Generate AOCS one shot HK")
defs.add_service(
name=CoreServiceList.SERVICE_3,
info="PUS Service 3 Housekeeping",
op_code_entry=srv_3
)
return defs
def perform_mode_operation(self, tmtc_backend: CcsdsTmtcBackend, mode: int):
@ -158,6 +167,24 @@ class PusHandler(SpecificApidHandlerBase):
self.printer.handle_long_tm_print(packet_if=tm_packet, info_if=tm_packet)
def make_addressable_id(target_id: int, unique_id: int) -> bytes:
byte_string = bytearray(struct.pack("!I", target_id))
byte_string.extend(struct.pack("!I", unique_id))
return byte_string
class RequestTargetId(enum.IntEnum):
ACS = 1
class AcsHkIds(enum.IntEnum):
MGM_SET = 1
class HkOpCodes:
GENERATE_ONE_SHOT = ["0", "oneshot"]
class TcHandler(TcHandlerBase):
def __init__(
self,
@ -197,17 +224,27 @@ class TcHandler(TcHandlerBase):
)
def feed_cb(self, helper: ProcedureWrapper, wrapper: FeedWrapper):
self.queue_helper.queue_wrapper = wrapper.queue_wrapper
q = self.queue_helper
q.queue_wrapper = wrapper.queue_wrapper
if helper.proc_type == TcProcedureType.DEFAULT:
def_proc = helper.to_def_procedure()
service = def_proc.service
op_code = def_proc.op_code
if (
service == CoreServiceList.SERVICE_17
or service == CoreServiceList.SERVICE_17_ALT
):
return self.queue_helper.add_pus_tc(
q.add_log_cmd("Sending PUS ping telecommand")
return q.add_pus_tc(
PusTelecommand(service=17, subservice=1)
)
if service == CoreServiceList.SERVICE_3:
if op_code in HkOpCodes.GENERATE_ONE_SHOT:
q.add_log_cmd("Sending HK one shot request")
q.add_pus_tc(
generate_one_hk_command(make_addressable_id(RequestTargetId.ACS, AcsHkIds.MGM_SET))
)
pass
def main():

15
satrs-example/src/hk.rs Normal file
View File

@ -0,0 +1,15 @@
#![allow(dead_code)]
pub type CollectionIntervalFactor = u32;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum AcsHkIds {
TestMgmSet = 1,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum HkRequest {
OneShot(u32),
Enable(u32),
Disable(u32),
ModifyCollectionInterval(CollectionIntervalFactor),
}

View File

@ -3,24 +3,47 @@ use std::net::Ipv4Addr;
use satrs_mib::res_code::{ResultU16, ResultU16Info};
use satrs_mib::resultcode;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum RequestTargetId {
AcsSubsystem = 1,
}
#[derive(Debug)]
pub enum GroupId {
Tmtc = 0,
Hk = 1,
}
pub const OBSW_SERVER_ADDR: Ipv4Addr = Ipv4Addr::UNSPECIFIED;
pub const SERVER_PORT: u16 = 7301;
#[resultcode]
pub const INVALID_PUS_SERVICE: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 0);
#[resultcode]
pub const INVALID_PUS_SUBSERVICE: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 1);
pub mod tmtc_err {
use super::*;
#[resultcode(info = "Not enough data inside the TC application data field")]
pub const NOT_ENOUGH_APP_DATA: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 2);
#[resultcode]
pub const INVALID_PUS_SERVICE: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 0);
#[resultcode]
pub const INVALID_PUS_SUBSERVICE: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 1);
pub const TMTC_RESULTS: &[ResultU16Info] = &[
INVALID_PUS_SERVICE_EXT,
INVALID_PUS_SUBSERVICE_EXT,
NOT_ENOUGH_APP_DATA_EXT,
];
#[resultcode(info = "Not enough data inside the TC application data field")]
pub const NOT_ENOUGH_APP_DATA: ResultU16 = ResultU16::const_new(GroupId::Tmtc as u8, 2);
pub const TMTC_RESULTS: &[ResultU16Info] = &[
INVALID_PUS_SERVICE_EXT,
INVALID_PUS_SUBSERVICE_EXT,
NOT_ENOUGH_APP_DATA_EXT,
];
}
pub mod hk_err {
use super::*;
#[resultcode]
pub const TARGET_ID_MISSING: ResultU16 = ResultU16::const_new(GroupId::Hk as u8, 0);
#[resultcode]
pub const UNIQUE_ID_MISSING: ResultU16 = ResultU16::const_new(GroupId::Hk as u8, 1);
#[resultcode]
pub const UNKNOWN_TARGET_ID: ResultU16 = ResultU16::const_new(GroupId::Hk as u8, 2);
#[resultcode]
pub const COLLECTION_INTERVAL_MISSING: ResultU16 = ResultU16::const_new(GroupId::Hk as u8, 3);
}

View File

@ -1,7 +1,10 @@
mod ccsds;
mod hk;
mod pus;
mod requests;
mod tmtc;
use crate::requests::RequestWithToken;
use crate::tmtc::{core_tmtc_task, CoreTmtcArgs, TmStore, PUS_APID};
use satrs_core::event_man::{
EventManagerWithMpscQueue, MpscEventReceiver, MpscEventU32SendProvider, SendEventProvider,
@ -19,14 +22,16 @@ use satrs_core::pus::verification::{
use satrs_core::pus::{EcssTmError, EcssTmSender};
use satrs_core::seq_count::SimpleSeqCountProvider;
use satrs_core::tmtc::CcsdsError;
use satrs_example::{OBSW_SERVER_ADDR, SERVER_PORT};
use satrs_example::{RequestTargetId, OBSW_SERVER_ADDR, SERVER_PORT};
use spacepackets::time::cds::TimeProvider;
use spacepackets::time::TimeWriter;
use spacepackets::tm::PusTm;
use std::collections::HashMap;
use std::net::{IpAddr, SocketAddr};
use std::sync::mpsc::channel;
use std::sync::mpsc::{channel, TryRecvError};
use std::sync::{mpsc, Arc, RwLock};
use std::thread;
use std::time::Duration;
struct TmFunnel {
tm_funnel_rx: mpsc::Receiver<StoreAddr>,
@ -78,6 +83,7 @@ fn main() {
let sender = MpscVerifSender::new(tm_store.clone(), tm_funnel_tx.clone());
let verif_cfg = VerificationReporterCfg::new(
PUS_APID,
#[allow(clippy::box_default)]
Box::new(SimpleSeqCountProvider::default()),
1,
2,
@ -97,15 +103,21 @@ fn main() {
PusEventDispatcher::new(event_reporter, Box::new(pus_tm_backend));
let (pus_event_man_tx, pus_event_man_rx) = channel();
let pus_event_man_send_provider = MpscEventU32SendProvider::new(1, pus_event_man_tx);
let mut reporter1 = reporter_with_sender_0.clone();
let mut reporter_event_handler = reporter_with_sender_0.clone();
let mut reporter_aocs = reporter_with_sender_0.clone();
event_man.subscribe_all(pus_event_man_send_provider.id());
let mut request_map = HashMap::new();
let (acs_thread_tx, acs_thread_rx) = channel::<RequestWithToken>();
request_map.insert(RequestTargetId::AcsSubsystem as u32, acs_thread_tx);
// Create clones here to allow move for thread 0
let core_args = CoreTmtcArgs {
tm_store: tm_store_helper.clone(),
tm_sender: tm_funnel_tx.clone(),
event_sender,
event_request_tx,
request_map,
};
println!("Starting TMTC task");
@ -135,7 +147,7 @@ fn main() {
let mut sender = EventTmSender::new(tm_store_helper, tm_funnel_tx);
let mut time_provider = TimeProvider::new_with_u16_days(0, 0);
let mut report_completion = |event_req: EventRequestWithToken, timestamp: &[u8]| {
reporter1
reporter_event_handler
.completion_success(event_req.token, timestamp)
.expect("Sending completion success failed");
};
@ -167,9 +179,37 @@ fn main() {
}
});
println!("Starting AOCS thread");
let jh3 = thread::spawn(move || {
let mut timestamp: [u8; 7] = [0; 7];
let mut time_provider = TimeProvider::new_with_u16_days(0, 0);
loop {
match acs_thread_rx.try_recv() {
Ok(request) => {
println!("ACS thread: Received HK request {:?}", request.0);
update_time(&mut time_provider, &mut timestamp);
let started_token = reporter_aocs
.start_success(request.1, &timestamp)
.expect("Sending start success failed");
reporter_aocs
.completion_success(started_token, &timestamp)
.expect("Sending completion success failed");
}
Err(e) => match e {
TryRecvError::Empty => {}
TryRecvError::Disconnected => {
println!("ACS thread: Message Queue TX disconnected!")
}
},
}
thread::sleep(Duration::from_millis(500));
}
});
jh0.join().expect("Joining UDP TMTC server thread failed");
jh1.join().expect("Joining TM Funnel thread failed");
jh2.join().expect("Joining Event Manager thread failed");
jh3.join().expect("Joining AOCS thread failed");
}
pub fn update_time(time_provider: &mut TimeProvider, timestamp: &mut [u8]) {

View File

@ -1,28 +1,33 @@
use crate::hk::{CollectionIntervalFactor, HkRequest};
use crate::requests::{Request, RequestWithToken};
use crate::tmtc::TmStore;
use satrs_core::events::EventU32;
use satrs_core::pool::StoreAddr;
use satrs_core::pus::event::Subservices;
use satrs_core::pus::event_man::{EventRequest, EventRequestWithToken};
use satrs_core::pus::hk;
use satrs_core::pus::verification::{
FailParams, StdVerifReporterWithSender, TcStateAccepted, VerificationToken,
};
use satrs_core::res_code::ResultU16;
use satrs_core::tmtc::tm_helper::PusTmWithCdsShortHelper;
use satrs_core::tmtc::PusServiceProvider;
use satrs_example::{INVALID_PUS_SERVICE, INVALID_PUS_SUBSERVICE, NOT_ENOUGH_APP_DATA};
use satrs_core::tmtc::{AddressableId, PusServiceProvider};
use satrs_example::{hk_err, tmtc_err};
use spacepackets::ecss::PusPacket;
use spacepackets::tc::PusTc;
use spacepackets::time::cds::TimeProvider;
use spacepackets::time::TimeWriter;
use spacepackets::SpHeader;
use std::sync::mpsc;
use std::collections::HashMap;
use std::sync::mpsc::Sender;
pub struct PusReceiver {
pub tm_helper: PusTmWithCdsShortHelper,
pub tm_tx: mpsc::Sender<StoreAddr>,
pub tm_tx: Sender<StoreAddr>,
pub tm_store: TmStore,
pub verif_reporter: StdVerifReporterWithSender,
event_request_tx: mpsc::Sender<EventRequestWithToken>,
event_request_tx: Sender<EventRequestWithToken>,
request_map: HashMap<u32, Sender<RequestWithToken>>,
stamper: TimeProvider,
time_stamp: [u8; 7],
}
@ -30,10 +35,11 @@ pub struct PusReceiver {
impl PusReceiver {
pub fn new(
apid: u16,
tm_tx: mpsc::Sender<StoreAddr>,
tm_tx: Sender<StoreAddr>,
tm_store: TmStore,
verif_reporter: StdVerifReporterWithSender,
event_request_tx: mpsc::Sender<EventRequestWithToken>,
event_request_tx: Sender<EventRequestWithToken>,
request_map: HashMap<u32, Sender<RequestWithToken>>,
) -> Self {
Self {
tm_helper: PusTmWithCdsShortHelper::new(apid),
@ -41,7 +47,8 @@ impl PusReceiver {
tm_store,
verif_reporter,
event_request_tx,
stamper: TimeProvider::default(),
request_map,
stamper: TimeProvider::new_with_u16_days(0, 0),
time_stamp: [0; 7],
}
}
@ -65,13 +72,15 @@ impl PusServiceProvider for PusReceiver {
if service == 17 {
self.handle_test_service(pus_tc, accepted_token);
} else if service == 5 {
self.handle_event_service(pus_tc, accepted_token);
self.handle_event_request(pus_tc, accepted_token);
} else if service == 3 {
self.handle_hk_request(pus_tc, accepted_token);
} else {
self.update_time_stamp();
self.verif_reporter
.start_failure(
accepted_token,
FailParams::new(&self.time_stamp, &INVALID_PUS_SERVICE, None),
FailParams::new(&self.time_stamp, &tmtc_err::INVALID_PUS_SERVICE, None),
)
.expect("Start failure verification failed")
}
@ -81,7 +90,7 @@ impl PusServiceProvider for PusReceiver {
impl PusReceiver {
fn handle_test_service(&mut self, pus_tc: &PusTc, token: VerificationToken<TcStateAccepted>) {
if pus_tc.subservice() == 1 {
if PusPacket::subservice(pus_tc) == 1 {
println!("Received PUS ping command TC[17,1]");
println!("Sending ping reply PUS TM[17,2]");
let ping_reply = self.tm_helper.create_pus_tm_timestamp_now(17, 2, None);
@ -101,7 +110,7 @@ impl PusReceiver {
self.verif_reporter
.start_failure(
token,
FailParams::new(&self.time_stamp, &INVALID_PUS_SUBSERVICE, None),
FailParams::new(&self.time_stamp, &tmtc_err::INVALID_PUS_SUBSERVICE, None),
)
.expect("Sending start failure TM failed");
}
@ -116,7 +125,75 @@ impl PusReceiver {
.expect("Writing timestamp failed");
}
fn handle_event_service(&mut self, pus_tc: &PusTc, token: VerificationToken<TcStateAccepted>) {
fn handle_hk_request(&mut self, pus_tc: &PusTc, token: VerificationToken<TcStateAccepted>) {
if pus_tc.user_data().is_none() {
self.update_time_stamp();
self.verif_reporter
.start_failure(
token,
FailParams::new(&self.time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, None),
)
.expect("Sending start failure TM failed");
return;
}
let user_data = pus_tc.user_data().unwrap();
if user_data.len() < 8 {
let err = if user_data.len() < 4 {
&hk_err::TARGET_ID_MISSING
} else {
&hk_err::UNIQUE_ID_MISSING
};
self.update_time_stamp();
self.verif_reporter
.start_failure(token, FailParams::new(&self.time_stamp, err, None))
.expect("Sending start failure TM failed");
return;
}
let addressable_id = AddressableId::from_raw_be(user_data).unwrap();
if !self.request_map.contains_key(&addressable_id.target_id) {
self.update_time_stamp();
self.verif_reporter
.start_failure(
token,
FailParams::new(&self.time_stamp, &hk_err::UNKNOWN_TARGET_ID, None),
)
.expect("Sending start failure TM failed");
return;
}
let send_request = |request: HkRequest| {
let sender = self.request_map.get(&addressable_id.target_id).unwrap();
sender
.send(RequestWithToken(Request::HkRequest(request), token))
.unwrap_or_else(|_| panic!("Sending HK request {:?} failed", request));
};
if PusPacket::subservice(pus_tc) == hk::Subservice::TcEnableGeneration as u8 {
send_request(HkRequest::Enable(addressable_id.unique_id));
} else if PusPacket::subservice(pus_tc) == hk::Subservice::TcDisableGeneration as u8 {
send_request(HkRequest::Disable(addressable_id.unique_id));
} else if PusPacket::subservice(pus_tc) == hk::Subservice::TcGenerateOneShotHk as u8 {
send_request(HkRequest::OneShot(addressable_id.unique_id));
} else if PusPacket::subservice(pus_tc) == hk::Subservice::TcModifyCollectionInterval as u8
{
if user_data.len() < 12 {
self.update_time_stamp();
self.verif_reporter
.start_failure(
token,
FailParams::new(
&self.time_stamp,
&hk_err::COLLECTION_INTERVAL_MISSING,
None,
),
)
.expect("Sending start failure TM failed");
return;
}
send_request(HkRequest::ModifyCollectionInterval(
CollectionIntervalFactor::from_be_bytes(user_data[8..12].try_into().unwrap()),
));
}
}
fn handle_event_request(&mut self, pus_tc: &PusTc, token: VerificationToken<TcStateAccepted>) {
let send_start_failure = |verif_reporter: &mut StdVerifReporterWithSender,
timestamp: &[u8; 7],
failure_code: &ResultU16,
@ -139,7 +216,7 @@ impl PusReceiver {
send_start_failure(
&mut self.verif_reporter,
&self.time_stamp,
&NOT_ENOUGH_APP_DATA,
&tmtc_err::NOT_ENOUGH_APP_DATA,
None,
);
return;
@ -150,7 +227,7 @@ impl PusReceiver {
send_start_failure(
&mut self.verif_reporter,
&self.time_stamp,
&NOT_ENOUGH_APP_DATA,
&tmtc_err::NOT_ENOUGH_APP_DATA,
None,
);
return;
@ -182,7 +259,7 @@ impl PusReceiver {
send_start_failure(
&mut self.verif_reporter,
&self.time_stamp,
&INVALID_PUS_SUBSERVICE,
&tmtc_err::INVALID_PUS_SUBSERVICE,
None,
);
}

View File

@ -0,0 +1,10 @@
use crate::hk::HkRequest;
use satrs_core::pus::verification::{TcStateAccepted, VerificationToken};
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Request {
HkRequest(HkRequest),
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct RequestWithToken(pub Request, pub VerificationToken<TcStateAccepted>);

View File

@ -1,6 +1,7 @@
use satrs_core::events::EventU32;
use satrs_core::hal::host::udp_server::{ReceiveResult, UdpTcServer};
use satrs_core::params::Params;
use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::mpsc;
use std::sync::mpsc::Sender;
@ -9,6 +10,7 @@ use std::time::Duration;
use crate::ccsds::CcsdsReceiver;
use crate::pus::PusReceiver;
use crate::requests::RequestWithToken;
use crate::UdpTmtcServer;
use satrs_core::pool::{SharedPool, StoreAddr};
use satrs_core::pus::event_man::EventRequestWithToken;
@ -23,6 +25,7 @@ pub struct CoreTmtcArgs {
pub tm_sender: Sender<StoreAddr>,
pub event_sender: Sender<(EventU32, Option<Params>)>,
pub event_request_tx: Sender<EventRequestWithToken>,
pub request_map: HashMap<u32, Sender<RequestWithToken>>,
}
#[derive(Clone)]
@ -53,6 +56,7 @@ pub fn core_tmtc_task(
args.tm_store.clone(),
verif_reporter,
args.event_request_tx,
args.request_map,
);
let pus_distributor = PusDistributor::new(Box::new(pus_receiver));
let ccsds_receiver = CcsdsReceiver {

@ -1 +1 @@
Subproject commit db471e313c92c313d270d5a6f06c0414abb5fae3
Subproject commit 9b091e3a3a6f599b093c96327751bcf1bc911ca1