updated STM32F3 RTICv2 example

This commit is contained in:
Robin Mueller
2025-09-10 18:06:50 +02:00
parent 526254851a
commit 2bb8a89e8b
22 changed files with 2063 additions and 40155 deletions

View File

@@ -0,0 +1,17 @@
[package]
name = "embedded-client"
version = "0.1.0"
edition = "2024"
[dependencies]
clap = { version = "4", features = ["derive"] }
serialport = "4"
toml = "0.9"
serde = { version = "1", features = ["derive"] }
satrs-stm32f3-disco-rtic = { path = "../stm32f3-disco-rtic" }
spacepackets = { git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git", version = "0.17" }
postcard = { version = "1", features = ["alloc"] }
cobs = "0.5"
fern = "0.7"
humantime = "2"
log = "0.4"

View File

@@ -0,0 +1,2 @@
[interface]
serial_port = "/dev/ttyUSB0"

View File

@@ -0,0 +1,126 @@
use std::{
fs::File,
io::Read,
path::Path,
time::{Duration, SystemTime},
};
use clap::Parser;
use cobs::CobsDecoderOwned;
use satrs_stm32f3_disco_rtic::Request;
use spacepackets::{CcsdsPacketCreator, CcsdsPacketReader, SpHeader};
#[derive(Parser, Debug)]
struct Cli {
#[arg(short, long)]
ping: bool,
/// Set frequency in milliseconds.
#[arg(short, long)]
set_led_frequency: Option<u32>,
}
#[derive(Debug, serde::Deserialize)]
struct Config {
interface: Interface,
}
#[derive(Debug, serde::Deserialize)]
struct Interface {
serial_port: String,
}
fn setup_logger() -> Result<(), fern::InitError> {
fern::Dispatch::new()
.format(|out, message, record| {
out.finish(format_args!(
"[{} {} {}] {}",
humantime::format_rfc3339_seconds(SystemTime::now()),
record.level(),
record.target(),
message
))
})
.level(log::LevelFilter::Debug)
.chain(std::io::stdout())
.chain(fern::log_file("output.log")?)
.apply()?;
Ok(())
}
fn main() {
setup_logger().expect("failed to initialize logger");
println!("sat-rs embedded examples TMTC client");
let cli = Cli::parse();
let mut config_file =
File::open(Path::new("config.toml")).expect("opening config.toml file failed");
let mut toml_str = String::new();
config_file
.read_to_string(&mut toml_str)
.expect("reading config.toml file failed");
let config: Config = toml::from_str(&toml_str).expect("parsing config.toml file failed");
println!("Connecting to serial port {}", config.interface.serial_port);
let mut serial = serialport::new(config.interface.serial_port, 115200)
.open()
.expect("opening serial port failed");
if cli.ping {
let request = Request::Ping;
let tc_encoded_raw = create_stm32f3_tc(&request);
log::info!("Sending ping request");
serial.write_all(&tc_encoded_raw).unwrap();
}
if let Some(freq_ms) = cli.set_led_frequency {
let request = Request::ChangeBlinkFrequency(Duration::from_millis(freq_ms as u64));
let tc_encoded_raw = create_stm32f3_tc(&request);
log::info!("Sending change blink frequency request: {:?}", request);
serial.write_all(&tc_encoded_raw).unwrap();
}
let mut cobs_decoder = CobsDecoderOwned::new(1024);
log::info!("Waiting for response...");
loop {
let mut reception_buffer = [0u8; 1024];
let received_bytes = serial.read(&mut reception_buffer);
match received_bytes {
Ok(0) => {
std::thread::sleep(std::time::Duration::from_millis(100));
}
Ok(n) => {
for byte in &reception_buffer[..n] {
match cobs_decoder.feed(*byte) {
Ok(Some(packet_len)) => {
let reader = CcsdsPacketReader::new_with_checksum(
&cobs_decoder.dest()[0..packet_len],
);
log::debug!("Received packet: {:?}", reader);
}
Ok(None) => (),
Err(e) => {
log::error!("COBS decoding error {e}, resetting decoder");
}
}
}
}
Err(e) => {
if e.kind() != std::io::ErrorKind::TimedOut
&& e.kind() != std::io::ErrorKind::WouldBlock
{
log::error!("Error reading from serial port: {:?}", e);
}
std::thread::sleep(std::time::Duration::from_millis(100));
}
}
}
}
fn create_stm32f3_tc(request: &Request) -> Vec<u8> {
let req_raw = postcard::to_allocvec(&request).unwrap();
let sp_header = SpHeader::new_from_apid(satrs_stm32f3_disco_rtic::APID);
let ccsds_tc_packet = CcsdsPacketCreator::new_tc_with_checksum(sp_header, &req_raw).unwrap();
let tc_raw = ccsds_tc_packet.to_vec();
cobs::encode_vec_including_sentinels(&tc_raw)
}