use std::time::{Duration, Instant}; macro_rules! to_ticks { ($dur:expr) => {($dur.as_millis() / 4) as u16}; } macro_rules! from_ticks { ($ticks:expr) => {Duration::from_millis(($ticks * 4).into())}; } macro_rules! now { () => { time::OffsetDateTime::now_local().unwrap_or_else(|_| time::OffsetDateTime::now_utc())};} /// Create a method to set the instant of a timer. macro_rules! generate_set_timer_method { ($i:tt) => { mini_paste::item!{ pub fn [< set_timer_ $i >] (&mut self) { let ticks = &mut self. [< timer_ $i >]; let instant = &mut self. [< timer_ $i _end >]; *instant = Instant::now() + from_ticks!(*ticks); } }}; } /// Create a method to update the value of a timer. macro_rules! generate_update_timer_method { ($i:tt) => { mini_paste::item!{ pub fn [< update_timer_ $i >] (&mut self) -> u16 { let ticks = &mut self. [< timer_ $i >]; let instant = &mut self. [< timer_ $i _end >]; if *ticks > 0 { *ticks = to_ticks!(instant.duration_since(Instant::now())); if *ticks == 0 { self.wake_flag = true; } } return *ticks; } }}; } pub struct ClockDevice { pub wake_flag: bool, pub program_start: Instant, pub uptime: u16, pub timer_1_end: Instant, pub timer_2_end: Instant, pub timer_3_end: Instant, pub timer_4_end: Instant, pub timer_1: u16, pub timer_2: u16, pub timer_3: u16, pub timer_4: u16, } impl ClockDevice { pub fn new() -> Self { Self { wake_flag: false, program_start: Instant::now(), uptime: 0, timer_1_end: Instant::now(), timer_2_end: Instant::now(), timer_3_end: Instant::now(), timer_4_end: Instant::now(), timer_1: 0, timer_2: 0, timer_3: 0, timer_4: 0, } } generate_set_timer_method!{1} generate_set_timer_method!{2} generate_set_timer_method!{3} generate_set_timer_method!{4} generate_update_timer_method!{1} generate_update_timer_method!{2} generate_update_timer_method!{3} generate_update_timer_method!{4} pub fn update_timers(&mut self) { self.update_timer_1(); self.update_timer_2(); self.update_timer_3(); self.update_timer_4(); } pub fn update_uptime(&mut self) -> u16 { self.uptime = to_ticks!(self.program_start.elapsed()); return self.uptime; } pub fn year(&self) -> u8 { now!().year().saturating_sub(2000).try_into().unwrap_or(u8::MAX) } pub fn month(&self) -> u8 { now!().month() as u8 - 1 } pub fn day(&self) -> u8 { now!().day() as u8 - 1 } pub fn hour(&self) -> u8 { now!().hour() } pub fn minute(&self) -> u8 { now!().minute() } pub fn second(&self) -> u8 { now!().second() } pub fn time_to_next_wake(&self) -> Option { [self.timer_1, self.timer_2, self.timer_3, self.timer_4] .iter() .filter(|t| **t > 0) .min() .and_then(|t| Some(from_ticks!(t))) } }