Repo of no-std crates for my personal embedded projects
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}