extern crate alloc; use spacepackets::{ CcsdsPacketIdAndPsc, time::cds::{CdsTime, MIN_CDS_FIELD_LEN}, }; pub mod ccsds; pub mod control; pub mod mgm; pub mod pcdu; #[derive( Debug, Copy, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, num_enum::TryFromPrimitive, num_enum::IntoPrimitive, )] #[repr(u64)] pub enum ComponentId { Controller, AcsSubsystem, AcsMgmAssembly, AcsMgm0, AcsMgm1, EpsSubsystem, EpsPcdu, UdpServer, TcpServer, EventManager, Ground, } #[derive(Debug, PartialEq, Eq, strum::EnumIter)] #[bitbybit::bitenum(u11)] pub enum Apid { Tmtc = 1, Cfdp = 2, Acs = 3, Eps = 6, } #[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)] pub enum Event { ControllerEvent(control::Event), } impl Message for Event { fn message_type(&self) -> MessageType { MessageType::Event } } #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[non_exhaustive] pub struct TmHeader { pub sender_id: ComponentId, pub target_id: ComponentId, pub message_type: MessageType, /// Telemetry can either be sent unsolicited, or as a response to telecommands. pub tc_id: Option, /// Raw CDS short timestamp. pub timestamp: Option<[u8; 7]>, } impl TmHeader { pub fn new( sender_id: ComponentId, target_id: ComponentId, message_type: MessageType, tc_id: Option, cds_timestamp: &CdsTime, ) -> Self { // Can not fail, CDS short always requires 7 bytes. let mut stamp_buf: [u8; MIN_CDS_FIELD_LEN] = [0; MIN_CDS_FIELD_LEN]; cds_timestamp.write_to_bytes(&mut stamp_buf).unwrap(); Self { sender_id, target_id, tc_id, message_type, timestamp: Some(stamp_buf), } } pub fn new_for_unsolicited_tm( sender_id: ComponentId, target_id: ComponentId, message_type: MessageType, cds_timestamp: &CdsTime, ) -> Self { Self::new(sender_id, target_id, message_type, None, cds_timestamp) } pub fn new_for_tc_response( sender_id: ComponentId, target_id: ComponentId, message_type: MessageType, tc_id: CcsdsPacketIdAndPsc, cds_timestamp: &CdsTime, ) -> Self { Self::new( sender_id, target_id, message_type, Some(tc_id), cds_timestamp, ) } pub fn from_bytes_postcard(data: &[u8]) -> Result<(Self, &[u8]), postcard::Error> { postcard::take_from_bytes::(data) } } #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[non_exhaustive] pub struct TcHeader { pub target_id: ComponentId, pub request_type: MessageType, } impl TcHeader { pub fn new(target_id: ComponentId, request_type: MessageType) -> Self { Self { target_id, request_type, } } } #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub enum MessageType { Ping, Mode, Hk, Action, Event, Verification, } pub trait Message { fn message_type(&self) -> MessageType; } #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum DeviceMode { Off = 0, On = 1, Normal = 2, } #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[non_exhaustive] pub enum HkRequestType { OneShot, EnablePeriodic(core::time::Duration), DisablePeriodic, ModifyInterval(core::time::Duration), } #[cfg(test)] mod tests {}