use crate::datetime::Weekday;
use crate::error::ErrorType;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AlarmConfig {
second: Option<u8>,
minute: Option<u8>,
hour: Option<u8>,
weekday: Option<Weekday>,
day_of_month: Option<u8>,
month: Option<u8>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum AlarmConfigError {
InvalidSecond,
InvalidMinute,
InvalidHour,
InvalidDayOfMonth,
InvalidMonth,
}
impl AlarmConfig {
fn validate(&self) -> Result<(), AlarmConfigError> {
if let Some(second) = self.second
&& second > 59
{
return Err(AlarmConfigError::InvalidSecond);
}
if let Some(minute) = self.minute
&& minute > 59
{
return Err(AlarmConfigError::InvalidMinute);
}
if let Some(hour) = self.hour
&& hour > 23
{
return Err(AlarmConfigError::InvalidHour);
}
if let Some(day) = self.day_of_month
&& !(1..=31).contains(&day)
{
return Err(AlarmConfigError::InvalidDayOfMonth);
}
if let Some(month) = self.month
&& !(1..=12).contains(&month)
{
return Err(AlarmConfigError::InvalidMonth);
}
Ok(())
}
pub const fn second(&self) -> Option<u8> {
self.second
}
pub const fn minute(&self) -> Option<u8> {
self.minute
}
pub const fn hour(&self) -> Option<u8> {
self.hour
}
pub const fn weekday(&self) -> Option<Weekday> {
self.weekday
}
pub const fn day_of_month(&self) -> Option<u8> {
self.day_of_month
}
pub const fn month(&self) -> Option<u8> {
self.month
}
}
pub struct AlarmBuilder {
config: AlarmConfig,
}
impl AlarmBuilder {
pub const fn at(hour: u8, minute: u8) -> Self {
let config = AlarmConfig {
hour: Some(hour),
minute: Some(minute),
second: None,
weekday: None,
day_of_month: None,
month: None,
};
Self { config }
}
pub const fn at_hms(hour: u8, minute: u8, second: u8) -> Self {
let config = AlarmConfig {
hour: Some(hour),
minute: Some(minute),
second: Some(second),
weekday: None,
day_of_month: None,
month: None,
};
Self { config }
}
pub const fn at_hour(hour: u8) -> Self {
let config = AlarmConfig {
hour: Some(hour),
minute: None,
second: None,
weekday: None,
day_of_month: None,
month: None,
};
Self { config }
}
pub const fn at_minute(minute: u8) -> Self {
let config = AlarmConfig {
hour: None,
minute: Some(minute),
second: None,
weekday: None,
day_of_month: None,
month: None,
};
Self { config }
}
pub const fn at_second(second: u8) -> Self {
let config = AlarmConfig {
hour: None,
minute: None,
second: Some(second),
weekday: None,
day_of_month: None,
month: None,
};
Self { config }
}
pub const fn on(mut self, weekday: Weekday) -> Self {
self.config.weekday = Some(weekday);
self
}
pub const fn on_day_of_month(mut self, day: u8) -> Self {
self.config.day_of_month = Some(day);
self
}
pub const fn on_month(mut self, month: u8) -> Self {
self.config.month = Some(month);
self
}
pub fn build(self) -> Result<AlarmConfig, AlarmConfigError> {
self.config.validate()?;
Ok(self.config)
}
}
pub trait Alarm: ErrorType {
type AlarmId;
fn set_alarm(&mut self, id: Self::AlarmId, alarm: AlarmConfig) -> Result<(), Self::Error>;
fn enable_alarm(&mut self, id: Self::AlarmId) -> Result<(), Self::Error>;
fn disable_alarm(&mut self, id: Self::AlarmId) -> Result<(), Self::Error>;
fn alarm_triggered(&mut self, id: Self::AlarmId) -> Result<bool, Self::Error>;
fn clear_alarm(&mut self, id: Self::AlarmId) -> Result<(), Self::Error>;
}
impl<T: Alarm + ?Sized> Alarm for &mut T {
type AlarmId = T::AlarmId;
#[inline]
fn set_alarm(&mut self, id: Self::AlarmId, alarm: AlarmConfig) -> Result<(), Self::Error> {
T::set_alarm(self, id, alarm)
}
#[inline]
fn enable_alarm(&mut self, id: Self::AlarmId) -> Result<(), Self::Error> {
T::enable_alarm(self, id)
}
#[inline]
fn disable_alarm(&mut self, id: Self::AlarmId) -> Result<(), Self::Error> {
T::disable_alarm(self, id)
}
#[inline]
fn alarm_triggered(&mut self, id: Self::AlarmId) -> Result<bool, Self::Error> {
T::alarm_triggered(self, id)
}
#[inline]
fn clear_alarm(&mut self, id: Self::AlarmId) -> Result<(), Self::Error> {
T::clear_alarm(self, id)
}
}