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, WifiRefGuard},
31};
32
33const RECEIVE_QUEUE_SIZE: usize = 10;
34
35pub const ESP_NOW_MAX_DATA_LEN_V1: usize = crate::sys::include::ESP_NOW_MAX_DATA_LEN as _;
37
38pub const ESP_NOW_MAX_DATA_LEN_V2: usize = crate::sys::include::ESP_NOW_MAX_DATA_LEN_V2 as _;
40
41pub const BROADCAST_ADDRESS: [u8; 6] = [0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8, 0xffu8];
43
44struct EspNowState {
45 rx_queue: VecDeque<ReceivedData>,
47}
48
49static STATE: NonReentrantMutex<EspNowState> = NonReentrantMutex::new(EspNowState {
50 rx_queue: VecDeque::new(),
51});
52
53static ESP_NOW_SEND_CB_INVOKED: AtomicBool = AtomicBool::new(false);
59static ESP_NOW_SEND_STATUS: AtomicBool = AtomicBool::new(true);
61
62static ESP_NOW_TX_WAKER: AtomicWaker = AtomicWaker::new();
63static ESP_NOW_RX_WAKER: AtomicWaker = AtomicWaker::new();
64
65macro_rules! check_error {
66 ($block:block) => {
67 match unsafe { $block } {
68 0 => Ok(()),
69 res => Err(EspNowError::Error(Error::from_code(res as u32))),
70 }
71 };
72}
73
74macro_rules! check_error_expect {
75 ($block:block, $msg:literal) => {
76 match unsafe { $block } {
77 0 => (),
78 res => panic!(
79 "{}: {:?}",
80 $msg,
81 EspNowError::Error(Error::from_code(res as u32))
82 ),
83 }
84 };
85}
86
87#[repr(u32)]
89#[derive(Display, Debug, Copy, Clone, Eq, PartialEq, Hash)]
90#[cfg_attr(feature = "defmt", derive(defmt::Format))]
91#[instability::unstable]
92pub enum Error {
93 NotInitialized = 12389,
95
96 InvalidArgument = 12390,
98
99 OutOfMemory = 12391,
101
102 PeerListFull = 12392,
104
105 NotFound = 12393,
107
108 Internal = 12394,
110
111 PeerExists = 12395,
113
114 InterfaceMismatch = 12396,
116
117 Other(u32),
120}
121
122impl Error {
123 fn from_code(code: u32) -> Error {
125 match code {
126 12389 => Error::NotInitialized,
127 12390 => Error::InvalidArgument,
128 12391 => Error::OutOfMemory,
129 12392 => Error::PeerListFull,
130 12393 => Error::NotFound,
131 12394 => Error::Internal,
132 12395 => Error::PeerExists,
133 12396 => Error::InterfaceMismatch,
134 _ => Error::Other(code),
135 }
136 }
137}
138
139impl core::error::Error for Error {}
140
141#[derive(Display, Debug, Copy, Clone, Eq, PartialEq, Hash)]
143#[cfg_attr(feature = "defmt", derive(defmt::Format))]
144#[instability::unstable]
145pub enum EspNowError {
146 Error(Error),
148 SendFailed,
150 DuplicateInstance,
152 Initialization(WifiError),
154}
155
156impl core::error::Error for EspNowError {}
157
158impl From<WifiError> for EspNowError {
159 fn from(f: WifiError) -> Self {
160 Self::Initialization(f)
161 }
162}
163
164#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
166#[cfg_attr(feature = "defmt", derive(defmt::Format))]
167#[instability::unstable]
168pub struct PeerCount {
169 pub total_count: i32,
171
172 pub encrypted_count: i32,
174}
175
176#[repr(u32)]
178#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
179#[cfg_attr(feature = "defmt", derive(defmt::Format))]
180#[instability::unstable]
181pub enum WifiPhyRate {
182 Rate1mL = wifi_phy_rate_t_WIFI_PHY_RATE_1M_L,
184 Rate2m = wifi_phy_rate_t_WIFI_PHY_RATE_2M_L,
186 Rate5mL = wifi_phy_rate_t_WIFI_PHY_RATE_5M_L,
188 Rate11mL = wifi_phy_rate_t_WIFI_PHY_RATE_11M_L,
190 Rate2mS = wifi_phy_rate_t_WIFI_PHY_RATE_2M_S,
192 Rate5mS = wifi_phy_rate_t_WIFI_PHY_RATE_5M_S,
194 Rate11mS = wifi_phy_rate_t_WIFI_PHY_RATE_11M_S,
196 Rate48m = wifi_phy_rate_t_WIFI_PHY_RATE_48M,
198 Rate24m = wifi_phy_rate_t_WIFI_PHY_RATE_24M,
200 Rate12m = wifi_phy_rate_t_WIFI_PHY_RATE_12M,
202 Rate6m = wifi_phy_rate_t_WIFI_PHY_RATE_6M,
204 Rate54m = wifi_phy_rate_t_WIFI_PHY_RATE_54M,
206 Rate36m = wifi_phy_rate_t_WIFI_PHY_RATE_36M,
208 Rate18m = wifi_phy_rate_t_WIFI_PHY_RATE_18M,
210 Rate9m = wifi_phy_rate_t_WIFI_PHY_RATE_9M,
212 RateMcs0Lgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS0_LGI,
214 RateMcs1Lgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS1_LGI,
216 RateMcs2Lgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS2_LGI,
218 RateMcs3Lgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS3_LGI,
220 RateMcs4Lgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS4_LGI,
222 RateMcs5Lgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS5_LGI,
224 RateMcs6Lgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS6_LGI,
226 RateMcs7Lgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS7_LGI,
228 #[cfg(not(wifi_mac_version = "1"))]
230 RateMcs8Lgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS8_LGI,
231 #[cfg(not(wifi_mac_version = "1"))]
233 RateMcs9Lgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS9_LGI,
234 RateMcs0Sgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS0_SGI,
236 RateMcs1Sgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS1_SGI,
238 RateMcs2Sgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS2_SGI,
240 RateMcs3Sgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS3_SGI,
242 RateMcs4Sgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS4_SGI,
244 RateMcs5Sgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS5_SGI,
246 RateMcs6Sgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS6_SGI,
248 RateMcs7Sgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS7_SGI,
250 #[cfg(not(wifi_mac_version = "1"))]
252 RateMcs8Sgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS8_SGI,
253 #[cfg(not(wifi_mac_version = "1"))]
255 RateMcs9Sgi = wifi_phy_rate_t_WIFI_PHY_RATE_MCS9_SGI,
256 RateLora250k = wifi_phy_rate_t_WIFI_PHY_RATE_LORA_250K,
258 RateLora500k = wifi_phy_rate_t_WIFI_PHY_RATE_LORA_500K,
260}
261
262#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
264#[cfg_attr(feature = "defmt", derive(defmt::Format))]
265#[instability::unstable]
266pub struct PeerInfo {
267 pub interface: EspNowWifiInterface,
269
270 pub peer_address: [u8; 6],
273
274 pub lmk: Option<[u8; 16]>,
276
277 pub channel: Option<u8>,
279
280 pub encrypt: bool,
282 }
284
285#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
287#[cfg_attr(feature = "defmt", derive(defmt::Format))]
288#[instability::unstable]
289pub struct ReceiveInfo {
290 pub src_address: [u8; 6],
292
293 pub dst_address: [u8; 6],
295
296 pub rx_control: RxControlInfo,
298}
299
300#[derive(Clone)]
303#[instability::unstable]
304pub struct ReceivedData {
305 data: Box<[u8]>,
306 pub info: ReceiveInfo,
308}
309
310impl ReceivedData {
311 #[instability::unstable]
313 pub fn data(&self) -> &[u8] {
314 &self.data
315 }
316}
317
318#[cfg(feature = "defmt")]
319impl defmt::Format for ReceivedData {
320 fn format(&self, fmt: defmt::Formatter<'_>) {
321 defmt::write!(fmt, "ReceivedData {}, Info {}", &self.data[..], &self.info,)
322 }
323}
324
325impl Debug for ReceivedData {
326 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
327 f.debug_struct("ReceivedData")
328 .field("data", &self.data())
329 .field("info", &self.info)
330 .finish()
331 }
332}
333
334#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
336#[cfg_attr(feature = "defmt", derive(defmt::Format))]
337#[instability::unstable]
338pub enum EspNowWifiInterface {
339 AccessPoint,
341 Station,
343}
344
345impl EspNowWifiInterface {
346 fn as_wifi_interface(&self) -> wifi_interface_t {
347 match self {
348 EspNowWifiInterface::AccessPoint => wifi_interface_t_WIFI_IF_AP,
349 EspNowWifiInterface::Station => wifi_interface_t_WIFI_IF_STA,
350 }
351 }
352
353 fn from_wifi_interface(interface: wifi_interface_t) -> Self {
354 #[allow(non_upper_case_globals)]
355 match interface {
356 wifi_interface_t_WIFI_IF_AP => EspNowWifiInterface::AccessPoint,
357 wifi_interface_t_WIFI_IF_STA => EspNowWifiInterface::Station,
358 wifi_interface_t_WIFI_IF_NAN => panic!("NAN is unsupported"),
359 _ => unreachable!("Unknown interface"),
360 }
361 }
362}
363
364#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
366#[repr(u32)]
367#[cfg_attr(feature = "defmt", derive(defmt::Format))]
368#[instability::unstable]
369pub enum PhyMode {
370 Lr = wifi_phy_mode_t_WIFI_PHY_MODE_LR,
372 _11b = wifi_phy_mode_t_WIFI_PHY_MODE_11B,
374 _11g = wifi_phy_mode_t_WIFI_PHY_MODE_11G,
376 _11a = wifi_phy_mode_t_WIFI_PHY_MODE_11A,
378 Ht20 = wifi_phy_mode_t_WIFI_PHY_MODE_HT20,
380 Ht40 = wifi_phy_mode_t_WIFI_PHY_MODE_HT40,
382 He20 = wifi_phy_mode_t_WIFI_PHY_MODE_HE20,
384 Vht20 = wifi_phy_mode_t_WIFI_PHY_MODE_VHT20,
386}
387
388#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
390#[cfg_attr(feature = "defmt", derive(defmt::Format))]
391#[instability::unstable]
392pub struct RateConfig {
393 pub phy_mode: PhyMode,
395 pub rate: WifiPhyRate,
397 pub ersu: bool,
400 pub dcm: bool,
402}
403
404#[derive(Debug)]
406#[cfg_attr(feature = "defmt", derive(defmt::Format))]
407#[instability::unstable]
408pub struct EspNowManager {
409 _rc: EspNowRc,
410}
411
412impl EspNowManager {
413 #[instability::unstable]
418 pub fn set_channel(&self, channel: u8) -> Result<(), EspNowError> {
419 check_error!({ esp_wifi_set_channel(channel, 0) })
420 }
421
422 #[instability::unstable]
428 pub fn version(&self) -> Result<u32, EspNowError> {
429 let mut version = 0u32;
430 check_error!({ esp_now_get_version(&mut version as *mut u32) })?;
431 Ok(version)
432 }
433
434 #[instability::unstable]
436 pub fn add_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
437 let raw_peer = esp_now_peer_info_t {
438 peer_addr: peer.peer_address,
439 lmk: peer.lmk.unwrap_or([0u8; 16]),
440 channel: peer.channel.unwrap_or(0),
441 ifidx: peer.interface.as_wifi_interface(),
442 encrypt: peer.encrypt,
443 priv_: core::ptr::null_mut(),
444 };
445 check_error!({ esp_now_add_peer(&raw_peer as *const _) })
446 }
447
448 #[cfg(feature = "csi")]
450 #[instability::unstable]
451 pub fn set_csi(
452 &mut self,
453 mut csi: CsiConfig,
454 cb: impl FnMut(crate::wifi::csi::WifiCsiInfo<'_>) + Send,
455 ) -> Result<(), WifiError> {
456 csi.apply_config()?;
457 csi.set_receive_cb(cb)?;
458 csi.set_csi(true)?;
459
460 Ok(())
461 }
462
463 #[instability::unstable]
465 pub fn remove_peer(&self, peer_address: &[u8; 6]) -> Result<(), EspNowError> {
466 check_error!({ esp_now_del_peer(peer_address.as_ptr()) })
467 }
468
469 #[instability::unstable]
471 pub fn modify_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
472 let raw_peer = esp_now_peer_info_t {
473 peer_addr: peer.peer_address,
474 lmk: peer.lmk.unwrap_or([0u8; 16]),
475 channel: peer.channel.unwrap_or(0),
476 ifidx: peer.interface.as_wifi_interface(),
477 encrypt: peer.encrypt,
478 priv_: core::ptr::null_mut(),
479 };
480 check_error!({ esp_now_mod_peer(&raw_peer as *const _) })
481 }
482
483 #[instability::unstable]
485 pub fn peer(&self, peer_address: &[u8; 6]) -> Result<PeerInfo, EspNowError> {
486 let mut raw_peer = esp_now_peer_info_t {
487 peer_addr: [0u8; 6],
488 lmk: [0u8; 16],
489 channel: 0,
490 ifidx: 0,
491 encrypt: false,
492 priv_: core::ptr::null_mut(),
493 };
494 check_error!({ esp_now_get_peer(peer_address.as_ptr(), &mut raw_peer as *mut _) })?;
495
496 Ok(PeerInfo {
497 interface: EspNowWifiInterface::from_wifi_interface(raw_peer.ifidx),
498 peer_address: raw_peer.peer_addr,
499 lmk: if raw_peer.lmk.is_empty() {
500 None
501 } else {
502 Some(raw_peer.lmk)
503 },
504 channel: if raw_peer.channel != 0 {
505 Some(raw_peer.channel)
506 } else {
507 None
508 },
509 encrypt: raw_peer.encrypt,
510 })
511 }
512
513 #[instability::unstable]
519 pub fn fetch_peer(&self, from_head: bool) -> Result<PeerInfo, EspNowError> {
520 let mut raw_peer = esp_now_peer_info_t {
521 peer_addr: [0u8; 6],
522 lmk: [0u8; 16],
523 channel: 0,
524 ifidx: 0,
525 encrypt: false,
526 priv_: core::ptr::null_mut(),
527 };
528 check_error!({ esp_now_fetch_peer(from_head, &mut raw_peer as *mut _) })?;
529
530 Ok(PeerInfo {
531 interface: EspNowWifiInterface::from_wifi_interface(raw_peer.ifidx),
532 peer_address: raw_peer.peer_addr,
533 lmk: if raw_peer.lmk.is_empty() {
534 None
535 } else {
536 Some(raw_peer.lmk)
537 },
538 channel: if raw_peer.channel != 0 {
539 Some(raw_peer.channel)
540 } else {
541 None
542 },
543 encrypt: raw_peer.encrypt,
544 })
545 }
546
547 #[instability::unstable]
549 pub fn peer_exists(&self, peer_address: &[u8; 6]) -> bool {
550 unsafe { esp_now_is_peer_exist(peer_address.as_ptr()) }
551 }
552
553 #[instability::unstable]
555 pub fn peer_count(&self) -> Result<PeerCount, EspNowError> {
556 let mut peer_num = esp_now_peer_num_t {
557 total_num: 0,
558 encrypt_num: 0,
559 };
560 check_error!({ esp_now_get_peer_num(&mut peer_num as *mut _) })?;
561
562 Ok(PeerCount {
563 total_count: peer_num.total_num,
564 encrypted_count: peer_num.encrypt_num,
565 })
566 }
567
568 #[instability::unstable]
570 pub fn set_pmk(&self, pmk: &[u8; 16]) -> Result<(), EspNowError> {
571 check_error!({ esp_now_set_pmk(pmk.as_ptr()) })
572 }
573
574 #[instability::unstable]
579 pub fn set_wake_window(&self, wake_window: Duration) -> Result<(), EspNowError> {
580 let ms = wake_window.as_millis();
581
582 if ms > u16::MAX as u64 {
583 return Err(EspNowError::Error(Error::InvalidArgument));
584 }
585 check_error!({ esp_now_set_wake_window(ms as u16) })
586 }
587
588 #[instability::unstable]
591 pub fn set_peer_rate(
592 &self,
593 peer_address: &[u8; 6],
594 cfg: RateConfig,
595 ) -> Result<(), EspNowError> {
596 check_error!({
597 esp_now_set_peer_rate_config(
598 peer_address.as_ptr(),
599 &mut esp_now_rate_config_t {
600 phymode: cfg.phy_mode as u32,
601 rate: cfg.rate as u32,
602 ersu: cfg.ersu,
603 dcm: cfg.dcm,
604 },
605 )
606 })
607 }
608}
609
610#[derive(Debug)]
618#[cfg_attr(feature = "defmt", derive(defmt::Format))]
619#[instability::unstable]
620pub struct EspNowSender {
621 _rc: EspNowRc,
622}
623
624impl EspNowSender {
625 #[instability::unstable]
629 pub fn send<'s>(
630 &'s mut self,
631 dst_addr: &[u8; 6],
632 data: &[u8],
633 ) -> Result<SendWaiter<'s>, EspNowError> {
634 ESP_NOW_SEND_CB_INVOKED.store(false, Ordering::Release);
635 check_error!({ esp_now_send(dst_addr.as_ptr(), data.as_ptr(), data.len()) })?;
636 Ok(SendWaiter(PhantomData))
637 }
638}
639
640#[allow(unknown_lints)]
641#[allow(clippy::too_long_first_doc_paragraph)]
642#[must_use]
653#[instability::unstable]
654pub struct SendWaiter<'s>(PhantomData<&'s mut EspNowSender>);
655
656impl SendWaiter<'_> {
657 #[instability::unstable]
660 pub fn wait(self) -> Result<(), EspNowError> {
661 core::mem::forget(self);
664 while !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {}
665
666 if ESP_NOW_SEND_STATUS.load(Ordering::Relaxed) {
667 Ok(())
668 } else {
669 Err(EspNowError::SendFailed)
670 }
671 }
672}
673
674impl Drop for SendWaiter<'_> {
675 fn drop(&mut self) {
678 while !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {}
679 }
680}
681
682#[derive(Debug)]
685#[cfg_attr(feature = "defmt", derive(defmt::Format))]
686#[instability::unstable]
687pub struct EspNowReceiver {
688 _rc: EspNowRc,
689}
690
691impl EspNowReceiver {
692 #[instability::unstable]
694 pub fn receive(&self) -> Option<ReceivedData> {
695 STATE.with(|state| state.rx_queue.pop_front())
696 }
697}
698
699#[derive(Debug)]
702struct EspNowRc {
703 rc: &'static AtomicU8,
704 _wifi_guard: WifiRefGuard,
705}
706
707#[cfg(feature = "defmt")]
708impl defmt::Format for EspNowRc {
709 fn format(&self, f: defmt::Formatter<'_>) {
710 defmt::write!(
711 f,
712 "EspNowRc {{ rc: {}, _wifi_guard: ... }}",
713 self.rc.load(Ordering::Relaxed)
714 );
715 }
716}
717
718impl EspNowRc {
719 fn new(wifi_guard: WifiRefGuard) -> Self {
720 static ESP_NOW_RC: AtomicU8 = AtomicU8::new(0);
721 assert!(
722 ESP_NOW_RC.fetch_add(1, Ordering::AcqRel) == 0,
723 "ESP-NOW already in use"
724 );
725
726 Self {
727 rc: &ESP_NOW_RC,
728 _wifi_guard: wifi_guard,
729 }
730 }
731}
732
733impl Clone for EspNowRc {
734 fn clone(&self) -> Self {
735 self.rc.fetch_add(1, Ordering::Release);
736 Self {
737 rc: self.rc,
738 _wifi_guard: self._wifi_guard.clone(),
739 }
740 }
741}
742
743impl Drop for EspNowRc {
744 fn drop(&mut self) {
745 if self.rc.fetch_sub(1, Ordering::AcqRel) == 1 {
746 unsafe {
747 esp_now_unregister_recv_cb();
748 esp_now_deinit();
749 }
750 }
751 }
752}
753
754#[allow(unknown_lints)]
755#[allow(clippy::too_long_first_doc_paragraph)]
756#[derive(Debug)]
766#[cfg_attr(feature = "defmt", derive(defmt::Format))]
767#[instability::unstable]
768pub struct EspNow {
769 manager: EspNowManager,
770 sender: EspNowSender,
771 receiver: EspNowReceiver,
772}
773
774impl EspNow {
775 pub(crate) fn new_internal(guard: WifiRefGuard) -> EspNow {
776 let espnow_rc = EspNowRc::new(guard);
777 let esp_now = EspNow {
778 manager: EspNowManager {
779 _rc: espnow_rc.clone(),
780 },
781 sender: EspNowSender {
782 _rc: espnow_rc.clone(),
783 },
784 receiver: EspNowReceiver { _rc: espnow_rc },
785 };
786
787 check_error_expect!({ esp_now_init() }, "esp-now-init failed");
788 check_error_expect!(
789 { esp_now_register_recv_cb(Some(rcv_cb)) },
790 "receiving callback failed"
791 );
792 check_error_expect!(
793 { esp_now_register_send_cb(Some(send_cb)) },
794 "sending callback failed"
795 );
796
797 esp_now
798 .add_peer(PeerInfo {
799 interface: EspNowWifiInterface::Station,
800 peer_address: BROADCAST_ADDRESS,
801 lmk: None,
802 channel: None,
803 encrypt: false,
804 })
805 .expect("adding peer failed");
806
807 esp_now
808 }
809
810 #[instability::unstable]
813 pub fn split(self) -> (EspNowManager, EspNowSender, EspNowReceiver) {
814 (self.manager, self.sender, self.receiver)
815 }
816
817 #[instability::unstable]
820 pub fn set_channel(&self, channel: u8) -> Result<(), EspNowError> {
821 self.manager.set_channel(channel)
822 }
823
824 #[instability::unstable]
826 pub fn version(&self) -> Result<u32, EspNowError> {
827 self.manager.version()
828 }
829
830 #[instability::unstable]
832 pub fn add_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
833 self.manager.add_peer(peer)
834 }
835
836 #[instability::unstable]
838 pub fn remove_peer(&self, peer_address: &[u8; 6]) -> Result<(), EspNowError> {
839 self.manager.remove_peer(peer_address)
840 }
841
842 #[instability::unstable]
844 pub fn modify_peer(&self, peer: PeerInfo) -> Result<(), EspNowError> {
845 self.manager.modify_peer(peer)
846 }
847
848 #[instability::unstable]
850 pub fn peer(&self, peer_address: &[u8; 6]) -> Result<PeerInfo, EspNowError> {
851 self.manager.peer(peer_address)
852 }
853
854 #[instability::unstable]
860 pub fn fetch_peer(&self, from_head: bool) -> Result<PeerInfo, EspNowError> {
861 self.manager.fetch_peer(from_head)
862 }
863
864 #[instability::unstable]
866 pub fn peer_exists(&self, peer_address: &[u8; 6]) -> bool {
867 self.manager.peer_exists(peer_address)
868 }
869
870 #[instability::unstable]
872 pub fn peer_count(&self) -> Result<PeerCount, EspNowError> {
873 self.manager.peer_count()
874 }
875
876 #[instability::unstable]
878 pub fn set_pmk(&self, pmk: &[u8; 16]) -> Result<(), EspNowError> {
879 self.manager.set_pmk(pmk)
880 }
881
882 #[instability::unstable]
887 pub fn set_wake_window(&self, wake_window: Duration) -> Result<(), EspNowError> {
888 self.manager.set_wake_window(wake_window)
889 }
890
891 #[instability::unstable]
894 pub fn set_peer_rate(
895 &self,
896 peer_address: &[u8; 6],
897 cfg: RateConfig,
898 ) -> Result<(), EspNowError> {
899 self.manager.set_peer_rate(peer_address, cfg)
900 }
901
902 #[instability::unstable]
906 pub fn send<'s>(
907 &'s mut self,
908 dst_addr: &[u8; 6],
909 data: &[u8],
910 ) -> Result<SendWaiter<'s>, EspNowError> {
911 self.sender.send(dst_addr, data)
912 }
913
914 #[instability::unstable]
916 pub fn receive(&self) -> Option<ReceivedData> {
917 self.receiver.receive()
918 }
919}
920
921unsafe extern "C" fn send_cb(_tx_info: *const esp_now_send_info_t, status: esp_now_send_status_t) {
922 let is_success = status == esp_now_send_status_t_ESP_NOW_SEND_SUCCESS;
923 ESP_NOW_SEND_STATUS.store(is_success, Ordering::Relaxed);
924
925 ESP_NOW_SEND_CB_INVOKED.store(true, Ordering::Release);
926
927 ESP_NOW_TX_WAKER.wake();
928}
929
930unsafe extern "C" fn rcv_cb(
931 esp_now_info: *const esp_now_recv_info_t,
932 data: *const u8,
933 data_len: i32,
934) {
935 let src = unsafe {
936 [
937 (*esp_now_info).src_addr.offset(0).read(),
938 (*esp_now_info).src_addr.offset(1).read(),
939 (*esp_now_info).src_addr.offset(2).read(),
940 (*esp_now_info).src_addr.offset(3).read(),
941 (*esp_now_info).src_addr.offset(4).read(),
942 (*esp_now_info).src_addr.offset(5).read(),
943 ]
944 };
945
946 let dst = unsafe {
947 [
948 (*esp_now_info).des_addr.offset(0).read(),
949 (*esp_now_info).des_addr.offset(1).read(),
950 (*esp_now_info).des_addr.offset(2).read(),
951 (*esp_now_info).des_addr.offset(3).read(),
952 (*esp_now_info).des_addr.offset(4).read(),
953 (*esp_now_info).des_addr.offset(5).read(),
954 ]
955 };
956
957 let rx_cntl = unsafe { (*esp_now_info).rx_ctrl };
958 let rx_control = unsafe { RxControlInfo::from_raw(rx_cntl) };
959
960 let info = ReceiveInfo {
961 src_address: src,
962 dst_address: dst,
963 rx_control,
964 };
965 let slice = unsafe { core::slice::from_raw_parts(data, data_len as usize) };
966
967 STATE.with(|state| {
968 let data = Box::from(slice);
969
970 if state.rx_queue.len() >= RECEIVE_QUEUE_SIZE {
971 state.rx_queue.pop_front();
972 }
973
974 state.rx_queue.push_back(ReceivedData { data, info });
975 ESP_NOW_RX_WAKER.wake();
976 });
977}
978
979impl EspNowReceiver {
980 #[instability::unstable]
984 pub fn receive_async(&mut self) -> ReceiveFuture<'_> {
985 ReceiveFuture(PhantomData)
986 }
987}
988
989impl EspNowSender {
990 #[instability::unstable]
992 pub fn send_async<'s, 'r>(
993 &'s mut self,
994 addr: &'r [u8; 6],
995 data: &'r [u8],
996 ) -> SendFuture<'s, 'r> {
997 SendFuture {
998 _sender: PhantomData,
999 addr,
1000 data,
1001 sent: false,
1002 }
1003 }
1004}
1005
1006impl EspNow {
1007 #[instability::unstable]
1011 pub fn receive_async(&mut self) -> ReceiveFuture<'_> {
1012 self.receiver.receive_async()
1013 }
1014
1015 #[instability::unstable]
1018 pub fn send_async<'s, 'r>(
1019 &'s mut self,
1020 dst_addr: &'r [u8; 6],
1021 data: &'r [u8],
1022 ) -> SendFuture<'s, 'r> {
1023 self.sender.send_async(dst_addr, data)
1024 }
1025}
1026
1027#[must_use = "futures do nothing unless you `.await` or poll them"]
1030#[instability::unstable]
1031pub struct SendFuture<'s, 'r> {
1032 _sender: PhantomData<&'s mut EspNowSender>,
1033 addr: &'r [u8; 6],
1034 data: &'r [u8],
1035 sent: bool,
1036}
1037
1038impl core::future::Future for SendFuture<'_, '_> {
1039 type Output = Result<(), EspNowError>;
1040
1041 fn poll(mut self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1042 if !self.sent {
1043 ESP_NOW_TX_WAKER.register(cx.waker());
1044 ESP_NOW_SEND_CB_INVOKED.store(false, Ordering::Release);
1045 if let Err(e) = check_error!({
1046 esp_now_send(self.addr.as_ptr(), self.data.as_ptr(), self.data.len())
1047 }) {
1048 return Poll::Ready(Err(e));
1049 }
1050 self.sent = true;
1051 }
1052
1053 if !ESP_NOW_SEND_CB_INVOKED.load(Ordering::Acquire) {
1054 Poll::Pending
1055 } else {
1056 Poll::Ready(if ESP_NOW_SEND_STATUS.load(Ordering::Relaxed) {
1057 Ok(())
1058 } else {
1059 Err(EspNowError::SendFailed)
1060 })
1061 }
1062 }
1063}
1064
1065#[must_use = "futures do nothing unless you `.await` or poll them"]
1069#[instability::unstable]
1070pub struct ReceiveFuture<'r>(PhantomData<&'r mut EspNowReceiver>);
1071
1072impl core::future::Future for ReceiveFuture<'_> {
1073 type Output = ReceivedData;
1074
1075 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1076 ESP_NOW_RX_WAKER.register(cx.waker());
1077
1078 if let Some(data) = STATE.with(|state| state.rx_queue.pop_front()) {
1079 Poll::Ready(data)
1080 } else {
1081 Poll::Pending
1082 }
1083 }
1084}