try to update more chapters
This commit is contained in:
@@ -10,7 +10,7 @@ toml = "0.9"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
spacepackets = { version = "0.18" }
|
||||
embedded-types = { path = "../types" }
|
||||
tmtc-utils = { git = "https://egit.irs.uni-stuttgart.de/rust/tmtc-utils.git", version = "0.1", rev = "d8015379a45e77400dd9c71afbf22ca415ed67d1" }
|
||||
tmtc-utils = { path = "../../tmtc-utils" }
|
||||
postcard = { version = "1", features = ["alloc"] }
|
||||
anyhow = "1"
|
||||
cobs = "0.5"
|
||||
|
||||
@@ -81,15 +81,14 @@ This is a protocol which already provides us with some useful fields:
|
||||
- Basic sequence counter which can be used to determine missed packets
|
||||
|
||||
However, how does the actual payload that we want to send to or from the satellite actually look
|
||||
like? While there are standards like the Packet Utilisation Standard (PUS), we recommend a payload
|
||||
format which is created with the excellent [`serde`](https://serde.rs/) library. The
|
||||
[TMTC modelling](./tmtc-modelling.md) chapter provides more information.
|
||||
like? We recommend a payload format which is created with the excellent [`serde`](https://serde.rs/)
|
||||
library. The [TMTC modelling](./tmtc-modelling.md) chapter provides more information.
|
||||
|
||||
# Low-level protocols and the bridge to the communcation subsystem
|
||||
|
||||
Many satellite systems usually use the lower levels of the OSI layer in addition to the application
|
||||
layer covered by the PUS standard or the CCSDS space packets standard. This oftentimes requires
|
||||
special hardware like dedicated FPGAs to handle forward error correction fast enough. `sat-rs`
|
||||
layer. This oftentimes requires special hardware like dedicated FPGAs to handle forward error
|
||||
correction fast enough. `sat-rs`
|
||||
might provide components to handle standard like the Unified Space Data Link Standard (USLP) in
|
||||
software but most of the time the handling of communication is performed through custom
|
||||
software and hardware. Still, connecting this custom software and hardware to `sat-rs` can mostly
|
||||
|
||||
@@ -2,23 +2,3 @@
|
||||
|
||||
Events are an important mechanism used for remote systems to monitor unexpected
|
||||
or expected anomalies and events occuring on these systems.
|
||||
|
||||
One common use case for events on remote systems is to offer a light-weight publish-subscribe
|
||||
mechanism and IPC mechanism for software and hardware events which are also packaged as telemetry
|
||||
(TM) or can trigger a system response. They can also be tied to
|
||||
Fault Detection, Isolation and Recovery (FDIR) operations, which need to happen autonomously.
|
||||
|
||||
The PUS Service 5 standardizes how the ground interface for events might look like, but does not
|
||||
specify how other software components might react to those events. There is the PUS Service 19,
|
||||
which might be used for that purpose, but the event components recommended by this framework do not
|
||||
rely on the present of this service.
|
||||
|
||||
The following images shows how the flow of events could look like in a system where components
|
||||
can generate events, and where other system components might be interested in those events:
|
||||
|
||||

|
||||
|
||||
For the concrete implementation of your own event management and/or event routing system, you
|
||||
can have a look at the event management documentation inside the
|
||||
[API documentation](https://docs.rs/satrs/latest/satrs/event_man/index.html) where you can also
|
||||
find references to all examples.
|
||||
|
||||
+68
-100
@@ -12,10 +12,59 @@ The example project contains components which could also be expected to be part
|
||||
On-Board Software. A structural diagram of the example application is given to provide
|
||||
a brief high-level view of the components used inside the example application:
|
||||
|
||||

|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph TMTC[TMTC Infrastructure]
|
||||
subgraph TMTCRow1[ ]
|
||||
direction LR
|
||||
Udp[UDP Server]
|
||||
Tcp[TCP Server]
|
||||
end
|
||||
subgraph TMTCRow2[ ]
|
||||
direction LR
|
||||
Source[TC Source]
|
||||
Sink[TM Sink]
|
||||
end
|
||||
end
|
||||
|
||||
The dotted lines are used to denote optional components. In this case, the static pool components
|
||||
are optional because the heap can be used as a simpler mechanism to store TMTC packets as well.
|
||||
subgraph AOCS[AOCS Stack]
|
||||
subgraph AOCSRow1[ ]
|
||||
direction LR
|
||||
Mgm0[MGM 0 Handler]
|
||||
Mgm1[MGM 1 Handler]
|
||||
Assy[MGM Assembly]
|
||||
end
|
||||
subgraph AOCSRow2[ ]
|
||||
direction LR
|
||||
AcsCtrl[ACS Controller]
|
||||
Mgt[MGT Handler]
|
||||
AcsSub[ACS Subsystem]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph EPS[EPS Stack]
|
||||
Pcdu[PCDU Handler]
|
||||
end
|
||||
|
||||
subgraph Core[Core]
|
||||
direction LR
|
||||
Ctrl[Core Controller]
|
||||
Evt[Event Manager]
|
||||
end
|
||||
|
||||
Sim[Sim Client]:::optional
|
||||
|
||||
TMTC ~~~ EPS
|
||||
AOCS ~~~ Core
|
||||
Core ~~~ Sim
|
||||
|
||||
classDef optional stroke-dasharray: 5 5;
|
||||
classDef invisible fill:none,stroke:none;
|
||||
class TMTCRow1,TMTCRow2,AOCSRow1,AOCSRow2 invisible;
|
||||
```
|
||||
|
||||
The dotted lines are used to denote optional components. In this case, the simulation client is
|
||||
optional because a dummy interface can be used instead to run the example without the simulator.
|
||||
Some additional explanation is provided for the various components.
|
||||
|
||||
### TCP/IP server components
|
||||
@@ -37,116 +86,35 @@ telecommands from the client.
|
||||
The most important components of the TMTC infrastructure include the following components:
|
||||
|
||||
- A TC source component which demultiplexes and routes telecommands based on parameters like
|
||||
packet APID or PUS service and subservice type.
|
||||
packet APID and a target ID which is part of the packet payload.
|
||||
- A TM sink sink component which is the target of all sent telemetry and sends it to downlink
|
||||
handlers like the UDP and TCP server.
|
||||
|
||||
You can read the [Communications chapter](./communication.md) for more
|
||||
background information on the chosen TMTC infrastructure approach.
|
||||
|
||||
### PUS Service Components
|
||||
|
||||
A PUS service stack is provided which exposes some functionality conformant with the ECSS PUS
|
||||
services. This currently includes the following services:
|
||||
|
||||
- Service 1 for telecommand verification. The verification handling is handled locally: Each
|
||||
component which generates verification telemetry in some shape or form receives a
|
||||
[reporter](https://docs.rs/satrs/latest/satrs/pus/verification/struct.VerificationReporterWithSender.html)
|
||||
object which can be used to send PUS 1 verification telemetry to the TM funnel.
|
||||
- Service 3 for housekeeping telemetry handling.
|
||||
- Service 5 for management and downlink of on-board events.
|
||||
- Service 8 for handling on-board actions.
|
||||
- Service 11 for scheduling telecommands to be released at a specific time. This component
|
||||
uses the [PUS scheduler class](https://docs.rs/satrs/latest/satrs/pus/scheduler/alloc_mod/struct.PusScheduler.html)
|
||||
which performs the core logic of scheduling telecommands. All telecommands released by the
|
||||
scheduler are sent to the central TC source using a message.
|
||||
- Service 17 for test purposes like pings.
|
||||
|
||||
### Event Management Component
|
||||
|
||||
An event manager based on the sat-rs
|
||||
[event manager component](https://docs.rs/satrs/latest/satrs/event_man/index.html)
|
||||
is provided to handle the event IPC and FDIR mechanism. The event message are converted to PUS 5
|
||||
telemetry by the
|
||||
[PUS event dispatcher](https://docs.rs/satrs/latest/satrs/pus/event_man/alloc_mod/struct.PusEventDispatcher.html).
|
||||
|
||||
You can read the [events](./events.md) chapter for more in-depth information about event management.
|
||||
|
||||
### Sample Application Components
|
||||
|
||||
These components are example mission specific. They provide an idea how mission specific modules
|
||||
would look like the sat-rs context. It currently includes the following components:
|
||||
|
||||
- An Attitute and Orbit Control (AOCS) example task which can also process some PUS commands.
|
||||
|
||||
## Dataflow
|
||||
|
||||
The interaction of the various components is provided in the following diagram:
|
||||
### TMTC component group
|
||||
|
||||

|
||||
|
||||
It should be noted that an arrow coming out of a component group refers to multiple components
|
||||
in that group. An explanation for important component groups will be given.
|
||||
|
||||
#### TMTC component group
|
||||
|
||||
This groups is the primary interface for clients to communicate with the on-board software
|
||||
using a standardized TMTC protocol. The example uses the
|
||||
[ECSS PUS protocol](https://ecss.nl/standard/ecss-e-st-70-41c-space-engineering-telemetry-and-telecommand-packet-utilization-15-april-2016/).
|
||||
This group is the primary interface for clients to communicate with the on-board software
|
||||
using the combination of CCSDS space packets and `serde` serialized payloads.
|
||||
In the future, this might be extended with the
|
||||
[CCSDS File Delivery Protocol](https://public.ccsds.org/Pubs/727x0b5.pdf).
|
||||
|
||||
A client can connect to the UDP or TCP server to send these PUS packets to the on-board software.
|
||||
These servers then forward the telecommads to a centralized TC source component using a dedicated
|
||||
message abstraction.
|
||||
A client can connect to the UDP or TCP server to send telecommands to the on-board software.
|
||||
These servers forward all telecommands to a centralized TC source component, which demultiplexes
|
||||
them and routes each one to its target component.
|
||||
|
||||
This TC source component then demultiplexes the message and forwards it to the relevant components.
|
||||
Right now, it forwards all PUS requests to the respective PUS service handlers using the PUS
|
||||
receiver component. The individual PUS services are running in a separate thread. In the future,
|
||||
additional forwarding to components like a CFDP handler might be added as well. It should be noted
|
||||
that PUS11 commands might contain other PUS commands which should be scheduled in the future.
|
||||
These wrapped commands are forwarded to the PUS11 handler. When the schedule releases those
|
||||
commands, it forwards the released commands to the TC source again. This allows the scheduler
|
||||
and the TC source to run in separate threads and keeps them cleanly separated.
|
||||
All telemetry generated by the on-board software is sent to a centralized TM sink. The core
|
||||
controller also forwards events to the event manager, which converts them into telemetry and
|
||||
sends it to the TM sink as well. The TM sink performs a demultiplexing step to forward all
|
||||
telemetry to the relevant recipients, which in the example case are the last connected UDP
|
||||
client and any connected TCP client.
|
||||
|
||||
All telemetry generated by the on-board software is sent to a centralized TM funnel. This component
|
||||
also performs a demultiplexing step to forward all telemetry to the relevant TM recipients.
|
||||
In the example case, this is the last UDP client, or a connected TCP client. In the future,
|
||||
forwarding to a persistent telemetry store and a simulated communication component might be
|
||||
added here as well. The centralized TM funnel also takes care of some packet processing steps which
|
||||
need to be applied for each ECSS PUS packet, for example CCSDS specific APID incrementation and
|
||||
PUS specific message counter incrementation.
|
||||
### Application Group
|
||||
|
||||
#### Application Group
|
||||
The application group contain some components you might also find in a real satellite software.
|
||||
This includes an AOCS stack with various device handlers and system level objects.
|
||||
|
||||
The application components generally do not receive raw PUS packets directly, even though
|
||||
this is certainly possible. Instead, they receive internalized messages from the PUS service
|
||||
handlers. For example, instead of receiving a PUS 8 Action Telecommand directly, an application
|
||||
component will receive a special `ActionRequest` message type reduced to the basic important
|
||||
information required to execute a request. These special requests are denoted by the blue arrow
|
||||
in the diagram.
|
||||
|
||||
It should be noted that the arrow pointing towards the event manager points in both directions.
|
||||
This is because the application components might be interested in events generated by other
|
||||
components as well. This mechanism is oftentimes used to implement the FDIR functionality on system
|
||||
and component level.
|
||||
|
||||
#### Shared components and functional interfaces
|
||||
|
||||
It should be noted that sometimes, a functional interface is used instead of a message. This
|
||||
is used for the generation of verification telemetry. The verification reporter is a clonable
|
||||
component which generates and sends PUS1 verification telemetry directly to the TM funnel. This
|
||||
introduces a loose coupling to the PUS standard but was considered the easiest solution for
|
||||
a project which utilizes PUS as the main communication protocol. In the future, a generic
|
||||
verification abstraction might be introduced to completely decouple the application layer from
|
||||
PUS.
|
||||
|
||||
The same concept is applied if the backing store of TMTC packets are shared pools. Every
|
||||
component which needs to read telecommands inside that shared pool or generate new telemetry
|
||||
into that shared pool will received a clonable shared handle to that pool.
|
||||
|
||||
The same concept could be extended to power or thermal handling. For example, a shared power helper
|
||||
component might be used to retrieve power state information and send power switch commands through
|
||||
a functional interface. The actual implementation of the functional interface might still use
|
||||
shared memory and/or messages, but the functional interface makes using and testing the interaction
|
||||
with these components easier.
|
||||
### Shared components and functional interfaces
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# Housekeeping Data
|
||||
|
||||
If you have not read [the TMTC modelling chapter](./tmtc-modelling.md) yet, it is recommended to
|
||||
do that first.
|
||||
|
||||
Remote systems like satellites and rovers oftentimes generate data autonomously and periodically.
|
||||
The most common example for this is temperature or attitude data. Data like this is commonly
|
||||
An example for this could be temperature or attitude data. Data like this is commonly
|
||||
referred to as housekeeping data, and is usually one of the most important and most resource heavy
|
||||
data sources received from a satellite. Standards like the PUS Service 3 make recommendation how to
|
||||
expose housekeeping data, but the applicability of the interface offered by PUS 3 has proven to be
|
||||
partially difficult and clunky for modular systems.
|
||||
data sources received from a satellite.
|
||||
|
||||
First, we are going to list some assumption and requirements about Housekeeping (HK) data:
|
||||
|
||||
@@ -18,7 +19,89 @@ First, we are going to list some assumption and requirements about Housekeeping
|
||||
3. HK data often needs to be shared to other software components. For example, a thermal controller
|
||||
wants to read the data samples of all sensor components.
|
||||
|
||||
A commonly required way to model HK data in a clean way is also to group related HK data into sets,
|
||||
which can then dumped via a similar interface.
|
||||
## Modelling our data
|
||||
|
||||
TODO: Write down `sat-rs` recommendations how to expose and work with HK data.
|
||||
Generally, it makes sense to model the data with Rust data structures for various reasons. For
|
||||
example, the sensor data received from a 3-axis magnetometer might me modelled like this:
|
||||
|
||||
```rust
|
||||
#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct MgmData {
|
||||
pub x: i16,
|
||||
pub y: i16,
|
||||
pub z: i16,
|
||||
}
|
||||
```
|
||||
|
||||
You can then re-use this data structure for various purposes. Also note the `serde` implementations,
|
||||
which are useful for generating the housekeeping data sent to ground.
|
||||
|
||||
We can model the housekeeping requests for a handler with a single data set like this:
|
||||
|
||||
```rust
|
||||
#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum HkRequest {
|
||||
OneShot,
|
||||
EnablePeriodic,
|
||||
DisablePeriodic,
|
||||
ModifyInterval(core::time::Duration)
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
which might then be a part of a top level request type, e.g.
|
||||
|
||||
```rust
|
||||
#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Request {
|
||||
Ping,
|
||||
Hk(HkRequest)
|
||||
}
|
||||
```
|
||||
|
||||
A corresponding `Response` type might just include a HK data variant:
|
||||
|
||||
```rust
|
||||
#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Response {
|
||||
Ok,
|
||||
Hk(MgmData)
|
||||
}
|
||||
```
|
||||
|
||||
If the software object managed multiple data sets, you could model it like this:
|
||||
|
||||
```rust
|
||||
/// Example set ID.
|
||||
#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum SetId {
|
||||
Data,
|
||||
Config
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Request {
|
||||
Ping,
|
||||
Hk {
|
||||
set_id: SetId,
|
||||
request: HkRequest
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Sometimes, you need to share the generated data as well. Furthermore, it might make sense to
|
||||
decouple the HK generation from the data acquisition and only return the latest snapshot
|
||||
of the data. In this case, you can put the `MgmData` inside an appropriate lock structure for your
|
||||
platform/runtime to share it safely with other software components. For example, in a `std` system,
|
||||
you might simply use an `Arc<Mutex<MgmData>>` or a `Arc<RwLock<MgmData>>` for this.
|
||||
|
||||
Now, you can update that shared data structure when acquiring new data, and other software objects
|
||||
or the HK generation routine can safely read from it.
|
||||
|
||||
## Helper components
|
||||
|
||||
You need some application logic to track whether periodic data generation is enabled, what
|
||||
the current generation interval is and whether a HK set needs to be generated if the interval
|
||||
period has elapsed.
|
||||
|
||||
`sat-rs` provides some simple helper components for this inside the [`hk`](https://docs.rs/satrs/latest/satrs/hk/index.html) module. The module documentation contains more information.
|
||||
|
||||
@@ -73,8 +73,6 @@ In summary, a component which has modes has to expose the following 4 capabiliti
|
||||
3. Announce the mode
|
||||
4. Announce the mode recursively
|
||||
|
||||
## Using ECSS PUS to perform mode commanding
|
||||
|
||||
# Health
|
||||
|
||||
Health is an important concept for systems and components which might fail.
|
||||
@@ -99,5 +97,3 @@ could be power-cycled if there were multiple communication issues in the last ti
|
||||
example, on operator might be interested in testing a component in isolation, and the interference
|
||||
of the system is not desired. In that case, the `EXTERNAL CONTROL` health state might be used
|
||||
to prevent mode commands from the system while allowing external mode commands.
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use arbitrary_int::u11;
|
||||
use lazy_static::lazy_static;
|
||||
use satrs::{
|
||||
res_code::ResultU16,
|
||||
legacy::res_code::ResultU16,
|
||||
spacepackets::{PacketId, PacketType},
|
||||
};
|
||||
use satrs_mib::res_code::ResultU16Info;
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use satrs::pus::HandlingStatus;
|
||||
use satrs::HandlingStatus;
|
||||
use satrs_minisim::{
|
||||
SerializableSimMsgPayload, SimComponent, SimMessageProvider, SimReply, SimRequest,
|
||||
udp::SIM_CTRL_PORT,
|
||||
|
||||
@@ -4,8 +4,8 @@ use std::net::{SocketAddr, UdpSocket};
|
||||
use std::sync::{Arc, Mutex, mpsc};
|
||||
|
||||
use log::warn;
|
||||
use satrs::HandlingStatus;
|
||||
use satrs::hal::std::udp_server::{ReceiveResult, UdpTcServer};
|
||||
use satrs::pus::HandlingStatus;
|
||||
use satrs::queue::GenericSendError;
|
||||
use types::ccsds::CcsdsTmPacketOwned;
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ use interface::{
|
||||
use log::info;
|
||||
use logger::setup_logger;
|
||||
use satrs::{
|
||||
HandlingStatus,
|
||||
hal::std::{tcp_server::ServerConfig, udp_server::UdpTcServer},
|
||||
pus::HandlingStatus,
|
||||
spacepackets::time::cds::CdsTime,
|
||||
};
|
||||
use satrs_example::{
|
||||
@@ -38,7 +38,7 @@ use types::{ComponentId, DeviceMode};
|
||||
|
||||
use crate::{
|
||||
acs::{ctrl, mgm, mgm_assembly, mgt, subsystem},
|
||||
control::Controller,
|
||||
controller::Controller,
|
||||
eps::pcdu::SwitchSet,
|
||||
event_manager::EventManager,
|
||||
interface::udp::UdpTmHandlerWithChannel,
|
||||
@@ -47,7 +47,7 @@ use crate::{
|
||||
|
||||
mod acs;
|
||||
mod ccsds;
|
||||
mod control;
|
||||
mod controller;
|
||||
mod eps;
|
||||
mod event_manager;
|
||||
mod interface;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use satrs::{
|
||||
pus::HandlingStatus,
|
||||
HandlingStatus,
|
||||
spacepackets::{CcsdsPacketReader, ChecksumType},
|
||||
tmtc::PacketAsVec,
|
||||
};
|
||||
|
||||
@@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# [unreleased]
|
||||
|
||||
- Added `hk` module helpers to track whether a single HK set needs regeneration:
|
||||
`SingleSetHkHelperStd` (`std`), `SingleSetHkHelperEmbassy` (new `embassy-time` feature),
|
||||
and `SingleSetHkHelperCountdown`, generic over the existing `Countdown` trait.
|
||||
|
||||
# [v0.3.0-alpha.3] 2025-11-06
|
||||
|
||||
- Bump `sat-rs` edition to 2024.
|
||||
|
||||
@@ -35,6 +35,7 @@ socket2 = { version = "0.6", features = ["all"], optional = true }
|
||||
arbitrary-int = "2"
|
||||
mio = { version = "1", features = ["os-poll", "net"], optional = true }
|
||||
defmt = { version = "1", optional = true }
|
||||
embassy-time = { version = "0.5", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde = "1"
|
||||
@@ -72,6 +73,7 @@ alloc = [
|
||||
serde = ["dep:serde", "spacepackets/serde", "satrs-shared/serde"]
|
||||
crossbeam = ["crossbeam-channel"]
|
||||
defmt = ["dep:defmt", "spacepackets/defmt"]
|
||||
embassy-time = ["dep:embassy-time"]
|
||||
test_util = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
//! # HK generation helpers
|
||||
//!
|
||||
//! Each helper contains the minimal state to support the periodic generation of housekeeping
|
||||
//! packets. Call [SingleSetHkHelperStd::needs_generation](crate::hk::SingleSetHkHelperStd::needs_generation) periodically, for example once per task
|
||||
//! cycle. When it returns `true`, generate the HK set and send it, the helper has already reset
|
||||
//! its clock for the next period.
|
||||
//!
|
||||
//! Pick a helper based on what clock is available:
|
||||
//!
|
||||
//! - [SingleSetHkHelperStd](crate::hk::SingleSetHkHelperStd): `std::time::Instant`, behind the `std` feature.
|
||||
//! - [SingleSetHkHelperEmbassy](crate::hk::SingleSetHkHelperEmbassy): `embassy_time::Instant`, behind the `embassy-time` feature.
|
||||
//! - [SingleSetHkHelperCountdown](crate::hk::SingleSetHkHelperCountdown): any clock implementing [Countdown](crate::time::Countdown), for example a
|
||||
//! `fugit`-based monotonic.
|
||||
//!
|
||||
//! If your software object has multiple HK sets, you can simply put the helpers inside a dynamic
|
||||
//! list like [alloc::vec::Vec], [heapless::vec::Vec] or a hash map.
|
||||
#![deny(missing_docs)]
|
||||
use crate::time::Countdown;
|
||||
|
||||
/// Generic single-set HK helper for any clock, backed by a [Countdown] implementation.
|
||||
///
|
||||
/// Useful for clocks not covered by [SingleSetHkHelperStd] or [SingleSetHkHelperEmbassy], for
|
||||
/// example a `fugit`-based monotonic. Users implement [Countdown] for their clock and hand it in.
|
||||
pub struct SingleSetHkHelperCountdown<C: Countdown> {
|
||||
countdown: C,
|
||||
enabled: bool,
|
||||
}
|
||||
|
||||
impl<C: Countdown> SingleSetHkHelperCountdown<C> {
|
||||
/// Create a new, enabled helper wrapping the given countdown.
|
||||
pub fn new(countdown: C) -> Self {
|
||||
Self {
|
||||
countdown,
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reference to the wrapped countdown.
|
||||
pub fn countdown(&self) -> &C {
|
||||
&self.countdown
|
||||
}
|
||||
|
||||
/// Mutable reference to the wrapped countdown.
|
||||
pub fn countdown_mut(&mut self) -> &mut C {
|
||||
&mut self.countdown
|
||||
}
|
||||
|
||||
/// Whether the helper is enabled.
|
||||
pub fn enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
|
||||
/// Enable or disable the helper.
|
||||
pub fn set_enabled(&mut self, enabled: bool) {
|
||||
self.enabled = enabled;
|
||||
}
|
||||
|
||||
/// Returns true if the HK set needs regeneration, resetting the countdown.
|
||||
///
|
||||
/// Always returns false while disabled, leaving the countdown untouched.
|
||||
pub fn needs_generation(&mut self) -> bool {
|
||||
if !self.enabled {
|
||||
return false;
|
||||
}
|
||||
if self.countdown.has_expired() {
|
||||
self.countdown.reset();
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Single-set HK helper backed by [std::time::Instant].
|
||||
#[cfg(feature = "std")]
|
||||
pub struct SingleSetHkHelperStd {
|
||||
interval: core::time::Duration,
|
||||
last_generated: std::time::Instant,
|
||||
enabled: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl SingleSetHkHelperStd {
|
||||
/// Create a new, enabled helper with the given interval, starting the clock now.
|
||||
pub fn new(initial_interval: core::time::Duration) -> Self {
|
||||
Self {
|
||||
interval: initial_interval,
|
||||
last_generated: std::time::Instant::now(),
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the generation interval.
|
||||
pub fn update_interval(&mut self, interval: core::time::Duration) {
|
||||
self.interval = interval;
|
||||
}
|
||||
|
||||
/// Current generation interval.
|
||||
pub fn interval(&self) -> core::time::Duration {
|
||||
self.interval
|
||||
}
|
||||
|
||||
/// Whether the helper is enabled.
|
||||
pub fn enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
|
||||
/// Enable or disable the helper.
|
||||
pub fn set_enabled(&mut self, enabled: bool) {
|
||||
self.enabled = enabled;
|
||||
}
|
||||
|
||||
/// Returns true if the HK set needs regeneration.
|
||||
///
|
||||
/// Always returns false while disabled, leaving the clock untouched.
|
||||
pub fn needs_generation(&mut self) -> bool {
|
||||
if !self.enabled {
|
||||
return false;
|
||||
}
|
||||
let now = std::time::Instant::now();
|
||||
if now - self.last_generated > self.interval {
|
||||
self.last_generated = now;
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Single-set HK helper backed by [embassy_time::Instant].
|
||||
#[cfg(feature = "embassy-time")]
|
||||
pub struct SingleSetHkHelperEmbassy {
|
||||
interval: embassy_time::Duration,
|
||||
last_generated: embassy_time::Instant,
|
||||
enabled: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "embassy-time")]
|
||||
impl SingleSetHkHelperEmbassy {
|
||||
/// Create a new, enabled helper with the given interval, starting the clock now.
|
||||
pub fn new(initial_interval: embassy_time::Duration) -> Self {
|
||||
Self {
|
||||
interval: initial_interval,
|
||||
last_generated: embassy_time::Instant::now(),
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the generation interval.
|
||||
pub fn update_interval(&mut self, interval: embassy_time::Duration) {
|
||||
self.interval = interval;
|
||||
}
|
||||
|
||||
/// Current generation interval.
|
||||
pub fn interval(&self) -> embassy_time::Duration {
|
||||
self.interval
|
||||
}
|
||||
|
||||
/// Whether the helper is enabled.
|
||||
pub fn enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
|
||||
/// Enable or disable the helper.
|
||||
pub fn set_enabled(&mut self, enabled: bool) {
|
||||
self.enabled = enabled;
|
||||
}
|
||||
|
||||
/// Returns true if the HK set needs regeneration.
|
||||
///
|
||||
/// Always returns false while disabled, leaving the clock untouched.
|
||||
pub fn needs_generation(&mut self) -> bool {
|
||||
if !self.enabled {
|
||||
return false;
|
||||
}
|
||||
let now = embassy_time::Instant::now();
|
||||
if now - self.last_generated > self.interval {
|
||||
self.last_generated = now;
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -579,7 +579,7 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
use crate::legacy::events::{EventErasedAlloc, Severity};
|
||||
use crate::pus::test_util::{TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1};
|
||||
use crate::legacy::pus::test_util::{TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1};
|
||||
use std::sync::mpsc;
|
||||
|
||||
const TEST_GROUP_ID_0: u14 = u14::new(0);
|
||||
|
||||
@@ -591,7 +591,7 @@ mod tests {
|
||||
use crate::legacy::event_man_legacy::EventManager;
|
||||
use crate::legacy::events_legacy::{EventU32, GenericEvent, Severity};
|
||||
use crate::params::{ParamsHeapless, ParamsRaw};
|
||||
use crate::pus::test_util::{TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1};
|
||||
use crate::legacy::pus::test_util::{TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_1};
|
||||
use std::format;
|
||||
use std::sync::mpsc::{self};
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
pub mod action;
|
||||
pub mod event_man;
|
||||
pub mod events;
|
||||
pub mod res_code;
|
||||
|
||||
pub mod pus;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
action::{ActionId, ActionRequest},
|
||||
legacy::action::{ActionId, ActionRequest},
|
||||
params::Params,
|
||||
request::{GenericMessage, MessageMetadata, RequestId},
|
||||
};
|
||||
@@ -66,7 +66,7 @@ impl GenericActionReplyPus {
|
||||
pub mod alloc_mod {
|
||||
use crate::{
|
||||
ComponentId,
|
||||
action::ActionRequest,
|
||||
legacy::action::ActionRequest,
|
||||
queue::{GenericReceiveError, GenericSendError},
|
||||
request::{
|
||||
GenericMessage, MessageReceiverProvider, MessageSenderAndReceiver,
|
||||
@@ -142,7 +142,7 @@ pub mod std_mod {
|
||||
|
||||
use crate::{
|
||||
ComponentId,
|
||||
pus::{
|
||||
legacy::pus::{
|
||||
ActivePusRequestStd, ActiveRequest, DefaultActiveRequestMap,
|
||||
verification::{self, TcStateToken},
|
||||
},
|
||||
@@ -1,4 +1,3 @@
|
||||
use crate::pus::source_buffer_large_enough;
|
||||
use arbitrary_int::u11;
|
||||
use spacepackets::ByteConversionError;
|
||||
use spacepackets::SpHeader;
|
||||
@@ -110,7 +109,7 @@ impl EventReportCreator {
|
||||
if let Some(aux_data) = params {
|
||||
src_data_len += aux_data.len();
|
||||
}
|
||||
source_buffer_large_enough(src_data_buf.len(), src_data_len)?;
|
||||
super::source_buffer_large_enough(src_data_buf.len(), src_data_len)?;
|
||||
let sec_header = PusTmSecondaryHeader::new(
|
||||
MessageTypeId::new(5, subservice.into()),
|
||||
0,
|
||||
@@ -137,7 +136,7 @@ impl EventReportCreator {
|
||||
mod alloc_mod {
|
||||
use super::*;
|
||||
use crate::ComponentId;
|
||||
use crate::pus::{EcssTmSender, EcssTmtcError};
|
||||
use crate::legacy::pus::{EcssTmSender, EcssTmtcError};
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
use core::cell::RefCell;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,12 @@
|
||||
use super::PusPacketHandlingError;
|
||||
use super::scheduler::PusScheduler;
|
||||
use super::verification::{VerificationReporter, VerificationReportingProvider};
|
||||
use super::{
|
||||
CacheAndReadRawEcssTc, DirectPusPacketHandlerResult, EcssTcInSharedPoolCacher, EcssTcReceiver,
|
||||
EcssTcVecCacher, EcssTmSender, HandlingStatus, MpscTcReceiver, PartialPusHandlingError,
|
||||
PusServiceHelper,
|
||||
EcssTcVecCacher, EcssTmSender, MpscTcReceiver, PartialPusHandlingError, PusServiceHelper,
|
||||
};
|
||||
use crate::HandlingStatus;
|
||||
use crate::pool::PoolProvider;
|
||||
use crate::pus::PusPacketHandlingError;
|
||||
use crate::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
|
||||
use alloc::string::ToString;
|
||||
use spacepackets::ecss::{PusPacket, scheduling};
|
||||
@@ -247,12 +247,14 @@ pub type PusService11SchedHandlerStaticWithBoundedMpsc<PusScheduler> = PusSchedS
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::legacy::pus::test_util::{PusTestHarness, TEST_APID};
|
||||
use crate::legacy::pus::verification::{VerificationReporter, VerificationReportingProvider};
|
||||
use crate::pool::{StaticMemoryPool, StaticPoolConfig};
|
||||
use crate::pus::test_util::{PusTestHarness, TEST_APID};
|
||||
use crate::pus::verification::{VerificationReporter, VerificationReportingProvider};
|
||||
|
||||
use crate::pus::{DirectPusPacketHandlerResult, MpscTcReceiver, PusPacketHandlingError};
|
||||
use crate::pus::{
|
||||
use crate::legacy::pus::{
|
||||
DirectPusPacketHandlerResult, MpscTcReceiver, PusPacketHandlingError,
|
||||
};
|
||||
use crate::legacy::pus::{
|
||||
EcssTcInSharedPoolCacher,
|
||||
scheduler::{self, PusScheduler, TcInfo},
|
||||
tests::PusServiceHandlerWithSharedStoreCommon,
|
||||
@@ -377,8 +379,8 @@ mod tests {
|
||||
fn insert_unwrapped_and_stored_tc(
|
||||
&mut self,
|
||||
_time_stamp: spacepackets::time::UnixTime,
|
||||
info: crate::pus::scheduler::TcInfo,
|
||||
) -> Result<(), crate::pus::scheduler::ScheduleError> {
|
||||
info: crate::legacy::pus::scheduler::TcInfo,
|
||||
) -> Result<(), crate::legacy::pus::scheduler::ScheduleError> {
|
||||
self.inserted_tcs.push_back(info);
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::pus::{
|
||||
use super::{
|
||||
DirectPusPacketHandlerResult, PartialPusHandlingError, PusPacketHandlingError, PusTmVariant,
|
||||
};
|
||||
use crate::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
|
||||
@@ -12,8 +12,9 @@ use std::sync::mpsc;
|
||||
use super::verification::{VerificationReporter, VerificationReportingProvider};
|
||||
use super::{
|
||||
CacheAndReadRawEcssTc, EcssTcInSharedPoolCacher, EcssTcReceiver, EcssTcVecCacher, EcssTmSender,
|
||||
GenericConversionError, HandlingStatus, MpscTcReceiver, PusServiceHelper,
|
||||
GenericConversionError, MpscTcReceiver, PusServiceHelper,
|
||||
};
|
||||
use crate::HandlingStatus;
|
||||
|
||||
/// This is a helper class for [std] environments to handle generic PUS 17 (test service) packets.
|
||||
/// This handler only processes ping requests and generates a ping reply for them accordingly.
|
||||
@@ -140,18 +141,19 @@ pub type PusService17TestHandlerStaticWithBoundedMpsc = PusService17TestHandler<
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ComponentId;
|
||||
use crate::pus::test_util::{PusTestHarness, SimplePusPacketHandler, TEST_APID};
|
||||
use crate::pus::tests::{
|
||||
use crate::HandlingStatus;
|
||||
use crate::legacy::pus::test_util::{PusTestHarness, SimplePusPacketHandler, TEST_APID};
|
||||
use crate::legacy::pus::tests::{
|
||||
PusServiceHandlerWithSharedStoreCommon, PusServiceHandlerWithVecCommon,
|
||||
};
|
||||
use crate::pus::verification::{
|
||||
use crate::legacy::pus::verification::{
|
||||
RequestId, VerificationReporter, VerificationReportingProvider,
|
||||
};
|
||||
use crate::pus::verification::{TcStateAccepted, VerificationToken};
|
||||
use crate::pus::{
|
||||
use crate::legacy::pus::verification::{TcStateAccepted, VerificationToken};
|
||||
use crate::legacy::pus::{
|
||||
DirectPusPacketHandlerResult, EcssTcInSharedPoolCacher, EcssTcVecCacher,
|
||||
GenericConversionError, HandlingStatus, MpscTcReceiver, MpscTmAsVecSender,
|
||||
PartialPusHandlingError, PusPacketHandlingError,
|
||||
GenericConversionError, MpscTcReceiver, MpscTmAsVecSender, PartialPusHandlingError,
|
||||
PusPacketHandlingError,
|
||||
};
|
||||
use crate::tmtc::PacketSenderWithSharedPool;
|
||||
use arbitrary_int::traits::Integer as _;
|
||||
@@ -16,7 +16,7 @@
|
||||
//! use std::sync::{Arc, mpsc, RwLock};
|
||||
//! use std::time::Duration;
|
||||
//! use satrs::pool::{PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig};
|
||||
//! use satrs::pus::verification::{
|
||||
//! use satrs::legacy::pus::verification::{
|
||||
//! VerificationReportingProvider, VerificationReporterConfig, VerificationReporter
|
||||
//! };
|
||||
//! use satrs::tmtc::{SharedStaticMemoryPool, PacketSenderWithSharedPool};
|
||||
@@ -80,8 +80,8 @@
|
||||
//! The [integration test](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/main/fsrc-core/tests/verification_test.rs)
|
||||
//! for the verification module contains examples how this module could be used in a more complex
|
||||
//! context involving multiple threads
|
||||
use super::{EcssTmSender, EcssTmtcError, source_buffer_large_enough};
|
||||
use crate::params::{Params, WritableToBeBytes};
|
||||
use crate::pus::{EcssTmSender, EcssTmtcError, source_buffer_large_enough};
|
||||
use arbitrary_int::{u3, u11, u14};
|
||||
use core::fmt::{Debug, Display, Formatter};
|
||||
use core::hash::{Hash, Hasher};
|
||||
@@ -841,7 +841,7 @@ pub mod alloc_mod {
|
||||
use spacepackets::ecss::PusError;
|
||||
|
||||
use super::*;
|
||||
use crate::pus::PusTmVariant;
|
||||
use crate::legacy::pus::PusTmVariant;
|
||||
use core::cell::RefCell;
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -1712,16 +1712,16 @@ pub mod test_util {
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use crate::ComponentId;
|
||||
use crate::params::Params;
|
||||
use crate::pool::{SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig};
|
||||
use crate::pus::test_util::{TEST_APID, TEST_COMPONENT_ID_0};
|
||||
use crate::pus::tests::CommonTmInfo;
|
||||
use crate::pus::verification::{
|
||||
use crate::legacy::pus::test_util::{TEST_APID, TEST_COMPONENT_ID_0};
|
||||
use crate::legacy::pus::tests::CommonTmInfo;
|
||||
use crate::legacy::pus::verification::{
|
||||
EcssTmSender, EcssTmtcError, FailParams, FailParamsWithStep, RequestId, TcStateNone,
|
||||
VerificationReporter, VerificationReporterConfig, VerificationToken,
|
||||
handle_step_failure_with_generic_params,
|
||||
};
|
||||
use crate::pus::{ChannelWithId, PusTmVariant};
|
||||
use crate::legacy::pus::{ChannelWithId, PusTmVariant};
|
||||
use crate::params::Params;
|
||||
use crate::pool::{SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig};
|
||||
use crate::request::MessageMetadata;
|
||||
use crate::spacepackets::seq_count::{SequenceCounter, SequenceCounterCcsdsSimple};
|
||||
use crate::tmtc::{PacketSenderWithSharedPool, SharedPacketPool};
|
||||
+14
-15
@@ -1,16 +1,7 @@
|
||||
//! # sat-rs: A library to build on-board software for remote systems
|
||||
//! # sat-rs: A helper library to build on-board software for remote systems
|
||||
//!
|
||||
//! You can find more information about the sat-rs framework on the
|
||||
//! [homepage](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/).
|
||||
//! The [satrs-book](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/book/) contains
|
||||
//! high-level information about this framework.
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The core modules of this crate include
|
||||
//!
|
||||
//! - The [pus] module which provides special support for projects using
|
||||
//! the [ECSS PUS C standard](https://ecss.nl/standard/ecss-e-st-70-41c-space-engineering-telemetry-and-telecommand-packet-utilization-15-april-2016/).
|
||||
//! The [satrs-book](https://robamu.github.io/sat-rs/book/) contains
|
||||
//! high-level information about this library.
|
||||
#![no_std]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#[cfg(any(feature = "alloc", test))]
|
||||
@@ -20,23 +11,22 @@ extern crate downcast_rs;
|
||||
#[cfg(any(feature = "std", test))]
|
||||
extern crate std;
|
||||
|
||||
pub mod action;
|
||||
pub mod ccsds;
|
||||
pub mod encoding;
|
||||
#[cfg(feature = "std")]
|
||||
pub mod executable;
|
||||
pub mod hal;
|
||||
pub mod health;
|
||||
/// Helpers to track when housekeeping sets need to be regenerated.
|
||||
pub mod hk;
|
||||
pub mod legacy;
|
||||
pub mod mode;
|
||||
#[cfg(feature = "std")]
|
||||
pub mod mode_tree;
|
||||
pub mod params;
|
||||
pub mod pool;
|
||||
pub mod pus;
|
||||
pub mod queue;
|
||||
pub mod request;
|
||||
pub mod res_code;
|
||||
#[cfg(feature = "alloc")]
|
||||
pub mod scheduling;
|
||||
#[cfg(feature = "alloc")]
|
||||
@@ -48,6 +38,15 @@ pub use spacepackets;
|
||||
|
||||
use spacepackets::PacketId;
|
||||
|
||||
/// Generic handling status for an object which is able to continuosly handle a queue to handle
|
||||
/// request or replies until the queue is empty.
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum HandlingStatus {
|
||||
HandledOne,
|
||||
Empty,
|
||||
}
|
||||
|
||||
/// Generic component ID type.
|
||||
pub type ComponentId = u32;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -229,8 +229,8 @@ pub mod std_mod {
|
||||
use spacepackets::ecss::WritablePusPacket;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::legacy::pus::{EcssTmSender, EcssTmtcError, PacketSenderPusTc};
|
||||
use crate::pool::PoolProvider;
|
||||
use crate::pus::{EcssTmSender, EcssTmtcError, PacketSenderPusTc};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -460,16 +460,16 @@ pub mod std_mod {
|
||||
fn send_tm(
|
||||
&self,
|
||||
sender_id: crate::ComponentId,
|
||||
tm: crate::pus::PusTmVariant,
|
||||
) -> Result<(), crate::pus::EcssTmtcError> {
|
||||
tm: crate::legacy::pus::PusTmVariant,
|
||||
) -> Result<(), crate::legacy::pus::EcssTmtcError> {
|
||||
let send_addr = |store_addr: PoolAddr| {
|
||||
self.sender
|
||||
.send_packet(sender_id, store_addr)
|
||||
.map_err(EcssTmtcError::Send)
|
||||
};
|
||||
match tm {
|
||||
crate::pus::PusTmVariant::InStore(store_addr) => send_addr(store_addr),
|
||||
crate::pus::PusTmVariant::Direct(tm_creator) => {
|
||||
crate::legacy::pus::PusTmVariant::InStore(store_addr) => send_addr(store_addr),
|
||||
crate::legacy::pus::PusTmVariant::Direct(tm_creator) => {
|
||||
let mut pool = self.shared_pool.borrow_mut();
|
||||
let store_addr = pool.add_pus_tm_from_creator(&tm_creator)?;
|
||||
send_addr(store_addr)
|
||||
|
||||
@@ -3,12 +3,12 @@ pub mod crossbeam_test {
|
||||
use arbitrary_int::traits::Integer as _;
|
||||
use arbitrary_int::u14;
|
||||
use hashbrown::HashMap;
|
||||
use satrs::pool::{PoolProvider, PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig};
|
||||
use satrs::pus::test_util::{TEST_APID, TEST_COMPONENT_ID_0};
|
||||
use satrs::pus::verification::{
|
||||
use satrs::legacy::pus::test_util::{TEST_APID, TEST_COMPONENT_ID_0};
|
||||
use satrs::legacy::pus::verification::{
|
||||
FailParams, RequestId, VerificationReporter, VerificationReporterConfig,
|
||||
VerificationReportingProvider,
|
||||
};
|
||||
use satrs::pool::{PoolProvider, PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig};
|
||||
use satrs::tmtc::{PacketSenderWithSharedPool, SharedStaticMemoryPool};
|
||||
use spacepackets::SpHeader;
|
||||
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader};
|
||||
|
||||
Reference in New Issue
Block a user