tests for time stamp provider

This commit is contained in:
Robin Müller 2022-07-28 02:09:07 +02:00
parent 6fe3086575
commit 88af155490
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
3 changed files with 117 additions and 13 deletions

View File

@ -17,6 +17,7 @@ serde = "1.0.137"
zerocopy = "0.6.1"
crc = "3.0.0"
delegate = "0.7.0"
chrono = "0.4.19"
[dependencies.heapless]
version = "0.7.14"

View File

@ -474,6 +474,7 @@ impl PusTcSecondaryHeader for PusTc<'_> {
fn ack_flags(&self) -> u8;
});
}
#[cfg(test)]
mod tests {
use crate::ecss::{PusError, PusPacket};

View File

@ -1,4 +1,6 @@
use crate::PacketError;
use chrono::{DateTime, TimeZone, Utc};
#[cfg(feature = "std")]
use std::time::SystemTime;
@ -34,8 +36,8 @@ pub const fn unix_to_ccsds_days(unix_days: i32) -> i32 {
///
/// - CCSDS epoch: 1958 January 1
/// - UNIX Epoch: 1970 January 1
pub const fn ccsds_to_unix_days(unix_days: i32) -> i32 {
unix_days + DAYS_CCSDS_TO_UNIX
pub const fn ccsds_to_unix_days(ccsds_days: i32) -> i32 {
ccsds_days + DAYS_CCSDS_TO_UNIX
}
/// Trait for generic CCSDS time providers
@ -48,26 +50,55 @@ trait CcsdsTimeProvider {
/// in big endian format.
fn p_field(&self) -> (usize, [u8; 2]);
fn ccdsd_time_code(&self) -> CcsdsTimeCodes;
fn as_unix_seconds(&self) -> u64;
fn unix_seconds(&self) -> i64;
fn date_time(&self) -> DateTime<Utc>;
}
#[derive(Debug, Copy, Clone)]
pub struct CdsShortTimeProvider {
pfield: u8,
ccsds_days: u16,
ms_of_day: u32,
unix_seconds: u64,
unix_seconds: i64,
date_time: Option<DateTime<Utc>>,
}
impl CdsShortTimeProvider {
pub fn new(ccsds_days: u16, ms_of_day: u32) -> Self {
let mut provider = Self {
let provider = Self {
pfield: (CcsdsTimeCodes::Cds as u8) << 4,
ccsds_days,
ms_of_day,
unix_seconds: 0,
date_time: None,
};
provider.calc_unix_seconds();
provider
let unix_days_seconds = ccsds_to_unix_days(ccsds_days as i32) as i64 * (24 * 60 * 60);
provider.setup(unix_days_seconds as i64, ms_of_day.into())
}
#[cfg(feature = "std")]
pub fn from_now() -> Self {
let now = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("Error retrieving UNIX epoch");
let epoch = now.as_secs();
let secs_of_day = epoch % SECONDS_PER_DAY as u64;
let unix_days_seconds = epoch - secs_of_day;
let ms_of_day = secs_of_day * 1000 + now.subsec_millis() as u64;
let provider = Self {
pfield: (CcsdsTimeCodes::Cds as u8) << 4,
ccsds_days: unix_to_ccsds_days((unix_days_seconds / SECONDS_PER_DAY as u64) as i32) as u16,
ms_of_day: ms_of_day as u32,
unix_seconds: 0,
date_time: None,
};
provider.setup(unix_days_seconds as i64, ms_of_day.into())
}
fn setup(mut self, unix_days_seconds: i64, ms_of_day: u64) -> Self {
self.calc_unix_seconds(unix_days_seconds, ms_of_day);
self.calc_date_time(unix_days_seconds, (ms_of_day % 1000) as u32);
self
}
#[cfg(feature = "std")]
@ -83,13 +114,23 @@ impl CdsShortTimeProvider {
ms_of_day
}
fn calc_unix_seconds(&mut self) {
let unix_days = ccsds_to_unix_days(self.ccsds_days as i32);
self.unix_seconds = unix_days as u64 * (24 * 60 * 60);
let seconds_of_day = (self.ms_of_day as f32 / 1000.0).floor() as u64;
self.unix_seconds += seconds_of_day;
fn calc_unix_seconds(&mut self, unix_days_seconds: i64, ms_of_day: u64) {
self.unix_seconds = unix_days_seconds;
let seconds_of_day = (ms_of_day / 1000) as i64;
if self.unix_seconds < 0 {
self.unix_seconds -= seconds_of_day;
} else {
self.unix_seconds += seconds_of_day;
}
}
fn calc_date_time(&mut self, unix_days_seconds: i64, ms_since_last_second: u32) {
assert!(ms_since_last_second < 1000, "Invalid MS since last second");
let ns_since_last_sec = ms_since_last_second * 1e6 as u32;
self.date_time = Some(Utc.timestamp(unix_days_seconds, ns_since_last_sec));
}
}
impl CcsdsTimeProvider for CdsShortTimeProvider {
fn len(&self) -> usize {
CDS_SHORT_LEN
@ -114,7 +155,68 @@ impl CcsdsTimeProvider for CdsShortTimeProvider {
CcsdsTimeCodes::Cds
}
fn as_unix_seconds(&self) -> u64 {
fn unix_seconds(&self) -> i64 {
self.unix_seconds
}
fn date_time(&self) -> DateTime<Utc> {
self.date_time.expect("Invalid date time")
}
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::{Datelike, Timelike};
#[cfg(feature = "std")]
use std::println;
#[test]
fn test_creation() {
assert_eq!(unix_to_ccsds_days(DAYS_CCSDS_TO_UNIX), 0);
assert_eq!(ccsds_to_unix_days(0), DAYS_CCSDS_TO_UNIX);
}
#[cfg(feature = "std")]
#[test]
fn test_get_current_time() {
let sec_floats = seconds_since_epoch();
assert!(sec_floats > 0.0);
}
#[test]
fn test_time_stamp_zero_args() {
let time_stamper = CdsShortTimeProvider::new(0, 0);
assert_eq!(
time_stamper.unix_seconds(),
(DAYS_CCSDS_TO_UNIX * 24 * 60 * 60) as i64
);
let date_time = time_stamper.date_time();
assert_eq!(date_time.year(), 1958);
assert_eq!(date_time.month(), 1);
assert_eq!(date_time.day(), 1);
assert_eq!(date_time.hour(), 0);
assert_eq!(date_time.minute(), 0);
assert_eq!(date_time.second(), 0);
}
#[test]
fn test_time_stamp_unix_epoch() {
let time_stamper = CdsShortTimeProvider::new((-DAYS_CCSDS_TO_UNIX) as u16, 0);
assert_eq!(time_stamper.unix_seconds(), 0);
let date_time = time_stamper.date_time();
assert_eq!(date_time.year(), 1970);
assert_eq!(date_time.month(), 1);
assert_eq!(date_time.day(), 1);
assert_eq!(date_time.hour(), 0);
assert_eq!(date_time.minute(), 0);
assert_eq!(date_time.second(), 0);
}
#[cfg(feature = "std")]
#[test]
fn test_time_now() {
let timestamp_now = CdsShortTimeProvider::from_now();
println!("{}", timestamp_now.date_time());
}
}