Skip to main content

esp_radio/wifi/sta/
mod.rs

1//! Wi-Fi station.
2
3use alloc::string::String;
4use core::fmt;
5
6use procmacros::BuilderLite;
7
8use super::{AuthenticationMethod, Protocols, Ssid};
9use crate::WifiError;
10
11unstable_module!(
12    #[cfg(feature = "wifi-eap")]
13    #[cfg_attr(docsrs, doc(cfg(feature = "wifi-eap")))]
14    pub mod eap;
15);
16
17/// Wi-Fi scan method.
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20#[non_exhaustive]
21#[repr(u8)]
22#[instability::unstable]
23pub enum ScanMethod {
24    /// Fast scan.
25    Fast,
26    /// Scan all channels.
27    AllChannels,
28}
29
30/// Station configuration for a Wi-Fi connection.
31#[derive(BuilderLite, Clone, Eq, PartialEq, Hash)]
32pub struct StationConfig {
33    /// The SSID of the Wi-Fi network.
34    #[builder_lite(skip_setter)]
35    pub(crate) ssid: Ssid,
36    /// The BSSID (MAC address) of the station.
37    pub(crate) bssid: Option<[u8; 6]>,
38    /// The authentication method for the Wi-Fi connection.
39    pub(crate) auth_method: AuthenticationMethod,
40    /// The password for the Wi-Fi connection.
41    #[builder_lite(reference)]
42    pub(crate) password: String,
43    /// The Wi-Fi channel to connect to.
44    pub(crate) channel: Option<u8>,
45    /// The set of protocols supported by the access point.
46    pub(crate) protocols: Protocols,
47    /// Interval for station to listen to beacon from access point.
48    ///
49    /// The unit of listen interval is one beacon interval.
50    /// For example, if beacon interval is 100 ms and listen interval is 3,
51    /// the interval for station to listen to beacon is 300 ms
52    #[builder_lite(unstable)]
53    pub(crate) listen_interval: u16,
54    /// Time to disconnect from access point if no data is received.
55    ///
56    /// Must be between 6 and 31.
57    #[builder_lite(unstable)]
58    pub(crate) beacon_timeout: u16,
59    /// Number of connection retries station will do before moving to next access point.
60    ///
61    /// `scan_method` should be set as [`ScanMethod::AllChannels`] to use this config.
62    ///
63    /// Note: Enabling this may cause connection time to increase in case the best access point
64    /// doesn't behave properly.
65    #[builder_lite(unstable)]
66    pub(crate) failure_retry_cnt: u8,
67    /// Scan method.
68    #[builder_lite(unstable)]
69    pub(crate) scan_method: ScanMethod,
70}
71
72impl StationConfig {
73    /// Set the SSID of the access point.
74    pub fn with_ssid(mut self, ssid: impl Into<Ssid>) -> Self {
75        self.ssid = ssid.into();
76        self
77    }
78
79    pub(crate) fn validate(&self) -> Result<(), WifiError> {
80        if self.ssid.len() > 32 {
81            return Err(WifiError::InvalidArguments);
82        }
83
84        if self.password.len() > 64 {
85            return Err(WifiError::InvalidArguments);
86        }
87
88        if !(6..=31).contains(&self.beacon_timeout) {
89            return Err(WifiError::InvalidArguments);
90        }
91
92        Ok(())
93    }
94}
95
96impl Default for StationConfig {
97    fn default() -> Self {
98        StationConfig {
99            ssid: Ssid::default(),
100            bssid: None,
101            auth_method: AuthenticationMethod::Wpa2Personal,
102            password: String::new(),
103            channel: None,
104            protocols: Protocols::default(),
105            listen_interval: 3,
106            beacon_timeout: 6,
107            failure_retry_cnt: 1,
108            scan_method: ScanMethod::Fast,
109        }
110    }
111}
112
113impl fmt::Debug for StationConfig {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        f.debug_struct("StationConfig")
116            .field("ssid", &self.ssid)
117            .field("bssid", &self.bssid)
118            .field("auth_method", &self.auth_method)
119            .field("password", &"**REDACTED**")
120            .field("channel", &self.channel)
121            .field("protocols", &self.protocols)
122            .field("listen_interval", &self.listen_interval)
123            .field("beacon_timeout", &self.beacon_timeout)
124            .field("failure_retry_cnt", &self.failure_retry_cnt)
125            .field("scan_method", &self.scan_method)
126            .finish()
127    }
128}
129
130#[cfg(feature = "defmt")]
131impl defmt::Format for StationConfig {
132    fn format(&self, fmt: defmt::Formatter<'_>) {
133        defmt::write!(
134            fmt,
135            "StationConfig {{\
136            ssid: {}, \
137            bssid: {:?}, \
138            auth_method: {:?}, \
139            password: **REDACTED**, \
140            channel: {:?}, \
141            protocols: {}, \
142            listen_interval: {}, \
143            beacon_timeout: {}, \
144            failure_retry_cnt: {}, \
145            scan_method: {} \
146            }}",
147            self.ssid.as_str(),
148            self.bssid,
149            self.auth_method,
150            self.channel,
151            self.protocols,
152            self.listen_interval,
153            self.beacon_timeout,
154            self.failure_retry_cnt,
155            self.scan_method
156        )
157    }
158}