1use alloc::{boxed::Box, collections::vec_deque::VecDeque};
13use core::{
14 fmt::Debug,
15 marker::PhantomData,
16 task::{Context, Poll},
17};
18
19use esp_hal::asynch::AtomicWaker;
20use esp_sync::NonReentrantMutex;
21use portable_atomic::{AtomicBool, AtomicU8, Ordering};
22
23use super::*;
24#[cfg(feature = "csi")]
25use crate::wifi::CsiConfig;
26use crate::{
27 binary::include::*,
28 wifi::{RxControlInfo, WifiError},
29};
30
31const RECEIVE_QUEUE_SIZE: usize = 10;
32
33pub const ESP_NOW_MAX_DATA_LEN: usize = 250;
35
36pub const BROADCAST_ADDRESS: [u8; 6] = [0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8];
38
39struct EspNowState {
40 rx_queue: VecDeque<ReceivedData>,
42}
43
44static STATE: NonReentrantMutex<EspNowState> = NonReentrantMutex::new(EspNowState {
45 rx_queue: VecDeque::new(),
46});
47
48static ESP_NOW_SEND_CB_INVOKED: AtomicBool = AtomicBool::new(false);
54static ESP_NOW_SEND_STATUS: AtomicBool = AtomicBool::new(true);
56
57static ESP_NOW_TX_WAKER: AtomicWaker = AtomicWaker::new();
58static ESP_NOW_RX_WAKER: AtomicWaker = AtomicWaker::new();
59
60macro_rules! check_error {
61 ($block:block) => {
62 match unsafe { $block } {
63 0 => Ok(()),
64 res => Err(EspNowError::Error(Error::from_code(res as u32))),
65 }
66 };
67}
68
69macro_rules! check_error_expect {
70 ($block:block, $msg:literal) => {
71 match unsafe { $block } {
72 0 => (),
73 res => panic!(
74 "{}: {:?}",
75 $msg,
76 EspNowError::Error(Error::from_code(res as u32))
77 ),
78 }
79 };
80}
81
82#[repr(u32)]
84#[derive(Debug)]
85#[cfg_attr(feature = "defmt", derive(defmt::Format))]
86#[instability::unstable]
87pub enum Error {
88 NotInitialized = 12389,
90
91 InvalidArgument = 12390,
93
94 OutOfMemory = 12391,
96
97 PeerListFull = 12392,
99
100 NotFound = 12393,
102
103 Internal = 12394,
105
106 PeerExists = 12395,
108
109 InterfaceMismatch = 12396,
111
112 Other(u32),
115}
116
117impl Error {
118 #[instability::unstable]
119 pub fn from_code(code: u32) -> Error {
121 match code {
122 12389 => Error::NotInitialized,
123 12390 => Error::InvalidArgument,
124 12391 => Error::OutOfMemory,
125 12392 => Error::PeerListFull,
126 12393 => Error::NotFound,
127 12394 => Error::Internal,
128 12395 => Error::PeerExists,
129 12396 => Error::InterfaceMismatch,
130 _ => Error::Other(code),
131 }
132 }
133}
134
135impl core::fmt::Display for Error {
136 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
137 match self {
138 Error::NotInitialized => write!(f, "ESP-NOW is not initialized."),
139 Error::InvalidArgument => write!(f, "Invalid argument."),
140 Error::OutOfMemory => write!(f, "Insufficient memory to complete the operation."),
141 Error::PeerListFull => write!(f, "ESP-NOW peer list is full."),
142 Error::NotFound => write!(f, "ESP-NOW peer is not found."),
143 Error::Internal => write!(f, "Internal error."),
144 Error::PeerExists => write!(f, "ESP-NOW peer already exists."),
145 Error::InterfaceMismatch => {
146 write!(
147 f,
148 "The Wi-Fi interface used for ESP-NOW doesn't match the expected one for the peer."
149 )
150 }
151 Error::Other(code) => write!(f, "Unknown error with code: {code}."),
152 }
153 }
154}
155
156impl core::error::Error for Error {}
157
158#[derive(Debug)]
160#[cfg_attr(feature = "defmt", derive(defmt::Format))]
161#[instability::unstable]
162pub enum EspNowError {
163 Error(Error),
165 SendFailed,
167 DuplicateInstance,
169 Initialization(WifiError),
171}
172
173impl core::fmt::Display for EspNowError {
174 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
175 match self {
176 EspNowError::Error(e) => write!(f, "Internal error: {e}."),
177 EspNowError::SendFailed => write!(f, "Failed to send an ESP-NOW message."),
178 EspNowError::DuplicateInstance => {
179 write!(f, "Attempt to create `EspNow` instance twice.")
180 }
181 EspNowError::Initialization(e) => write!(f, "Initialization error: {e}."),
182 }
183 }
184}
185
186impl core::error::Error for EspNowError {}
187
188impl From<WifiError> for EspNowError {
189 fn from(f: WifiError) -> Self {
190 Self::Initialization(f)
191 }
192}
193
194#[derive(Debug)]
196#[cfg_attr(feature = "defmt", derive(defmt::Format))]
197#[instability::unstable]
198pub struct PeerCount {
199 pub total_count: i32,
201
202 pub encrypted_count: i32,
204}
205
206#[repr(u32)]
208#[cfg_attr(feature = "defmt", derive(defmt::Format))]
209#[instability::unstable]
210pub enum WifiPhyRate {
211 Rate1mL = 0,
213 Rate2m,
215 Rate5mL,
217 Rate11mL,
219 Rate2mS,
221 Rate5mS,
223 Rate11mS,
225 Rate48m,
227 Rate24m,
229 Rate12m,
231 Rate6m,
233 Rate54m,
235 Rate36m,
237 Rate18m,
239 Rate9m,
241 RateMcs0Lgi,
243 RateMcs1Lgi,
245 RateMcs2Lgi,
247 RateMcs3Lgi,
249 RateMcs4Lgi,
251 RateMcs5Lgi,
253 RateMcs6Lgi,
255 RateMcs7Lgi,
257 RateMcs0Sgi,
259 RateMcs1Sgi,
261 RateMcs2Sgi,
263 RateMcs3Sgi,
265 RateMcs4Sgi,
267 RateMcs5Sgi,
269 RateMcs6Sgi,
271 RateMcs7Sgi,
273 RateLora250k,
275 RateLora500k,
277 RateMax,
279}
280
281#[derive(Debug, Clone, Copy)]
283#[cfg_attr(feature = "defmt", derive(defmt::Format))]
284#[instability::unstable]
285pub struct PeerInfo {
286 pub interface: EspNowWifiInterface,
288
289 pub peer_address: [u8; 6],
292
293 pub lmk: Option<[u8; 16]>,
295
296 pub channel: Option<u8>,
298
299 pub encrypt: bool,
301 }
303
304#[derive(Debug, Clone, Copy)]
306#[cfg_attr(feature = "defmt", derive(defmt::Format))]
307#[instability::unstable]
308pub struct ReceiveInfo {
309 pub src_address: [u8; 6],
311
312 pub dst_address: [u8; 6],
314
315 pub rx_control: RxControlInfo,
317}
318
319#[derive(Clone)]
322#[instability::unstable]
323pub struct ReceivedData {
324 data: Box<[u8]>,
325 pub info: ReceiveInfo,
327}
328
329impl ReceivedData {
330 #[instability::unstable]
332 pub fn data(&self) -> &[u8] {
333 &self.data
334 }
335}
336
337#[cfg(feature = "defmt")]
338impl defmt::Format for ReceivedData {
339 fn format(&self, fmt: defmt::Formatter<'_>) {
340 defmt::write!(fmt, "ReceivedData {}, Info {}", &self.data[..], &self.info,)
341 }
342}
343
344impl Debug for ReceivedData {
345 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
346 f.debug_struct("ReceivedData")
347 .field("data", &self.data())
348 .field("info", &self.info)
349 .finish()
350 }
351}
352
353#[derive(Debug, Clone, Copy, PartialEq)]
355#[cfg_attr(feature = "defmt", derive(defmt::Format))]
356#[instability::unstable]
357pub enum EspNowWifiInterface {
358 Ap,
360 Sta,
362}
363
364impl EspNowWifiInterface {
365 fn as_wifi_interface(&self) -> wifi_interface_t {
366 match self {
367 EspNowWifiInterface::Ap => wifi_interface_t_WIFI_IF_AP,
368 EspNowWifiInterface::Sta => wifi_interface_t_WIFI_IF_STA,
369 }
370 }
371
372 fn from_wifi_interface(interface: wifi_interface_t) -> Self {
373 #[allow(non_upper_case_globals)]
374 match interface {
375 wifi_interface_t_WIFI_IF_AP => EspNowWifiInterface::Ap,
376 wifi_interface_t_WIFI_IF_STA => EspNowWifiInterface::Sta,
377 wifi_interface_t_WIFI_IF_NAN => panic!("NAN is unsupported"),
378 _ => unreachable!("Unknown interface"),
379 }
380 }
381}
382
383#[instability::unstable]
385pub struct EspNowManager<'d> {
386 _rc: EspNowRc<'d>,
387}
388
389impl EspNowManager<'_> {
390 #[instability::unstable]
393 pub fn set_channel(&self, channel: u8) -> Result<(), EspNowError> {
394 check_error!({ esp_wifi_set_channel(channel, 0) })
395 }
396
397 #[instability::unstable]
399 pub fn version(&self) -> Result<u32, EspNowError> {
400 let mut version = 0u32;
401 check_error!({ esp_now_get_version(&mut version as *mut u32) })?;
402 Ok(version)
403 }
404
405 #[instability::unstable]
407 pub fn add_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
408 let raw_peer = esp_now_peer_info_t {
409 peer_addr: peer.peer_address,
410 lmk: peer.lmk.unwrap_or([0u8; 16]),
411 channel: peer.channel.unwrap_or(0),
412 ifidx: peer.interface.as_wifi_interface(),
413 encrypt: peer.encrypt,
414 priv_: core::ptr::null_mut(),
415 };
416 check_error!({ esp_now_add_peer(&raw_peer as *const _) })
417 }
418
419 #[cfg(feature = "csi")]
421 #[instability::unstable]
422 pub fn set_csi(
423 &mut self,
424 mut csi: CsiConfig,
425 cb: impl FnMut(crate::wifi::wifi_csi_info_t) + Send,
426 ) -> Result<(), WifiError> {
427 csi.apply_config()?;
428 csi.set_receive_cb(cb)?;
429 csi.set_csi(true)?;
430
431 Ok(())
432 }
433
434 #[instability::unstable]
436 pub fn remove_peer(&self, peer_address: &[u8; 6]) -> Result<(), EspNowError> {
437 check_error!({ esp_now_del_peer(peer_address.as_ptr()) })
438 }
439
440 #[instability::unstable]
442 pub fn modify_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
443 let raw_peer = esp_now_peer_info_t {
444 peer_addr: peer.peer_address,
445 lmk: peer.lmk.unwrap_or([0u8; 16]),
446 channel: peer.channel.unwrap_or(0),
447 ifidx: peer.interface.as_wifi_interface(),
448 encrypt: peer.encrypt,
449 priv_: core::ptr::null_mut(),
450 };
451 check_error!({ esp_now_mod_peer(&raw_peer as *const _) })
452 }
453
454 #[instability::unstable]
456 pub fn peer(&self, peer_address: &[u8; 6]) -> Result<PeerInfo, EspNowError> {
457 let mut raw_peer = esp_now_peer_info_t {
458 peer_addr: [0u8; 6],
459 lmk: [0u8; 16],
460 channel: 0,
461 ifidx: 0,
462 encrypt: false,
463 priv_: core::ptr::null_mut(),
464 };
465 check_error!({ esp_now_get_peer(peer_address.as_ptr(), &mut raw_peer as *mut _) })?;
466
467 Ok(PeerInfo {
468 interface: EspNowWifiInterface::from_wifi_interface(raw_peer.ifidx),
469 peer_address: raw_peer.peer_addr,
470 lmk: if raw_peer.lmk.is_empty() {
471 None
472 } else {
473 Some(raw_peer.lmk)
474 },
475 channel: if raw_peer.channel != 0 {
476 Some(raw_peer.channel)
477 } else {
478 None
479 },
480 encrypt: raw_peer.encrypt,
481 })
482 }
483
484 #[instability::unstable]
490 pub fn fetch_peer(&self, from_head: bool) -> Result<PeerInfo, EspNowError> {
491 let mut raw_peer = esp_now_peer_info_t {
492 peer_addr: [0u8; 6],
493 lmk: [0u8; 16],
494 channel: 0,
495 ifidx: 0,
496 encrypt: false,
497 priv_: core::ptr::null_mut(),
498 };
499 check_error!({ esp_now_fetch_peer(from_head, &mut raw_peer as *mut _) })?;
500
501 Ok(PeerInfo {
502 interface: EspNowWifiInterface::from_wifi_interface(raw_peer.ifidx),
503 peer_address: raw_peer.peer_addr,
504 lmk: if raw_peer.lmk.is_empty() {
505 None
506 } else {
507 Some(raw_peer.lmk)
508 },
509 channel: if raw_peer.channel != 0 {
510 Some(raw_peer.channel)
511 } else {
512 None
513 },
514 encrypt: raw_peer.encrypt,
515 })
516 }
517
518 #[instability::unstable]
520 pub fn peer_exists(&self, peer_address: &[u8; 6]) -> bool {
521 unsafe { esp_now_is_peer_exist(peer_address.as_ptr()) }
522 }
523
524 #[instability::unstable]
526 pub fn peer_count(&self) -> Result<PeerCount, EspNowError> {
527 let mut peer_num = esp_now_peer_num_t {
528 total_num: 0,
529 encrypt_num: 0,
530 };
531 check_error!({ esp_now_get_peer_num(&mut peer_num as *mut _) })?;
532
533 Ok(PeerCount {
534 total_count: peer_num.total_num,
535 encrypted_count: peer_num.encrypt_num,
536 })
537 }
538
539 #[instability::unstable]
541 pub fn set_pmk(&self, pmk: &[u8; 16]) -> Result<(), EspNowError> {
542 check_error!({ esp_now_set_pmk(pmk.as_ptr()) })
543 }
544
545 #[instability::unstable]
550 pub fn set_wake_window(&self, wake_window: u16) -> Result<(), EspNowError> {
551 check_error!({ esp_now_set_wake_window(wake_window) })
552 }
553
554 #[instability::unstable]
556 pub fn set_rate(&self, rate: WifiPhyRate) -> Result<(), EspNowError> {
557 check_error!({ esp_wifi_config_espnow_rate(wifi_interface_t_WIFI_IF_STA, rate as u32,) })
558 }
559}
560
561#[instability::unstable]
569pub struct EspNowSender<'d> {
570 _rc: EspNowRc<'d>,
571}
572
573impl EspNowSender<'_> {
574 #[instability::unstable]
578 pub fn send<'s>(
579 &'s mut self,
580 dst_addr: &[u8; 6],
581 data: &[u8],
582 ) -> Result<SendWaiter<'s>, EspNowError> {
583 ESP_NOW_SEND_CB_INVOKED.store(false, Ordering::Release);
584 check_error!({ esp_now_send(dst_addr.as_ptr(), data.as_ptr(), data.len()) })?;
585 Ok(SendWaiter(PhantomData))
586 }
587}
588
589#[allow(unknown_lints)]
590#[allow(clippy::too_long_first_doc_paragraph)]
591#[must_use]
602#[instability::unstable]
603pub struct SendWaiter<'s>(PhantomData<&'s mut EspNowSender<'s>>);
604
605impl SendWaiter<'_> {
606 #[instability::unstable]
609 pub fn wait(self) -> Result<(), EspNowError> {
610 core::mem::forget(self);
613 while !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {}
614
615 if ESP_NOW_SEND_STATUS.load(Ordering::Relaxed) {
616 Ok(())
617 } else {
618 Err(EspNowError::SendFailed)
619 }
620 }
621}
622
623impl Drop for SendWaiter<'_> {
624 fn drop(&mut self) {
627 while !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {}
628 }
629}
630
631#[instability::unstable]
634pub struct EspNowReceiver<'d> {
635 _rc: EspNowRc<'d>,
636}
637
638impl EspNowReceiver<'_> {
639 #[instability::unstable]
641 pub fn receive(&self) -> Option<ReceivedData> {
642 STATE.with(|state| state.rx_queue.pop_front())
643 }
644}
645
646struct EspNowRc<'d> {
649 rc: &'static AtomicU8,
650 inner: PhantomData<EspNow<'d>>,
651}
652
653impl EspNowRc<'_> {
654 fn new() -> Self {
655 static ESP_NOW_RC: AtomicU8 = AtomicU8::new(0);
656 assert!(ESP_NOW_RC.fetch_add(1, Ordering::AcqRel) == 0);
657
658 Self {
659 rc: &ESP_NOW_RC,
660 inner: PhantomData,
661 }
662 }
663}
664
665impl Clone for EspNowRc<'_> {
666 fn clone(&self) -> Self {
667 self.rc.fetch_add(1, Ordering::Release);
668 Self {
669 rc: self.rc,
670 inner: PhantomData,
671 }
672 }
673}
674
675impl Drop for EspNowRc<'_> {
676 fn drop(&mut self) {
677 if self.rc.fetch_sub(1, Ordering::AcqRel) == 1 {
678 unsafe {
679 esp_now_unregister_recv_cb();
680 esp_now_deinit();
681 }
682 }
683 }
684}
685
686#[allow(unknown_lints)]
687#[allow(clippy::too_long_first_doc_paragraph)]
688#[instability::unstable]
698pub struct EspNow<'d> {
699 manager: EspNowManager<'d>,
700 sender: EspNowSender<'d>,
701 receiver: EspNowReceiver<'d>,
702 _phantom: PhantomData<&'d ()>,
703}
704
705impl<'d> EspNow<'d> {
706 pub(crate) fn new_internal() -> EspNow<'d> {
707 let espnow_rc = EspNowRc::new();
708 let esp_now = EspNow {
709 manager: EspNowManager {
710 _rc: espnow_rc.clone(),
711 },
712 sender: EspNowSender {
713 _rc: espnow_rc.clone(),
714 },
715 receiver: EspNowReceiver { _rc: espnow_rc },
716 _phantom: PhantomData,
717 };
718
719 check_error_expect!({ esp_now_init() }, "esp-now-init failed");
720 check_error_expect!(
721 { esp_now_register_recv_cb(Some(rcv_cb)) },
722 "receiving callback failed"
723 );
724 check_error_expect!(
725 { esp_now_register_send_cb(Some(send_cb)) },
726 "sending callback failed"
727 );
728
729 esp_now
730 .add_peer(PeerInfo {
731 interface: EspNowWifiInterface::Sta,
732 peer_address: BROADCAST_ADDRESS,
733 lmk: None,
734 channel: None,
735 encrypt: false,
736 })
737 .expect("adding peer failed");
738
739 esp_now
740 }
741
742 #[instability::unstable]
745 pub fn split(self) -> (EspNowManager<'d>, EspNowSender<'d>, EspNowReceiver<'d>) {
746 (self.manager, self.sender, self.receiver)
747 }
748
749 #[instability::unstable]
752 pub fn set_channel(&self, channel: u8) -> Result<(), EspNowError> {
753 self.manager.set_channel(channel)
754 }
755
756 #[instability::unstable]
758 pub fn version(&self) -> Result<u32, EspNowError> {
759 self.manager.version()
760 }
761
762 #[instability::unstable]
764 pub fn add_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
765 self.manager.add_peer(peer)
766 }
767
768 #[instability::unstable]
770 pub fn remove_peer(&self, peer_address: &[u8; 6]) -> Result<(), EspNowError> {
771 self.manager.remove_peer(peer_address)
772 }
773
774 #[instability::unstable]
776 pub fn modify_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
777 self.manager.modify_peer(peer)
778 }
779
780 #[instability::unstable]
782 pub fn peer(&self, peer_address: &[u8; 6]) -> Result<PeerInfo, EspNowError> {
783 self.manager.peer(peer_address)
784 }
785
786 #[instability::unstable]
792 pub fn fetch_peer(&self, from_head: bool) -> Result<PeerInfo, EspNowError> {
793 self.manager.fetch_peer(from_head)
794 }
795
796 #[instability::unstable]
798 pub fn peer_exists(&self, peer_address: &[u8; 6]) -> bool {
799 self.manager.peer_exists(peer_address)
800 }
801
802 #[instability::unstable]
804 pub fn peer_count(&self) -> Result<PeerCount, EspNowError> {
805 self.manager.peer_count()
806 }
807
808 #[instability::unstable]
810 pub fn set_pmk(&self, pmk: &[u8; 16]) -> Result<(), EspNowError> {
811 self.manager.set_pmk(pmk)
812 }
813
814 #[instability::unstable]
819 pub fn set_wake_window(&self, wake_window: u16) -> Result<(), EspNowError> {
820 self.manager.set_wake_window(wake_window)
821 }
822
823 #[instability::unstable]
825 pub fn set_rate(&self, rate: WifiPhyRate) -> Result<(), EspNowError> {
826 self.manager.set_rate(rate)
827 }
828
829 #[instability::unstable]
833 pub fn send<'s>(
834 &'s mut self,
835 dst_addr: &[u8; 6],
836 data: &[u8],
837 ) -> Result<SendWaiter<'s>, EspNowError> {
838 self.sender.send(dst_addr, data)
839 }
840
841 #[instability::unstable]
843 pub fn receive(&self) -> Option<ReceivedData> {
844 self.receiver.receive()
845 }
846}
847
848unsafe extern "C" fn send_cb(_tx_info: *const esp_now_send_info_t, status: esp_now_send_status_t) {
849 let is_success = status == esp_now_send_status_t_ESP_NOW_SEND_SUCCESS;
850 ESP_NOW_SEND_STATUS.store(is_success, Ordering::Relaxed);
851
852 ESP_NOW_SEND_CB_INVOKED.store(true, Ordering::Release);
853
854 ESP_NOW_TX_WAKER.wake();
855}
856
857unsafe extern "C" fn rcv_cb(
858 esp_now_info: *const esp_now_recv_info_t,
859 data: *const u8,
860 data_len: i32,
861) {
862 let src = unsafe {
863 [
864 (*esp_now_info).src_addr.offset(0).read(),
865 (*esp_now_info).src_addr.offset(1).read(),
866 (*esp_now_info).src_addr.offset(2).read(),
867 (*esp_now_info).src_addr.offset(3).read(),
868 (*esp_now_info).src_addr.offset(4).read(),
869 (*esp_now_info).src_addr.offset(5).read(),
870 ]
871 };
872
873 let dst = unsafe {
874 [
875 (*esp_now_info).des_addr.offset(0).read(),
876 (*esp_now_info).des_addr.offset(1).read(),
877 (*esp_now_info).des_addr.offset(2).read(),
878 (*esp_now_info).des_addr.offset(3).read(),
879 (*esp_now_info).des_addr.offset(4).read(),
880 (*esp_now_info).des_addr.offset(5).read(),
881 ]
882 };
883
884 let rx_cntl = unsafe { (*esp_now_info).rx_ctrl };
885 let rx_control = unsafe { RxControlInfo::from_raw(rx_cntl) };
886
887 let info = ReceiveInfo {
888 src_address: src,
889 dst_address: dst,
890 rx_control,
891 };
892 let slice = unsafe { core::slice::from_raw_parts(data, data_len as usize) };
893
894 STATE.with(|state| {
895 let data = Box::from(slice);
896
897 if state.rx_queue.len() >= RECEIVE_QUEUE_SIZE {
898 state.rx_queue.pop_front();
899 }
900
901 state.rx_queue.push_back(ReceivedData { data, info });
902 ESP_NOW_RX_WAKER.wake();
903 });
904}
905
906impl EspNowReceiver<'_> {
907 #[instability::unstable]
911 pub fn receive_async(&mut self) -> ReceiveFuture<'_> {
912 ReceiveFuture(PhantomData)
913 }
914}
915
916impl EspNowSender<'_> {
917 #[instability::unstable]
919 pub fn send_async<'s, 'r>(
920 &'s mut self,
921 addr: &'r [u8; 6],
922 data: &'r [u8],
923 ) -> SendFuture<'s, 'r> {
924 SendFuture {
925 _sender: PhantomData,
926 addr,
927 data,
928 sent: false,
929 }
930 }
931}
932
933impl EspNow<'_> {
934 #[instability::unstable]
938 pub fn receive_async(&mut self) -> ReceiveFuture<'_> {
939 self.receiver.receive_async()
940 }
941
942 #[instability::unstable]
945 pub fn send_async<'s, 'r>(
946 &'s mut self,
947 dst_addr: &'r [u8; 6],
948 data: &'r [u8],
949 ) -> SendFuture<'s, 'r> {
950 self.sender.send_async(dst_addr, data)
951 }
952}
953
954#[must_use = "futures do nothing unless you `.await` or poll them"]
957#[instability::unstable]
958pub struct SendFuture<'s, 'r> {
959 _sender: PhantomData<&'s mut EspNowSender<'s>>,
960 addr: &'r [u8; 6],
961 data: &'r [u8],
962 sent: bool,
963}
964
965impl core::future::Future for SendFuture<'_, '_> {
966 type Output = Result<(), EspNowError>;
967
968 fn poll(mut self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
969 if !self.sent {
970 ESP_NOW_TX_WAKER.register(cx.waker());
971 ESP_NOW_SEND_CB_INVOKED.store(false, Ordering::Release);
972 if let Err(e) = check_error!({
973 esp_now_send(self.addr.as_ptr(), self.data.as_ptr(), self.data.len())
974 }) {
975 return Poll::Ready(Err(e));
976 }
977 self.sent = true;
978 }
979
980 if !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {
981 Poll::Pending
982 } else {
983 Poll::Ready(if ESP_NOW_SEND_STATUS.load(Ordering::Relaxed) {
984 Ok(())
985 } else {
986 Err(EspNowError::SendFailed)
987 })
988 }
989 }
990}
991
992#[must_use = "futures do nothing unless you `.await` or poll them"]
996#[instability::unstable]
997pub struct ReceiveFuture<'r>(PhantomData<&'r mut EspNowReceiver<'r>>);
998
999impl core::future::Future for ReceiveFuture<'_> {
1000 type Output = ReceivedData;
1001
1002 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1003 ESP_NOW_RX_WAKER.register(cx.waker());
1004
1005 if let Some(data) = STATE.with(|state| state.rx_queue.pop_front()) {
1006 Poll::Ready(data)
1007 } else {
1008 Poll::Pending
1009 }
1010 }
1011}