From 2d62d4a61b761873e8c26296d349540506469316 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 17:18:22 +0200 Subject: [PATCH 01/31] bump spacepackets --- satrs-core/Cargo.toml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/satrs-core/Cargo.toml b/satrs-core/Cargo.toml index 4b75576..8affc47 100644 --- a/satrs-core/Cargo.toml +++ b/satrs-core/Cargo.toml @@ -72,10 +72,9 @@ features = ["all"] optional = true [dependencies.spacepackets] -# version = "0.7.0-beta.1" -# path = "../../spacepackets" -git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git" -rev = "79d26e1a6" +version = "0.7.0-beta.2" +# git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git" +# rev = "79d26e1a6" # branch = "" default-features = false From 338243b228231718738b59c8646ea6ce9ef874de Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 17:26:42 +0200 Subject: [PATCH 02/31] use new spacepackets API --- .../src/hal/std/tcp_spacepackets_server.rs | 34 +++++-------------- satrs-core/tests/tcp_servers.rs | 31 ++++++++--------- 2 files changed, 23 insertions(+), 42 deletions(-) diff --git a/satrs-core/src/hal/std/tcp_spacepackets_server.rs b/satrs-core/src/hal/std/tcp_spacepackets_server.rs index b9fc86b..42c61e9 100644 --- a/satrs-core/src/hal/std/tcp_spacepackets_server.rs +++ b/satrs-core/src/hal/std/tcp_spacepackets_server.rs @@ -220,13 +220,10 @@ mod tests { }); let mut sph = SpHeader::tc_unseg(TEST_APID_0, 0, 0).unwrap(); let ping_tc = PusTcCreator::new_simple(&mut sph, 17, 1, None, true); - let mut buffer: [u8; 32] = [0; 32]; - let packet_len_ping = ping_tc - .write_to_bytes(&mut buffer) - .expect("writing packet failed"); + let tc_0 = ping_tc.to_vec().expect("packet generation failed"); let mut stream = TcpStream::connect(dest_addr).expect("connecting to TCP server failed"); stream - .write_all(&buffer[..packet_len_ping]) + .write_all(&tc_0) .expect("writing to TCP server failed"); drop(stream); @@ -242,12 +239,11 @@ mod tests { // Check that TC has arrived. let mut tc_queue = tc_receiver.tc_queue.lock().unwrap(); assert_eq!(tc_queue.len(), 1); - assert_eq!(tc_queue.pop_front().unwrap(), buffer[..packet_len_ping]); + assert_eq!(tc_queue.pop_front().unwrap(), tc_0); } #[test] fn test_multi_tc_multi_tm() { - let mut buffer: [u8; 32] = [0; 32]; let auto_port_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0); let tc_receiver = SyncTcCacher::default(); let mut tm_source = SyncTmSource::default(); @@ -256,19 +252,13 @@ mod tests { let mut total_tm_len = 0; let mut sph = SpHeader::tc_unseg(TEST_APID_0, 0, 0).unwrap(); let verif_tm = PusTcCreator::new_simple(&mut sph, 1, 1, None, true); - let tm_packet_len = verif_tm - .write_to_bytes(&mut buffer) - .expect("writing packet failed"); - total_tm_len += tm_packet_len; - let tm_0 = buffer[..tm_packet_len].to_vec(); + let tm_0 = verif_tm.to_vec().expect("writing packet failed"); + total_tm_len += tm_0.len(); tm_source.add_tm(&tm_0); let mut sph = SpHeader::tc_unseg(TEST_APID_1, 0, 0).unwrap(); let verif_tm = PusTcCreator::new_simple(&mut sph, 1, 3, None, true); - let tm_packet_len = verif_tm - .write_to_bytes(&mut buffer) - .expect("writing packet failed"); - total_tm_len += tm_packet_len; - let tm_1 = buffer[..tm_packet_len].to_vec(); + let tm_1 = verif_tm.to_vec().expect("writing packet failed"); + total_tm_len += tm_1.len(); tm_source.add_tm(&tm_1); // Set up server @@ -309,19 +299,13 @@ mod tests { // Send telecommands let mut sph = SpHeader::tc_unseg(TEST_APID_0, 0, 0).unwrap(); let ping_tc = PusTcCreator::new_simple(&mut sph, 17, 1, None, true); - let packet_len = ping_tc - .write_to_bytes(&mut buffer) - .expect("writing packet failed"); - let tc_0 = buffer[..packet_len].to_vec(); + let tc_0 = ping_tc.to_vec().expect("ping tc creation failed"); stream .write_all(&tc_0) .expect("writing to TCP server failed"); let mut sph = SpHeader::tc_unseg(TEST_APID_1, 0, 0).unwrap(); let action_tc = PusTcCreator::new_simple(&mut sph, 8, 0, None, true); - let packet_len = action_tc - .write_to_bytes(&mut buffer) - .expect("writing packet failed"); - let tc_1 = buffer[..packet_len].to_vec(); + let tc_1 = action_tc.to_vec().expect("action tc creation failed"); stream .write_all(&tc_1) .expect("writing to TCP server failed"); diff --git a/satrs-core/tests/tcp_servers.rs b/satrs-core/tests/tcp_servers.rs index b3e7993..d66c1fb 100644 --- a/satrs-core/tests/tcp_servers.rs +++ b/satrs-core/tests/tcp_servers.rs @@ -166,16 +166,12 @@ const TEST_PACKET_ID_0: PacketId = PacketId::const_tc(true, TEST_APID_0); #[test] fn test_ccsds_server() { - let mut buffer: [u8; 32] = [0; 32]; let tc_receiver = SyncTcCacher::default(); let mut tm_source = SyncTmSource::default(); let mut sph = SpHeader::tc_unseg(TEST_APID_0, 0, 0).unwrap(); let verif_tm = PusTcCreator::new_simple(&mut sph, 1, 1, None, true); - let tm_packet_len = verif_tm - .write_to_bytes(&mut buffer) - .expect("writing packet failed"); - tm_source.add_tm(&buffer[..tm_packet_len]); - let tm_vec = buffer[..tm_packet_len].to_vec(); + let tm_0 = verif_tm.to_vec().expect("tm generation failed"); + tm_source.add_tm(&tm_0); let mut packet_id_lookup = HashSet::new(); packet_id_lookup.insert(TEST_PACKET_ID_0); let mut tcp_server = TcpSpacepacketsServer::new( @@ -202,29 +198,30 @@ fn test_ccsds_server() { set_if_done.store(true, Ordering::Relaxed); }); let mut stream = TcpStream::connect(dest_addr).expect("connecting to TCP server failed"); - let mut sph = SpHeader::tc_unseg(TEST_APID_0, 0, 0).unwrap(); - let ping_tc = PusTcCreator::new_simple(&mut sph, 17, 1, None, true); stream .set_read_timeout(Some(Duration::from_millis(10))) .expect("setting reas timeout failed"); - let packet_len = ping_tc - .write_to_bytes(&mut buffer) - .expect("writing packet failed"); - stream - .write_all(&buffer[..packet_len]) - .expect("writing to TCP server failed"); + // Send ping telecommand. + let mut sph = SpHeader::tc_unseg(TEST_APID_0, 0, 0).unwrap(); + let ping_tc = PusTcCreator::new_simple(&mut sph, 17, 1, None, true); + let tc_0 = ping_tc.to_vec().expect("packet creation failed"); + stream + .write_all(&tc_0) + .expect("writing to TCP server failed"); // Done with writing. stream .shutdown(std::net::Shutdown::Write) .expect("shutting down write failed"); + + // Now read all the telemetry from the server. let mut read_buf: [u8; 16] = [0; 16]; let mut read_len_total = 0; // Timeout ensures this does not block forever. - while read_len_total < tm_packet_len { + while read_len_total < tm_0.len() { let read_len = stream.read(&mut read_buf).expect("read failed"); read_len_total += read_len; - assert_eq!(read_buf[..read_len], tm_vec); + assert_eq!(read_buf[..read_len], tm_0); } drop(stream); @@ -240,5 +237,5 @@ fn test_ccsds_server() { // Check that TC has arrived. let mut tc_queue = tc_receiver.tc_queue.lock().unwrap(); assert_eq!(tc_queue.len(), 1); - assert_eq!(tc_queue.pop_front().unwrap(), buffer[..packet_len]); + assert_eq!(tc_queue.pop_front().unwrap(), tc_0); } From ecf5ebaf2f256c516201fbbd8dff4e0933e4947f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 17:30:41 +0200 Subject: [PATCH 03/31] bump satrs-core alpha version --- satrs-core/Cargo.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/satrs-core/Cargo.toml b/satrs-core/Cargo.toml index 8affc47..2db74a8 100644 --- a/satrs-core/Cargo.toml +++ b/satrs-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "satrs-core" -version = "0.1.0-alpha.0" +version = "0.1.0-alpha.1" edition = "2021" rust-version = "1.61" authors = ["Robin Mueller "] @@ -15,6 +15,7 @@ categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-sup [dependencies] delegate = ">0.7, <=0.10" paste = "1" +# TODO: Remove this as soon as the image including the description was moved to the satrs-book. embed-doc-image = "0.1" [dependencies.smallvec] @@ -73,10 +74,10 @@ optional = true [dependencies.spacepackets] version = "0.7.0-beta.2" +default-features = false # git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git" # rev = "79d26e1a6" # branch = "" -default-features = false [dependencies.cobs] git = "https://github.com/robamu/cobs.rs.git" From 9bec69291bd2612ee096b431458a31ac3d97c518 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 17:31:48 +0200 Subject: [PATCH 04/31] re-point MIB dependency to satrs-core --- satrs-mib/Cargo.toml | 6 +++--- satrs-mib/codegen/Cargo.toml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/satrs-mib/Cargo.toml b/satrs-mib/Cargo.toml index cdfa4f5..99fc71b 100644 --- a/satrs-mib/Cargo.toml +++ b/satrs-mib/Cargo.toml @@ -23,9 +23,9 @@ version = "1" optional = true [dependencies.satrs-core] -# version = "0.1.0-alpha.0" -git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" -rev = "35e1f7a983f6535c5571186e361fe101d4306b89" +version = "0.1.0-alpha.1" +# git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" +# rev = "35e1f7a983f6535c5571186e361fe101d4306b89" [dependencies.satrs-mib-codegen] path = "codegen" diff --git a/satrs-mib/codegen/Cargo.toml b/satrs-mib/codegen/Cargo.toml index db6a671..cf3b70f 100644 --- a/satrs-mib/codegen/Cargo.toml +++ b/satrs-mib/codegen/Cargo.toml @@ -20,9 +20,9 @@ quote = "1" proc-macro2 = "1" [dependencies.satrs-core] -# version = "0.1.0-alpha.0" -git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" -rev = "35e1f7a983f6535c5571186e361fe101d4306b89" +version = "0.1.0-alpha.1" +# git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" +# rev = "35e1f7a983f6535c5571186e361fe101d4306b89" [dev-dependencies] trybuild = { version = "1", features = ["diff"] } From 41145f89aac03d2359a388836e3ecffede3b9d23 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 17:35:30 +0200 Subject: [PATCH 05/31] ci-check --- satrs-mib/Cargo.toml | 5 +++-- satrs-mib/codegen/Cargo.toml | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/satrs-mib/Cargo.toml b/satrs-mib/Cargo.toml index 99fc71b..e1c66ad 100644 --- a/satrs-mib/Cargo.toml +++ b/satrs-mib/Cargo.toml @@ -23,8 +23,9 @@ version = "1" optional = true [dependencies.satrs-core] -version = "0.1.0-alpha.1" -# git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" +# version = "0.1.0-alpha.1" +git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" +branch = "main" # rev = "35e1f7a983f6535c5571186e361fe101d4306b89" [dependencies.satrs-mib-codegen] diff --git a/satrs-mib/codegen/Cargo.toml b/satrs-mib/codegen/Cargo.toml index cf3b70f..fc82778 100644 --- a/satrs-mib/codegen/Cargo.toml +++ b/satrs-mib/codegen/Cargo.toml @@ -20,8 +20,9 @@ quote = "1" proc-macro2 = "1" [dependencies.satrs-core] -version = "0.1.0-alpha.1" -# git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" +# version = "0.1.0-alpha.1" +git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" +branch = "main" # rev = "35e1f7a983f6535c5571186e361fe101d4306b89" [dev-dependencies] From 6a0396a337318e39fe57204fb93f358a3444e60e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 17:36:32 +0200 Subject: [PATCH 06/31] small tweak for release checklist --- satrs-core/release-checklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/satrs-core/release-checklist.md b/satrs-core/release-checklist.md index e8b8ee3..a8359f0 100644 --- a/satrs-core/release-checklist.md +++ b/satrs-core/release-checklist.md @@ -4,7 +4,7 @@ Checklist for new releases # Pre-Release 1. Make sure any new modules are documented sufficiently enough and check docs with - `cargo doc --all-features --open`. + `cargo +nightly doc --all-features --open`. 2. Bump version specifier in `Cargo.toml`. 3. Update `CHANGELOG.md`: Convert `unreleased` section into version section with date and add new `unreleased` section. From e7e243d0c141dc8f49fb539d1b45c1bec175b17d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 18:02:11 +0200 Subject: [PATCH 07/31] bump release checklist again --- satrs-core/release-checklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/satrs-core/release-checklist.md b/satrs-core/release-checklist.md index a8359f0..d0359b0 100644 --- a/satrs-core/release-checklist.md +++ b/satrs-core/release-checklist.md @@ -4,7 +4,7 @@ Checklist for new releases # Pre-Release 1. Make sure any new modules are documented sufficiently enough and check docs with - `cargo +nightly doc --all-features --open`. + `cargo +nightly doc --all-features --config 'rustdocflags=["--cfg", "doc_cfg"]' --open`. 2. Bump version specifier in `Cargo.toml`. 3. Update `CHANGELOG.md`: Convert `unreleased` section into version section with date and add new `unreleased` section. From d89e2ecfce78f8e3d9c425ca3d968fbaab8d7760 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 18:04:18 +0200 Subject: [PATCH 08/31] version specifier for COBS --- satrs-core/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/satrs-core/Cargo.toml b/satrs-core/Cargo.toml index 2db74a8..6fa8535 100644 --- a/satrs-core/Cargo.toml +++ b/satrs-core/Cargo.toml @@ -81,6 +81,7 @@ default-features = false [dependencies.cobs] git = "https://github.com/robamu/cobs.rs.git" +version = "0.2.3" branch = "all_features" default-features = false From 777630c4990e2f634eaf89fcce86c0abaf03f44e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 18:07:41 +0200 Subject: [PATCH 09/31] bump mib dependencies --- satrs-mib/Cargo.toml | 4 ++-- satrs-mib/codegen/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/satrs-mib/Cargo.toml b/satrs-mib/Cargo.toml index e1c66ad..60d4daa 100644 --- a/satrs-mib/Cargo.toml +++ b/satrs-mib/Cargo.toml @@ -23,8 +23,8 @@ version = "1" optional = true [dependencies.satrs-core] -# version = "0.1.0-alpha.1" -git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" +version = "0.1.0-alpha.1" +# git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" branch = "main" # rev = "35e1f7a983f6535c5571186e361fe101d4306b89" diff --git a/satrs-mib/codegen/Cargo.toml b/satrs-mib/codegen/Cargo.toml index fc82778..1567183 100644 --- a/satrs-mib/codegen/Cargo.toml +++ b/satrs-mib/codegen/Cargo.toml @@ -20,8 +20,8 @@ quote = "1" proc-macro2 = "1" [dependencies.satrs-core] -# version = "0.1.0-alpha.1" -git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" +version = "0.1.0-alpha.1" +# git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" branch = "main" # rev = "35e1f7a983f6535c5571186e361fe101d4306b89" From d20e205c32330611e166d54362dcdd10c810756e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 18:14:07 +0200 Subject: [PATCH 10/31] small fix --- satrs-mib/Cargo.toml | 2 +- satrs-mib/codegen/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/satrs-mib/Cargo.toml b/satrs-mib/Cargo.toml index 60d4daa..a34d886 100644 --- a/satrs-mib/Cargo.toml +++ b/satrs-mib/Cargo.toml @@ -25,7 +25,7 @@ optional = true [dependencies.satrs-core] version = "0.1.0-alpha.1" # git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" -branch = "main" +# branch = "main" # rev = "35e1f7a983f6535c5571186e361fe101d4306b89" [dependencies.satrs-mib-codegen] diff --git a/satrs-mib/codegen/Cargo.toml b/satrs-mib/codegen/Cargo.toml index 1567183..cba83eb 100644 --- a/satrs-mib/codegen/Cargo.toml +++ b/satrs-mib/codegen/Cargo.toml @@ -22,7 +22,7 @@ proc-macro2 = "1" [dependencies.satrs-core] version = "0.1.0-alpha.1" # git = "https://egit.irs.uni-stuttgart.de/rust/sat-rs.git" -branch = "main" +# branch = "main" # rev = "35e1f7a983f6535c5571186e361fe101d4306b89" [dev-dependencies] From e0b8280c41515fda37acb4584f30ac95c24126c1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 18:21:10 +0200 Subject: [PATCH 11/31] bump README --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 585d3a9..5906c8b 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,11 @@ sat-rs This is the repository of the sat-rs framework. Its primary goal is to provide re-usable components to write on-board software for remote systems like rovers or satellites. It is specifically written -for the special requirements for these systems. +for the special requirements for these systems. You can find an overview of the project and the +link to the [sat-rs book](https://documentation.irs.uni-stuttgart.de/projects/sat-rs/) +at the [IRS documentation website](https://documentation.irs.uni-stuttgart.de/sat-rs.html). +It is recommended to read the book first before delving into the example application and the +API documentation. A lot of the architecture and general design considerations are based on the [FSFW](https://egit.irs.uni-stuttgart.de/fsfw/fsfw) C++ framework which has flight heritage @@ -16,6 +20,9 @@ and [EIVE](https://www.irs.uni-stuttgart.de/en/research/satellitetechnology-and- This project currently contains 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. It is recommended to read + this first before delving into the example application and the API documentation. * [`satrs-core`](https://egit.irs.uni-stuttgart.de/rust/satrs-launchpad/src/branch/main/satrs-core): Core components of sat-rs. * [`satrs-example`](https://egit.irs.uni-stuttgart.de/rust/satrs-launchpad/src/branch/main/satrs-example): From 466206e133f39f9a78a9054352640e1c16d1270b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 18:23:59 +0200 Subject: [PATCH 12/31] better --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5906c8b..0dd8276 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,8 @@ sat-rs This is the repository of the sat-rs framework. Its primary goal is to provide re-usable components to write on-board software for remote systems like rovers or satellites. It is specifically written for the special requirements for these systems. You can find an overview of the project and the -link to the [sat-rs book](https://documentation.irs.uni-stuttgart.de/projects/sat-rs/) +link to the [more high-level sat-rs book](https://documentation.irs.uni-stuttgart.de/projects/sat-rs/) at the [IRS documentation website](https://documentation.irs.uni-stuttgart.de/sat-rs.html). -It is recommended to read the book first before delving into the example application and the -API documentation. A lot of the architecture and general design considerations are based on the [FSFW](https://egit.irs.uni-stuttgart.de/fsfw/fsfw) C++ framework which has flight heritage @@ -21,7 +19,8 @@ and [EIVE](https://www.irs.uni-stuttgart.de/en/research/satellitetechnology-and- This project currently contains 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. It is recommended to read + Primary information resource in addition to the API documentation, hosted + [here](https://documentation.irs.uni-stuttgart.de/projects/sat-rs/). It can be useful to read this first before delving into the example application and the API documentation. * [`satrs-core`](https://egit.irs.uni-stuttgart.de/rust/satrs-launchpad/src/branch/main/satrs-core): Core components of sat-rs. From d21e98d2e5c49cb2cb42f50c052826ebfa95454e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 23:00:47 +0200 Subject: [PATCH 13/31] start adding tcp server --- satrs-example/Cargo.toml | 2 +- satrs-mib/Cargo.toml | 4 ++-- satrs-mib/codegen/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/satrs-example/Cargo.toml b/satrs-example/Cargo.toml index 6e2bc16..0446f51 100644 --- a/satrs-example/Cargo.toml +++ b/satrs-example/Cargo.toml @@ -19,7 +19,7 @@ num_enum = "0.7" thiserror = "1" [dependencies.satrs-core] -# version = "0.1.0-alpha.0" +# version = "0.1.0-alpha.1" path = "../satrs-core" diff --git a/satrs-mib/Cargo.toml b/satrs-mib/Cargo.toml index a34d886..e901ebe 100644 --- a/satrs-mib/Cargo.toml +++ b/satrs-mib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "satrs-mib" -version = "0.1.0-alpha.0" +version = "0.1.0-alpha.1" edition = "2021" rust-version = "1.61" authors = ["Robin Mueller "] @@ -30,7 +30,7 @@ version = "0.1.0-alpha.1" [dependencies.satrs-mib-codegen] path = "codegen" -version = "0.1.0-alpha.0" +version = "0.1.0-alpha.1" [dependencies.serde] version = "1" diff --git a/satrs-mib/codegen/Cargo.toml b/satrs-mib/codegen/Cargo.toml index cba83eb..9a3887c 100644 --- a/satrs-mib/codegen/Cargo.toml +++ b/satrs-mib/codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "satrs-mib-codegen" -version = "0.1.0-alpha.0" +version = "0.1.0-alpha.1" edition = "2021" description = "satrs-mib proc macro implementation" homepage = "https://egit.irs.uni-stuttgart.de/rust/sat-rs" From b13e9b59ac412332b2eed303791b3b28c3edd018 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 23:02:30 +0200 Subject: [PATCH 14/31] bump mib versions --- satrs-mib/Cargo.toml | 4 ++-- satrs-mib/codegen/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/satrs-mib/Cargo.toml b/satrs-mib/Cargo.toml index a34d886..e901ebe 100644 --- a/satrs-mib/Cargo.toml +++ b/satrs-mib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "satrs-mib" -version = "0.1.0-alpha.0" +version = "0.1.0-alpha.1" edition = "2021" rust-version = "1.61" authors = ["Robin Mueller "] @@ -30,7 +30,7 @@ version = "0.1.0-alpha.1" [dependencies.satrs-mib-codegen] path = "codegen" -version = "0.1.0-alpha.0" +version = "0.1.0-alpha.1" [dependencies.serde] version = "1" diff --git a/satrs-mib/codegen/Cargo.toml b/satrs-mib/codegen/Cargo.toml index cba83eb..9a3887c 100644 --- a/satrs-mib/codegen/Cargo.toml +++ b/satrs-mib/codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "satrs-mib-codegen" -version = "0.1.0-alpha.0" +version = "0.1.0-alpha.1" edition = "2021" description = "satrs-mib proc macro implementation" homepage = "https://egit.irs.uni-stuttgart.de/rust/sat-rs" From 7ca8d52368eb68ddcc16605d8625b8e9da3c23c7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Sep 2023 23:06:52 +0200 Subject: [PATCH 15/31] use explicit versions for sat-rs dependencies --- satrs-example/Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/satrs-example/Cargo.toml b/satrs-example/Cargo.toml index 0446f51..3ca175e 100644 --- a/satrs-example/Cargo.toml +++ b/satrs-example/Cargo.toml @@ -19,9 +19,9 @@ num_enum = "0.7" thiserror = "1" [dependencies.satrs-core] -# version = "0.1.0-alpha.1" -path = "../satrs-core" - +version = "0.1.0-alpha.1" +# path = "../satrs-core" [dependencies.satrs-mib] -path = "../satrs-mib" +version = "0.1.0-alpha.1" +# path = "../satrs-mib" From 5a3b9fb46b6ac574468f6d05285b6968f02c46c1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 27 Sep 2023 00:21:03 +0200 Subject: [PATCH 16/31] why is this so problematic.. --- satrs-example/pyclient/requirements.txt | 2 +- satrs-example/src/main.rs | 27 ++- satrs-example/src/tmtc.rs | 233 +++++++++++------------- 3 files changed, 134 insertions(+), 128 deletions(-) diff --git a/satrs-example/pyclient/requirements.txt b/satrs-example/pyclient/requirements.txt index bcb3cb4..4f61463 100644 --- a/satrs-example/pyclient/requirements.txt +++ b/satrs-example/pyclient/requirements.txt @@ -1,2 +1,2 @@ -tmtccmd == 5.0.0rc0 +tmtccmd == 6.0.0 # -e git+https://github.com/robamu-org/tmtccmd@97e5e51101a08b21472b3ddecc2063359f7e307a#egg=tmtccmd diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index 4053e50..4bfdbda 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -6,7 +6,9 @@ mod requests; mod tmtc; use log::{info, warn}; +use satrs_core::hal::std::udp_server::UdpTcServer; +use crate::ccsds::CcsdsReceiver; use crate::hk::AcsHkIds; use crate::logging::setup_logger; use crate::pus::action::{Pus8Wrapper, PusService8ActionHandler}; @@ -14,9 +16,9 @@ use crate::pus::event::Pus5Wrapper; use crate::pus::hk::{Pus3Wrapper, PusService3HkHandler}; use crate::pus::scheduler::Pus11Wrapper; use crate::pus::test::Service17CustomWrapper; -use crate::pus::PusTcMpscRouter; +use crate::pus::{PusReceiver, PusTcMpscRouter}; use crate::requests::{Request, RequestWithToken}; -use crate::tmtc::{core_tmtc_task, PusTcSource, TcArgs, TcStore, TmArgs, TmFunnel}; +use crate::tmtc::{PusTcSource, TcArgs, TcStore, TmArgs, TmFunnel, TmtcTask, UdpTmtcServer}; use satrs_core::event_man::{ EventManagerWithMpscQueue, MpscEventReceiver, MpscEventU32SendProvider, SendEventProvider, }; @@ -43,7 +45,7 @@ use satrs_core::spacepackets::{ SpHeader, }; use satrs_core::tmtc::tm_helper::SharedTmStore; -use satrs_core::tmtc::{AddressableId, TargetId}; +use satrs_core::tmtc::{AddressableId, CcsdsDistributor, TargetId}; use satrs_core::ChannelId; use satrs_example::{ RequestTargetId, TcReceiverId, TmSenderId, OBSW_SERVER_ADDR, PUS_APID, SERVER_PORT, @@ -266,11 +268,27 @@ fn main() { ); let mut pus_3_wrapper = Pus3Wrapper { pus_3_handler }; + let ccsds_receiver = CcsdsReceiver { + tc_source: tc_args.tc_source.clone(), + }; + let mut tmtc_task = TmtcTask::new(tc_args, PusReceiver::new(verif_reporter, pus_router)); + + let ccsds_distributor = CcsdsDistributor::new(Box::new(ccsds_receiver)); + let udp_tc_server = UdpTcServer::new(sock_addr, 2048, Box::new(ccsds_distributor)) + .expect("creating UDP TMTC server failed"); + let mut udp_tmtc_server = UdpTmtcServer { + udp_tc_server, + tm_rx: tm_args.tm_server_rx, + tm_store: tm_args.tm_store.clone_backing_pool(), + }; + info!("Starting TMTC task"); let jh0 = thread::Builder::new() .name("TMTC".to_string()) .spawn(move || { - core_tmtc_task(sock_addr, tc_args, tm_args, verif_reporter, pus_router); + udp_tmtc_server.periodic_operation(); + tmtc_task.periodic_operation(); + thread::sleep(Duration::from_millis(400)); }) .unwrap(); @@ -382,6 +400,7 @@ fn main() { let mut timestamp: [u8; 7] = [0; 7]; let mut time_provider = TimeProvider::new_with_u16_days(0, 0); loop { + // TODO: Move this into a separate thread.. match acs_thread_rx.try_recv() { Ok(request) => { info!( diff --git a/satrs-example/src/tmtc.rs b/satrs-example/src/tmtc.rs index 5d2ea5e..8ab22a1 100644 --- a/satrs-example/src/tmtc.rs +++ b/satrs-example/src/tmtc.rs @@ -1,21 +1,18 @@ use log::{info, warn}; use satrs_core::hal::std::udp_server::{ReceiveResult, UdpTcServer}; +use satrs_core::pus::ReceivesEcssPusTc; +use satrs_core::spacepackets::SpHeader; use std::net::SocketAddr; use std::sync::mpsc::{Receiver, SendError, Sender, TryRecvError}; -use std::thread; -use std::time::Duration; use thiserror::Error; -use crate::ccsds::CcsdsReceiver; -use crate::pus::{PusReceiver, PusTcMpscRouter}; +use crate::pus::PusReceiver; use satrs_core::pool::{SharedPool, StoreAddr, StoreError}; -use satrs_core::pus::verification::StdVerifReporterWithSender; -use satrs_core::pus::{ReceivesEcssPusTc, TcAddrWithToken}; +use satrs_core::pus::TcAddrWithToken; use satrs_core::spacepackets::ecss::tc::PusTcReader; use satrs_core::spacepackets::ecss::PusPacket; -use satrs_core::spacepackets::SpHeader; use satrs_core::tmtc::tm_helper::SharedTmStore; -use satrs_core::tmtc::{CcsdsDistributor, CcsdsError, ReceivesCcsdsTc}; +use satrs_core::tmtc::{CcsdsError, ReceivesCcsdsTc}; pub struct TmArgs { pub tm_store: SharedTmStore, @@ -65,9 +62,9 @@ pub struct TmFunnel { } pub struct UdpTmtcServer { - udp_tc_server: UdpTcServer>, - tm_rx: Receiver, - tm_store: SharedPool, + pub udp_tc_server: UdpTcServer>, + pub tm_rx: Receiver, + pub tm_store: SharedPool, } #[derive(Clone)] @@ -98,131 +95,121 @@ impl ReceivesCcsdsTc for PusTcSource { } } -pub fn core_tmtc_task( - socket_addr: SocketAddr, - mut tc_args: TcArgs, - tm_args: TmArgs, - verif_reporter: StdVerifReporterWithSender, - pus_router: PusTcMpscRouter, -) { - let mut pus_receiver = PusReceiver::new(verif_reporter, pus_router); - - let ccsds_receiver = CcsdsReceiver { - tc_source: tc_args.tc_source.clone(), - }; - - let ccsds_distributor = CcsdsDistributor::new(Box::new(ccsds_receiver)); - - let udp_tc_server = UdpTcServer::new(socket_addr, 2048, Box::new(ccsds_distributor)) - .expect("creating UDP TMTC server failed"); - - let mut udp_tmtc_server = UdpTmtcServer { - udp_tc_server, - tm_rx: tm_args.tm_server_rx, - tm_store: tm_args.tm_store.clone_backing_pool(), - }; - - let mut tc_buf: [u8; 4096] = [0; 4096]; - loop { - core_tmtc_loop( - &mut udp_tmtc_server, - &mut tc_args, - &mut tc_buf, - &mut pus_receiver, - ); - thread::sleep(Duration::from_millis(400)); - } +pub struct TmtcTask { + tc_args: TcArgs, + tc_buf: [u8; 4096], + pus_receiver: PusReceiver, } -fn core_tmtc_loop( - udp_tmtc_server: &mut UdpTmtcServer, - tc_args: &mut TcArgs, - tc_buf: &mut [u8], - pus_receiver: &mut PusReceiver, -) { - while poll_tc_server(udp_tmtc_server) {} - match tc_args.tc_receiver.try_recv() { - Ok(addr) => { - let pool = tc_args - .tc_source - .tc_store - .pool - .read() - .expect("locking tc pool failed"); - let data = pool.read(&addr).expect("reading pool failed"); - tc_buf[0..data.len()].copy_from_slice(data); - drop(pool); - match PusTcReader::new(tc_buf) { - Ok((pus_tc, _)) => { - pus_receiver - .handle_tc_packet(addr, pus_tc.service(), &pus_tc) - .ok(); - } - Err(e) => { - warn!("error creating PUS TC from raw data: {e}"); - warn!("raw data: {tc_buf:x?}"); - } - } - } - Err(e) => { - if let TryRecvError::Disconnected = e { - warn!("tmtc thread: sender disconnected") - } +impl TmtcTask { + pub fn new(tc_args: TcArgs, pus_receiver: PusReceiver) -> Self { + Self { + tc_args, + tc_buf: [0; 4096], + pus_receiver, } } - if let Some(recv_addr) = udp_tmtc_server.udp_tc_server.last_sender() { - core_tm_handling(udp_tmtc_server, &recv_addr); - } -} -fn poll_tc_server(udp_tmtc_server: &mut UdpTmtcServer) -> bool { - match udp_tmtc_server.udp_tc_server.try_recv_tc() { - Ok(_) => true, - Err(e) => match e { - ReceiveResult::ReceiverError(e) => match e { - CcsdsError::ByteConversionError(e) => { - warn!("packet error: {e:?}"); - true + pub fn periodic_operation(&mut self) { + //while self.poll_tc() {} + self.poll_tc(); + } + + pub fn poll_tc(&mut self) -> bool { + match self.tc_args.tc_receiver.try_recv() { + Ok(addr) => { + let pool = self + .tc_args + .tc_source + .tc_store + .pool + .read() + .expect("locking tc pool failed"); + let data = pool.read(&addr).expect("reading pool failed"); + self.tc_buf[0..data.len()].copy_from_slice(data); + drop(pool); + match PusTcReader::new(&self.tc_buf) { + Ok((pus_tc, _)) => { + self.pus_receiver + .handle_tc_packet(addr, pus_tc.service(), &pus_tc) + .ok(); + true + } + Err(e) => { + warn!("error creating PUS TC from raw data: {e}"); + warn!("raw data: {:x?}", self.tc_buf); + true + } } - CcsdsError::CustomError(e) => { - warn!("mpsc store and send error {e:?}"); - true + } + Err(e) => match e { + TryRecvError::Empty => false, + TryRecvError::Disconnected => { + warn!("tmtc thread: sender disconnected"); + false } }, - ReceiveResult::IoError(e) => { - warn!("IO error {e}"); - false - } - ReceiveResult::NothingReceived => false, - }, + } } } -fn core_tm_handling(udp_tmtc_server: &mut UdpTmtcServer, recv_addr: &SocketAddr) { - while let Ok(addr) = udp_tmtc_server.tm_rx.try_recv() { - let store_lock = udp_tmtc_server.tm_store.write(); - if store_lock.is_err() { - warn!("Locking TM store failed"); - continue; +impl UdpTmtcServer { + pub fn periodic_operation(&mut self) { + while self.poll_tc_server() {} + if let Some(recv_addr) = self.udp_tc_server.last_sender() { + self.send_tm_to_udp_client(&recv_addr); } - let mut store_lock = store_lock.unwrap(); - let pg = store_lock.read_with_guard(addr); - let read_res = pg.read(); - if read_res.is_err() { - warn!("Error reading TM pool data"); - continue; + } + + fn poll_tc_server(&mut self) -> bool { + match self.udp_tc_server.try_recv_tc() { + Ok(_) => true, + Err(e) => match e { + ReceiveResult::ReceiverError(e) => match e { + CcsdsError::ByteConversionError(e) => { + warn!("packet error: {e:?}"); + true + } + CcsdsError::CustomError(e) => { + warn!("mpsc store and send error {e:?}"); + true + } + }, + ReceiveResult::IoError(e) => { + warn!("IO error {e}"); + false + } + ReceiveResult::NothingReceived => false, + }, } - let buf = read_res.unwrap(); - if buf.len() > 9 { - let service = buf[7]; - let subservice = buf[8]; - info!("Sending PUS TM[{service},{subservice}]") - } else { - info!("Sending PUS TM"); - } - let result = udp_tmtc_server.udp_tc_server.socket.send_to(buf, recv_addr); - if let Err(e) = result { - warn!("Sending TM with UDP socket failed: {e}") + } + + fn send_tm_to_udp_client(&mut self, recv_addr: &SocketAddr) { + while let Ok(addr) = self.tm_rx.try_recv() { + let store_lock = self.tm_store.write(); + if store_lock.is_err() { + warn!("Locking TM store failed"); + continue; + } + let mut store_lock = store_lock.unwrap(); + let pg = store_lock.read_with_guard(addr); + let read_res = pg.read(); + if read_res.is_err() { + warn!("Error reading TM pool data"); + continue; + } + let buf = read_res.unwrap(); + if buf.len() > 9 { + let service = buf[7]; + let subservice = buf[8]; + info!("Sending PUS TM[{service},{subservice}]") + } else { + info!("Sending PUS TM"); + } + let result = self.udp_tc_server.socket.send_to(buf, recv_addr); + if let Err(e) = result { + warn!("Sending TM with UDP socket failed: {e}") + } } } } From 8f325138ff9d1307c705bd028ffecd6c52b32638 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 27 Sep 2023 00:25:50 +0200 Subject: [PATCH 17/31] found the bug --- satrs-example/src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index 4bfdbda..3a8664f 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -282,10 +282,10 @@ fn main() { tm_store: tm_args.tm_store.clone_backing_pool(), }; - info!("Starting TMTC task"); + info!("Starting TMTC and UDP task"); let jh0 = thread::Builder::new() - .name("TMTC".to_string()) - .spawn(move || { + .name("TMTC_UDP".to_string()) + .spawn(move || loop { udp_tmtc_server.periodic_operation(); tmtc_task.periodic_operation(); thread::sleep(Duration::from_millis(400)); @@ -400,7 +400,7 @@ fn main() { let mut timestamp: [u8; 7] = [0; 7]; let mut time_provider = TimeProvider::new_with_u16_days(0, 0); loop { - // TODO: Move this into a separate thread.. + // TODO: Move this into a separate function/task/module.. match acs_thread_rx.try_recv() { Ok(request) => { info!( From 6bee0f35ff725067ff2e425a22a3ddc3350e11cb Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 27 Sep 2023 14:28:42 +0200 Subject: [PATCH 18/31] add structure overview --- satrs-example/README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/satrs-example/README.md b/satrs-example/README.md index 021ae67..75a067b 100644 --- a/satrs-example/README.md +++ b/satrs-example/README.md @@ -17,7 +17,7 @@ cargo run --bin simpleclient This repository also contains a more complex client using the [Python tmtccmd](https://github.com/robamu-org/tmtccmd) module. -# Using the tmtccmd Python client +# Using the tmtccmd Python client The python client requires a valid installation of the [tmtccmd package](https://github.com/robamu-org/tmtccmd). @@ -51,3 +51,24 @@ the `simpleclient`: You can also simply call the script without any arguments to view a list of services (`-s` flag) and corresponding op codes (`-o` flag) for each service. + +# Structure of the example project + +The example project contains components which could also be expected to be part of a production +On-Board Software. + +1. A UDP server to receive telecommands and poll telemetry from. This might be an optional + component for an OBSW which is only used during the development phase on ground. +2. A PUS service stack which exposes some functionality conformant with the ECSS PUS service. This + currently includes the following services: + - Service 1 for telecommand verification. + - Service 3 for housekeeping telemetry handling. + - Service 5 for management and downlink of on-board events. + - Service 8 for handling on-board actions. + - Service 17 for test purposes (pings) +3. An event manager component which handles the event IPC mechanism. +4. A TC source component which demultiplexes and routes telecommands based on parameters like + packet APID or PUS service and subservice type. +5. 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. +6. An AOCS example task which can also process some PUS commands. From 77c06718c92907da48d35d55c19eb46cfe0c57b6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 27 Sep 2023 14:33:24 +0200 Subject: [PATCH 19/31] README update --- satrs-example/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/satrs-example/README.md b/satrs-example/README.md index 75a067b..5841a9d 100644 --- a/satrs-example/README.md +++ b/satrs-example/README.md @@ -65,6 +65,7 @@ On-Board Software. - 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. - Service 17 for test purposes (pings) 3. An event manager component which handles the event IPC mechanism. 4. A TC source component which demultiplexes and routes telecommands based on parameters like From 47b794e12f4487d4c69d223b4b4b7c706c28a420 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Sep 2023 12:38:57 +0200 Subject: [PATCH 20/31] smaller modules --- satrs-example/src/main.rs | 4 ++- satrs-example/src/tmtc.rs | 66 ---------------------------------- satrs-example/src/udp.rs | 76 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 67 deletions(-) create mode 100644 satrs-example/src/udp.rs diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index 3a8664f..2f4c1d2 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -4,6 +4,7 @@ mod logging; mod pus; mod requests; mod tmtc; +mod udp; use log::{info, warn}; use satrs_core::hal::std::udp_server::UdpTcServer; @@ -18,7 +19,8 @@ use crate::pus::scheduler::Pus11Wrapper; use crate::pus::test::Service17CustomWrapper; use crate::pus::{PusReceiver, PusTcMpscRouter}; use crate::requests::{Request, RequestWithToken}; -use crate::tmtc::{PusTcSource, TcArgs, TcStore, TmArgs, TmFunnel, TmtcTask, UdpTmtcServer}; +use crate::tmtc::{PusTcSource, TcArgs, TcStore, TmArgs, TmFunnel, TmtcTask}; +use crate::udp::UdpTmtcServer; use satrs_core::event_man::{ EventManagerWithMpscQueue, MpscEventReceiver, MpscEventU32SendProvider, SendEventProvider, }; diff --git a/satrs-example/src/tmtc.rs b/satrs-example/src/tmtc.rs index 8ab22a1..9b52367 100644 --- a/satrs-example/src/tmtc.rs +++ b/satrs-example/src/tmtc.rs @@ -61,11 +61,6 @@ pub struct TmFunnel { pub tm_server_tx: Sender, } -pub struct UdpTmtcServer { - pub udp_tc_server: UdpTcServer>, - pub tm_rx: Receiver, - pub tm_store: SharedPool, -} #[derive(Clone)] pub struct PusTcSource { @@ -152,64 +147,3 @@ impl TmtcTask { } } } - -impl UdpTmtcServer { - pub fn periodic_operation(&mut self) { - while self.poll_tc_server() {} - if let Some(recv_addr) = self.udp_tc_server.last_sender() { - self.send_tm_to_udp_client(&recv_addr); - } - } - - fn poll_tc_server(&mut self) -> bool { - match self.udp_tc_server.try_recv_tc() { - Ok(_) => true, - Err(e) => match e { - ReceiveResult::ReceiverError(e) => match e { - CcsdsError::ByteConversionError(e) => { - warn!("packet error: {e:?}"); - true - } - CcsdsError::CustomError(e) => { - warn!("mpsc store and send error {e:?}"); - true - } - }, - ReceiveResult::IoError(e) => { - warn!("IO error {e}"); - false - } - ReceiveResult::NothingReceived => false, - }, - } - } - - fn send_tm_to_udp_client(&mut self, recv_addr: &SocketAddr) { - while let Ok(addr) = self.tm_rx.try_recv() { - let store_lock = self.tm_store.write(); - if store_lock.is_err() { - warn!("Locking TM store failed"); - continue; - } - let mut store_lock = store_lock.unwrap(); - let pg = store_lock.read_with_guard(addr); - let read_res = pg.read(); - if read_res.is_err() { - warn!("Error reading TM pool data"); - continue; - } - let buf = read_res.unwrap(); - if buf.len() > 9 { - let service = buf[7]; - let subservice = buf[8]; - info!("Sending PUS TM[{service},{subservice}]") - } else { - info!("Sending PUS TM"); - } - let result = self.udp_tc_server.socket.send_to(buf, recv_addr); - if let Err(e) = result { - warn!("Sending TM with UDP socket failed: {e}") - } - } - } -} diff --git a/satrs-example/src/udp.rs b/satrs-example/src/udp.rs new file mode 100644 index 0000000..e3ca9f6 --- /dev/null +++ b/satrs-example/src/udp.rs @@ -0,0 +1,76 @@ +use std::{net::SocketAddr, sync::mpsc::Receiver}; + +use log::{info, warn}; +use satrs_core::{ + hal::std::udp_server::{ReceiveResult, UdpTcServer}, + pool::{SharedPool, StoreAddr}, + tmtc::CcsdsError, +}; + +use crate::tmtc::MpscStoreAndSendError; + +pub struct UdpTmtcServer { + pub udp_tc_server: UdpTcServer>, + pub tm_rx: Receiver, + pub tm_store: SharedPool, +} +impl UdpTmtcServer { + pub fn periodic_operation(&mut self) { + while self.poll_tc_server() {} + if let Some(recv_addr) = self.udp_tc_server.last_sender() { + self.send_tm_to_udp_client(&recv_addr); + } + } + + fn poll_tc_server(&mut self) -> bool { + match self.udp_tc_server.try_recv_tc() { + Ok(_) => true, + Err(e) => match e { + ReceiveResult::ReceiverError(e) => match e { + CcsdsError::ByteConversionError(e) => { + warn!("packet error: {e:?}"); + true + } + CcsdsError::CustomError(e) => { + warn!("mpsc store and send error {e:?}"); + true + } + }, + ReceiveResult::IoError(e) => { + warn!("IO error {e}"); + false + } + ReceiveResult::NothingReceived => false, + }, + } + } + + fn send_tm_to_udp_client(&mut self, recv_addr: &SocketAddr) { + while let Ok(addr) = self.tm_rx.try_recv() { + let store_lock = self.tm_store.write(); + if store_lock.is_err() { + warn!("Locking TM store failed"); + continue; + } + let mut store_lock = store_lock.unwrap(); + let pg = store_lock.read_with_guard(addr); + let read_res = pg.read(); + if read_res.is_err() { + warn!("Error reading TM pool data"); + continue; + } + let buf = read_res.unwrap(); + if buf.len() > 9 { + let service = buf[7]; + let subservice = buf[8]; + info!("Sending PUS TM[{service},{subservice}]") + } else { + info!("Sending PUS TM"); + } + let result = self.udp_tc_server.socket.send_to(buf, recv_addr); + if let Err(e) = result { + warn!("Sending TM with UDP socket failed: {e}") + } + } + } +} From 183aca32191de19ab584cb235d16981d044ef5fb Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Sep 2023 14:11:03 +0200 Subject: [PATCH 21/31] TCP support working --- satrs-core/src/encoding/ccsds.rs | 12 ++ satrs-core/src/hal/std/tcp_cobs_server.rs | 2 +- .../src/hal/std/tcp_spacepackets_server.rs | 2 +- satrs-example/Cargo.toml | 4 +- satrs-example/pyclient/common.py | 4 + satrs-example/pyclient/main.py | 4 +- satrs-example/pyclient/tmtc_conf.json | 8 +- satrs-example/src/ccsds.rs | 1 + satrs-example/src/main.rs | 54 +++++++-- satrs-example/src/tcp.rs | 110 ++++++++++++++++++ satrs-example/src/tmtc.rs | 9 +- 11 files changed, 184 insertions(+), 26 deletions(-) create mode 100644 satrs-example/src/tcp.rs diff --git a/satrs-core/src/encoding/ccsds.rs b/satrs-core/src/encoding/ccsds.rs index ec7da4c..ecd4ff5 100644 --- a/satrs-core/src/encoding/ccsds.rs +++ b/satrs-core/src/encoding/ccsds.rs @@ -30,6 +30,12 @@ impl PacketIdLookup for [u16] { } } +impl PacketIdLookup for &[u16] { + fn validate(&self, packet_id: u16) -> bool { + self.binary_search(&packet_id).is_ok() + } +} + #[cfg(feature = "alloc")] impl PacketIdLookup for Vec { fn validate(&self, packet_id: u16) -> bool { @@ -49,6 +55,12 @@ impl PacketIdLookup for [PacketId] { } } +impl PacketIdLookup for &[PacketId] { + fn validate(&self, packet_id: u16) -> bool { + self.binary_search(&PacketId::from(packet_id)).is_ok() + } +} + /// This function parses a given buffer for tightly packed CCSDS space packets. It uses the /// [PacketId] field of the CCSDS packets to detect the start of a CCSDS space packet and then /// uses the length field of the packet to extract CCSDS packets. diff --git a/satrs-core/src/hal/std/tcp_cobs_server.rs b/satrs-core/src/hal/std/tcp_cobs_server.rs index 4a22a8a..dc00c44 100644 --- a/satrs-core/src/hal/std/tcp_cobs_server.rs +++ b/satrs-core/src/hal/std/tcp_cobs_server.rs @@ -130,7 +130,7 @@ impl TcpTmtcInCobsServer { cfg: ServerConfig, tm_source: Box>, tc_receiver: Box>, - ) -> Result> { + ) -> Result { Ok(Self { generic_server: TcpTmtcGenericServer::new( cfg, diff --git a/satrs-core/src/hal/std/tcp_spacepackets_server.rs b/satrs-core/src/hal/std/tcp_spacepackets_server.rs index 42c61e9..c256578 100644 --- a/satrs-core/src/hal/std/tcp_spacepackets_server.rs +++ b/satrs-core/src/hal/std/tcp_spacepackets_server.rs @@ -113,7 +113,7 @@ impl TcpSpacepacketsServer tm_source: Box>, tc_receiver: Box>, packet_id_lookup: Box, - ) -> Result> { + ) -> Result { Ok(Self { generic_server: TcpTmtcGenericServer::new( cfg, diff --git a/satrs-example/Cargo.toml b/satrs-example/Cargo.toml index 3ca175e..3d61254 100644 --- a/satrs-example/Cargo.toml +++ b/satrs-example/Cargo.toml @@ -19,8 +19,8 @@ num_enum = "0.7" thiserror = "1" [dependencies.satrs-core] -version = "0.1.0-alpha.1" -# path = "../satrs-core" +# version = "0.1.0-alpha.1" +path = "../satrs-core" [dependencies.satrs-mib] version = "0.1.0-alpha.1" diff --git a/satrs-example/pyclient/common.py b/satrs-example/pyclient/common.py index 81df032..c2d0777 100644 --- a/satrs-example/pyclient/common.py +++ b/satrs-example/pyclient/common.py @@ -4,7 +4,11 @@ import dataclasses import enum import struct +from spacepackets.ecss.tc import PacketId, PacketType + EXAMPLE_PUS_APID = 0x02 +EXAMPLE_PUS_PACKET_ID_TM = PacketId(PacketType.TM, True, EXAMPLE_PUS_APID) +TM_PACKET_IDS = [EXAMPLE_PUS_PACKET_ID_TM] class EventSeverity(enum.IntEnum): diff --git a/satrs-example/pyclient/main.py b/satrs-example/pyclient/main.py index 39217e7..4f3c6c4 100755 --- a/satrs-example/pyclient/main.py +++ b/satrs-example/pyclient/main.py @@ -45,7 +45,7 @@ from tmtccmd.util.obj_id import ObjectIdDictT import pus_tc import tc_definitions -from common import EXAMPLE_PUS_APID, EventU32 +from common import EXAMPLE_PUS_APID, TM_PACKET_IDS, EventU32 _LOGGER = logging.getLogger() @@ -63,7 +63,7 @@ class SatRsConfigHook(HookBase): cfg = create_com_interface_cfg_default( com_if_key=com_if_key, json_cfg_path=self.cfg_path, - space_packet_ids=None, + space_packet_ids=TM_PACKET_IDS, ) return create_com_interface_default(cfg) diff --git a/satrs-example/pyclient/tmtc_conf.json b/satrs-example/pyclient/tmtc_conf.json index ab02100..f2c8afd 100644 --- a/satrs-example/pyclient/tmtc_conf.json +++ b/satrs-example/pyclient/tmtc_conf.json @@ -1,6 +1,8 @@ { - "com_if": "udp", + "com_if": "tcp", "tcpip_udp_ip_addr": "127.0.0.1", "tcpip_udp_port": 7301, - "tcpip_udp_recv_max_size": 1500 -} \ No newline at end of file + "tcpip_udp_recv_max_size": 1500, + "tcpip_tcp_ip_addr": "127.0.0.1", + "tcpip_tcp_port": 7301 +} diff --git a/satrs-example/src/ccsds.rs b/satrs-example/src/ccsds.rs index ef361f2..d0616c9 100644 --- a/satrs-example/src/ccsds.rs +++ b/satrs-example/src/ccsds.rs @@ -3,6 +3,7 @@ use satrs_core::spacepackets::{CcsdsPacket, SpHeader}; use satrs_core::tmtc::{CcsdsPacketHandler, ReceivesCcsdsTc}; use satrs_example::PUS_APID; +#[derive(Clone)] pub struct CcsdsReceiver { pub tc_source: PusTcSource, } diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index 2f4c1d2..c537ab2 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -3,10 +3,12 @@ mod hk; mod logging; mod pus; mod requests; +mod tcp; mod tmtc; mod udp; use log::{info, warn}; +use satrs_core::hal::std::tcp_server::ServerConfig; use satrs_core::hal::std::udp_server::UdpTcServer; use crate::ccsds::CcsdsReceiver; @@ -19,6 +21,7 @@ use crate::pus::scheduler::Pus11Wrapper; use crate::pus::test::Service17CustomWrapper; use crate::pus::{PusReceiver, PusTcMpscRouter}; use crate::requests::{Request, RequestWithToken}; +use crate::tcp::{SyncTcpTmSource, TcpTask}; use crate::tmtc::{PusTcSource, TcArgs, TcStore, TmArgs, TmFunnel, TmtcTask}; use crate::udp::UdpTmtcServer; use satrs_core::event_man::{ @@ -143,7 +146,7 @@ fn main() { let tm_args = TmArgs { tm_store: shared_tm_store.clone(), tm_sink_sender: tm_funnel_tx.clone(), - tm_server_rx, + tm_udp_server_rx: tm_server_rx, }; let aocs_tm_funnel = tm_funnel_tx.clone(); @@ -275,22 +278,45 @@ fn main() { }; let mut tmtc_task = TmtcTask::new(tc_args, PusReceiver::new(verif_reporter, pus_router)); - let ccsds_distributor = CcsdsDistributor::new(Box::new(ccsds_receiver)); - let udp_tc_server = UdpTcServer::new(sock_addr, 2048, Box::new(ccsds_distributor)) + let udp_ccsds_distributor = CcsdsDistributor::new(Box::new(ccsds_receiver.clone())); + let udp_tc_server = UdpTcServer::new(sock_addr, 2048, Box::new(udp_ccsds_distributor)) .expect("creating UDP TMTC server failed"); let mut udp_tmtc_server = UdpTmtcServer { udp_tc_server, - tm_rx: tm_args.tm_server_rx, + tm_rx: tm_args.tm_udp_server_rx, tm_store: tm_args.tm_store.clone_backing_pool(), }; info!("Starting TMTC and UDP task"); - let jh0 = thread::Builder::new() - .name("TMTC_UDP".to_string()) - .spawn(move || loop { - udp_tmtc_server.periodic_operation(); - tmtc_task.periodic_operation(); - thread::sleep(Duration::from_millis(400)); + let jh_udp_tmtc = thread::Builder::new() + .name("TMTC and UDP".to_string()) + .spawn(move || { + info!("Running UDP server on port {SERVER_PORT}"); + loop { + udp_tmtc_server.periodic_operation(); + tmtc_task.periodic_operation(); + thread::sleep(Duration::from_millis(400)); + } + }) + .unwrap(); + + let tcp_ccsds_distributor = CcsdsDistributor::new(Box::new(ccsds_receiver)); + let tcp_server_cfg = ServerConfig::new(sock_addr, Duration::from_millis(400), 4096, 8192); + let mut sync_tm_tcp_source = SyncTcpTmSource::new(200); + let mut tcp_server = TcpTask::new( + tcp_server_cfg, + sync_tm_tcp_source.clone(), + tcp_ccsds_distributor, + ) + .expect("tcp server creation failed"); + info!("Starting TCP task"); + let jh_tcp = thread::Builder::new() + .name("TCP".to_string()) + .spawn(move || { + info!("Running TCP server on port {SERVER_PORT}"); + loop { + tcp_server.periodic_operation(); + } }) .unwrap(); @@ -331,6 +357,7 @@ fn main() { .tm_server_tx .send(addr) .expect("Sending TM to server failed"); + sync_tm_tcp_source.add_tm(tm_raw); } } }) @@ -502,7 +529,12 @@ fn main() { thread::sleep(Duration::from_millis(200)); }) .unwrap(); - jh0.join().expect("Joining UDP TMTC server thread failed"); + jh_udp_tmtc + .join() + .expect("Joining UDP TMTC server thread failed"); + jh_tcp + .join() + .expect("Joining TCP TMTC server thread failed"); jh1.join().expect("Joining TM Funnel thread failed"); jh2.join().expect("Joining Event Manager thread failed"); jh3.join().expect("Joining AOCS thread failed"); diff --git a/satrs-example/src/tcp.rs b/satrs-example/src/tcp.rs new file mode 100644 index 0000000..a25804a --- /dev/null +++ b/satrs-example/src/tcp.rs @@ -0,0 +1,110 @@ +use std::{ + collections::VecDeque, + sync::{Arc, Mutex}, +}; + +use log::{info, warn}; +use satrs_core::{ + hal::std::tcp_server::{ServerConfig, TcpSpacepacketsServer}, + spacepackets::PacketId, + tmtc::{CcsdsDistributor, CcsdsError, TmPacketSourceCore}, +}; +use satrs_example::PUS_APID; + +use crate::tmtc::MpscStoreAndSendError; + +pub const PACKET_ID_LOOKUP: &[PacketId] = &[PacketId::const_tc(true, PUS_APID)]; + +#[derive(Default, Clone)] +pub struct SyncTcpTmSource { + tm_queue: Arc>>>, + max_packets_stored: usize, + pub silent_packet_overwrite: bool, +} + +impl SyncTcpTmSource { + pub fn new(max_packets_stored: usize) -> Self { + Self { + tm_queue: Arc::default(), + max_packets_stored, + silent_packet_overwrite: true, + } + } + + pub fn add_tm(&mut self, tm: &[u8]) { + let mut tm_queue = self.tm_queue.lock().expect("locking tm queue failec"); + if tm_queue.len() > self.max_packets_stored { + if !self.silent_packet_overwrite { + warn!("TPC TM source is full, deleting oldest packet"); + } + tm_queue.pop_front(); + } + tm_queue.push_back(tm.to_vec()); + } +} + +impl TmPacketSourceCore for SyncTcpTmSource { + type Error = (); + + fn retrieve_packet(&mut self, buffer: &mut [u8]) -> Result { + let mut tm_queue = self.tm_queue.lock().expect("locking tm queue failed"); + if !tm_queue.is_empty() { + let next_vec = tm_queue.front().unwrap(); + if buffer.len() < next_vec.len() { + panic!( + "provided buffer too small, must be at least {} bytes", + next_vec.len() + ); + } + let next_vec = tm_queue.pop_front().unwrap(); + buffer[0..next_vec.len()].copy_from_slice(&next_vec); + if next_vec.len() > 9 { + let service = next_vec[7]; + let subservice = next_vec[8]; + info!("Sending PUS TM[{service},{subservice}]") + } else { + info!("Sending PUS TM"); + } + return Ok(next_vec.len()); + } + Ok(0) + } +} + +pub struct TcpTask { + server: TcpSpacepacketsServer<(), CcsdsError>, +} + +impl TcpTask { + pub fn new( + cfg: ServerConfig, + tm_source: SyncTcpTmSource, + tc_receiver: CcsdsDistributor, + ) -> Result { + Ok(Self { + server: TcpSpacepacketsServer::new( + cfg, + Box::new(tm_source), + Box::new(tc_receiver), + Box::new(PACKET_ID_LOOKUP), + )?, + }) + } + + pub fn periodic_operation(&mut self) { + loop { + let result = self.server.handle_next_connection(); + match result { + Ok(conn_result) => { + info!( + "Served {} TMs and {} TCs for client {:?}", + conn_result.num_sent_tms, conn_result.num_received_tcs, conn_result.addr + ); + } + Err(e) => { + warn!("TCP server error: {e:?}"); + } + } + } + } +} diff --git a/satrs-example/src/tmtc.rs b/satrs-example/src/tmtc.rs index 9b52367..8af701a 100644 --- a/satrs-example/src/tmtc.rs +++ b/satrs-example/src/tmtc.rs @@ -1,8 +1,6 @@ -use log::{info, warn}; -use satrs_core::hal::std::udp_server::{ReceiveResult, UdpTcServer}; +use log::warn; use satrs_core::pus::ReceivesEcssPusTc; use satrs_core::spacepackets::SpHeader; -use std::net::SocketAddr; use std::sync::mpsc::{Receiver, SendError, Sender, TryRecvError}; use thiserror::Error; @@ -12,12 +10,12 @@ use satrs_core::pus::TcAddrWithToken; use satrs_core::spacepackets::ecss::tc::PusTcReader; use satrs_core::spacepackets::ecss::PusPacket; use satrs_core::tmtc::tm_helper::SharedTmStore; -use satrs_core::tmtc::{CcsdsError, ReceivesCcsdsTc}; +use satrs_core::tmtc::ReceivesCcsdsTc; pub struct TmArgs { pub tm_store: SharedTmStore, pub tm_sink_sender: Sender, - pub tm_server_rx: Receiver, + pub tm_udp_server_rx: Receiver, } pub struct TcArgs { @@ -61,7 +59,6 @@ pub struct TmFunnel { pub tm_server_tx: Sender, } - #[derive(Clone)] pub struct PusTcSource { pub tc_source: Sender, From 7cfa4f978516fa02757c8893374180166900bc5a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Sep 2023 14:13:22 +0200 Subject: [PATCH 22/31] extend README --- satrs-example/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/satrs-example/README.md b/satrs-example/README.md index 5841a9d..da5551f 100644 --- a/satrs-example/README.md +++ b/satrs-example/README.md @@ -57,8 +57,9 @@ and corresponding op codes (`-o` flag) for each service. The example project contains components which could also be expected to be part of a production On-Board Software. -1. A UDP server to receive telecommands and poll telemetry from. This might be an optional - component for an OBSW which is only used during the development phase on ground. +1. A UDP and TCP server to receive telecommands and poll telemetry from. This might be an optional + component for an OBSW which is only used during the development phase on ground. The TCP + server parses space packets by using the CCSDS space packet ID as the packet start delimiter. 2. A PUS service stack which exposes some functionality conformant with the ECSS PUS service. This currently includes the following services: - Service 1 for telecommand verification. From 40bf53d261fa1ce7d1d2fab598b85ba393982d07 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Sep 2023 14:17:25 +0200 Subject: [PATCH 23/31] extend introduction --- satrs-book/src/introduction.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/satrs-book/src/introduction.md b/satrs-book/src/introduction.md index 31a0b0c..f448441 100644 --- a/satrs-book/src/introduction.md +++ b/satrs-book/src/introduction.md @@ -21,3 +21,9 @@ A lot of the architecture and general design considerations are based on the through the 2 missions [FLP](https://www.irs.uni-stuttgart.de/en/research/satellitetechnology-and-instruments/smallsatelliteprogram/flying-laptop/) and [EIVE](https://www.irs.uni-stuttgart.de/en/research/satellitetechnology-and-instruments/smallsatelliteprogram/EIVE/). +# Getting started with the example + +The [`satrs-example`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-example) +provides various practical usage examples of the `sat-rs` framework. If you are more interested in +the practical application of `sat-rs` inside an application, it is recommended to have a look at +the example application. From 76546709674b7304d0ab7242426eb0f685eab7ad Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 1 Oct 2023 13:55:42 +0200 Subject: [PATCH 24/31] this intermediate struct is not necessary --- satrs-core/src/hal/std/tcp_server.rs | 95 +++++++++++----------------- 1 file changed, 36 insertions(+), 59 deletions(-) diff --git a/satrs-core/src/hal/std/tcp_server.rs b/satrs-core/src/hal/std/tcp_server.rs index e9fe657..cc721bd 100644 --- a/satrs-core/src/hal/std/tcp_server.rs +++ b/satrs-core/src/hal/std/tcp_server.rs @@ -137,7 +137,13 @@ pub struct TcpTmtcGenericServer< TmHandler: TcpTmSender, TcHandler: TcpTcParser, > { - base: TcpTmtcServerBase, + // base: TcpTmtcServerBase, + pub(crate) listener: TcpListener, + pub(crate) inner_loop_delay: Duration, + pub(crate) tm_source: Box>, + pub(crate) tm_buffer: Vec, + pub(crate) tc_receiver: Box>, + pub(crate) tc_buffer: Vec, tc_handler: TcHandler, tm_handler: TmHandler, } @@ -168,22 +174,34 @@ impl< tm_source: Box>, tc_receiver: Box>, ) -> Result, std::io::Error> { + // Create a TCP listener bound to two addresses. + let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; + socket.set_reuse_address(cfg.reuse_addr)?; + socket.set_reuse_port(cfg.reuse_port)?; + let addr = (cfg.addr).into(); + socket.bind(&addr)?; + socket.listen(128)?; Ok(Self { - base: TcpTmtcServerBase::new(cfg, tm_source, tc_receiver)?, tc_handler: tc_parser, tm_handler: tm_sender, + listener: socket.into(), + inner_loop_delay: cfg.inner_loop_delay, + tm_source, + tm_buffer: vec![0; cfg.tm_buffer_size], + tc_receiver, + tc_buffer: vec![0; cfg.tc_buffer_size], }) } /// Retrieve the internal [TcpListener] class. pub fn listener(&mut self) -> &mut TcpListener { - self.base.listener() + &mut self.listener } /// Can be used to retrieve the local assigned address of the TCP server. This is especially /// useful if using the port number 0 for OS auto-assignment. pub fn local_addr(&self) -> std::io::Result { - self.base.local_addr() + self.listener.local_addr() } /// This call is used to handle the next connection to a client. Right now, it performs @@ -205,20 +223,20 @@ impl< let mut connection_result = ConnectionResult::default(); let mut current_write_idx; let mut next_write_idx = 0; - let (mut stream, addr) = self.base.listener.accept()?; + let (mut stream, addr) = self.listener.accept()?; stream.set_nonblocking(true)?; connection_result.addr = Some(addr); current_write_idx = next_write_idx; loop { - let read_result = stream.read(&mut self.base.tc_buffer[current_write_idx..]); + let read_result = stream.read(&mut self.tc_buffer[current_write_idx..]); match read_result { Ok(0) => { // Connection closed by client. If any TC was read, parse for complete packets. // After that, break the outer loop. if current_write_idx > 0 { self.tc_handler.handle_tc_parsing( - &mut self.base.tc_buffer, - self.base.tc_receiver.as_mut(), + &mut self.tc_buffer, + self.tc_receiver.as_mut(), &mut connection_result, current_write_idx, &mut next_write_idx, @@ -229,10 +247,10 @@ impl< Ok(read_len) => { current_write_idx += read_len; // TC buffer is full, we must parse for complete packets now. - if current_write_idx == self.base.tc_buffer.capacity() { + if current_write_idx == self.tc_buffer.capacity() { self.tc_handler.handle_tc_parsing( - &mut self.base.tc_buffer, - self.base.tc_receiver.as_mut(), + &mut self.tc_buffer, + self.tc_receiver.as_mut(), &mut connection_result, current_write_idx, &mut next_write_idx, @@ -245,8 +263,8 @@ impl< // both UNIX and Windows. std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut => { self.tc_handler.handle_tc_parsing( - &mut self.base.tc_buffer, - self.base.tc_receiver.as_mut(), + &mut self.tc_buffer, + self.tc_receiver.as_mut(), &mut connection_result, current_write_idx, &mut next_write_idx, @@ -254,14 +272,14 @@ impl< current_write_idx = next_write_idx; if !self.tm_handler.handle_tm_sending( - &mut self.base.tm_buffer, - self.base.tm_source.as_mut(), + &mut self.tm_buffer, + self.tm_source.as_mut(), &mut connection_result, &mut stream, )? { // No TC read, no TM was sent, but the client has not disconnected. // Perform an inner delay to avoid burning CPU time. - thread::sleep(self.base.inner_loop_delay); + thread::sleep(self.inner_loop_delay); } } _ => { @@ -271,8 +289,8 @@ impl< } } self.tm_handler.handle_tm_sending( - &mut self.base.tm_buffer, - self.base.tm_source.as_mut(), + &mut self.tm_buffer, + self.tm_source.as_mut(), &mut connection_result, &mut stream, )?; @@ -280,47 +298,6 @@ impl< } } -pub(crate) struct TcpTmtcServerBase { - pub(crate) listener: TcpListener, - pub(crate) inner_loop_delay: Duration, - pub(crate) tm_source: Box>, - pub(crate) tm_buffer: Vec, - pub(crate) tc_receiver: Box>, - pub(crate) tc_buffer: Vec, -} - -impl TcpTmtcServerBase { - pub(crate) fn new( - cfg: ServerConfig, - tm_source: Box>, - tc_receiver: Box>, - ) -> Result { - // Create a TCP listener bound to two addresses. - let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; - socket.set_reuse_address(cfg.reuse_addr)?; - socket.set_reuse_port(cfg.reuse_port)?; - let addr = (cfg.addr).into(); - socket.bind(&addr)?; - socket.listen(128)?; - Ok(Self { - listener: socket.into(), - inner_loop_delay: cfg.inner_loop_delay, - tm_source, - tm_buffer: vec![0; cfg.tm_buffer_size], - tc_receiver, - tc_buffer: vec![0; cfg.tc_buffer_size], - }) - } - - pub(crate) fn listener(&mut self) -> &mut TcpListener { - &mut self.listener - } - - pub(crate) fn local_addr(&self) -> std::io::Result { - self.listener.local_addr() - } -} - #[cfg(test)] pub(crate) mod tests { use std::sync::Mutex; From 157d90479457dbd9e2ccebe924495d7d03580162 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 1 Oct 2023 14:32:15 +0200 Subject: [PATCH 25/31] no box necessary.. --- satrs-core/src/hal/std/tcp_cobs_server.rs | 31 +++++++++++----- satrs-core/src/hal/std/tcp_server.rs | 36 ++++++++++-------- .../src/hal/std/tcp_spacepackets_server.rs | 37 +++++++++++++------ satrs-core/tests/tcp_servers.rs | 8 ++-- 4 files changed, 71 insertions(+), 41 deletions(-) diff --git a/satrs-core/src/hal/std/tcp_cobs_server.rs b/satrs-core/src/hal/std/tcp_cobs_server.rs index 4a22a8a..cd99f47 100644 --- a/satrs-core/src/hal/std/tcp_cobs_server.rs +++ b/satrs-core/src/hal/std/tcp_cobs_server.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::vec; use cobs::encode; use delegate::delegate; @@ -111,11 +110,23 @@ impl TcpTmSender for CobsTmSender { /// /// The [TCP integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-core/tests/tcp_servers.rs) /// test also serves as the example application for this module. -pub struct TcpTmtcInCobsServer { - generic_server: TcpTmtcGenericServer, +pub struct TcpTmtcInCobsServer< + TmError, + TcError: 'static, + TmSource: TmPacketSource, + TcReceiver: ReceivesTc, +> { + generic_server: + TcpTmtcGenericServer, } -impl TcpTmtcInCobsServer { +impl< + TmError: 'static, + TcError: 'static, + TmSource: TmPacketSource, + TcReceiver: ReceivesTc, + > TcpTmtcInCobsServer +{ /// Create a new TCP TMTC server which exchanges TMTC packets encoded with /// [COBS protocol](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing). /// @@ -128,8 +139,8 @@ impl TcpTmtcInCobsServer { /// forwarded to this TC receiver. pub fn new( cfg: ServerConfig, - tm_source: Box>, - tc_receiver: Box>, + tm_source: TmSource, + tc_receiver: TcReceiver, ) -> Result> { Ok(Self { generic_server: TcpTmtcGenericServer::new( @@ -177,7 +188,7 @@ mod tests { ServerConfig, }, }; - use alloc::{boxed::Box, sync::Arc}; + use alloc::sync::Arc; use cobs::encode; use super::TcpTmtcInCobsServer; @@ -202,11 +213,11 @@ mod tests { addr: &SocketAddr, tc_receiver: SyncTcCacher, tm_source: SyncTmSource, - ) -> TcpTmtcInCobsServer<(), ()> { + ) -> TcpTmtcInCobsServer<(), (), SyncTmSource, SyncTcCacher> { TcpTmtcInCobsServer::new( ServerConfig::new(*addr, Duration::from_millis(2), 1024, 1024), - Box::new(tm_source), - Box::new(tc_receiver), + tm_source, + tc_receiver, ) .expect("TCP server generation failed") } diff --git a/satrs-core/src/hal/std/tcp_server.rs b/satrs-core/src/hal/std/tcp_server.rs index cc721bd..0b5359d 100644 --- a/satrs-core/src/hal/std/tcp_server.rs +++ b/satrs-core/src/hal/std/tcp_server.rs @@ -1,6 +1,6 @@ //! Generic TCP TMTC servers with different TMTC format flavours. use alloc::vec; -use alloc::{boxed::Box, vec::Vec}; +use alloc::vec::Vec; use core::time::Duration; use socket2::{Domain, Socket, Type}; use std::io::Read; @@ -134,26 +134,30 @@ pub trait TcpTmSender { pub struct TcpTmtcGenericServer< TmError, TcError, - TmHandler: TcpTmSender, - TcHandler: TcpTcParser, + TmSource: TmPacketSource, + TcReceiver: ReceivesTc, + TmSender: TcpTmSender, + TcParser: TcpTcParser, > { // base: TcpTmtcServerBase, pub(crate) listener: TcpListener, pub(crate) inner_loop_delay: Duration, - pub(crate) tm_source: Box>, + pub(crate) tm_source: TmSource, pub(crate) tm_buffer: Vec, - pub(crate) tc_receiver: Box>, + pub(crate) tc_receiver: TcReceiver, pub(crate) tc_buffer: Vec, - tc_handler: TcHandler, - tm_handler: TmHandler, + tc_handler: TcParser, + tm_handler: TmSender, } impl< TmError: 'static, TcError: 'static, + TmSource: TmPacketSource, + TcReceiver: ReceivesTc, TmSender: TcpTmSender, TcParser: TcpTcParser, - > TcpTmtcGenericServer + > TcpTmtcGenericServer { /// Create a new generic TMTC server instance. /// @@ -171,9 +175,9 @@ impl< cfg: ServerConfig, tc_parser: TcParser, tm_sender: TmSender, - tm_source: Box>, - tc_receiver: Box>, - ) -> Result, std::io::Error> { + tm_source: TmSource, + tc_receiver: TcReceiver, + ) -> Result { // Create a TCP listener bound to two addresses. let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; socket.set_reuse_address(cfg.reuse_addr)?; @@ -236,7 +240,7 @@ impl< if current_write_idx > 0 { self.tc_handler.handle_tc_parsing( &mut self.tc_buffer, - self.tc_receiver.as_mut(), + &mut self.tc_receiver, &mut connection_result, current_write_idx, &mut next_write_idx, @@ -250,7 +254,7 @@ impl< if current_write_idx == self.tc_buffer.capacity() { self.tc_handler.handle_tc_parsing( &mut self.tc_buffer, - self.tc_receiver.as_mut(), + &mut self.tc_receiver, &mut connection_result, current_write_idx, &mut next_write_idx, @@ -264,7 +268,7 @@ impl< std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut => { self.tc_handler.handle_tc_parsing( &mut self.tc_buffer, - self.tc_receiver.as_mut(), + &mut self.tc_receiver, &mut connection_result, current_write_idx, &mut next_write_idx, @@ -273,7 +277,7 @@ impl< if !self.tm_handler.handle_tm_sending( &mut self.tm_buffer, - self.tm_source.as_mut(), + &mut self.tm_source, &mut connection_result, &mut stream, )? { @@ -290,7 +294,7 @@ impl< } self.tm_handler.handle_tm_sending( &mut self.tm_buffer, - self.tm_source.as_mut(), + &mut self.tm_source, &mut connection_result, &mut stream, )?; diff --git a/satrs-core/src/hal/std/tcp_spacepackets_server.rs b/satrs-core/src/hal/std/tcp_spacepackets_server.rs index 42c61e9..23c8466 100644 --- a/satrs-core/src/hal/std/tcp_spacepackets_server.rs +++ b/satrs-core/src/hal/std/tcp_spacepackets_server.rs @@ -88,16 +88,31 @@ impl TcpTmSender for SpacepacketsTmSender { /// [spacepackets::PacketId]s as part of the server configuration for that purpose. /// /// ## Example -/// /// The [TCP server integration tests](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-core/tests/tcp_servers.rs) /// also serves as the example application for this module. -pub struct TcpSpacepacketsServer { - generic_server: - TcpTmtcGenericServer, +pub struct TcpSpacepacketsServer< + TmError, + TcError: 'static, + TmSource: TmPacketSource, + TcReceiver: ReceivesTc, +> { + generic_server: TcpTmtcGenericServer< + TmError, + TcError, + TmSource, + TcReceiver, + SpacepacketsTmSender, + SpacepacketsTcParser, + >, } -impl TcpSpacepacketsServer { - /// Create a new TCP TMTC server which exchanges CCSDS space packets. +impl< + TmError: 'static, + TcError: 'static, + TmSource: TmPacketSource, + TcReceiver: ReceivesTc, + > TcpSpacepacketsServer +{ /// /// ## Parameter /// @@ -110,8 +125,8 @@ impl TcpSpacepacketsServer /// parsing. This mechanism is used to have a start marker for finding CCSDS packets. pub fn new( cfg: ServerConfig, - tm_source: Box>, - tc_receiver: Box>, + tm_source: TmSource, + tc_receiver: TcReceiver, packet_id_lookup: Box, ) -> Result> { Ok(Self { @@ -179,11 +194,11 @@ mod tests { tc_receiver: SyncTcCacher, tm_source: SyncTmSource, packet_id_lookup: HashSet, - ) -> TcpSpacepacketsServer<(), ()> { + ) -> TcpSpacepacketsServer<(), (), SyncTmSource, SyncTcCacher> { TcpSpacepacketsServer::new( ServerConfig::new(*addr, Duration::from_millis(2), 1024, 1024), - Box::new(tm_source), - Box::new(tc_receiver), + tm_source, + tc_receiver, Box::new(packet_id_lookup), ) .expect("TCP server generation failed") diff --git a/satrs-core/tests/tcp_servers.rs b/satrs-core/tests/tcp_servers.rs index d66c1fb..251eead 100644 --- a/satrs-core/tests/tcp_servers.rs +++ b/satrs-core/tests/tcp_servers.rs @@ -94,8 +94,8 @@ fn test_cobs_server() { tm_source.add_tm(&INVERTED_PACKET); let mut tcp_server = TcpTmtcInCobsServer::new( ServerConfig::new(AUTO_PORT_ADDR, Duration::from_millis(2), 1024, 1024), - Box::new(tm_source), - Box::new(tc_receiver.clone()), + tm_source, + tc_receiver.clone(), ) .expect("TCP server generation failed"); let dest_addr = tcp_server @@ -176,8 +176,8 @@ fn test_ccsds_server() { packet_id_lookup.insert(TEST_PACKET_ID_0); let mut tcp_server = TcpSpacepacketsServer::new( ServerConfig::new(AUTO_PORT_ADDR, Duration::from_millis(2), 1024, 1024), - Box::new(tm_source), - Box::new(tc_receiver.clone()), + tm_source, + tc_receiver.clone(), Box::new(packet_id_lookup), ) .expect("TCP server generation failed"); From 922631022cb1944e912588d6848c44e039c70a17 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 1 Oct 2023 14:48:41 +0200 Subject: [PATCH 26/31] some tiny tweaks --- satrs-core/src/hal/std/tcp_cobs_server.rs | 1 - satrs-core/src/hal/std/tcp_server.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/satrs-core/src/hal/std/tcp_cobs_server.rs b/satrs-core/src/hal/std/tcp_cobs_server.rs index cd99f47..0f43710 100644 --- a/satrs-core/src/hal/std/tcp_cobs_server.rs +++ b/satrs-core/src/hal/std/tcp_cobs_server.rs @@ -28,7 +28,6 @@ impl TcpTcParser for CobsTcParser { current_write_idx: usize, next_write_idx: &mut usize, ) -> Result<(), TcpTmtcError> { - // Reader vec full, need to parse for packets. conn_result.num_received_tcs += parse_buffer_for_cobs_encoded_packets( &mut tc_buffer[..current_write_idx], tc_receiver.upcast_mut(), diff --git a/satrs-core/src/hal/std/tcp_server.rs b/satrs-core/src/hal/std/tcp_server.rs index 0b5359d..184c4c1 100644 --- a/satrs-core/src/hal/std/tcp_server.rs +++ b/satrs-core/src/hal/std/tcp_server.rs @@ -139,7 +139,6 @@ pub struct TcpTmtcGenericServer< TmSender: TcpTmSender, TcParser: TcpTcParser, > { - // base: TcpTmtcServerBase, pub(crate) listener: TcpListener, pub(crate) inner_loop_delay: Duration, pub(crate) tm_source: TmSource, From e75a145b0e8b56776586be135ab77b3707085737 Mon Sep 17 00:00:00 2001 From: lkoester Date: Thu, 26 Oct 2023 13:34:37 +0200 Subject: [PATCH 27/31] made set_reuse_port unix only --- satrs-core/src/hal/std/tcp_server.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/satrs-core/src/hal/std/tcp_server.rs b/satrs-core/src/hal/std/tcp_server.rs index 184c4c1..deeb902 100644 --- a/satrs-core/src/hal/std/tcp_server.rs +++ b/satrs-core/src/hal/std/tcp_server.rs @@ -180,6 +180,7 @@ impl< // Create a TCP listener bound to two addresses. let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; socket.set_reuse_address(cfg.reuse_addr)?; + #[cfg(unix)] socket.set_reuse_port(cfg.reuse_port)?; let addr = (cfg.addr).into(); socket.bind(&addr)?; From 80305466e507749823064b3f71ece89206ad2722 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 11 Nov 2023 16:33:43 +0100 Subject: [PATCH 28/31] bump tmtccmd dependency --- satrs-example/pyclient/main.py | 4 ++-- satrs-example/pyclient/pus_tc.py | 6 +++--- satrs-example/pyclient/requirements.txt | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/satrs-example/pyclient/main.py b/satrs-example/pyclient/main.py index 4f3c6c4..53a15f6 100755 --- a/satrs-example/pyclient/main.py +++ b/satrs-example/pyclient/main.py @@ -14,7 +14,7 @@ from spacepackets.ccsds.time import CdsShortTimestamp from tmtccmd import CcsdsTmtcBackend, TcHandlerBase, ProcedureParamsWrapper from tmtccmd.core.base import BackendRequest from tmtccmd.pus import VerificationWrapper -from tmtccmd.tm import CcsdsTmHandler, SpecificApidHandlerBase +from tmtccmd.tmtc import CcsdsTmHandler, SpecificApidHandlerBase from tmtccmd.com import ComInterface from tmtccmd.config import ( default_json_path, @@ -30,7 +30,7 @@ from tmtccmd.logging.pus import ( RawTmtcTimedLogWrapper, TimedLogWhen, ) -from tmtccmd.tc import ( +from tmtccmd.tmtc import ( TcQueueEntryType, ProcedureWrapper, TcProcedureType, diff --git a/satrs-example/pyclient/pus_tc.py b/satrs-example/pyclient/pus_tc.py index 4373cb4..9996e5b 100644 --- a/satrs-example/pyclient/pus_tc.py +++ b/satrs-example/pyclient/pus_tc.py @@ -3,9 +3,9 @@ import datetime from spacepackets.ccsds import CdsShortTimestamp from spacepackets.ecss import PusTelecommand from tmtccmd.config import CoreServiceList -from tmtccmd.tc import DefaultPusQueueHelper -from tmtccmd.tc.pus_11_tc_sched import create_time_tagged_cmd -from tmtccmd.tc.pus_3_fsfw_hk import create_request_one_hk_command +from tmtccmd.tmtc import DefaultPusQueueHelper +from tmtccmd.pus.s11_tc_sched import create_time_tagged_cmd +from tmtccmd.pus.tc.s3_fsfw_hk import create_request_one_hk_command from common import ( EXAMPLE_PUS_APID, diff --git a/satrs-example/pyclient/requirements.txt b/satrs-example/pyclient/requirements.txt index 4f61463..485c76a 100644 --- a/satrs-example/pyclient/requirements.txt +++ b/satrs-example/pyclient/requirements.txt @@ -1,2 +1,2 @@ -tmtccmd == 6.0.0 +tmtccmd == 7.0.0 # -e git+https://github.com/robamu-org/tmtccmd@97e5e51101a08b21472b3ddecc2063359f7e307a#egg=tmtccmd From ca360d2d8dcebe43eb3ed0a0ce276874d8035dd7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 11 Nov 2023 16:36:13 +0100 Subject: [PATCH 29/31] ruff fix --- satrs-example/pyclient/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/satrs-example/pyclient/main.py b/satrs-example/pyclient/main.py index 53a15f6..c749e26 100755 --- a/satrs-example/pyclient/main.py +++ b/satrs-example/pyclient/main.py @@ -128,6 +128,7 @@ class PusHandler(SpecificApidHandlerBase): if len(pus_tm.source_data) < 8: raise ValueError("No addressable ID in HK packet") json_str = pus_tm.source_data[8:] + _LOGGER.info(json_str) dedicated_handler = True if service == 5: tm_packet = PusTelemetry.unpack( From 8142ae9c389095de9c3770ad18524a733b7df732 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 1 Dec 2023 22:21:12 +0100 Subject: [PATCH 30/31] add coverage --- README.md | 13 ++++++++++++ coverage.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100755 coverage.py diff --git a/README.md b/README.md index 0dd8276..172d0ce 100644 --- a/README.md +++ b/README.md @@ -43,3 +43,16 @@ Each project has its own `CHANGELOG.md`. packet protocol implementations. This repository is re-exported in the [`satrs-core`](https://egit.irs.uni-stuttgart.de/rust/satrs-launchpad/src/branch/main/satrs-core) crate. + +# Coverage + +Coverage was generated using [`grcov`](https://github.com/mozilla/grcov). If you have not done so +already, install the `llvm-tools-preview`: + +```sh +rustup component add llvm-tools-preview +cargo install grcov --locked +``` + +After that, you can simply run `coverage.py` to test the `satrs-core` crate with coverage. You can +optionally supply the `--open` flag to open the coverage report in your webbrowser. diff --git a/coverage.py b/coverage.py new file mode 100755 index 0000000..b7efbe9 --- /dev/null +++ b/coverage.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +import os +import logging +import argparse +import webbrowser + + +_LOGGER = logging.getLogger() + + +def generate_cov_report(open_report: bool, format: str, package: str): + logging.basicConfig(level=logging.INFO) + os.environ["RUSTFLAGS"] = "-Cinstrument-coverage" + os.environ["LLVM_PROFILE_FILE"] = "target/coverage/%p-%m.profraw" + _LOGGER.info("Executing tests with coverage") + os.system(f"cargo test -p {package}") + + out_path = "./target/debug/coverage" + if format == "lcov": + out_path = "./target/debug/lcov.info" + os.system( + f"grcov . -s . --binary-path ./target/debug/ -t {format} --branch --ignore-not-existing " + f"-o {out_path}" + ) + if format == "lcov": + os.system( + "genhtml -o ./target/debug/coverage/ --show-details --highlight --ignore-errors source " + "--legend ./target/debug/lcov.info" + ) + if open_report: + coverage_report_path = os.path.abspath("./target/debug/coverage/index.html") + webbrowser.open_new_tab(coverage_report_path) + _LOGGER.info("Done") + + +def main(): + parser = argparse.ArgumentParser( + description="Generate coverage report and optionally open it in a browser" + ) + parser.add_argument( + "--open", action="store_true", help="Open the coverage report in a browser" + ) + parser.add_argument( + "-p", + "--package", + choices=["satrs-core"], + default="satrs-core", + help="Choose project to generate coverage for", + ) + parser.add_argument( + "--format", + choices=["html", "lcov"], + default="html", + help="Choose report format (html or lcov)", + ) + args = parser.parse_args() + generate_cov_report(args.open, args.format, args.package) + + +if __name__ == "__main__": + main() From 094a9f0956bf54a99ac911f4c9cc3832e6140088 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 11 Dec 2023 15:12:50 +0100 Subject: [PATCH 31/31] remove those trailing slashes --- automation/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automation/Jenkinsfile b/automation/Jenkinsfile index 937fea1..0a27b8b 100644 --- a/automation/Jenkinsfile +++ b/automation/Jenkinsfile @@ -67,7 +67,7 @@ pipeline { sh 'mdbook build' sshagent(credentials: ['documentation-buildfix']) { // Deploy to Apache webserver - sh 'rsync -r --delete book/ buildfix@documentation.irs.uni-stuttgart.de:/projects/sat-rs' + sh 'rsync -r --delete book buildfix@documentation.irs.uni-stuttgart.de:/projects/sat-rs' } } }