first step in unifying the examples: one example folder

One example folder for all examples, including std and embedded examples
This commit is contained in:
Robin Mueller committed 2026-09-29 13:39:39 +02:00
1 parent bb8decfc74
commit 7cc2ff3ff9
130 files changed
+399 -368

No files matched your search

+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
run: sudo apt update && sudo apt install -y libudev-dev
- run: cargo check
# Check example with static pool configuration
- run: cargo check -p satrs-example --no-default-features
- run: cargo check -p example-std --no-default-features
test:
name: Run Tests
+9 -8
View File
@@ -3,17 +3,18 @@ resolver = "2"
members = [
"satrs",
"satrs-mib",
"satrs-example",
"satrs-example/types",
"satrs-example/client",
"satrs-example/minisim",
"examples/example-std",
"examples/types",
"examples/client",
"examples/minisim",
"examples/minisim-types",
"satrs-shared",
"tmtc-utils",
"embedded-examples/embedded-client",
"embedded-examples/types",
"examples/embedded-client",
"examples/embedded-types",
]
exclude = [
"embedded-examples/stm32f3-disco-rtic",
"embedded-examples/stm32h7-nucleo-rtic",
"examples/stm32f3-disco-rtic",
"examples/stm32h7-nucleo-rtic",
]
+28 -16
View File
@@ -26,7 +26,7 @@ and [EIVE](https://www.irs.uni-stuttgart.de/en/research/satellitetechnology-and-
# Overview
This project currently contains following crates:
This project currently contains the following crates:
* [`satrs-book`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-book):
Primary information resource in addition to the API documentation, hosted
@@ -34,24 +34,36 @@ This project currently contains following crates:
this first before delving into the example application and the API documentation.
* [`satrs`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs):
Primary crate.
* [`satrs-example`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-example):
Example of a simple example on-board software using various sat-rs components which can be run
on a host computer or on any system with a standard runtime like a Raspberry Pi.
* [`satrs-minisim`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-minisim):
Mini-Simulator based on [nexosim](https://github.com/asynchronics/nexosim) which
simulates some physical devices for the `satrs-example` application device handlers.
* [`satrs-mib`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-mib):
Components to build a mission information base from the on-board software directly.
* [`satrs-stm32f3-disco-rtic`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/embedded-examples/stm32f3-disco-rtic):
Example of a simple example using low-level sat-rs components on a bare-metal system
with constrained resources. This example uses the [RTIC](https://github.com/rtic-rs/rtic)
framework on the STM32F3-Discovery device.
* [`satrs-stm32h-nucleo-rtic`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/embedded-examples/stm32h7-nucleo-rtic):
Example of a simple example using sat-rs components on a bare-metal system
with constrained resources. This example uses the [RTIC](https://github.com/rtic-rs/rtic)
framework on the STM32H743ZIT device.
Each project has its own `CHANGELOG.md`.
## Examples
All examples and their helper crates are located inside the
[`examples`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples) folder:
* [`example-std`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/example-std):
Example on-board software using various sat-rs components which can be run on a host computer
or on any system with a standard runtime like a Raspberry Pi.
* [`minisim`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/minisim):
Mini-Simulator based on [nexosim](https://github.com/asynchronics/nexosim) which
simulates some physical devices for the `example-std` application device handlers.
* [`client`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/client): Ground client to command the `example-std` application.
* [`types`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/types): Telecommand and telemetry definitions shared by the
`example-std` application and the `client`.
* [`stm32f3-disco-rtic`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/stm32f3-disco-rtic):
Simple example using low-level sat-rs components on a bare-metal system with constrained
resources. This example uses the [RTIC](https://github.com/rtic-rs/rtic) framework on the
STM32F3-Discovery device.
* [`stm32h7-nucleo-rtic`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/stm32h7-nucleo-rtic):
Simple example using sat-rs components on a bare-metal system with constrained resources.
This example uses the [RTIC](https://github.com/rtic-rs/rtic) framework on the NUCLEO-H753ZI
board.
* [`embedded-client`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/embedded-client) and
[`embedded-types`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/embedded-types): Client and shared telecommand and telemetry
definitions for the embedded examples.
The library crates and the `example-std` application have their own `CHANGELOG.md`.
# Related projects
+1 -1
View File
@@ -47,7 +47,7 @@ def main():
parser.add_argument(
"-p",
"--package",
choices=["satrs", "satrs-minisim", "satrs-example"],
choices=["satrs", "minisim", "example-std"],
default="satrs",
help="Choose project to generate coverage for",
)
@@ -9,14 +9,13 @@ log = "0.4"
fern = "0.7"
humantime = "2"
serde = { version = "1" }
serde_json = "1"
satrs = { path = "../../satrs" }
satrs-example = { path = ".." }
satrs-minisim = { path = "../minisim" }
example-std = { path = "../example-std" }
minisim-types = { path = "../minisim-types" }
types = { path = "../types" }
spacepackets = { version = "0.18", default-features = false }
bitbybit = "2"
arbitrary-int = "2"
ctrlc = { version = "3.5" }
postcard = { version = "1" }
postcard = { version = "1", features = ["alloc"] }
anyhow = "1"
@@ -1,8 +1,8 @@
use anyhow::{Context as _, bail};
use arbitrary_int::u11;
use clap::Parser as _;
use satrs_example::config::{OBSW_SERVER_ADDR, SERVER_PORT};
use satrs_minisim::{
use example_std::config::{OBSW_SERVER_ADDR, SERVER_PORT};
use minisim_types::{
SimCtrlReply, SimCtrlRequest, SimReply, SimRequest, SimRequestWithTime, acs::mgm,
udp::SIM_CTRL_PORT,
};
@@ -383,9 +383,9 @@ fn handle_mgm_command(
let request = types::ccsds::CcsdsTcPacketOwned::new_with_request(
SpacePacketHeader::new_from_apid(u11::new(Apid::Acs as u16)),
TcHeader::new(target_id, types::MessageType::Health),
types::acs::mgm::request::Request::Health(
types::HealthRequest::SetHealth(health.into()),
),
types::acs::mgm::request::Request::Health(types::HealthRequest::SetHealth(
health.into(),
)),
);
let sent_tc_id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(&request.sp_header);
log::info!(
@@ -621,10 +621,10 @@ fn inject_mgm_failure(target_id: types::ComponentId, fault: mgm::SpiFault) -> an
let mut reply_buf = [0u8; 4096];
let ping = SimRequestWithTime::new_with_epoch_time(SimCtrlRequest::Ping);
sim_socket.send_to(&serde_json::to_vec(&ping)?, sim_addr)?;
sim_socket.send_to(&postcard::to_allocvec(&ping)?, sim_addr)?;
match sim_socket.recv(&mut reply_buf) {
Ok(len) => {
let reply: SimReply = serde_json::from_slice(&reply_buf[..len])?;
let reply: SimReply = postcard::from_bytes(&reply_buf[..len])?;
if reply != SimReply::SimCtrl(SimCtrlReply::Pong) {
bail!("unexpected reply while checking minisim connectivity: {reply:?}");
}
@@ -649,7 +649,7 @@ fn inject_mgm_failure(target_id: types::ComponentId, fault: mgm::SpiFault) -> an
id,
request: mgm::Request::SetSpiFault(fault),
});
sim_socket.send_to(&serde_json::to_vec(&request)?, sim_addr)?;
sim_socket.send_to(&postcard::to_allocvec(&request)?, sim_addr)?;
log::info!("injected SPI fault {fault:?} into minisim {target_id:?}");
Ok(())
}
@@ -6,10 +6,10 @@ edition = "2024"
[dependencies]
clap = { version = "4", features = ["derive"] }
serialport = "4"
toml = "0.9"
toml = "1"
serde = { version = "1", features = ["derive"] }
spacepackets = { version = "0.18" }
embedded-types = { path = "../types" }
embedded-types = { path = "../embedded-types" }
tmtc-utils = { path = "../../tmtc-utils" }
postcard = { version = "1", features = ["alloc"] }
anyhow = "1"
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,8 +1,8 @@
[package]
name = "satrs-example"
name = "example-std"
version = "0.1.1"
edition = "2024"
default-run = "satrs-example"
default-run = "example-std"
repository = "https://egit.irs.uni-stuttgart.de/rust/sat-rs"
[dependencies]
@@ -21,15 +21,14 @@ derive-new = "0.7"
cfg-if = "1"
arbitrary-int = "2"
bitbybit = "2"
postcard = "1"
postcard = { version = "1", features = ["alloc"] }
ctrlc = "3"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
satrs = { path = "../satrs", features = ["test_util"] }
types = { path = "./types" }
satrs-minisim = { path = "./minisim" }
satrs-mib = { path = "../satrs-mib" }
satrs = { path = "../../satrs", features = ["test_util"] }
types = { path = "../types" }
minisim-types = { path = "../minisim-types" }
satrs-mib = { path = "../../satrs-mib" }
[features]
# default = ["heap_tmtc"]
File renamed without changes.
@@ -40,7 +40,7 @@ Use `cargo run -p client -- --help` to list all available commands.
## Adding the mini simulator application
This example application features a few device handlers. The
[`satrs-minisim`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-example/minisim)
[`minisim`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/minisim)
can be used to simulate the physical devices managed by these device handlers.
The example application will attempt communication with the mini simulator on UDP port 7303.
@@ -51,7 +51,7 @@ return constant values or behave like ideal devices.
In summary, you can use the following command command to run the mini-simulator first:
```sh
cargo run -p satrs-minisim
cargo run -p minisim
```
and then start the example using `cargo run -p satrs-example`.
and then start the example using `cargo run -p example-std`.
File renamed without changes.
@@ -1,10 +1,10 @@
use example_std::{HkHelperSingleSet, TimestampHelper, TmtcQueues};
use minisim_types::acs::mgm as sim_mgm;
use minisim_types::acs::mgm::{FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR};
use minisim_types::{SimReply, SimRequest, SimRequestWithTime};
use satrs::fdir::{FaultCounterStd, RecoveryEvent};
use satrs::health::HealthTableMapSync;
use satrs::spacepackets::CcsdsPacketIdAndPsc;
use satrs_example::{HkHelperSingleSet, TimestampHelper, TmtcQueues};
use satrs_minisim::acs::mgm as sim_mgm;
use satrs_minisim::acs::mgm::{FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR};
use satrs_minisim::{SimReply, SimRequest, SimRequestWithTime};
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::time::Duration;
@@ -567,9 +567,9 @@ mod tests {
};
use arbitrary_int::u11;
use minisim_types::acs::mgm as sim_mgm;
use satrs::health::{HealthState, HealthTableProvider};
use satrs::spacepackets::SpacePacketHeader;
use satrs_minisim::acs::mgm as sim_mgm;
use types::{
Apid, ComponentId, TcHeader,
acs::mgm::request::HkRequest,
@@ -1,7 +1,7 @@
use std::{sync::mpsc, time::Duration};
use example_std::{ModeHelper, TmtcQueues};
use satrs::spacepackets::CcsdsPacketIdAndPsc;
use satrs_example::{ModeHelper, TmtcQueues};
use types::{
ComponentId, DeviceMode,
acs::mgm_assembly::{Mode, request, response},
@@ -2,12 +2,12 @@ use std::collections::VecDeque;
use std::sync::mpsc;
use std::time::{Duration, Instant};
use example_std::{HkHelperSingleSet, TmtcQueues};
use minisim_types::acs::mgt as sim_mgt;
use minisim_types::{SimReply, SimRequest, SimRequestWithTime};
use satrs::fdir::{FaultCounterStd, RecoveryEvent};
use satrs::health::HealthTableMapSync;
use satrs::spacepackets::CcsdsPacketIdAndPsc;
use satrs_example::{HkHelperSingleSet, TmtcQueues};
use satrs_minisim::acs::mgt as sim_mgt;
use satrs_minisim::{SimReply, SimRequest, SimRequestWithTime};
use types::acs::mgt::{
self, HkSet,
request::{ModeRequest, Request},
File renamed without changes.
@@ -4,6 +4,7 @@ use std::{
time::Duration,
};
use example_std::{ModeHelper, TmtcQueues};
use satrs::{
mode_tree::{
ModeStoreProvider, ModeStoreVec, SequenceModeTables, SequenceTableEntry,
@@ -15,7 +16,6 @@ use satrs::{
SubsystemCommandingHelper, SubsystemHelperResult,
},
};
use satrs_example::{ModeHelper, TmtcQueues};
use types::{
ComponentId,
acs::subsystem::{Mode, response},
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -68,7 +68,7 @@ pub enum ModeTransitionEvent<Mode> {
/// a parent) are not this helper's concern: [`Self::handle_mode_transition`] just reports when a
/// transition finishes (or fails) and leaves what to do about it to the caller.
pub struct SwitchAndModeHelper<Mode: PowerSwitchedMode> {
mode_helper: satrs_example::ModeHelper<Mode, SwitchTransitionState>,
mode_helper: example_std::ModeHelper<Mode, SwitchTransitionState>,
switch_helper: PowerSwitchHelper,
switch_id: SwitchId,
power_cycle_state: PowerCycleState<Mode>,
@@ -83,7 +83,7 @@ impl<Mode: PowerSwitchedMode> SwitchAndModeHelper<Mode> {
switch_id: SwitchId,
) -> Self {
Self {
mode_helper: satrs_example::ModeHelper::new(init_mode, timeout),
mode_helper: example_std::ModeHelper::new(init_mode, timeout),
switch_helper,
switch_id,
power_cycle_state: PowerCycleState::Idle,
File renamed without changes.
@@ -5,13 +5,13 @@ use std::{
};
use derive_new::new;
use num_enum::{IntoPrimitive, TryFromPrimitive};
use satrs::spacepackets::CcsdsPacketIdAndPsc;
use satrs_example::TimestampHelper;
use satrs_minisim::{
use example_std::TimestampHelper;
use minisim_types::{
SimReply, SimRequestWithTime,
eps::{PcduReply, PcduRequest},
};
use num_enum::{IntoPrimitive, TryFromPrimitive};
use satrs::spacepackets::CcsdsPacketIdAndPsc;
use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator as _;
use types::{
@@ -134,7 +134,7 @@ impl SerialInterface for SerialInterfaceToSim {
type Error = ();
fn send(&self, data: &[u8]) -> Result<(), Self::Error> {
let request: PcduRequest = serde_json::from_slice(data).expect("expected a PCDU request");
let request: PcduRequest = postcard::from_bytes(data).expect("expected a PCDU request");
self.sim_request_tx
.send(SimRequestWithTime::new_with_epoch_time(request))
.expect("failed to send request to simulation");
@@ -148,8 +148,8 @@ impl SerialInterface for SerialInterfaceToSim {
loop {
match self.sim_reply_rx.try_recv() {
Ok(reply) => {
let reply = serde_json::to_string(&reply).unwrap();
f(reply.as_bytes());
let reply = postcard::to_allocvec(&reply).unwrap();
f(&reply);
}
Err(e) => match e {
mpsc::TryRecvError::Empty => break,
@@ -175,18 +175,13 @@ impl SerialInterface for SerialInterfaceDummy {
type Error = ();
fn send(&self, data: &[u8]) -> Result<(), Self::Error> {
let pcdu_req: PcduRequest = serde_json::from_slice(data).unwrap();
let pcdu_req: PcduRequest = postcard::from_bytes(data).unwrap();
let switch_map_mut = &mut self.switch_map.borrow_mut().0;
match pcdu_req {
PcduRequest::SwitchDevice { switch, state } => {
match switch_map_mut.entry(switch) {
std::collections::hash_map::Entry::Occupied(mut val) => {
*val.get_mut() = state;
}
std::collections::hash_map::Entry::Vacant(vacant) => {
vacant.insert(state);
}
};
switch_map_mut
.insert(switch, state)
.expect("switch map capacity exceeded");
}
PcduRequest::RequestSwitchInfo => {
let mut reply_deque_mut = self.reply_deque.borrow_mut();
@@ -206,8 +201,8 @@ impl SerialInterface for SerialInterfaceDummy {
return Ok(());
}
loop {
let reply = self.get_next_reply_as_string();
f(reply.as_bytes());
let reply = self.next_reply_serialized();
f(&reply);
if self.reply_queue_empty() {
break;
}
@@ -217,10 +212,10 @@ impl SerialInterface for SerialInterfaceDummy {
}
impl SerialInterfaceDummy {
fn get_next_reply_as_string(&self) -> String {
fn next_reply_serialized(&self) -> Vec<u8> {
let mut reply_deque_mut = self.reply_deque.borrow_mut();
let next_reply = reply_deque_mut.pop_front().unwrap();
serde_json::to_string(&next_reply).unwrap()
postcard::to_allocvec(&next_reply).unwrap()
}
fn reply_queue_empty(&self) -> bool {
@@ -437,8 +432,8 @@ impl<ComInterface: SerialInterface> PcduHandler<ComInterface> {
pub fn handle_periodic_commands(&self) {
let pcdu_req = PcduRequest::RequestSwitchInfo;
let pcdu_req_ser = serde_json::to_string(&pcdu_req).unwrap();
if let Err(_e) = self.com_interface.send(pcdu_req_ser.as_bytes()) {
let pcdu_req_ser = postcard::to_allocvec(&pcdu_req).unwrap();
if let Err(_e) = self.com_interface.send(&pcdu_req_ser) {
log::warn!("polling PCDU switch info failed");
if let Err(e) = self.event_tx.send(pcdu::Event::SerialCommError) {
log::warn!("failed to send comm error event: {}", e);
@@ -484,9 +479,9 @@ impl<ComInterface: SerialInterface> PcduHandler<ComInterface> {
switch: switch_id,
state,
};
let pcdu_req_ser = serde_json::to_string(&pcdu_req).unwrap();
let pcdu_req_ser = postcard::to_allocvec(&pcdu_req).unwrap();
self.com_interface
.send(pcdu_req_ser.as_bytes())
.send(&pcdu_req_ser)
.expect("failed to send switch request to PCDU");
}
@@ -509,7 +504,7 @@ impl<ComInterface: SerialInterface> PcduHandler<ComInterface> {
pub fn poll_and_handle_replies(&mut self) {
if let Err(e) = self.com_interface.try_recv_replies(|reply| {
let sim_reply: SimReply = serde_json::from_slice(reply).expect("invalid reply format");
let sim_reply: SimReply = postcard::from_bytes(reply).expect("invalid reply format");
let SimReply::Pcdu(pcdu_reply) = sim_reply else {
log::warn!("unexpected PCDU SIM reply: {sim_reply:?}");
return;
@@ -559,7 +554,7 @@ mod tests {
pub struct SerialInterfaceTest {
pub inner: SerialInterfaceDummy,
pub send_queue: RefCell<VecDeque<Vec<u8>>>,
pub reply_queue: RefCell<VecDeque<String>>,
pub reply_queue: RefCell<VecDeque<Vec<u8>>>,
/// Makes the next `send` call fail, to exercise comm-error handling.
pub fail_next_send: RefCell<bool>,
}
@@ -584,9 +579,9 @@ mod tests {
return Ok(());
}
loop {
let reply = self.inner.get_next_reply_as_string();
let reply = self.inner.next_reply_serialized();
self.reply_queue.borrow_mut().push_back(reply.clone());
f(reply.as_bytes());
f(&reply);
if self.inner.reply_queue_empty() {
break;
}
@@ -642,7 +637,7 @@ mod tests {
assert_eq!(send_queue_mut.len(), expected_queue_len);
let packet_sent = send_queue_mut.pop_front().unwrap();
drop(send_queue_mut);
let pcdu_req: PcduRequest = serde_json::from_slice(&packet_sent).unwrap();
let pcdu_req: PcduRequest = postcard::from_bytes(&packet_sent).unwrap();
assert_eq!(pcdu_req, PcduRequest::RequestSwitchInfo);
}
@@ -657,7 +652,7 @@ mod tests {
assert_eq!(send_queue_mut.len(), expected_queue_len);
let packet_sent = send_queue_mut.pop_front().unwrap();
drop(send_queue_mut);
let pcdu_req: PcduRequest = serde_json::from_slice(&packet_sent).unwrap();
let pcdu_req: PcduRequest = postcard::from_bytes(&packet_sent).unwrap();
assert_eq!(
pcdu_req,
PcduRequest::SwitchDevice {
@@ -676,7 +671,7 @@ mod tests {
let mut reply_received_mut = self.handler.com_interface.reply_queue.borrow_mut();
assert_eq!(reply_received_mut.len(), expected_queue_len);
let reply_received = reply_received_mut.pop_front().unwrap();
let sim_reply: SimReply = serde_json::from_str(&reply_received).unwrap();
let sim_reply: SimReply = postcard::from_bytes(&reply_received).unwrap();
assert_eq!(
sim_reply,
SimReply::Pcdu(PcduReply::SwitchInfo(expected_map))
File renamed without changes.
File renamed without changes.
@@ -5,9 +5,9 @@ use std::{
time::Duration,
};
use minisim_types::{ComponentId, SimReply, SimRequestWithTime, udp::SIM_CTRL_PORT};
use minisim_types::{SimCtrlReply, SimCtrlRequest};
use satrs::HandlingStatus;
use satrs_minisim::{ComponentId, SimReply, SimRequestWithTime, udp::SIM_CTRL_PORT};
use satrs_minisim::{SimCtrlReply, SimCtrlRequest};
struct SimReplyMap(pub HashMap<ComponentId, mpsc::Sender<SimReply>>);
@@ -35,10 +35,10 @@ pub enum SimClientCreationError {
Io(#[from] std::io::Error),
#[error("timeout when trying to connect to sim UDP server")]
Timeout,
#[error("invalid ping reply when trying connection to UDP sim server")]
InvalidReplyJsonError(#[from] serde_json::Error),
#[error("invalid ping reply when trying connection to UDP sim server: {0}")]
InvalidReply(#[from] postcard::Error),
#[error("invalid sim reply, not pong reply as expected: {0:?}")]
ReplyIsNotPong(SimReply),
ReplyIsNotPong(Box<SimReply>),
}
pub struct SimClientUdp {
@@ -74,14 +74,14 @@ impl SimClientUdp {
reply_buf: &mut [u8],
) -> Result<(), SimClientCreationError> {
let sim_req = SimRequestWithTime::new_with_epoch_time(SimCtrlRequest::Ping);
let sim_req_json = serde_json::to_string(&sim_req).expect("failed to serialize SimRequest");
udp_client.send_to(sim_req_json.as_bytes(), simulator_addr)?;
let sim_req_raw = postcard::to_allocvec(&sim_req).expect("failed to serialize SimRequest");
udp_client.send_to(&sim_req_raw, simulator_addr)?;
match udp_client.recv(reply_buf) {
Ok(reply_len) => {
let sim_reply: SimReply = serde_json::from_slice(&reply_buf[0..reply_len])?;
let sim_reply: SimReply = postcard::from_bytes(&reply_buf[0..reply_len])?;
match sim_reply {
SimReply::SimCtrl(SimCtrlReply::Pong) => Ok(()),
_ => Err(SimClientCreationError::ReplyIsNotPong(sim_reply)),
_ => Err(SimClientCreationError::ReplyIsNotPong(Box::new(sim_reply))),
}
}
Err(e) => {
@@ -102,12 +102,9 @@ impl SimClientUdp {
loop {
match self.sim_request_rx.try_recv() {
Ok(request) => {
let request_json =
serde_json::to_string(&request).expect("failed to serialize SimRequest");
if let Err(e) = self
.udp_client
.send_to(request_json.as_bytes(), self.simulator_addr)
{
let request_raw =
postcard::to_allocvec(&request).expect("failed to serialize SimRequest");
if let Err(e) = self.udp_client.send_to(&request_raw, self.simulator_addr) {
log::error!("error sending data to UDP SIM server: {e}");
break;
} else {
@@ -129,8 +126,8 @@ impl SimClientUdp {
match self.udp_client.recv(&mut self.reply_buf) {
Ok(recvd_bytes) => {
no_data_from_udp_server_received = false;
let sim_reply_result: serde_json::Result<SimReply> =
serde_json::from_slice(&self.reply_buf[0..recvd_bytes]);
let sim_reply_result: postcard::Result<SimReply> =
postcard::from_bytes(&self.reply_buf[0..recvd_bytes]);
match sim_reply_result {
Ok(sim_reply) => {
if let Some(sender) = self.reply_map.0.get(&sim_reply.component()) {
@@ -176,7 +173,6 @@ impl SimClientUdp {
#[cfg(test)]
pub mod tests {
use std::{
collections::HashMap,
net::{SocketAddr, UdpSocket},
sync::{
Arc,
@@ -186,11 +182,13 @@ pub mod tests {
time::Duration,
};
use satrs_minisim::{
use minisim_types::{
ComponentId, SimCtrlReply, SimCtrlRequest, SimReply, SimRequest, SimRequestWithTime,
eps::{PcduReply, PcduRequest},
};
use types::pcdu::SwitchMapBinary;
use super::SimClientUdp;
struct UdpSimTestServer {
@@ -233,10 +231,10 @@ pub mod tests {
loop {
match self.reply_rx.try_recv() {
Ok(sim_reply) => {
let sim_reply_json = serde_json::to_string(&sim_reply)
let sim_reply_raw = postcard::to_allocvec(&sim_reply)
.expect("failed to serialize SimReply");
self.udp_server
.send_to(sim_reply_json.as_bytes(), last_sender)
.send_to(&sim_reply_raw, last_sender)
.expect("failed to send reply to client from UDP server");
no_sim_replies_handled = false;
}
@@ -254,17 +252,17 @@ pub mod tests {
match self.udp_server.recv_from(&mut self.recv_buf) {
Ok((read_bytes, from)) => {
let sim_request: SimRequestWithTime =
serde_json::from_slice(&self.recv_buf[0..read_bytes])
postcard::from_bytes(&self.recv_buf[0..read_bytes])
.expect("failed to deserialize SimRequest");
// For a ping, we perform the reply handling here directly
if sim_request.request == SimRequest::SimCtrl(SimCtrlRequest::Ping) {
no_data_received = false;
self.last_sender = Some(from);
let sim_reply = SimReply::from(SimCtrlReply::Pong);
let sim_reply_json = serde_json::to_string(&sim_reply)
let sim_reply_raw = postcard::to_allocvec(&sim_reply)
.expect("failed to serialize SimReply");
self.udp_server
.send_to(sim_reply_json.as_bytes(), from)
.send_to(&sim_reply_raw, from)
.expect("failed to send reply to client from UDP server");
}
// Forward each SIM request for testing purposes.
@@ -369,7 +367,7 @@ pub mod tests {
);
// We inject the reply ourselves.
let pcdu_reply = PcduReply::SwitchInfo(HashMap::new());
let pcdu_reply = PcduReply::SwitchInfo(SwitchMapBinary::default());
server_sim_reply_tx
.send(SimReply::from(pcdu_reply.clone()))
.expect("sending PCDU reply failed");
File renamed without changes.
@@ -112,6 +112,7 @@ mod tests {
use arbitrary_int::traits::Integer as _;
use arbitrary_int::u14;
use example_std::config::OBSW_SERVER_ADDR;
use satrs::spacepackets::ecss::{CreatorConfig, MessageTypeId};
use satrs::{
ComponentId,
@@ -120,7 +121,6 @@ mod tests {
ecss::{WritablePusPacket, tc::PusTcCreator},
},
};
use satrs_example::config::OBSW_SERVER_ADDR;
use types::Apid;
use crate::tmtc::sender::MockSender;
@@ -15,7 +15,7 @@ use satrs::{
},
spacepackets::time::cds::CdsTime,
};
use satrs_example::ids::generic_pus::PUS_EVENT_MANAGEMENT;
use example_std::ids::generic_pus::PUS_EVENT_MANAGEMENT;
use crate::update_time;
File renamed without changes.
@@ -16,9 +16,9 @@ use satrs::pus::{
use satrs::request::{GenericMessage, UniqueApidTargetId};
use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::{EcssEnumU16, PusPacket, PusServiceId};
use satrs_example::config::tmtc_err;
use satrs_example::ids;
use satrs_example::ids::generic_pus::PUS_ACTION;
use example_std::config::tmtc_err;
use example_std::ids;
use example_std::ids::generic_pus::PUS_ACTION;
use std::sync::mpsc;
use std::time::Duration;
@@ -10,7 +10,7 @@ use satrs::pus::{
PartialPusHandlingError, PusServiceHelper,
};
use satrs::spacepackets::ecss::PusServiceId;
use satrs_example::ids::generic_pus::PUS_EVENT_MANAGEMENT;
use example_std::ids::generic_pus::PUS_EVENT_MANAGEMENT;
use super::{DirectPusService, HandlingStatus};
@@ -13,8 +13,8 @@ use satrs::request::{GenericMessage, UniqueApidTargetId};
use satrs::res_code::ResultU16;
use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::{hk, PusPacket, PusServiceId};
use satrs_example::config::{hk_err, tmtc_err};
use satrs_example::ids::generic_pus::PUS_HK;
use example_std::config::{hk_err, tmtc_err};
use example_std::ids::generic_pus::PUS_HK;
use std::sync::mpsc;
use std::time::Duration;
@@ -321,7 +321,7 @@ mod tests {
SpHeader,
},
};
use satrs_example::config::tmtc_err;
use example_std::config::tmtc_err;
use crate::pus::{
hk::HkReplyVariant,
@@ -18,9 +18,9 @@ use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::{PusPacket, PusServiceId};
use satrs::tmtc::{PacketAsVec, PacketInPool};
use satrs::ComponentId;
use satrs_example::config::{tmtc_err, CustomPusServiceId};
use satrs_example::ids::generic_pus::PUS_ROUTING;
use satrs_example::TimestampHelper;
use example_std::config::{tmtc_err, CustomPusServiceId};
use example_std::ids::generic_pus::PUS_ROUTING;
use example_std::TimestampHelper;
use std::fmt::Debug;
use std::sync::mpsc;
@@ -3,7 +3,7 @@ use arbitrary_int::u14;
use derive_new::new;
use satrs::mode_tree::{ModeNode, ModeParent};
use satrs::spacepackets::ecss::{CreatorConfig, MessageTypeId};
use satrs_example::ids;
use example_std::ids;
use std::sync::mpsc;
use std::time::Duration;
@@ -37,7 +37,7 @@ use satrs::{
},
ComponentId,
};
use satrs_example::config::{mode_err, tmtc_err, CustomPusServiceId};
use example_std::config::{mode_err, tmtc_err, CustomPusServiceId};
use super::{
create_verification_reporter, generic_pus_request_timeout_handler, HandlingStatus,
@@ -316,7 +316,7 @@ mod tests {
SpHeader,
},
};
use satrs_example::config::tmtc_err;
use example_std::config::tmtc_err;
use crate::pus::{
mode::ModeReplyHandler,
@@ -15,7 +15,7 @@ use satrs::pus::{
use satrs::spacepackets::ecss::PusServiceId;
use satrs::tmtc::{PacketAsVec, PacketInPool, PacketSenderWithSharedPool};
use satrs::ComponentId;
use satrs_example::ids::sched::PUS_SCHED;
use example_std::ids::sched::PUS_SCHED;
use super::{DirectPusService, HandlingStatus};
@@ -11,8 +11,8 @@ use satrs::pus::{
};
use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::{PusPacket, PusServiceId};
use satrs_example::config::{tmtc_err, TEST_EVENT};
use satrs_example::ids::generic_pus::PUS_TEST;
use example_std::config::{tmtc_err, TEST_EVENT};
use example_std::ids::generic_pus::PUS_TEST;
use std::sync::mpsc;
use super::{DirectPusService, HandlingStatus};
@@ -14,7 +14,7 @@ use satrs::request::{GenericMessage, MessageMetadata, UniqueApidTargetId};
use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::PusPacket;
use satrs::ComponentId;
use satrs_example::config::tmtc_err;
use example_std::config::tmtc_err;
/*
#[derive(Clone, Debug)]
File renamed without changes.
File renamed without changes.
@@ -13,6 +13,13 @@ use eps::{
PowerSwitchHelper,
pcdu::{PcduHandler, SerialInterfaceDummy, SerialInterfaceToSim, SerialSimInterfaceWrapper},
};
use example_std::{
TmtcQueues,
config::{
OBSW_SERVER_ADDR, PACKET_ID_VALIDATOR, SERVER_PORT,
tasks::{FREQ_MS_AOCS, FREQ_MS_CONTROLLER, FREQ_MS_UDP_TMTC, SIM_CLIENT_IDLE_DELAY_MS},
},
};
use interface::{
sim_client_udp::create_sim_client,
tcp::{SyncTcpTmSource, TcpTask},
@@ -25,13 +32,6 @@ use satrs::{
hal::std::{tcp_server::ServerConfig, udp_server::UdpTcServer},
spacepackets::time::cds::CdsTime,
};
use satrs_example::{
TmtcQueues,
config::{
OBSW_SERVER_ADDR, PACKET_ID_VALIDATOR, SERVER_PORT,
tasks::{FREQ_MS_AOCS, FREQ_MS_CONTROLLER, FREQ_MS_UDP_TMTC, SIM_CLIENT_IDLE_DELAY_MS},
},
};
use tmtc::sender::TmTcSender;
use tmtc::{tc_source::TcSourceTask, tm_sink::TmSink};
use types::{ComponentId, DeviceMode};
@@ -182,8 +182,8 @@ fn main() {
let (mgm_0_spi_interface, mgm_1_spi_interface) = if let Some(sim_client) =
opt_sim_client.as_mut()
{
sim_client.add_reply_recipient(satrs_minisim::ComponentId::Mgm0Lis3Mdl, mgm_0_sim_reply_tx);
sim_client.add_reply_recipient(satrs_minisim::ComponentId::Mgm1Lis3Mdl, mgm_1_sim_reply_tx);
sim_client.add_reply_recipient(minisim_types::ComponentId::Mgm0Lis3Mdl, mgm_0_sim_reply_tx);
sim_client.add_reply_recipient(minisim_types::ComponentId::Mgm1Lis3Mdl, mgm_1_sim_reply_tx);
(
mgm::SpiCommunication::Sim(mgm::SpiSimInterface {
id: mgm::MgmId::_0,
@@ -259,7 +259,7 @@ fn main() {
});
let mgt_com = if let Some(sim_client) = opt_sim_client.as_mut() {
sim_client.add_reply_recipient(satrs_minisim::ComponentId::Mgt, mgt_sim_reply_tx);
sim_client.add_reply_recipient(minisim_types::ComponentId::Mgt, mgt_sim_reply_tx);
mgt::MgtCommunication::Sim(mgt::SimInterface {
sim_request_tx: sim_request_tx.clone(),
sim_reply_rx: mgt_sim_reply_rx,
@@ -301,7 +301,7 @@ fn main() {
);
let pcdu_serial_interface = if let Some(sim_client) = opt_sim_client.as_mut() {
sim_client.add_reply_recipient(satrs_minisim::ComponentId::Pcdu, pcdu_sim_reply_tx);
sim_client.add_reply_recipient(minisim_types::ComponentId::Pcdu, pcdu_sim_reply_tx);
SerialSimInterfaceWrapper::Sim(SerialInterfaceToSim::new(
sim_request_tx.clone(),
pcdu_sim_reply_rx,
File renamed without changes.
File renamed without changes.
File renamed without changes.
+14
View File
@@ -0,0 +1,14 @@
[package]
name = "minisim-types"
version = "0.1.0"
edition = "2024"
[dependencies]
num_enum = { version = "0.7", default-features = false }
serde = { version = "1", default-features = false, features = ["derive"] }
tai-time = { version = "1", default-features = false, features = ["serde"] }
thiserror = { version = "2", default-features = false }
types = { path = "../types" }
[dev-dependencies]
postcard = { version = "1", features = ["alloc"] }
@@ -1,5 +1,9 @@
use nexosim::time::MonotonicTime;
#![no_std]
extern crate alloc;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use tai_time::MonotonicTime;
use crate::{
acs::{mgm, mgt},
@@ -231,43 +235,6 @@ pub mod acs {
z: value,
}
}
pub fn from_microtesla(values: SensorValuesMicroTesla) -> Self {
let to_raw = |microtesla: f32| {
(microtesla / (GAUSS_TO_MICROTESLA_FACTOR as f32 * FIELD_LSB_PER_GAUSS_4_SENS))
.round() as i16
};
Self {
x: to_raw(values.x),
y: to_raw(values.y),
z: to_raw(values.z),
}
}
}
impl Reply {
pub fn new(
switch_state: SwitchStateBinary,
sensor_values: SensorValuesMicroTesla,
fault_mode: SpiFaultMode,
) -> Self {
// An injected fault always wins. A switched off device reads back like an
// undriven bus.
let raw = match (fault_mode, switch_state) {
(SpiFaultMode::AllZeros, _) => RawValues::splat(ALL_ZEROS_SENSOR_VAL),
(SpiFaultMode::AllOnes, _) | (SpiFaultMode::None, SwitchStateBinary::Off) => {
RawValues::splat(ALL_ONES_SENSOR_VAL)
}
(SpiFaultMode::None, SwitchStateBinary::On) => {
RawValues::from_microtesla(sensor_values)
}
};
Self {
switch_state,
sensor_values,
raw,
}
}
}
}
@@ -281,7 +248,8 @@ pub mod acs {
/// framing and error detection, for example COBS encoding and a CRC. Here, the transport
/// always delivers complete and intact frames.
pub mod mgt {
use std::time::Duration;
use alloc::{vec, vec::Vec};
use core::time::Duration;
use num_enum::{IntoPrimitive, TryFromPrimitive};
pub use types::acs::mgt::Dipole;
@@ -431,7 +399,9 @@ pub mod acs {
let frame = request.to_frame();
assert_eq!(
frame,
[0x02, 0xff, 0xfe, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04]
[
0x02, 0xff, 0xfe, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04
]
);
assert_eq!(Request::from_frame(&frame), Ok(request));
}
@@ -480,14 +450,14 @@ pub mod udp {
}
#[cfg(test)]
pub mod tests {
mod tests {
use super::*;
#[test]
fn test_request_serde_roundtrip() {
let sim_request = SimRequestWithTime::new_with_epoch_time(SimCtrlRequest::Ping);
let json = serde_json::to_string(&sim_request).unwrap();
let deserialized: SimRequestWithTime = serde_json::from_str(&json).unwrap();
let bytes = postcard::to_allocvec(&sim_request).unwrap();
let deserialized: SimRequestWithTime = postcard::from_bytes(&bytes).unwrap();
assert_eq!(deserialized, sim_request);
}
@@ -495,8 +465,8 @@ pub mod tests {
fn test_reply_serde_roundtrip() {
let sim_reply = SimReply::from(SimCtrlReply::Pong);
assert_eq!(sim_reply.component(), ComponentId::SimCtrl);
let json = serde_json::to_string(&sim_reply).unwrap();
let deserialized: SimReply = serde_json::from_str(&json).unwrap();
let bytes = postcard::to_allocvec(&sim_reply).unwrap();
let deserialized: SimReply = postcard::from_bytes(&bytes).unwrap();
assert_eq!(deserialized, sim_reply);
}
}
@@ -1,24 +1,24 @@
[package]
name = "satrs-minisim"
name = "minisim"
version = "0.1.0"
edition = "2021"
edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
postcard = { version = "1", features = ["alloc"] }
log = "0.4"
thiserror = "2"
fern = "0.7"
strum = { version = "0.28", features = ["derive"] }
num_enum = "0.7"
humantime = "2"
tai-time = { version = "0.3", features = ["serde"] }
nexosim = "1"
satrs = { path = "../../satrs" }
types = { path = "../types" }
minisim-types = { path = "../minisim-types" }
[dev-dependencies]
delegate = "0.13"
@@ -5,7 +5,7 @@ This crate contains a mini-simulator based on the open-source discrete-event sim
[nexosim](https://github.com/asynchronics/nexosim).
Right now, this crate is primarily used together with the
[`satrs-example` application](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-example)
[`example-std` application](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/examples/example-std)
to simulate the devices connected to the example application.
You can simply run this application using
@@ -17,7 +17,7 @@ cargo run
or
```sh
cargo run -p satrs-minisim
cargo run -p minisim
```
in the workspace. The mini simulator uses the UDP port 7303 to exchange simulation requests and
@@ -1,10 +1,10 @@
use std::f32::consts::PI;
use minisim_types::{SimReply, acs::mgm};
use nexosim::{
model::{Context, Model},
ports::Output,
};
use satrs_minisim::{acs::mgm, SimReply};
use serde::{Deserialize, Serialize};
use types::pcdu::SwitchStateBinary;
@@ -59,7 +59,7 @@ impl MgmModel {
pub async fn send_sensor_values(&mut self, _: (), cx: &Context<Self>) {
let reply = SimReply::Mgm {
id: self.id,
reply: mgm::Reply::new(
reply: create_reply(
self.switch_state,
self.calculate_current_mgm_tuple(current_millis(cx.time())),
self.spi_fault.mode,
@@ -98,11 +98,46 @@ impl MgmModel {
}
}
/// Builds the reply of the simulated LIS3MDL, including the raw register values.
fn create_reply(
switch_state: SwitchStateBinary,
sensor_values: mgm::SensorValuesMicroTesla,
fault_mode: mgm::SpiFaultMode,
) -> mgm::Reply {
// An injected fault always wins. A switched off device reads back like an undriven bus.
let raw = match (fault_mode, switch_state) {
(mgm::SpiFaultMode::AllZeros, _) => mgm::RawValues::splat(mgm::ALL_ZEROS_SENSOR_VAL),
(mgm::SpiFaultMode::AllOnes, _) | (mgm::SpiFaultMode::None, SwitchStateBinary::Off) => {
mgm::RawValues::splat(mgm::ALL_ONES_SENSOR_VAL)
}
(mgm::SpiFaultMode::None, SwitchStateBinary::On) => {
raw_values_from_microtesla(sensor_values)
}
};
mgm::Reply {
switch_state,
sensor_values,
raw,
}
}
fn raw_values_from_microtesla(values: mgm::SensorValuesMicroTesla) -> mgm::RawValues {
let to_raw = |microtesla: f32| {
(microtesla / (mgm::GAUSS_TO_MICROTESLA_FACTOR as f32 * mgm::FIELD_LSB_PER_GAUSS_4_SENS))
.round() as i16
};
mgm::RawValues {
x: to_raw(values.x),
y: to_raw(values.y),
z: to_raw(values.z),
}
}
#[cfg(test)]
mod tests {
use std::time::Duration;
use satrs_minisim::{acs::mgm, SimReply, SimRequest};
use minisim_types::{SimReply, SimRequest, acs::mgm};
use types::pcdu::{SwitchId, SwitchStateBinary};
use crate::{
@@ -1,10 +1,10 @@
use nexosim::{
model::{schedulable, Context, Model},
ports::Output,
};
use satrs_minisim::{
acs::{mgm, mgt},
use minisim_types::{
SimReply,
acs::{mgm, mgt},
};
use nexosim::{
model::{Context, Model, schedulable},
ports::Output,
};
use serde::{Deserialize, Serialize};
use std::time::Duration;
@@ -116,10 +116,10 @@ impl MgtModel {
mod tests {
use std::time::Duration;
use satrs_minisim::{
use minisim_types::{
SimReply, SimRequest, SimRequestWithTime,
acs::{mgm, mgt},
eps::PcduRequest,
SimReply, SimRequest, SimRequestWithTime,
};
use types::pcdu::{SwitchId, SwitchStateBinary};
@@ -215,9 +215,11 @@ mod tests {
fn test_invalid_frame_is_dropped() {
let mut sim_testbench = SimTestbench::new();
switch_device_on(&mut sim_testbench, SwitchId::Mgt);
assert!(sim_testbench
.request_reply(SimRequest::Mgt(vec![0x01, 0x00]))
.is_none());
assert!(
sim_testbench
.request_reply(SimRequest::Mgt(vec![0x01, 0x00]))
.is_none()
);
}
/// Processes the request without stepping, so scheduled events like the torque clearing do
File renamed without changes.
@@ -3,15 +3,15 @@ use std::{
time::{Duration, SystemTime},
};
use nexosim::{
ports::{event_queue, EventQueueReader, EventSinkReader, EventSource, SinkState},
simulation::{EventId, ExecutionError, Mailbox, SimInit, Simulation},
time::{Clock, Deadline, MonotonicTime, SystemClock},
};
use satrs_minisim::{
use minisim_types::{
SimCtrlReply, SimCtrlRequest, SimReply, SimRequest, SimRequestWithTime,
acs::{mgm, mgt},
eps::PcduRequest,
SimCtrlReply, SimCtrlRequest, SimReply, SimRequest, SimRequestWithTime,
};
use nexosim::{
ports::{EventQueueReader, EventSinkReader, EventSource, SinkState, event_queue},
simulation::{EventId, ExecutionError, Mailbox, SimInit, Simulation},
time::{Clock, Deadline, MonotonicTime, SystemClock},
};
use types::pcdu::{SwitchId, SwitchStateBinary};
@@ -1,10 +1,10 @@
use std::time::Duration;
use minisim_types::{SimReply, eps::PcduReply};
use nexosim::{
model::{schedulable, Context, Model},
model::{Context, Model, schedulable},
ports::Output,
};
use satrs_minisim::{eps::PcduReply, SimReply};
use serde::{Deserialize, Serialize};
use types::pcdu::{SwitchId, SwitchMapBinary, SwitchMapBinaryWrapper, SwitchStateBinary};
@@ -76,7 +76,7 @@ pub(crate) mod tests {
use super::*;
use std::time::Duration;
use satrs_minisim::{eps::PcduRequest, SimRequestWithTime};
use minisim_types::{SimRequestWithTime, eps::PcduRequest};
use types::pcdu::SwitchMapBinary;
use crate::test_helpers::SimTestbench;
@@ -1,6 +1,6 @@
use controller::{SimController, ThreadingModel};
use minisim_types::udp::SIM_CTRL_PORT;
use nexosim::time::MonotonicTime;
use satrs_minisim::udp::SIM_CTRL_PORT;
use std::sync::mpsc;
use std::thread;
use udp::SimUdpServer;
@@ -1,11 +1,11 @@
use delegate::delegate;
use std::sync::mpsc;
use minisim_types::{SimReply, SimRequest, SimRequestWithTime};
use nexosim::{
simulation::ExecutionError,
time::{Deadline, MonotonicTime},
};
use satrs_minisim::{SimReply, SimRequest, SimRequestWithTime};
use crate::controller::{SimController, ThreadingModel};
File renamed without changes.
@@ -2,11 +2,11 @@ use std::{
collections::VecDeque,
io::ErrorKind,
net::{SocketAddr, UdpSocket},
sync::{atomic::AtomicBool, mpsc, Arc},
sync::{Arc, atomic::AtomicBool, mpsc},
time::Duration,
};
use satrs_minisim::{SimReply, SimRequestWithTime};
use minisim_types::{SimReply, SimRequestWithTime};
// A UDP server which handles all TC received by a client application.
pub struct SimUdpServer {
@@ -53,10 +53,10 @@ impl SimUdpServer {
pub fn run(&mut self) {
loop {
if let Some(stop_signal) = &self.stop_signal {
if stop_signal.load(std::sync::atomic::Ordering::Relaxed) {
break;
}
if let Some(stop_signal) = &self.stop_signal
&& stop_signal.load(std::sync::atomic::Ordering::Relaxed)
{
break;
}
let processed_requests = self.process_requests();
let processed_replies = self.process_replies();
@@ -89,7 +89,7 @@ impl SimUdpServer {
self.sender_addr = Some(src);
let sim_req = serde_json::from_slice::<SimRequestWithTime>(&self.req_buf[..bytes_read]);
let sim_req = postcard::from_bytes::<SimRequestWithTime>(&self.req_buf[..bytes_read]);
if let Err(e) = sim_req {
log::warn!("received UDP request with invalid format: {}", e);
return processed_requests;
@@ -130,9 +130,7 @@ impl SimUdpServer {
let next_reply_to_send = self.reply_queue.pop_front().unwrap();
self.socket
.send_to(
serde_json::to_string(&next_reply_to_send)
.unwrap()
.as_bytes(),
&postcard::to_allocvec(&next_reply_to_send).unwrap(),
self.sender_addr.unwrap(),
)
.expect("sending reply failed");
@@ -148,15 +146,16 @@ mod tests {
io::ErrorKind,
net::{SocketAddr, UdpSocket},
sync::{
Arc,
atomic::{AtomicBool, Ordering},
mpsc, Arc,
mpsc,
},
time::Duration,
};
use satrs_minisim::{
eps::{PcduReply, PcduRequest},
use minisim_types::{
SimCtrlReply, SimCtrlRequest, SimReply, SimRequestWithTime,
eps::{PcduReply, PcduRequest},
};
use crate::eps::tests::get_all_off_switch_map;
@@ -171,8 +170,8 @@ mod tests {
pub enum ReceptionError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Serde JSON error: {0}")]
SerdeJson(#[from] serde_json::Error),
#[error("postcard error: {0}")]
Postcard(#[from] postcard::Error),
}
pub struct SimUdpTestClient {
@@ -203,7 +202,8 @@ mod tests {
pub fn send_request(&self, sim_request: &SimRequestWithTime) -> std::io::Result<usize> {
self.socket.send(
&serde_json::to_vec(sim_request).expect("conversion of request to vector failed"),
&postcard::to_allocvec(sim_request)
.expect("conversion of request to vector failed"),
)
}
@@ -213,7 +213,7 @@ mod tests {
pub fn recv_sim_reply(&mut self) -> Result<SimReply, ReceptionError> {
let read_len = self.recv_raw()?;
Ok(serde_json::from_slice(&self.reply_buf[0..read_len])?)
Ok(postcard::from_bytes(&self.reply_buf[0..read_len])?)
}
}
struct UdpTestbench {
@@ -302,8 +302,8 @@ mod tests {
panic!("unexpected request server error: {e}");
}
}
ReceptionError::SerdeJson(json_error) => {
panic!("unexpected JSON error: {json_error}");
ReceptionError::Postcard(postcard_error) => {
panic!("unexpected postcard error: {postcard_error}");
}
},
}
@@ -1148,35 +1148,6 @@ version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
[[package]]
name = "satrs-stm32f3-disco-rtic"
version = "0.1.0"
dependencies = [
"arbitrary-int",
"cobs 0.5.1",
"cortex-m",
"cortex-m-rt",
"cortex-m-semihosting",
"defmt 1.1.1",
"defmt-rtt",
"defmt-test",
"embassy-stm32",
"embassy-sync",
"embassy-time",
"embedded-hal 1.0.0",
"embedded-types",
"enumset",
"heapless 0.9.3",
"panic-probe",
"postcard",
"rtic",
"rtic-sync",
"serde",
"spacepackets",
"static_cell",
"thiserror",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
@@ -1343,6 +1314,35 @@ dependencies = [
"defmt 0.3.100",
]
[[package]]
name = "stm32f3-disco-rtic"
version = "0.1.0"
dependencies = [
"arbitrary-int",
"cobs 0.5.1",
"cortex-m",
"cortex-m-rt",
"cortex-m-semihosting",
"defmt 1.1.1",
"defmt-rtt",
"defmt-test",
"embassy-stm32",
"embassy-sync",
"embassy-time",
"embedded-hal 1.0.0",
"embedded-types",
"enumset",
"heapless 0.9.3",
"panic-probe",
"postcard",
"rtic",
"rtic-sync",
"serde",
"spacepackets",
"static_cell",
"thiserror",
]
[[package]]
name = "syn"
version = "1.0.109"
@@ -1,13 +1,13 @@
[package]
name = "satrs-stm32f3-disco-rtic"
name = "stm32f3-disco-rtic"
version = "0.1.0"
edition = "2021"
default-run = "satrs-stm32f3-disco-rtic"
edition = "2024"
default-run = "stm32f3-disco-rtic"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
embedded-types = { path = "../types", features = ["defmt"] }
embedded-types = { path = "../embedded-types", features = ["defmt"] }
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
defmt = "1"
File renamed without changes.
@@ -7,7 +7,7 @@ use rtic::app;
#[app(device = embassy_stm32)]
mod app {
use embassy_time::Timer;
use satrs_stm32f3_disco_rtic::{Direction, LedPinSet, Leds};
use stm32f3_disco_rtic::{Direction, LedPinSet, Leds};
#[shared]
struct Shared {}
@@ -3,7 +3,7 @@
use arbitrary_int::u14;
use cortex_m_semihosting::debug::{self, EXIT_FAILURE, EXIT_SUCCESS};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embedded_types::{create_tm_packet, stm32f3, tm_size, TmHeader};
use embedded_types::{TmHeader, create_tm_packet, stm32f3, tm_size};
use spacepackets::{CcsdsPacketCreationError, CcsdsPacketIdAndPsc, SpHeader};
use defmt_rtt as _; // global logger
@@ -56,8 +56,8 @@ mod app {
channel::{Receiver, Sender},
make_channel,
};
use satrs_stm32f3_disco_rtic::LedPinSet;
use spacepackets::CcsdsPacketReader;
use stm32f3_disco_rtic::LedPinSet;
embassy_stm32::bind_interrupts!(struct Irqs {
USART2 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART2>;
@@ -72,8 +72,8 @@ mod app {
#[local]
struct Local {
leds: satrs_stm32f3_disco_rtic::Leds,
current_dir: satrs_stm32f3_disco_rtic::Direction,
leds: stm32f3_disco_rtic::Leds,
current_dir: stm32f3_disco_rtic::Direction,
seq_count: u14,
tx: embassy_stm32::usart::UartTx<'static, embassy_stm32::mode::Async>,
rx: embassy_stm32::usart::RingBufferedUartRx<'static>,
@@ -99,7 +99,7 @@ mod app {
pin_w: p.PE14,
pin_nw: p.PE15,
};
let leds = satrs_stm32f3_disco_rtic::Leds::new(led_pin_set);
let leds = stm32f3_disco_rtic::Leds::new(led_pin_set);
let mut config = embassy_stm32::usart::Config::default();
config.baudrate = UART_BAUD;
@@ -124,7 +124,7 @@ mod app {
tx,
seq_count: u14::new(0),
rx: rx.into_ring_buffered(DMA_BUF.take()),
current_dir: satrs_stm32f3_disco_rtic::Direction::North,
current_dir: stm32f3_disco_rtic::Direction::North,
},
)
}
@@ -12,7 +12,7 @@
"chip": "STM32F303VCTx",
"coreConfigs": [
{
"programBinary": "${workspaceFolder}/target/thumbv7em-none-eabihf/debug/satrs-stm32f3-disco-rtic",
"programBinary": "${workspaceFolder}/target/thumbv7em-none-eabihf/debug/stm32f3-disco-rtic",
"rttEnabled": true,
"svdFile": "STM32F303.svd"
}
@@ -1015,29 +1015,6 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "satrs-stm32h7-nucleo-rtic"
version = "0.1.0"
dependencies = [
"arbitrary-int",
"cortex-m",
"cortex-m-rt",
"defmt 1.1.0",
"defmt-rtt",
"defmt-test",
"embassy-net",
"embassy-stm32",
"embassy-sync",
"embassy-time",
"embedded-alloc",
"embedded-types",
"panic-probe",
"postcard",
"rtic",
"spacepackets",
"static_cell",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@@ -1191,6 +1168,29 @@ dependencies = [
"defmt 0.3.100",
]
[[package]]
name = "stm32h7-nucleo-rtic"
version = "0.1.0"
dependencies = [
"arbitrary-int",
"cortex-m",
"cortex-m-rt",
"defmt 1.1.0",
"defmt-rtt",
"defmt-test",
"embassy-net",
"embassy-stm32",
"embassy-sync",
"embassy-time",
"embedded-alloc",
"embedded-types",
"panic-probe",
"postcard",
"rtic",
"spacepackets",
"static_cell",
]
[[package]]
name = "svgbobdoc"
version = "0.3.0"
@@ -1,8 +1,8 @@
[package]
name = "satrs-stm32h7-nucleo-rtic"
edition = "2021"
name = "stm32h7-nucleo-rtic"
edition = "2024"
version = "0.1.0"
default-run = "satrs-stm32h7-nucleo-rtic"
default-run = "stm32h7-nucleo-rtic"
[lib]
harness = false
@@ -13,7 +13,7 @@ name = "integration"
harness = false
[dependencies]
embedded-types = { path = "../types", features = ["defmt"] }
embedded-types = { path = "../embedded-types", features = ["defmt"] }
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
arbitrary-int = "2"
File renamed without changes.
@@ -7,7 +7,7 @@
#![no_std]
#![no_main]
use rtic::app;
use satrs_stm32h7_nucleo_rtic as _;
use stm32h7_nucleo_rtic as _;
#[app(device = embassy_stm32, peripherals = false, dispatchers = [SPI1])]
mod app {
@@ -2,7 +2,7 @@
#![no_std]
// global logger + panicking-behavior + memory layout
use satrs_stm32h7_nucleo_rtic as _;
use stm32h7_nucleo_rtic as _;
#[cortex_m_rt::entry]
fn main() -> ! {
@@ -5,7 +5,7 @@ extern crate alloc;
use rtic::app;
// global logger + panicking-behavior + memory layout
use embassy_stm32::bind_interrupts;
use satrs_stm32h7_nucleo_rtic as _;
use stm32h7_nucleo_rtic as _;
use core::mem::MaybeUninit;
use embedded_alloc::LlffHeap as Heap;
@@ -29,8 +29,8 @@ mod app {
use super::*;
use arbitrary_int::u14;
use embassy_net::udp::UdpSocket;
use embassy_net::StackResources;
use embassy_net::udp::UdpSocket;
use embassy_stm32::eth;
use embassy_stm32::gpio;
use embassy_stm32::peripherals;
@@ -39,10 +39,10 @@ mod app {
use embassy_time::Duration;
use embassy_time::Timer;
use embassy_time::WithTimeout as _;
use embedded_types::TmHeader;
use embedded_types::create_tm_packet;
use embedded_types::stm32h7;
use embedded_types::tm_size;
use embedded_types::TmHeader;
use spacepackets::CcsdsPacketCreationError;
use spacepackets::CcsdsPacketIdAndPsc;
use spacepackets::CcsdsPacketReader;
@@ -174,7 +174,7 @@ mod app {
embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed);
// Set up global allocator. Use AXISRAM for the heap.
#[link_section = ".axisram"]
#[unsafe(link_section = ".axisram")]
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) }
@@ -1,7 +1,7 @@
#![no_std]
#![no_main]
use satrs_stm32h7_nucleo_rtic as _; // memory layout + panic handler
use stm32h7_nucleo_rtic as _; // memory layout + panic handler
// See https://crates.io/crates/defmt-test/0.3.0 for more documentation (e.g. about the 'state'
// feature)
+16
View File
@@ -0,0 +1,16 @@
[package]
name = "types"
version = "0.1.0"
edition = "2024"
[dependencies]
serde = { version = "1", default-features = false, features = ["derive"] }
spacepackets = { version = "0.18", default-features = false, features = ["serde"] }
satrs = { path = "../../satrs", default-features = false, features = ["serde"] }
num_enum = { version = "0.7", default-features = false }
strum = { version = "0.28", default-features = false, features = ["derive"] }
postcard = { version = "1", features = ["alloc"] }
thiserror = { version = "2", default-features = false }
bitbybit = "2"
arbitrary-int = "2"
heapless = { version = "0.9", features = ["serde"] }
File renamed without changes.
Loaded 100 of 130 files, more files were not shown because too many files have changed in this diff. Show more