19 Commits

Author SHA1 Message Date
35073a45a5 this should make clippy happy
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-16 11:12:47 +02:00
3b11af8d4a fix for ci.yml
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-16 11:03:51 +02:00
0fcf150707 some links added
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-16 10:51:40 +02:00
dbe0e3062f now this should work
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-16 10:50:21 +02:00
20d5baaa0d tiny typo
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
2022-08-16 10:47:33 +02:00
8146c4953c remove chrono serde subfeature
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
2022-08-16 10:46:51 +02:00
c6f7b04a6c some doc sync
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
2022-08-16 10:43:32 +02:00
72b8f45161 small jenkinsfile fix
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
2022-08-16 10:38:06 +02:00
c5b16f006f weird permission errors
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
2022-08-16 10:35:44 +02:00
0cd6817415 one more attempt
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
2022-08-16 10:33:09 +02:00
8f20b1962c try cross-compilation in docker
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
2022-08-16 10:28:06 +02:00
3e80dd314a try without cross
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-16 10:24:50 +02:00
1bac620853 maybe this works?
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
2022-08-16 10:23:39 +02:00
41fa073c74 added test stage in jenkinsfile
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
2022-08-16 10:20:00 +02:00
388a8ba616 some more dependency cleanup
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-16 10:11:49 +02:00
933230126e tested cross-compilation 2022-08-16 02:15:57 +02:00
15b32c9444 add github workflow
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-16 01:26:39 +02:00
14b6171112 update changelog
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-16 01:17:10 +02:00
1969f1bfa0 bump postcard deps
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-14 18:12:52 +02:00
11 changed files with 216 additions and 69 deletions

83
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,83 @@
on: [push]
name: ci
jobs:
check:
name: Check
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
- uses: actions-rs/cargo@v1
with:
command: check
args: --release
cross-check:
name: Check Cross
runs-on: ubuntu-latest
strategy:
matrix:
target:
- armv7-unknown-linux-gnueabihf
- thumbv7em-none-eabihf
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
target: ${{ matrix.target }}
override: true
- uses: actions-rs/cargo@v1
with:
use-cross: true
command: check
args: --release --target=${{ matrix.target }} --no-default-features
fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- run: rustup component add rustfmt
- uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
- run: rustup component add clippy
- uses: actions-rs/cargo@v1
with:
command: clippy
args: -- -D warnings
ci:
if: ${{ success() }}
# all new jobs must be added to this list
needs: [check, fmt, clippy]
runs-on: ubuntu-latest
steps:
- name: CI succeeded
run: exit 0

View File

@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased]
## [0.1.0]
## [v0.1.0] 16.08.2022
Initial version with CCSDS Space Packet Primary Header
implementation and basic PUS TC and TM implementations
Initial release with CCSDS Space Packet Primary Header implementation and basic PUS TC and TM
implementations.

View File

@ -12,18 +12,27 @@ categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-sup
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
num = "0.4"
serde = { version = "1.0.142", features = ["derive"] }
zerocopy = "0.6.1"
crc = "3.0.0"
delegate = "0.7.0"
chrono = "0.4.20"
[dependencies.serde]
version = "1.0.142"
default-features = false
features = ["derive"]
[dependencies.chrono]
version = "0.4.20"
default-features = false
[dependencies.num-traits]
version = "0.2"
default-features = false
[dev-dependencies.postcard]
version = "0.7.3"
features = ["use-std"]
version = "1.0.1"
[features]
default = ["alloc"]
std = ["postcard/use-std"]
alloc = ["serde/alloc"]
default = ["std"]
std = ["chrono/std", "chrono/clock", "alloc"]
alloc = ["postcard/alloc"]

View File

