1use alloc::{boxed::Box, collections::vec_deque::VecDeque};
13use core::{
14 fmt::Debug,
15 marker::PhantomData,
16 task::{Context, Poll},
17};
18
19use docsplay::Display;
20use esp_hal::time::Duration;
21use esp_sync::NonReentrantMutex;
22use portable_atomic::{AtomicBool, AtomicU8, Ordering};
23
24use super::*;
25#[cfg(feature = "csi")]
26use crate::wifi::csi::CsiConfig;
27use crate::{
28 asynch::AtomicWaker,
29 sys::include::*,
30 wifi::{RxControlInfo, WifiError},
31};
32
33const RECEIVE_QUEUE_SIZE: usize = 10;
34
35pub const ESP_NOW_MAX_DATA_LEN: usize = 250;
37
38pub const BROADCAST_ADDRESS: [u8; 6] = [0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8];
40
41struct EspNowState {
42 rx_queue: VecDeque<ReceivedData>,
44}
45
46static STATE: NonReentrantMutex<EspNowState> = NonReentrantMutex::new(EspNowState {
47 rx_queue: VecDeque::new(),
48});
49
50static ESP_NOW_SEND_CB_INVOKED: AtomicBool = AtomicBool::new(false);
56static ESP_NOW_SEND_STATUS: AtomicBool = AtomicBool::new(true);
58
59static ESP_NOW_TX_WAKER: AtomicWaker = AtomicWaker::new();
60static ESP_NOW_RX_WAKER: AtomicWaker = AtomicWaker::new();
61
62macro_rules! check_error {
63 ($block:block) => {
64 match unsafe { $block } {
65 0 => Ok(()),
66 res => Err(EspNowError::Error(Error::from_code(res as u32))),
67 }
68 };
69}
70
71macro_rules! check_error_expect {
72 ($block:block, $msg:literal) => {
73 match unsafe { $block } {
74 0 => (),
75 res => panic!(
76 "{}: {:?}",
77 $msg,
78 EspNowError::Error(Error::from_code(res as u32))
79 ),
80 }
81 };
82}
83
84#[repr(u32)]
86#[derive(Display, Debug, Copy, Clone, Eq, PartialEq, Hash)]
87#[cfg_attr(feature = "defmt", derive(defmt::Format))]
88#[instability::unstable]
89pub enum Error {
90 NotInitialized = 12389,
92
93 InvalidArgument = 12390,
95
96 OutOfMemory = 12391,
98
99 PeerListFull = 12392,
101
102 NotFound = 12393,
104
105 Internal = 12394,
107
108 PeerExists = 12395,
110
111 InterfaceMismatch = 12396,
113
114 Other(u32),
117}
118
119impl Error {
120 fn from_code(code: u32) -> Error {
122 match code {
123 12389 => Error::NotInitialized,
124 12390 => Error::InvalidArgument,
125 12391 => Error::OutOfMemory,
126 12392 => Error::PeerListFull,
127 12393 => Error::NotFound,
128 12394 => Error::Internal,
129 12395 => Error::PeerExists,
130 12396 => Error::InterfaceMismatch,
131 _ => Error::Other(code),
132 }
133 }
134}
135
136impl core::error::Error for Error {}
137
138#[derive(Display, Debug, Copy, Clone, Eq, PartialEq, Hash)]
140#[cfg_attr(feature = "defmt", derive(defmt::Format))]
141#[instability::unstable]
142pub enum EspNowError {
143 Error(Error),
145 SendFailed,
147 DuplicateInstance,
149 Initialization(WifiError),
151}
152
153impl core::error::Error for EspNowError {}
154
155impl From<WifiError> for EspNowError {
156 fn from(f: WifiError) -> Self {
157 Self::Initialization(f)
158 }
159}
160
161#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
163#[cfg_attr(feature = "defmt", derive(defmt::Format))]
164#[instability::unstable]
165pub struct PeerCount {
166 pub total_count: i32,
168
169 pub encrypted_count: i32,
171}
172
173#[repr(u32)]
175#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
176#[cfg_attr(feature = "defmt", derive(defmt::Format))]
177#[instability::unstable]
178pub enum WifiPhyRate {
179 Rate1mL = 0,
181 Rate2m,
183 Rate5mL,
185 Rate11mL,
187 Rate2mS,
189 Rate5mS,
191 Rate11mS,
193 Rate48m,
195 Rate24m,
197 Rate12m,
199 Rate6m,
201 Rate54m,
203 Rate36m,
205 Rate18m,
207 Rate9m,
209 RateMcs0Lgi,
211 RateMcs1Lgi,
213 RateMcs2Lgi,
215 RateMcs3Lgi,
217 RateMcs4Lgi,
219 RateMcs5Lgi,
221 RateMcs6Lgi,
223 RateMcs7Lgi,
225 RateMcs0Sgi,
227 RateMcs1Sgi,
229 RateMcs2Sgi,
231 RateMcs3Sgi,
233 RateMcs4Sgi,
235 RateMcs5Sgi,
237 RateMcs6Sgi,
239 RateMcs7Sgi,
241 RateLora250k,
243 RateLora500k,
245 RateMax,
247}
248
249#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
251#[cfg_attr(feature = "defmt", derive(defmt::Format))]
252#[instability::unstable]
253pub struct PeerInfo {
254 pub interface: EspNowWifiInterface,
256
257 pub peer_address: [u8; 6],
260
261 pub lmk: Option<[u8; 16]>,
263
264 pub channel: Option<u8>,
266
267 pub encrypt: bool,
269 }
271
272#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
274#[cfg_attr(feature = "defmt", derive(defmt::Format))]
275#[instability::unstable]
276pub struct ReceiveInfo {
277 pub src_address: [u8; 6],
279
280 pub dst_address: [u8; 6],
282
283 pub rx_control: RxControlInfo,
285}
286
287#[derive(Clone)]
290#[instability::unstable]
291pub struct ReceivedData {
292 data: Box<[u8]>,
293 pub info: ReceiveInfo,
295}
296
297impl ReceivedData {
298 #[instability::unstable]
300 pub fn data(&self) -> &[u8] {
301 &self.data
302 }
303}
304
305#[cfg(feature = "defmt")]
306impl defmt::Format for ReceivedData {
307 fn format(&self, fmt: defmt::Formatter<'_>) {
308 defmt::write!(fmt, "ReceivedData {}, Info {}", &self.data[..], &self.info,)
309 }
310}
311
312impl Debug for ReceivedData {
313 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
314 f.debug_struct("ReceivedData")
315 .field("data", &self.data())
316 .field("info", &self.info)
317 .finish()
318 }
319}
320
321#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
323#[cfg_attr(feature = "defmt", derive(defmt::Format))]
324#[instability::unstable]
325pub enum EspNowWifiInterface {
326 AccessPoint,
328 Station,
330}
331
332impl EspNowWifiInterface {
333 fn as_wifi_interface(&self) -> wifi_interface_t {
334 match self {
335 EspNowWifiInterface::AccessPoint => wifi_interface_t_WIFI_IF_AP,
336 EspNowWifiInterface::Station => wifi_interface_t_WIFI_IF_STA,
337 }
338 }
339
340 fn from_wifi_interface(interface: wifi_interface_t) -> Self {
341 #[allow(non_upper_case_globals)]
342 match interface {
343 wifi_interface_t_WIFI_IF_AP => EspNowWifiInterface::AccessPoint,
344 wifi_interface_t_WIFI_IF_STA => EspNowWifiInterface::Station,
345 wifi_interface_t_WIFI_IF_NAN => panic!("NAN is unsupported"),
346 _ => unreachable!("Unknown interface"),
347 }
348 }
349}
350
351#[derive(Debug)]
353#[cfg_attr(feature = "defmt", derive(defmt::Format))]
354#[instability::unstable]
355pub struct EspNowManager<'d> {
356 _rc: EspNowRc<'d>,
357}
358
359impl EspNowManager<'_> {
360 #[instability::unstable]
363 pub fn set_channel(&self, channel: u8) -> Result<(), EspNowError> {
364 check_error!({ esp_wifi_set_channel(channel, 0) })
365 }
366
367 #[instability::unstable]
369 pub fn version(&self) -> Result<u32, EspNowError> {
370 let mut version = 0u32;
371 check_error!({ esp_now_get_version(&mut version as *mut u32) })?;
372 Ok(version)
373 }
374
375 #[instability::unstable]
377 pub fn add_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
378 let raw_peer = esp_now_peer_info_t {
379 peer_addr: peer.peer_address,
380 lmk: peer.lmk.unwrap_or([0u8; 16]),
381 channel: peer.channel.unwrap_or(0),
382 ifidx: peer.interface.as_wifi_interface(),
383 encrypt: peer.encrypt,
384 priv_: core::ptr::null_mut(),
385 };
386 check_error!({ esp_now_add_peer(&raw_peer as *const _) })
387 }
388
389 #[cfg(feature = "csi")]
391 #[instability::unstable]
392 pub fn set_csi(
393 &mut self,
394 mut csi: CsiConfig,
395 cb: impl FnMut(crate::wifi::csi::WifiCsiInfo<'_>) + Send,
396 ) -> Result<(), WifiError> {
397 csi.apply_config()?;
398 csi.set_receive_cb(cb)?;
399 csi.set_csi(true)?;
400
401 Ok(())
402 }
403
404 #[instability::unstable]
406 pub fn remove_peer(&self, peer_address: &[u8; 6]) -> Result<(), EspNowError> {
407 check_error!({ esp_now_del_peer(peer_address.as_ptr()) })
408 }
409
410 #[instability::unstable]
412 pub fn modify_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
413 let raw_peer = esp_now_peer_info_t {
414 peer_addr: peer.peer_address,
415 lmk: peer.lmk.unwrap_or([0u8; 16]),
416 channel: peer.channel.unwrap_or(0),
417 ifidx: peer.interface.as_wifi_interface(),
418 encrypt: peer.encrypt,
419 priv_: core::ptr::null_mut(),
420 };
421 check_error!({ esp_now_mod_peer(&raw_peer as *const _) })
422 }
423
424 #[instability::unstable]
426 pub fn peer(&self, peer_address: &[u8; 6]) -> Result<PeerInfo, EspNowError> {
427 let mut raw_peer = esp_now_peer_info_t {
428 peer_addr: [0u8; 6],
429 lmk: [0u8; 16],
430 channel: 0,
431 ifidx: 0,
432 encrypt: false,
433 priv_: core::ptr::null_mut(),
434 };
435 check_error!({ esp_now_get_peer(peer_address.as_ptr(), &mut raw_peer as *mut _) })?;
436
437 Ok(PeerInfo {
438 interface: EspNowWifiInterface::from_wifi_interface(raw_peer.ifidx),
439 peer_address: raw_peer.peer_addr,
440 lmk: if raw_peer.lmk.is_empty() {
441 None
442 } else {
443 Some(raw_peer.lmk)
444 },
445 channel: if raw_peer.channel != 0 {
446 Some(raw_peer.channel)
447 } else {
448 None
449 },
450 encrypt: raw_peer.encrypt,
451 })
452 }
453
454 #[instability::unstable]
460 pub fn fetch_peer(&self, from_head: bool) -> Result<PeerInfo, EspNowError> {
461 let mut raw_peer = esp_now_peer_info_t {
462 peer_addr: [0u8; 6],
463 lmk: [0u8; 16],
464 channel: 0,
465 ifidx: 0,
466 encrypt: false,
467 priv_: core::ptr::null_mut(),
468 };
469 check_error!({ esp_now_fetch_peer(from_head, &mut raw_peer as *mut _) })?;
470
471 Ok(PeerInfo {
472 interface: EspNowWifiInterface::from_wifi_interface(raw_peer.ifidx),
473 peer_address: raw_peer.peer_addr,
474 lmk: if raw_peer.lmk.is_empty() {
475 None
476 } else {
477 Some(raw_peer.lmk)
478 },
479 channel: if raw_peer.channel != 0 {
480 Some(raw_peer.channel)
481 } else {
482 None
483 },
484 encrypt: raw_peer.encrypt,
485 })
486 }
487
488 #[instability::unstable]
490 pub fn peer_exists(&self, peer_address: &[u8; 6]) -> bool {
491 unsafe { esp_now_is_peer_exist(peer_address.as_ptr()) }
492 }
493
494 #[instability::unstable]
496 pub fn peer_count(&self) -> Result<PeerCount, EspNowError> {
497 let mut peer_num = esp_now_peer_num_t {
498 total_num: 0,
499 encrypt_num: 0,
500 };
501 check_error!({ esp_now_get_peer_num(&mut peer_num as *mut _) })?;
502
503 Ok(PeerCount {
504 total_count: peer_num.total_num,
505 encrypted_count: peer_num.encrypt_num,
506 })
507 }
508
509 #[instability::unstable]
511 pub fn set_pmk(&self, pmk: &[u8; 16]) -> Result<(), EspNowError> {
512 check_error!({ esp_now_set_pmk(pmk.as_ptr()) })
513 }
514
515 #[instability::unstable]
520 pub fn set_wake_window(&self, wake_window: Duration) -> Result<(), EspNowError> {
521 let ms = wake_window.as_millis();
522
523 if ms > u16::MAX as u64 {
524 return Err(EspNowError::Error(Error::InvalidArgument));
525 }
526 check_error!({ esp_now_set_wake_window(ms as u16) })
527 }
528
529 #[instability::unstable]
531 pub fn set_rate(&self, rate: WifiPhyRate) -> Result<(), EspNowError> {
532 check_error!({ esp_wifi_config_espnow_rate(wifi_interface_t_WIFI_IF_STA, rate as u32,) })
533 }
534}
535
536#[derive(Debug)]
544#[cfg_attr(feature = "defmt", derive(defmt::Format))]
545#[instability::unstable]
546pub struct EspNowSender<'d> {
547 _rc: EspNowRc<'d>,
548}
549
550impl EspNowSender<'_> {
551 #[instability::unstable]
555 pub fn send<'s>(
556 &'s mut self,
557 dst_addr: &[u8; 6],
558 data: &[u8],
559 ) -> Result<SendWaiter<'s>, EspNowError> {
560 ESP_NOW_SEND_CB_INVOKED.store(false, Ordering::Release);
561 check_error!({ esp_now_send(dst_addr.as_ptr(), data.as_ptr(), data.len()) })?;
562 Ok(SendWaiter(PhantomData))
563 }
564}
565
566#[allow(unknown_lints)]
567#[allow(clippy::too_long_first_doc_paragraph)]
568#[must_use]
579#[instability::unstable]
580pub struct SendWaiter<'s>(PhantomData<&'s mut EspNowSender<'s>>);
581
582impl SendWaiter<'_> {
583 #[instability::unstable]
586 pub fn wait(self) -> Result<(), EspNowError> {
587 core::mem::forget(self);
590 while !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {}
591
592 if ESP_NOW_SEND_STATUS.load(Ordering::Relaxed) {
593 Ok(())
594 } else {
595 Err(EspNowError::SendFailed)
596 }
597 }
598}
599
600impl Drop for SendWaiter<'_> {
601 fn drop(&mut self) {
604 while !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {}
605 }
606}
607
608#[derive(Debug)]
611#[cfg_attr(feature = "defmt", derive(defmt::Format))]
612#[instability::unstable]
613pub struct EspNowReceiver<'d> {
614 _rc: EspNowRc<'d>,
615}
616
617impl EspNowReceiver<'_> {
618 #[instability::unstable]
620 pub fn receive(&self) -> Option<ReceivedData> {
621 STATE.with(|state| state.rx_queue.pop_front())
622 }
623}
624
625#[derive(Debug)]
628struct EspNowRc<'d> {
629 rc: &'static AtomicU8,
630 inner: PhantomData<EspNow<'d>>,
631}
632
633#[cfg(feature = "defmt")]
634impl defmt::Format for EspNowRc<'_> {
635 fn format(&self, f: defmt::Formatter<'_>) {
636 defmt::write!(
637 f,
638 "EspNowRc {{ rc: {}, inner: ... }}",
639 self.rc.load(Ordering::Relaxed)
640 );
641 }
642}
643
644impl EspNowRc<'_> {
645 fn new() -> Self {
646 static ESP_NOW_RC: AtomicU8 = AtomicU8::new(0);
647 assert!(
648 ESP_NOW_RC.fetch_add(1, Ordering::AcqRel) == 0,
649 "ESP-NOW already in use"
650 );
651
652 Self {
653 rc: &ESP_NOW_RC,
654 inner: PhantomData,
655 }
656 }
657}
658
659impl Clone for EspNowRc<'_> {
660 fn clone(&self) -> Self {
661 self.rc.fetch_add(1, Ordering::Release);
662 Self {
663 rc: self.rc,
664 inner: PhantomData,
665 }
666 }
667}
668
669impl Drop for EspNowRc<'_> {
670 fn drop(&mut self) {
671 if self.rc.fetch_sub(1, Ordering::AcqRel) == 1 {
672 unsafe {
673 esp_now_unregister_recv_cb();
674 esp_now_deinit();
675 }
676 }
677 }
678}
679
680#[allow(unknown_lints)]
681#[allow(clippy::too_long_first_doc_paragraph)]
682#[derive(Debug)]
692#[cfg_attr(feature = "defmt", derive(defmt::Format))]
693#[instability::unstable]
694pub struct EspNow<'d> {
695 manager: EspNowManager<'d>,
696 sender: EspNowSender<'d>,
697 receiver: EspNowReceiver<'d>,
698 _phantom: PhantomData<&'d ()>,
699}
700
701impl<'d> EspNow<'d> {
702 pub(crate) fn new_internal() -> EspNow<'d> {
703 let espnow_rc = EspNowRc::new();
704 let esp_now = EspNow {
705 manager: EspNowManager {
706 _rc: espnow_rc.clone(),
707 },
708 sender: EspNowSender {
709 _rc: espnow_rc.clone(),
710 },
711 receiver: EspNowReceiver { _rc: espnow_rc },
712 _phantom: PhantomData,
713 };
714
715 check_error_expect!({ esp_now_init() }, "esp-now-init failed");
716 check_error_expect!(
717 { esp_now_register_recv_cb(Some(rcv_cb)) },
718 "receiving callback failed"
719 );
720 check_error_expect!(
721 { esp_now_register_send_cb(Some(send_cb)) },
722 "sending callback failed"
723 );
724
725 esp_now
726 .add_peer(PeerInfo {
727 interface: EspNowWifiInterface::Station,
728 peer_address: BROADCAST_ADDRESS,
729 lmk: None,
730 channel: None,
731 encrypt: false,
732 })
733 .expect("adding peer failed");
734
735 esp_now
736 }
737
738 #[instability::unstable]
741 pub fn split(self) -> (EspNowManager<'d>, EspNowSender<'d>, EspNowReceiver<'d>) {
742 (self.manager, self.sender, self.receiver)
743 }
744
745 #[instability::unstable]
748 pub fn set_channel(&self, channel: u8) -> Result<(), EspNowError> {
749 self.manager.set_channel(channel)
750 }
751
752 #[instability::unstable]
754 pub fn version(&self) -> Result<u32, EspNowError> {
755 self.manager.version()
756 }
757
758 #[instability::unstable]
760 pub fn add_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
761 self.manager.add_peer(peer)
762 }
763
764 #[instability::unstable]
766 pub fn remove_peer(&self, peer_address: &[u8; 6]) -> Result<(), EspNowError> {
767 self.manager.remove_peer(peer_address)
768 }
769
770 #[instability::unstable]
772 pub fn modify_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
773 self.manager.modify_peer(peer)
774 }
775
776 #[instability::unstable]
778 pub fn peer(&self, peer_address: &[u8; 6]) -> Result<PeerInfo, EspNowError> {
779 self.manager.peer(peer_address)
780 }
781
782 #[instability::unstable]
788 pub fn fetch_peer(&self, from_head: bool) -> Result<PeerInfo, EspNowError> {
789 self.manager.fetch_peer(from_head)
790 }
791
792 #[instability::unstable]
794 pub fn peer_exists(&self, peer_address: &[u8; 6]) -> bool {
795 self.manager.peer_exists(peer_address)
796 }
797
798 #[instability::unstable]
800 pub fn peer_count(&self) -> Result<PeerCount, EspNowError> {
801 self.manager.peer_count()
802 }
803
804 #[instability::unstable]
806 pub fn set_pmk(&self, pmk: &[u8; 16]) -> Result<(), EspNowError> {
807 self.manager.set_pmk(pmk)
808 }
809
810 #[instability::unstable]
815 pub fn set_wake_window(&self, wake_window: Duration) -> Result<(), EspNowError> {
816 self.manager.set_wake_window(wake_window)
817 }
818
819 #[instability::unstable]
821 pub fn set_rate(&self, rate: WifiPhyRate) -> Result<(), EspNowError> {
822 self.manager.set_rate(rate)
823 }
824
825 #[instability::unstable]
829 pub fn send<'s>(
830 &'s mut self,
831 dst_addr: &[u8; 6],
832 data: &[u8],
833 ) -> Result<SendWaiter<'s>, EspNowError> {
834 self.sender.send(dst_addr, data)
835 }
836
837 #[instability::unstable]
839 pub fn receive(&self) -> Option<ReceivedData> {
840 self.receiver.receive()
841 }
842}
843
844unsafe extern "C" fn send_cb(_tx_info: *const esp_now_send_info_t, status: esp_now_send_status_t) {
845 let is_success = status == esp_now_send_status_t_ESP_NOW_SEND_SUCCESS;
846 ESP_NOW_SEND_STATUS.store(is_success, Ordering::Relaxed);
847
848 ESP_NOW_SEND_CB_INVOKED.store(true, Ordering::Release);
849
850 ESP_NOW_TX_WAKER.wake();
851}
852
853unsafe extern "C" fn rcv_cb(
854 esp_now_info: *const esp_now_recv_info_t,
855 data: *const u8,
856 data_len: i32,
857) {
858 let src = unsafe {
859 [
860 (*esp_now_info).src_addr.offset(0).read(),
861 (*esp_now_info).src_addr.offset(1).read(),
862 (*esp_now_info).src_addr.offset(2).read(),
863 (*esp_now_info).src_addr.offset(3).read(),
864 (*esp_now_info).src_addr.offset(4).read(),
865 (*esp_now_info).src_addr.offset(5).read(),
866 ]
867 };
868
869 let dst = unsafe {
870 [
871 (*esp_now_info).des_addr.offset(0).read(),
872 (*esp_now_info).des_addr.offset(1).read(),
873 (*esp_now_info).des_addr.offset(2).read(),
874 (*esp_now_info).des_addr.offset(3).read(),
875 (*esp_now_info).des_addr.offset(4).read(),
876 (*esp_now_info).des_addr.offset(5).read(),
877 ]
878 };
879
880 let rx_cntl = unsafe { (*esp_now_info).rx_ctrl };
881 let rx_control = unsafe { RxControlInfo::from_raw(rx_cntl) };
882
883 let info = ReceiveInfo {
884 src_address: src,
885 dst_address: dst,
886 rx_control,
887 };
888 let slice = unsafe { core::slice::from_raw_parts(data, data_len as usize) };
889
890 STATE.with(|state| {
891 let data = Box::from(slice);
892
893 if state.rx_queue.len() >= RECEIVE_QUEUE_SIZE {
894 state.rx_queue.pop_front();
895 }
896
897 state.rx_queue.push_back(ReceivedData { data, info });
898 ESP_NOW_RX_WAKER.wake();
899 });
900}
901
902impl EspNowReceiver<'_> {
903 #[instability::unstable]
907 pub fn receive_async(&mut self) -> ReceiveFuture<'_> {
908 ReceiveFuture(PhantomData)
909 }
910}
911
912impl EspNowSender<'_> {
913 #[instability::unstable]
915 pub fn send_async<'s, 'r>(
916 &'s mut self,
917 addr: &'r [u8; 6],
918 data: &'r [u8],
919 ) -> SendFuture<'s, 'r> {
920 SendFuture {
921 _sender: PhantomData,
922 addr,
923 data,
924 sent: false,
925 }
926 }
927}
928
929impl EspNow<'_> {
930 #[instability::unstable]
934 pub fn receive_async(&mut self) -> ReceiveFuture<'_> {
935 self.receiver.receive_async()
936 }
937
938 #[instability::unstable]
941 pub fn send_async<'s, 'r>(
942 &'s mut self,
943 dst_addr: &'r [u8; 6],
944 data: &'r [u8],
945 ) -> SendFuture<'s, 'r> {
946 self.sender.send_async(dst_addr, data)
947 }
948}
949
950#[must_use = "futures do nothing unless you `.await` or poll them"]
953#[instability::unstable]
954pub struct SendFuture<'s, 'r> {
955 _sender: PhantomData<&'s mut EspNowSender<'s>>,
956 addr: &'r [u8; 6],
957 data: &'r [u8],
958 sent: bool,
959}
960
961impl core::future::Future for SendFuture<'_, '_> {
962 type Output = Result<(), EspNowError>;
963
964 fn poll(mut self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
965 if !self.sent {
966 ESP_NOW_TX_WAKER.register(cx.waker());
967 ESP_NOW_SEND_CB_INVOKED.store(false, Ordering::Release);
968 if let Err(e) = check_error!({
969 esp_now_send(self.addr.as_ptr(), self.data.as_ptr(), self.data.len())
970 }) {
971 return Poll::Ready(Err(e));
972 }
973 self.sent = true;
974 }
975
976 if !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {
977 Poll::Pending
978 } else {
979 Poll::Ready(if ESP_NOW_SEND_STATUS.load(Ordering::Relaxed) {
980 Ok(())
981 } else {
982 Err(EspNowError::SendFailed)
983 })
984 }
985 }
986}
987
988#[must_use = "futures do nothing unless you `.await` or poll them"]
992#[instability::unstable]
993pub struct ReceiveFuture<'r>(PhantomData<&'r mut EspNowReceiver<'r>>);
994
995impl core::future::Future for ReceiveFuture<'_> {
996 type Output = ReceivedData;
997
998 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
999 ESP_NOW_RX_WAKER.register(cx.waker());
1000
1001 if let Some(data) = STATE.with(|state| state.rx_queue.pop_front()) {
1002 Poll::Ready(data)
1003 } else {
1004 Poll::Pending
1005 }
1006 }
1007}