1use alloc::{boxed::Box, collections::vec_deque::VecDeque};
13use core::{cell::RefCell, fmt::Debug, marker::PhantomData};
14
15use critical_section::Mutex;
16use enumset::EnumSet;
17use portable_atomic::{AtomicBool, AtomicU8, Ordering};
18
19#[cfg(feature = "csi")]
20use crate::wifi::CsiConfig;
21use crate::{
22 binary::include::*,
23 config::PowerSaveMode,
24 hal::peripheral::{Peripheral, PeripheralRef},
25 wifi::{Protocol, RxControlInfo, WifiError},
26 EspWifiController,
27};
28
29const RECEIVE_QUEUE_SIZE: usize = 10;
30
31pub const ESP_NOW_MAX_DATA_LEN: usize = 250;
33
34pub const BROADCAST_ADDRESS: [u8; 6] = [0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8];
36
37static RECEIVE_QUEUE: Mutex<RefCell<VecDeque<ReceivedData>>> =
39 Mutex::new(RefCell::new(VecDeque::new()));
40
41static ESP_NOW_SEND_CB_INVOKED: AtomicBool = AtomicBool::new(false);
47static ESP_NOW_SEND_STATUS: AtomicBool = AtomicBool::new(true);
49
50macro_rules! check_error {
51 ($block:block) => {
52 match unsafe { $block } {
53 0 => Ok(()),
54 res => Err(EspNowError::Error(Error::from_code(res as u32))),
55 }
56 };
57}
58
59#[repr(u32)]
61#[derive(Debug)]
62#[cfg_attr(feature = "defmt", derive(defmt::Format))]
63#[allow(clippy::enum_variant_names)] pub enum Error {
65 NotInitialized = 12389,
67
68 InvalidArgument = 12390,
70
71 OutOfMemory = 12391,
73
74 PeerListFull = 12392,
76
77 NotFound = 12393,
79
80 InternalError = 12394,
82
83 PeerExists = 12395,
85
86 InterfaceError = 12396,
88
89 Other(u32),
92}
93
94impl Error {
95 pub fn from_code(code: u32) -> Error {
96 match code {
97 12389 => Error::NotInitialized,
98 12390 => Error::InvalidArgument,
99 12391 => Error::OutOfMemory,
100 12392 => Error::PeerListFull,
101 12393 => Error::NotFound,
102 12394 => Error::InternalError,
103 12395 => Error::PeerExists,
104 12396 => Error::InterfaceError,
105 _ => Error::Other(code),
106 }
107 }
108}
109
110#[derive(Debug)]
112#[cfg_attr(feature = "defmt", derive(defmt::Format))]
113pub enum EspNowError {
114 Error(Error),
116 SendFailed,
118 DuplicateInstance,
120 Initialization(WifiError),
122}
123
124impl From<WifiError> for EspNowError {
125 fn from(f: WifiError) -> Self {
126 Self::Initialization(f)
127 }
128}
129
130#[derive(Debug)]
132#[cfg_attr(feature = "defmt", derive(defmt::Format))]
133pub struct PeerCount {
134 pub total_count: i32,
136
137 pub encrypted_count: i32,
139}
140
141#[repr(u32)]
143#[cfg_attr(feature = "defmt", derive(defmt::Format))]
144pub enum WifiPhyRate {
145 Rate1mL = 0,
147 Rate2m,
149 Rate5mL,
151 Rate11mL,
153 Rate2mS,
155 Rate5mS,
157 Rate11mS,
159 Rate48m,
161 Rate24m,
163 Rate12m,
165 Rate6m,
167 Rate54m,
169 Rate36m,
171 Rate18m,
173 Rate9m,
175 RateMcs0Lgi,
177 RateMcs1Lgi,
179 RateMcs2Lgi,
181 RateMcs3Lgi,
183 RateMcs4Lgi,
185 RateMcs5Lgi,
187 RateMcs6Lgi,
189 RateMcs7Lgi,
191 RateMcs0Sgi,
193 RateMcs1Sgi,
195 RateMcs2Sgi,
197 RateMcs3Sgi,
199 RateMcs4Sgi,
201 RateMcs5Sgi,
203 RateMcs6Sgi,
205 RateMcs7Sgi,
207 RateLora250k,
209 RateLora500k,
211 RateMax,
213}
214
215#[derive(Debug, Clone, Copy)]
217#[cfg_attr(feature = "defmt", derive(defmt::Format))]
218pub struct PeerInfo {
219 pub peer_address: [u8; 6],
222
223 pub lmk: Option<[u8; 16]>,
225
226 pub channel: Option<u8>,
228
229 pub encrypt: bool,
231 }
233
234#[derive(Debug, Clone, Copy)]
236#[cfg_attr(feature = "defmt", derive(defmt::Format))]
237pub struct ReceiveInfo {
238 pub src_address: [u8; 6],
240
241 pub dst_address: [u8; 6],
243
244 pub rx_control: RxControlInfo,
246}
247
248#[derive(Clone)]
251pub struct ReceivedData {
252 data: Box<[u8]>,
253 pub info: ReceiveInfo,
254}
255
256impl ReceivedData {
257 pub fn data(&self) -> &[u8] {
259 &self.data
260 }
261}
262
263#[cfg(feature = "defmt")]
264impl defmt::Format for ReceivedData {
265 fn format(&self, fmt: defmt::Formatter<'_>) {
266 defmt::write!(fmt, "ReceivedData {}, Info {}", &self.data[..], &self.info,)
267 }
268}
269
270impl Debug for ReceivedData {
271 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
272 f.debug_struct("ReceivedData")
273 .field("data", &self.data())
274 .field("info", &self.info)
275 .finish()
276 }
277}
278
279pub struct EspNowWithWifiCreateToken {
281 _private: (),
282}
283
284pub fn enable_esp_now_with_wifi(
286 device: crate::hal::peripherals::WIFI,
287) -> (crate::hal::peripherals::WIFI, EspNowWithWifiCreateToken) {
288 (device, EspNowWithWifiCreateToken { _private: () })
289}
290
291pub struct EspNowManager<'d> {
293 _rc: EspNowRc<'d>,
294}
295
296impl EspNowManager<'_> {
297 pub fn set_protocol(&self, protocols: EnumSet<Protocol>) -> Result<(), EspNowError> {
305 let mut protocol = 0u8;
306
307 protocols.into_iter().for_each(|v| match v {
308 Protocol::P802D11B => protocol |= WIFI_PROTOCOL_11B as u8,
309 Protocol::P802D11BG => protocol |= WIFI_PROTOCOL_11B as u8 | WIFI_PROTOCOL_11G as u8,
310 Protocol::P802D11BGN => {
311 protocol |=
312 WIFI_PROTOCOL_11B as u8 | WIFI_PROTOCOL_11G as u8 | WIFI_PROTOCOL_11N as u8
313 }
314 Protocol::P802D11BGNLR => {
315 protocol |= WIFI_PROTOCOL_11B as u8
316 | WIFI_PROTOCOL_11G as u8
317 | WIFI_PROTOCOL_11N as u8
318 | WIFI_PROTOCOL_LR as u8
319 }
320 Protocol::P802D11LR => protocol |= WIFI_PROTOCOL_LR as u8,
321 Protocol::P802D11BGNAX => {
322 protocol |= WIFI_PROTOCOL_11B as u8
323 | WIFI_PROTOCOL_11G as u8
324 | WIFI_PROTOCOL_11N as u8
325 | WIFI_PROTOCOL_11AX as u8
326 }
327 });
328
329 let mut mode = wifi_mode_t_WIFI_MODE_NULL;
330 check_error!({ esp_wifi_get_mode(&mut mode) })?;
331
332 if mode == wifi_mode_t_WIFI_MODE_STA || mode == wifi_mode_t_WIFI_MODE_APSTA {
333 check_error!({ esp_wifi_set_protocol(wifi_interface_t_WIFI_IF_STA, protocol) })?;
334 }
335 if mode == wifi_mode_t_WIFI_MODE_AP || mode == wifi_mode_t_WIFI_MODE_APSTA {
336 check_error!({ esp_wifi_set_protocol(wifi_interface_t_WIFI_IF_AP, protocol) })?;
337 }
338
339 Ok(())
340 }
341
342 pub fn set_power_saving(&self, ps: PowerSaveMode) -> Result<(), WifiError> {
344 crate::wifi::apply_power_saving(ps)
345 }
346
347 pub fn set_channel(&self, channel: u8) -> Result<(), EspNowError> {
350 check_error!({ esp_wifi_set_channel(channel, 0) })
351 }
352
353 pub fn version(&self) -> Result<u32, EspNowError> {
355 let mut version = 0u32;
356 check_error!({ esp_now_get_version(&mut version as *mut u32) })?;
357 Ok(version)
358 }
359
360 pub fn add_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
362 let raw_peer = esp_now_peer_info_t {
363 peer_addr: peer.peer_address,
364 lmk: peer.lmk.unwrap_or([0u8; 16]),
365 channel: peer.channel.unwrap_or(0),
366 ifidx: wifi_interface_t_WIFI_IF_STA,
367 encrypt: peer.encrypt,
368 priv_: core::ptr::null_mut(),
369 };
370 check_error!({ esp_now_add_peer(&raw_peer as *const _) })
371 }
372
373 #[cfg(feature = "csi")]
375 pub fn set_csi(
376 &mut self,
377 mut csi: CsiConfig,
378 cb: impl FnMut(crate::wifi::wifi_csi_info_t) + Send,
379 ) -> Result<(), WifiError> {
380 csi.apply_config()?;
381 csi.set_receive_cb(cb)?;
382 csi.set_csi(true)?;
383
384 Ok(())
385 }
386
387 pub fn remove_peer(&self, peer_address: &[u8; 6]) -> Result<(), EspNowError> {
389 check_error!({ esp_now_del_peer(peer_address.as_ptr()) })
390 }
391
392 pub fn modify_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
394 let raw_peer = esp_now_peer_info_t {
395 peer_addr: peer.peer_address,
396 lmk: peer.lmk.unwrap_or([0u8; 16]),
397 channel: peer.channel.unwrap_or(0),
398 ifidx: wifi_interface_t_WIFI_IF_STA,
399 encrypt: peer.encrypt,
400 priv_: core::ptr::null_mut(),
401 };
402 check_error!({ esp_now_mod_peer(&raw_peer as *const _) })
403 }
404
405 pub fn peer(&self, peer_address: &[u8; 6]) -> Result<PeerInfo, EspNowError> {
407 let mut raw_peer = esp_now_peer_info_t {
408 peer_addr: [0u8; 6],
409 lmk: [0u8; 16],
410 channel: 0,
411 ifidx: 0,
412 encrypt: false,
413 priv_: core::ptr::null_mut(),
414 };
415 check_error!({ esp_now_get_peer(peer_address.as_ptr(), &mut raw_peer as *mut _) })?;
416
417 Ok(PeerInfo {
418 peer_address: raw_peer.peer_addr,
419 lmk: if raw_peer.lmk.is_empty() {
420 None
421 } else {
422 Some(raw_peer.lmk)
423 },
424 channel: if raw_peer.channel != 0 {
425 Some(raw_peer.channel)
426 } else {
427 None
428 },
429 encrypt: raw_peer.encrypt,
430 })
431 }
432
433 pub fn fetch_peer(&self, from_head: bool) -> Result<PeerInfo, EspNowError> {
439 let mut raw_peer = esp_now_peer_info_t {
440 peer_addr: [0u8; 6],
441 lmk: [0u8; 16],
442 channel: 0,
443 ifidx: 0,
444 encrypt: false,
445 priv_: core::ptr::null_mut(),
446 };
447 check_error!({ esp_now_fetch_peer(from_head, &mut raw_peer as *mut _) })?;
448
449 Ok(PeerInfo {
450 peer_address: raw_peer.peer_addr,
451 lmk: if raw_peer.lmk.is_empty() {
452 None
453 } else {
454 Some(raw_peer.lmk)
455 },
456 channel: if raw_peer.channel != 0 {
457 Some(raw_peer.channel)
458 } else {
459 None
460 },
461 encrypt: raw_peer.encrypt,
462 })
463 }
464
465 pub fn peer_exists(&self, peer_address: &[u8; 6]) -> bool {
467 unsafe { esp_now_is_peer_exist(peer_address.as_ptr()) }
468 }
469
470 pub fn peer_count(&self) -> Result<PeerCount, EspNowError> {
472 let mut peer_num = esp_now_peer_num_t {
473 total_num: 0,
474 encrypt_num: 0,
475 };
476 check_error!({ esp_now_get_peer_num(&mut peer_num as *mut _) })?;
477
478 Ok(PeerCount {
479 total_count: peer_num.total_num,
480 encrypted_count: peer_num.encrypt_num,
481 })
482 }
483
484 pub fn set_pmk(&self, pmk: &[u8; 16]) -> Result<(), EspNowError> {
486 check_error!({ esp_now_set_pmk(pmk.as_ptr()) })
487 }
488
489 pub fn set_wake_window(&self, wake_window: u16) -> Result<(), EspNowError> {
494 check_error!({ esp_now_set_wake_window(wake_window) })
495 }
496
497 pub fn set_rate(&self, rate: WifiPhyRate) -> Result<(), EspNowError> {
499 check_error!({ esp_wifi_config_espnow_rate(wifi_interface_t_WIFI_IF_STA, rate as u32,) })
500 }
501}
502
503impl Drop for EspNowManager<'_> {
504 fn drop(&mut self) {
505 if unwrap!(
506 crate::flags::WIFI.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
507 Some(x.saturating_sub(1))
508 })
509 ) == 0
510 {
511 if let Err(e) = crate::wifi::wifi_deinit() {
512 warn!("Failed to cleanly deinit wifi: {:?}", e);
513 }
514 }
515 }
516}
517
518pub struct EspNowSender<'d> {
526 _rc: EspNowRc<'d>,
527}
528
529impl EspNowSender<'_> {
530 pub fn send<'s>(
534 &'s mut self,
535 dst_addr: &[u8; 6],
536 data: &[u8],
537 ) -> Result<SendWaiter<'s>, EspNowError> {
538 ESP_NOW_SEND_CB_INVOKED.store(false, Ordering::Release);
539 check_error!({ esp_now_send(dst_addr.as_ptr(), data.as_ptr(), data.len()) })?;
540 Ok(SendWaiter(PhantomData))
541 }
542}
543
544#[allow(unknown_lints)]
545#[allow(clippy::too_long_first_doc_paragraph)]
546#[must_use]
557pub struct SendWaiter<'s>(PhantomData<&'s mut EspNowSender<'s>>);
558
559impl SendWaiter<'_> {
560 pub fn wait(self) -> Result<(), EspNowError> {
563 core::mem::forget(self);
566 while !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {}
567
568 if ESP_NOW_SEND_STATUS.load(Ordering::Relaxed) {
569 Ok(())
570 } else {
571 Err(EspNowError::SendFailed)
572 }
573 }
574}
575
576impl Drop for SendWaiter<'_> {
577 fn drop(&mut self) {
580 while !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {}
581 }
582}
583
584pub struct EspNowReceiver<'d> {
587 _rc: EspNowRc<'d>,
588}
589
590impl EspNowReceiver<'_> {
591 pub fn receive(&self) -> Option<ReceivedData> {
593 critical_section::with(|cs| {
594 let mut queue = RECEIVE_QUEUE.borrow_ref_mut(cs);
595 queue.pop_front()
596 })
597 }
598}
599
600struct EspNowRc<'d> {
603 rc: &'static AtomicU8,
604 inner: PhantomData<EspNow<'d>>,
605}
606
607impl EspNowRc<'_> {
608 fn new() -> Result<Self, EspNowError> {
609 static ESP_NOW_RC: AtomicU8 = AtomicU8::new(0);
610 if ESP_NOW_RC.fetch_add(1, Ordering::AcqRel) != 0 {
613 return Err(EspNowError::DuplicateInstance);
614 }
615
616 Ok(Self {
617 rc: &ESP_NOW_RC,
618 inner: PhantomData,
619 })
620 }
621}
622
623impl Clone for EspNowRc<'_> {
624 fn clone(&self) -> Self {
625 self.rc.fetch_add(1, Ordering::Release);
626 Self {
627 rc: self.rc,
628 inner: PhantomData,
629 }
630 }
631}
632
633impl Drop for EspNowRc<'_> {
634 fn drop(&mut self) {
635 if self.rc.fetch_sub(1, Ordering::AcqRel) == 1 {
636 unsafe {
637 esp_now_unregister_recv_cb();
638 esp_now_deinit();
639 }
640 }
641 }
642}
643
644#[allow(unknown_lints)]
645#[allow(clippy::too_long_first_doc_paragraph)]
646pub struct EspNow<'d> {
656 manager: EspNowManager<'d>,
657 sender: EspNowSender<'d>,
658 receiver: EspNowReceiver<'d>,
659 _phantom: PhantomData<&'d ()>,
660}
661
662impl<'d> EspNow<'d> {
663 pub fn new(
665 inited: &'d EspWifiController<'d>,
666 device: impl Peripheral<P = crate::hal::peripherals::WIFI> + 'd,
667 ) -> Result<EspNow<'d>, EspNowError> {
668 EspNow::new_internal(inited, Some(device.into_ref()))
669 }
670
671 pub fn new_with_wifi(
673 inited: &'d EspWifiController<'d>,
674 _token: EspNowWithWifiCreateToken,
675 ) -> Result<EspNow<'d>, EspNowError> {
676 EspNow::new_internal(
677 inited,
678 None::<PeripheralRef<'d, crate::hal::peripherals::WIFI>>,
679 )
680 }
681
682 fn new_internal(
683 inited: &'d EspWifiController<'d>,
684 device: Option<PeripheralRef<'d, crate::hal::peripherals::WIFI>>,
685 ) -> Result<EspNow<'d>, EspNowError> {
686 if !inited.wifi() {
687 assert!(device.is_some());
689 crate::wifi::wifi_init()?;
690 }
691
692 let espnow_rc = EspNowRc::new()?;
693 let esp_now = EspNow {
694 manager: EspNowManager {
695 _rc: espnow_rc.clone(),
696 },
697 sender: EspNowSender {
698 _rc: espnow_rc.clone(),
699 },
700 receiver: EspNowReceiver { _rc: espnow_rc },
701 _phantom: PhantomData,
702 };
703 check_error!({ esp_wifi_set_mode(wifi_mode_t_WIFI_MODE_STA) })?;
704 check_error!({ esp_wifi_start() })?;
705 check_error!({
706 esp_wifi_set_inactive_time(wifi_interface_t_WIFI_IF_STA, crate::CONFIG.beacon_timeout)
707 })?;
708 check_error!({ esp_now_init() })?;
709 check_error!({ esp_now_register_recv_cb(Some(rcv_cb)) })?;
710 check_error!({ esp_now_register_send_cb(Some(send_cb)) })?;
711
712 esp_now.add_peer(PeerInfo {
713 peer_address: BROADCAST_ADDRESS,
714 lmk: None,
715 channel: None,
716 encrypt: false,
717 })?;
718
719 Ok(esp_now)
720 }
721
722 pub fn split(self) -> (EspNowManager<'d>, EspNowSender<'d>, EspNowReceiver<'d>) {
725 (self.manager, self.sender, self.receiver)
726 }
727
728 pub fn set_protocol(&self, protocols: EnumSet<Protocol>) -> Result<(), EspNowError> {
736 self.manager.set_protocol(protocols)
737 }
738
739 pub fn set_channel(&self, channel: u8) -> Result<(), EspNowError> {
742 self.manager.set_channel(channel)
743 }
744
745 pub fn version(&self) -> Result<u32, EspNowError> {
747 self.manager.version()
748 }
749
750 pub fn add_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
752 self.manager.add_peer(peer)
753 }
754
755 pub fn remove_peer(&self, peer_address: &[u8; 6]) -> Result<(), EspNowError> {
757 self.manager.remove_peer(peer_address)
758 }
759
760 pub fn modify_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
762 self.manager.modify_peer(peer)
763 }
764
765 pub fn peer(&self, peer_address: &[u8; 6]) -> Result<PeerInfo, EspNowError> {
767 self.manager.peer(peer_address)
768 }
769
770 pub fn fetch_peer(&self, from_head: bool) -> Result<PeerInfo, EspNowError> {
776 self.manager.fetch_peer(from_head)
777 }
778
779 pub fn peer_exists(&self, peer_address: &[u8; 6]) -> bool {
781 self.manager.peer_exists(peer_address)
782 }
783
784 pub fn peer_count(&self) -> Result<PeerCount, EspNowError> {
786 self.manager.peer_count()
787 }
788
789 pub fn set_pmk(&self, pmk: &[u8; 16]) -> Result<(), EspNowError> {
791 self.manager.set_pmk(pmk)
792 }
793
794 pub fn set_wake_window(&self, wake_window: u16) -> Result<(), EspNowError> {
799 self.manager.set_wake_window(wake_window)
800 }
801
802 pub fn set_rate(&self, rate: WifiPhyRate) -> Result<(), EspNowError> {
804 self.manager.set_rate(rate)
805 }
806
807 pub fn send<'s>(
811 &'s mut self,
812 dst_addr: &[u8; 6],
813 data: &[u8],
814 ) -> Result<SendWaiter<'s>, EspNowError> {
815 self.sender.send(dst_addr, data)
816 }
817
818 pub fn receive(&self) -> Option<ReceivedData> {
820 self.receiver.receive()
821 }
822}
823
824unsafe extern "C" fn send_cb(_mac_addr: *const u8, status: esp_now_send_status_t) {
825 critical_section::with(|_| {
826 let is_success = status == esp_now_send_status_t_ESP_NOW_SEND_SUCCESS;
827 ESP_NOW_SEND_STATUS.store(is_success, Ordering::Relaxed);
828
829 ESP_NOW_SEND_CB_INVOKED.store(true, Ordering::Release);
830
831 asynch::ESP_NOW_TX_WAKER.wake();
832 })
833}
834
835unsafe extern "C" fn rcv_cb(
836 esp_now_info: *const esp_now_recv_info_t,
837 data: *const u8,
838 data_len: i32,
839) {
840 let src = [
841 (*esp_now_info).src_addr.offset(0).read(),
842 (*esp_now_info).src_addr.offset(1).read(),
843 (*esp_now_info).src_addr.offset(2).read(),
844 (*esp_now_info).src_addr.offset(3).read(),
845 (*esp_now_info).src_addr.offset(4).read(),
846 (*esp_now_info).src_addr.offset(5).read(),
847 ];
848
849 let dst = [
850 (*esp_now_info).des_addr.offset(0).read(),
851 (*esp_now_info).des_addr.offset(1).read(),
852 (*esp_now_info).des_addr.offset(2).read(),
853 (*esp_now_info).des_addr.offset(3).read(),
854 (*esp_now_info).des_addr.offset(4).read(),
855 (*esp_now_info).des_addr.offset(5).read(),
856 ];
857
858 let rx_cntl = (*esp_now_info).rx_ctrl;
859 let rx_control = RxControlInfo::from_raw(rx_cntl);
860
861 let info = ReceiveInfo {
862 src_address: src,
863 dst_address: dst,
864 rx_control,
865 };
866 let slice = core::slice::from_raw_parts(data, data_len as usize);
867 critical_section::with(|cs| {
868 let mut queue = RECEIVE_QUEUE.borrow_ref_mut(cs);
869 let data = Box::from(slice);
870
871 if queue.len() >= RECEIVE_QUEUE_SIZE {
872 queue.pop_front();
873 }
874
875 queue.push_back(ReceivedData { data, info });
876
877 asynch::ESP_NOW_RX_WAKER.wake();
878 });
879}
880
881pub use asynch::SendFuture;
882
883mod asynch {
884 use core::task::{Context, Poll};
885
886 use esp_hal::asynch::AtomicWaker;
887
888 use super::*;
889
890 pub(super) static ESP_NOW_TX_WAKER: AtomicWaker = AtomicWaker::new();
891 pub(super) static ESP_NOW_RX_WAKER: AtomicWaker = AtomicWaker::new();
892
893 impl EspNowReceiver<'_> {
894 pub fn receive_async(&mut self) -> ReceiveFuture<'_> {
898 ReceiveFuture(PhantomData)
899 }
900 }
901
902 impl EspNowSender<'_> {
903 pub fn send_async<'s, 'r>(
905 &'s mut self,
906 addr: &'r [u8; 6],
907 data: &'r [u8],
908 ) -> SendFuture<'s, 'r> {
909 SendFuture {
910 _sender: PhantomData,
911 addr,
912 data,
913 sent: false,
914 }
915 }
916 }
917
918 impl EspNow<'_> {
919 pub fn receive_async(&mut self) -> ReceiveFuture<'_> {
923 self.receiver.receive_async()
924 }
925
926 pub fn send_async<'s, 'r>(
929 &'s mut self,
930 dst_addr: &'r [u8; 6],
931 data: &'r [u8],
932 ) -> SendFuture<'s, 'r> {
933 self.sender.send_async(dst_addr, data)
934 }
935 }
936
937 #[must_use = "futures do nothing unless you `.await` or poll them"]
940 pub struct SendFuture<'s, 'r> {
941 _sender: PhantomData<&'s mut EspNowSender<'s>>,
942 addr: &'r [u8; 6],
943 data: &'r [u8],
944 sent: bool,
945 }
946
947 impl core::future::Future for SendFuture<'_, '_> {
948 type Output = Result<(), EspNowError>;
949
950 fn poll(mut self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
951 if !self.sent {
952 ESP_NOW_TX_WAKER.register(cx.waker());
953 ESP_NOW_SEND_CB_INVOKED.store(false, Ordering::Release);
954 if let Err(e) = check_error!({
955 esp_now_send(self.addr.as_ptr(), self.data.as_ptr(), self.data.len())
956 }) {
957 return Poll::Ready(Err(e));
958 }
959 self.sent = true;
960 }
961
962 if !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {
963 Poll::Pending
964 } else {
965 Poll::Ready(if ESP_NOW_SEND_STATUS.load(Ordering::Relaxed) {
966 Ok(())
967 } else {
968 Err(EspNowError::SendFailed)
969 })
970 }
971 }
972 }
973
974 #[must_use = "futures do nothing unless you `.await` or poll them"]
978 pub struct ReceiveFuture<'r>(PhantomData<&'r mut EspNowReceiver<'r>>);
979
980 impl core::future::Future for ReceiveFuture<'_> {
981 type Output = ReceivedData;
982
983 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
984 ESP_NOW_RX_WAKER.register(cx.waker());
985
986 if let Some(data) = critical_section::with(|cs| {
987 let mut queue = RECEIVE_QUEUE.borrow_ref_mut(cs);
988 queue.pop_front()
989 }) {
990 Poll::Ready(data)
991 } else {
992 Poll::Pending
993 }
994 }
995 }
996}