Repo of no-std crates for my personal embedded projects
at main 3.2 kB view raw
1use embassy_time::{Duration, Instant}; 2use sachy_fmt::{debug, unwrap}; 3 4#[derive(Debug, Default)] 5#[cfg_attr(feature = "defmt", derive(defmt::Format))] 6pub(crate) enum MdnsStateMachine { 7 #[default] 8 Start, 9 Announce { 10 last_sent: Instant, 11 }, 12 ListenFor { 13 last_sent: Instant, 14 timeout: Duration, 15 }, 16 WaitFor { 17 last_sent: Instant, 18 duration: Duration, 19 }, 20} 21 22impl MdnsStateMachine { 23 /// Set the state to announced, if we have timed out the listening period and need 24 /// to announce, or if we received a query while listening and have sent a response. 25 pub(crate) fn announced(&mut self) { 26 *self = Self::Announce { 27 last_sent: Instant::now(), 28 }; 29 } 30 31 fn next_state(&mut self) { 32 match self { 33 Self::Start => self.announced(), 34 &mut Self::Announce { last_sent } => { 35 let duration_since = last_sent.elapsed(); 36 let duration = Duration::from_secs(1) - duration_since; 37 38 *self = Self::WaitFor { 39 last_sent, 40 duration, 41 }; 42 } 43 &mut Self::ListenFor { last_sent, .. } => { 44 let duration_since = last_sent.elapsed(); 45 let time_limit = Duration::from_secs(120); 46 47 if duration_since >= time_limit { 48 self.announced(); 49 } else { 50 let timeout = time_limit - duration_since; 51 *self = Self::ListenFor { last_sent, timeout }; 52 } 53 } 54 &mut Self::WaitFor { last_sent, .. } => { 55 let duration_since = last_sent.elapsed(); 56 let time_limit = Duration::from_secs(120); 57 let timeout = time_limit - duration_since; 58 59 *self = Self::ListenFor { last_sent, timeout }; 60 } 61 } 62 } 63 64 pub(crate) fn drive_next_action(&mut self) -> MdnsAction { 65 self.next_state(); 66 unwrap!(MdnsAction::try_from(self)) 67 } 68} 69 70#[derive(Debug)] 71#[cfg_attr(feature = "defmt", derive(defmt::Format))] 72pub enum MdnsAction { 73 Announce, 74 ListenFor { timeout: Duration }, 75 WaitFor { duration: Duration }, 76} 77 78impl TryFrom<&mut MdnsStateMachine> for MdnsAction { 79 type Error = MdnsStateMachine; 80 81 fn try_from(value: &mut MdnsStateMachine) -> Result<Self, Self::Error> { 82 match value { 83 // We should start in this state, but never remain nor return to it when 84 // executing our state machine event loop. 85 MdnsStateMachine::Start => Err(MdnsStateMachine::Start), 86 MdnsStateMachine::Announce { .. } => { 87 debug!("ANNOUNCE"); 88 Ok(Self::Announce) 89 } 90 &mut MdnsStateMachine::ListenFor { timeout, .. } => { 91 debug!("LISTEN FOR {}ms", timeout.as_millis()); 92 Ok(Self::ListenFor { timeout }) 93 } 94 &mut MdnsStateMachine::WaitFor { duration, .. } => { 95 debug!("WAIT FOR {}ms", duration.as_millis()); 96 Ok(Self::WaitFor { duration }) 97 } 98 } 99 } 100}