@ -1,3 +1,7 @@
[![Crates.io](https://img.shields.io/crates/v/spacepackets)](https://crates.io/crates/spacepackets)
[![docs.rs](https://img.shields.io/docsrs/spacepackets)](https://docs.rs/spacepackets)
[![ci](https://github.com/us-irs/spacepackets-rs/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/us-irs/spacepackets-rs/actions/workflows/ci.yml)
ECSS and CCSDS Spacepackets
======
@ -11,13 +15,23 @@ Currently, this includes the following components:
[CCSDS Blue Book 133.0-B-2](https://public.ccsds.org/Pubs/133x0b2e1.pdf)
- PUS Telecommand and PUS Telemetry implementation according to the
[ECSS-E-ST-70-41C standard](https://ecss.nl/standard/ecss-e-st-70-41c-space-engineering-telemetry-and-telecommand-packet-utilization-15-april-2016/).
- CDS Short Time Code implementations according to
- CDS Short Time Code implementation according to
[CCSDS CCSDS 301.0-B-4](https://public.ccsds.org/Pubs/301x0b4e1.pdf)
This package is suitable for `no_std` environments.
# Features
It features optional support for the [`alloc`](https://doc.rust-lang.org/alloc/) crate
and also offers support for [`serde`](https://serde.rs/). The Space Paccket, PUS TM and TC implementations
derive the `serde` `Serialize` and `Deserialize` trait. This allows serializing and
`spacepackets` supports various runtime environments and is also suitable
for suitable for `no_std` environments. It has several features which may be enabled
for disabled.
It also offers support for [`serde`](https://serde.rs/). The Space Paccket, PUS TM and TC
implementations derive the `serde` `Serialize` and `Deserialize` trait. This allows serializing and
deserializing them with an appropriate `serde` provider like
[`postcard`](https://github.com/jamesmunns/postcard).
Default features:
- [`std`](https://doc.rust-lang.org/std/): Enables functionality relying on the standard library.
- [`alloc`](https://doc.rust-lang.org/alloc/): Enables features which operate on containers
like [`alloc::vec::Vec`](https://doc.rust-lang.org/beta/alloc/vec/struct.Vec.html).
Enabled by the `std` feature.

View File

@ -7,4 +7,9 @@ RUN apt-get --yes upgrade
# tzdata is a dependency, won't install otherwise
ARG DEBIAN_FRONTEND=noninteractive
RUN rustup component add rustfmt clippy
# set CROSS_CONTAINER_IN_CONTAINER to inform `cross` that it is executed from within a container
ENV CROSS_CONTAINER_IN_CONTAINER=true
# TODO: installing cross is problematic, permission issues
RUN rustup target add thumbv7em-none-eabihf armv7-unknown-linux-gnueabihf && \
rustup component add rustfmt clippy

View File

@ -1,39 +1,42 @@
pipeline {
agent any
stages {
stage('Clippy') {
agent {
dockerfile {
dir 'automation'
reuseNode true
}
}
stages {
stage('Clippy') {
steps {
sh 'cargo clippy'
}
}
stage('Rustfmt') {
agent {
dockerfile {
dir 'automation'
reuseNode true
}
}
steps {
sh 'cargo fmt'
}
}
stage('Test') {
steps {
sh 'cargo test'
}
}
stage('Check') {
agent {
dockerfile {
dir 'automation'
reuseNode true
}
}
steps {
sh 'cargo check'
}
}
stage('Check Cross Embedded Bare Metal') {
steps {
sh 'cargo check --target thumbv7em-none-eabihf --no-default-features'
}
}
stage('Check Cross Embedded Linux') {
steps {
sh 'cargo check --target armv7-unknown-linux-gnueabihf'
}
}
}
}

View File

@ -12,7 +12,7 @@ pub const CRC_CCITT_FALSE: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_3740);
pub const CCSDS_HEADER_LEN: usize = size_of::<crate::zc::SpHeader>();
/// All PUS versions. Only PUS C is supported by this library.
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize, Debug)]
#[derive(PartialEq, Eq, Copy, Clone, Serialize, Deserialize, Debug)]
pub enum PusVersion {
EsaPus = 0,
PusA = 1,
@ -33,7 +33,7 @@ impl TryFrom<u8> for PusVersion {
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PusError {
VersionNotSupported(PusVersion),
IncorrectCrc(u16),

View File

@ -5,18 +5,38 @@
//! ECSS (European Cooperation for Space Standardization) packet standards.
//! Currently, this includes the following components:
//!
//! - [Space Packet][crate::SpHeader] implementation according to
//! - Space Packet implementation according to
//! [CCSDS Blue Book 133.0-B-2](https://public.ccsds.org/Pubs/133x0b2e1.pdf)
//! - [PUS Telecommand][crate::tc] and [PUS Telemetry][crate::tm] implementation according to the
//! - PUS Telecommand and PUS Telemetry implementation according to the
//! [ECSS-E-ST-70-41C standard](https://ecss.nl/standard/ecss-e-st-70-41c-space-engineering-telemetry-and-telecommand-packet-utilization-15-april-2016/).
//! - CDS Short Time Code implementation according to
//! [CCSDS CCSDS 301.0-B-4](https://public.ccsds.org/Pubs/301x0b4e1.pdf)
//!
//! # Module
//! ## Features
//!
//! `spacepackets` supports various runtime environments and is also suitable
//! for suitable for `no_std` environments. It has several features which may be enabled
//! for disabled.
//!
//! It also offers support for [`serde`](https://serde.rs/). The Space Paccket, PUS TM and TC
//! implementations derive the `serde` `Serialize` and `Deserialize` trait. This allows serializing and
//! deserializing them with an appropriate `serde` provider like
//! [`postcard`](https://github.com/jamesmunns/postcard).
//!
//! Default features:
//!
//! - [`std`](https://doc.rust-lang.org/std/): Enables functionality relying on the standard library.
//! - [`alloc`](https://doc.rust-lang.org/alloc/): Enables features which operate on containers
//! like [`alloc::vec::Vec`](https://doc.rust-lang.org/beta/alloc/vec/struct.Vec.html).
//! Enabled by the `std` feature.
//!
//! ## Module
//!
//! This module contains helpers and data structures to generate Space Packets according to the
//! [CCSDS 133.0-B-2](https://public.ccsds.org/Pubs/133x0b2e1.pdf). This includes the
//! [SpHeader] class to generate the Space Packet Header component common to all space packets
//!
//! # Example
//! ## Example
//!
//! ```rust
//! use spacepackets::SpHeader;
@ -24,13 +44,14 @@
//! println!("{:?}", sp_header);
//! ```
#![no_std]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
use crate::ecss::CCSDS_HEADER_LEN;
use delegate::delegate;
use serde::{Deserialize, Serialize};
pub mod ecss;
@ -38,12 +59,12 @@ pub mod tc;
pub mod time;
pub mod tm;
#[derive(Debug, Copy, Clone, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct SizeMissmatch {
pub found: usize,
pub expected: usize,
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PacketError {
/// The passed slice is too small. Returns the found and expected minimum size
ToBytesSliceTooSmall(SizeMissmatch),
@ -54,7 +75,7 @@ pub enum PacketError {
FromBytesZeroCopyError,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Copy, Clone)]
pub enum PacketType {
Tm = 0,
Tc = 1,
@ -76,7 +97,7 @@ pub fn packet_type_in_raw_packet_id(packet_id: u16) -> PacketType {
PacketType::try_from((packet_id >> 12) as u8 & 0b1).unwrap()
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Copy, Clone)]
pub enum SequenceFlags {
ContinuationSegment = 0b00,
FirstSegment = 0b01,
@ -100,7 +121,7 @@ impl TryFrom<u8> for SequenceFlags {
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Copy, Clone)]
pub struct PacketId {
pub ptype: PacketType,
pub sec_header_flag: bool,
@ -121,7 +142,7 @@ impl PacketId {
/// not be set and false will be returned. The maximum allowed value for the 11-bit field is
/// 2047
pub fn set_apid(&mut self, apid: u16) -> bool {
if apid > num::pow(2, 11) - 1 {
if apid > 2u16.pow(11) - 1 {
return false;
}
self.apid = apid;
@ -147,7 +168,7 @@ impl From<u16> for PacketId {
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Copy, Clone)]
pub struct PacketSequenceCtrl {
pub seq_flags: SequenceFlags,
seq_count: u16,
@ -168,7 +189,7 @@ impl PacketSequenceCtrl {
/// Set a new sequence count. If the passed number is invalid, the sequence count will not be
/// set and false will be returned. The maximum allowed value for the 14-bit field is 16383
pub fn set_seq_count(&mut self, ssc: u16) -> bool {
if ssc > num::pow(2, 14) - 1 {
if ssc > 2u16.pow(14) - 1 {
return false;
}
self.seq_count = ssc;
@ -293,7 +314,7 @@ pub trait CcsdsPrimaryHeader {
/// 13 bits of the first two bytes of the raw header
/// * `psc` - Packet Sequence Control, occupies the third and fourth byte of the raw header
/// * `data_len` - Data length field occupies the fifth and the sixth byte of the raw header
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Copy, Clone)]
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Copy, Clone)]
pub struct SpHeader {
pub version: u8,
pub packet_id: PacketId,
@ -325,7 +346,7 @@ impl SpHeader {
ssc: u16,
data_len: u16,
) -> Option<Self> {
if ssc > num::pow(2, 14) - 1 || apid > num::pow(2, 11) - 1 {
if ssc > 2u16.pow(14) - 1 || apid > 2u16.pow(11) - 1 {
return None;
}
let mut header = SpHeader::default();
@ -510,13 +531,21 @@ pub mod zc {
#[cfg(test)]
mod tests {
#[cfg(feature = "std")]
use crate::CcsdsPrimaryHeader;
use crate::SpHeader;
use crate::{
packet_type_in_raw_packet_id, zc, CcsdsPacket, CcsdsPrimaryHeader, PacketId,
PacketSequenceCtrl, PacketType, SequenceFlags,
packet_type_in_raw_packet_id, zc, CcsdsPacket, PacketId, PacketSequenceCtrl, PacketType,
SequenceFlags,
};
use alloc::vec;
use postcard::{from_bytes, to_stdvec};
#[cfg(not(feature = "std"))]
use num::pow;
#[cfg(feature = "std")]
use num_traits::pow;
use postcard::from_bytes;
#[cfg(feature = "alloc")]
use postcard::to_allocvec;
#[test]
fn test_seq_flag_helpers() {
@ -589,7 +618,7 @@ mod tests {
let psc_from_raw = PacketSequenceCtrl::from(psc.raw());
assert_eq!(psc_from_raw, psc);
// Fails because SSC is limited to 14 bits
assert!(!psc.set_seq_count(num::pow(2, 15)));
assert!(!psc.set_seq_count(2u16.pow(15)));
assert_eq!(psc.raw(), 77);
let psc_invalid = PacketSequenceCtrl::new(SequenceFlags::FirstSegment, 0xFFFF);
@ -599,6 +628,7 @@ mod tests {
}
#[test]
#[cfg(feature = "std")]
fn test_serde_sph() {
let sp_header = SpHeader::tc(0x42, 12, 0).expect("Error creating SP header");
assert_eq!(sp_header.ccsds_version(), 0b000);
@ -609,7 +639,7 @@ mod tests {
assert_eq!(sp_header.apid(), 0x42);
assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented);
assert_eq!(sp_header.data_len(), 0);
let output = to_stdvec(&sp_header).unwrap();
let output = to_allocvec(&sp_header).unwrap();
let sp_header: SpHeader = from_bytes(&output).unwrap();
assert_eq!(sp_header.version, 0b000);
assert!(!sp_header.packet_id.sec_header_flag);
@ -674,8 +704,7 @@ mod tests {
fn test_zc_sph() {
use zerocopy::AsBytes;
let sp_header =
SpHeader::tc(0x7FF, num::pow(2, 14) - 1, 0).expect("Error creating SP header");
let sp_header = SpHeader::tc(0x7FF, pow(2, 14) - 1, 0).expect("Error creating SP header");
assert_eq!(sp_header.ptype(), PacketType::Tc);
assert_eq!(sp_header.apid(), 0x7FF);
assert_eq!(sp_header.data_len(), 0);

View File

@ -134,7 +134,7 @@ pub mod zc {
}
}
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize, Debug)]
#[derive(PartialEq, Eq, Copy, Clone, Serialize, Deserialize, Debug)]
pub struct PusTcSecondaryHeader {
pub service: u8,
pub subservice: u8,
@ -209,7 +209,7 @@ impl PusTcSecondaryHeader {
/// [postcard](https://docs.rs/postcard/latest/postcard/).
///
/// There is no spare bytes support yet.
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize, Debug)]
#[derive(PartialEq, Eq, Copy, Clone, Serialize, Deserialize, Debug)]
pub struct PusTc<'slice> {
sp_header: SpHeader,
pub sec_header: PusTcSecondaryHeader,

View File

@ -2,6 +2,10 @@
use crate::{PacketError, SizeMissmatch};
use chrono::{DateTime, TimeZone, Utc};
#[allow(unused_imports)]
#[cfg(not(feature = "std"))]
use num_traits::float::FloatCore;
use crate::time::CcsdsTimeCodes::Cds;
#[cfg(feature = "std")]
use std::time::{SystemTime, SystemTimeError};
@ -10,7 +14,7 @@ pub const CDS_SHORT_LEN: usize = 7;
pub const DAYS_CCSDS_TO_UNIX: i32 = -4383;
pub const SECONDS_PER_DAY: u32 = 86400;
#[derive(Debug, PartialEq, Copy, Clone)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum CcsdsTimeCodes {
None = 0,
CucCcsdsEpoch = 0b001,
@ -34,7 +38,7 @@ impl TryFrom<u8> for CcsdsTimeCodes {
}
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq)]
pub enum TimestampError {
/// Contains tuple where first value is the expected time code and the second
/// value is the found raw value
@ -128,7 +132,7 @@ impl CdsShortTimeProvider {
unix_seconds: 0,
date_time: None,
};
Ok(provider.setup(unix_days_seconds as i64, ms_of_day.into()))
Ok(provider.setup(unix_days_seconds as i64, ms_of_day))
}
fn setup(mut self, unix_days_seconds: i64, ms_of_day: u64) -> Self {

View File

@ -103,7 +103,7 @@ pub mod zc {
}
}
#[derive(PartialEq, Serialize, Deserialize, Copy, Clone, Debug)]
#[derive(PartialEq, Eq, Serialize, Deserialize, Copy, Clone, Debug)]
pub struct PusTmSecondaryHeader<'slice> {
pus_version: PusVersion,
pub sc_time_ref_status: u8,
@ -197,7 +197,7 @@ impl<'slice> TryFrom<zc::PusTmSecHeader<'slice>> for PusTmSecondaryHeader<'slice
/// [postcard](https://docs.rs/postcard/latest/postcard/).
///
/// There is no spare bytes support yet.
#[derive(PartialEq, Serialize, Deserialize, Debug, Copy, Clone)]
#[derive(PartialEq, Eq, Serialize, Deserialize, Debug, Copy, Clone)]
pub struct PusTm<'slice> {
pub sp_header: SpHeader,
pub sec_header: PusTmSecondaryHeader<'slice>,