pub struct WifiDriver<'d> { /* private fields */ }
Expand description

This struct provides a safe wrapper over the ESP IDF Wifi C driver. The driver works on Layer 2 (Data Link) in the OSI model, in that it provides facilities for sending and receiving ethernet packets over the WiFi radio.

For most use cases, utilizing EspWifi - which provides a networking (IP) layer as well - should be preferred. Using WifiDriver directly is beneficial only when one would like to utilize a custom, non-STD network stack like smoltcp.

Implementations§

source§

impl<'d> WifiDriver<'d>

source

pub fn new<M: WifiModemPeripheral>( _modem: impl Peripheral<P = M> + 'd, sysloop: EspSystemEventLoop, nvs: Option<EspDefaultNvsPartition> ) -> Result<Self, EspError>

source

pub fn get_capabilities(&self) -> Result<EnumSet<Capability>, EspError>

Returns the set of [Capabilities] for this driver. In esp-idf, all drivers always have Client, AP and Mixed capabilities.

source

pub fn start(&mut self) -> Result<(), EspError>

source

pub fn stop(&mut self) -> Result<(), EspError>

source

pub fn connect(&mut self) -> Result<(), EspError>

source

pub fn disconnect(&mut self) -> Result<(), EspError>

source

pub fn is_ap_enabled(&self) -> Result<bool, EspError>

Returns true if the driver is in Access Point (AP) mode, as reported by crate::sys::esp_wifi_get_mode

source

pub fn is_sta_enabled(&self) -> Result<bool, EspError>

Returns true if the driver is in Client (station or STA) mode, as reported by crate::sys::esp_wifi_get_mode

source

pub fn is_ap_started(&self) -> Result<bool, EspError>

source

pub fn is_sta_started(&self) -> Result<bool, EspError>

source

pub fn is_sta_connected(&self) -> Result<bool, EspError>

source

pub fn is_started(&self) -> Result<bool, EspError>

source

pub fn is_connected(&self) -> Result<bool, EspError>

source

pub fn is_scan_done(&self) -> Result<bool, EspError>

source

pub fn get_configuration(&self) -> Result<Configuration, EspError>

Returns the <Configuration> currently in use

source

pub fn set_configuration( &mut self, conf: &Configuration ) -> Result<(), EspError>

Sets the <Configuration> (SSID, channel, etc). This also defines whether the driver will work in AP mode, client mode, client+AP mode, or none.

Calls crate::sys::esp_wifi_set_mode and crate::sys::esp_wifi_set_config

source

pub fn scan_n<const N: usize>( &mut self ) -> Result<(Vec<AccessPointInfo, N>, usize), EspError>

Scan for nearby, visible access points.

It scans for all available access points nearby, but returns only the first N access points found. In addition, it returns the actual amount it found. The function blocks until the scan is done.

Before calling this function the Wifi driver must be configured and started in either Client or Mixed mode.

§Example
let mut wifi_driver = WifiDriver::new(peripherals.modem, sysloop.clone());
wifi_driver.set_configuration(
    &Configuration::Client(ClientConfiguration::default())
)
.unwrap();
wifi_driver.start().unwrap();

let (scan_result, found_aps) = wifi_driver.scan_n::<10>().unwrap();
source

pub fn scan(&mut self) -> Result<Vec<AccessPointInfo>, EspError>

Scan for nearby, visible access points.

Unlike WifiDriver::scan_n(), it returns all found access points by allocating memory dynamically.

For more details see WifiDriver::scan_n().

source

pub fn start_scan( &mut self, scan_config: &ScanConfig, blocking: bool ) -> Result<(), EspError>

Start scanning for nearby, visible access points.

Unlike WifiDriver::scan_n() or WifiDriver::scan() it can be called as either blocking or not blocking. A [ScanConfig] can be provided as well. To get the scan result call either WifiDriver::get_scan_result_n() or WifiDriver::get_scan_result().

This function can be used in async context, when the current thread shouldn’t be blocked.

§Example

This example shows how to use it in a async context.

let mut wifi_driver = WifiDriver::new(peripherals.modem, sysloop.clone());
wifi_driver.set_configuration(
    &Configuration::Client(ClientConfiguration::default())
)
.unwrap();
wifi_driver.start().unwrap();

let scan_finish_signal = Arc::new(channel_bridge::notification::Notification::new());
let _sub = {
    let scan_finish_signal = scan_finish_signal.clone();
    sysloop.subscribe::<WifiEvent>(move |event| {
        if *event == WifiEvent::ScanDone {
            scan_finish_signal.notify();
        }
    }).unwrap()
};

wifi_driver.start_scan(&ScanConfig::default(), false).unwrap();

scan_finish_signal.wait().await;

let res = wifi_driver.get_scan_result().unwrap();
source

pub fn stop_scan(&mut self) -> Result<(), EspError>

Stops a previous started access point scan.

source

pub fn get_scan_result_n<const N: usize>( &mut self ) -> Result<(Vec<AccessPointInfo, N>, usize), EspError>

Get the results of an access point scan.

This call returns a list of the first N found access points. A scan can be started with WifiDriver::start_scan(). As WifiDriver::scan_n() it returns the actual amount of found access points as well.

source

pub fn get_scan_result(&mut self) -> Result<Vec<AccessPointInfo>, EspError>

Get the results of an access point scan.

Unlike WifiDriver::get_scan_result_n(), it returns all found access points by allocating memory dynamically.

For more details see WifiDriver::get_scan_result_n().

source

pub fn set_callbacks<R, T>( &mut self, rx_callback: R, tx_callback: T ) -> Result<(), EspError>
where R: FnMut(WifiDeviceId, &[u8]) -> Result<(), EspError> + Send + 'static, T: FnMut(WifiDeviceId, &[u8], bool) + Send + 'static,

Sets callback functions for receiving and sending data, as per crate::sys::esp_wifi_internal_reg_rxcb and crate::sys::esp_wifi_set_tx_done_cb

source

pub unsafe fn set_nonstatic_callbacks<R, T>( &mut self, rx_callback: R, tx_callback: T ) -> Result<(), EspError>
where R: FnMut(WifiDeviceId, &[u8]) -> Result<(), EspError> + Send + 'd, T: FnMut(WifiDeviceId, &[u8], bool) + Send + 'd,

Sets callback functions for receiving and sending data, as per crate::sys::esp_wifi_internal_reg_rxcb and crate::sys::esp_wifi_set_tx_done_cb

§Safety

This method - in contrast to method set_callbacks - allows the user to pass non-static callbacks/closures. This enables users to borrow

  • in the closure - variables that live on the stack - or more generally - in the same scope where the service is created.

HOWEVER: care should be taken NOT to call core::mem::forget() on the service, as that would immediately lead to an UB (crash). Also note that forgetting the service might happen with Rc and Arc when circular references are introduced: https://github.com/rust-lang/rust/issues/24456

The reason is that the closure is actually sent to a hidden ESP IDF thread. This means that if the service is forgotten, Rust is free to e.g. unwind the stack and the closure now owned by this other thread will end up with references to variables that no longer exist.

The destructor of the service takes care - prior to the service being dropped and e.g. the stack being unwind - to remove the closure from the hidden thread and destroy it. Unfortunately, when the service is forgotten, the un-subscription does not happen and invalid references are left dangling.

This “local borrowing” will only be possible to express in a safe way once/if !Leak types are introduced to Rust (i.e. the impossibility to “forget” a type and thus not call its destructor).

source

pub fn send( &mut self, device_id: WifiDeviceId, frame: &[u8] ) -> Result<(), EspError>

source

pub fn get_ap_info(&mut self) -> Result<AccessPointInfo, EspError>

Get information of AP which the ESP32 station is associated with. Useful to get the current signal strength of the AP.

source

pub fn set_rssi_threshold(&mut self, rssi_threshold: i8) -> Result<(), EspError>

Set RSSI threshold below which APP will get an WifiEvent::StaBssRssiLow, as per crate::sys::esp_wifi_set_rssi_threshold rssi_threshold: threshold value in dbm between -100 to 0

§Example

This example shows how to use it in a async context.

let mut wifi_driver = WifiDriver::new(peripherals.modem, sysloop.clone());
wifi_driver.set_configuration(
    &Configuration::Client(ClientConfiguration::default())
)
.unwrap();
wifi_driver.start().unwrap();
wifi_driver.connect().unwrap();

let rssi_low = -40;
wifi_driver.driver_mut().set_sta_rssi_low(rssi_low).unwrap();

// Subscribe to RSSI events.
let rssi_low_signal = Arc::new(channel_bridge::notification::Notification::new());
let _sub = {
    let rssi_low_signal = rssi_low_signal.clone();
    sysloop.subscribe::<WifiEvent>(move |event| {
        if *event == WifiEvent::StaBssRssiLow {
            rssi_low_signal.notify();
        }
    }).unwrap()
};

rssi_low_signal.wait().await;
// do stuff with the information

// set_rssi_threshold() has to be called again after every StaBssRssiLow event received.
source

pub fn get_mac(&self, interface: WifiDeviceId) -> Result<[u8; 6], EspError>

Returns the MAC address of the interface, as per crate::sys::esp_wifi_get_mac

source

pub fn set_mac( &mut self, interface: WifiDeviceId, mac: [u8; 6] ) -> Result<(), EspError>

Seta the MAC address of the interface, as per crate::sys::esp_wifi_set_mac

source

pub fn start_wps(&mut self, config: &WpsConfig<'_>) -> Result<(), EspError>

Enable and start WPS

Trait Implementations§

source§

impl<'d> Drop for WifiDriver<'d>

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl<'d> NonBlocking for WifiDriver<'d>

source§

fn is_scan_done(&self) -> Result<bool, EspError>

source§

fn start_scan( &mut self, scan_config: &ScanConfig, blocking: bool ) -> Result<(), EspError>

source§

fn stop_scan(&mut self) -> Result<(), EspError>

source§

fn get_scan_result_n<const N: usize>( &mut self ) -> Result<(Vec<AccessPointInfo, N>, usize), EspError>

source§

fn get_scan_result(&mut self) -> Result<Vec<AccessPointInfo>, EspError>

source§

fn start_wps(&mut self, config: &WpsConfig<'_>) -> Result<(), EspError>

source§

fn stop_wps(&mut self) -> Result<WpsStatus, EspError>

source§

fn is_wps_finished(&self) -> Result<bool, EspError>

source§

impl<'d> Wifi for WifiDriver<'d>

§

type Error = EspError

source§

fn get_capabilities(&self) -> Result<EnumSet<Capability>, Self::Error>

source§

fn is_started(&self) -> Result<bool, Self::Error>

source§

fn is_connected(&self) -> Result<bool, Self::Error>

source§

fn get_configuration(&self) -> Result<Configuration, Self::Error>

source§

fn set_configuration(&mut self, conf: &Configuration) -> Result<(), Self::Error>

source§

fn start(&mut self) -> Result<(), Self::Error>

source§

fn stop(&mut self) -> Result<(), Self::Error>

source§

fn connect(&mut self) -> Result<(), Self::Error>

source§

fn disconnect(&mut self) -> Result<(), Self::Error>

source§

fn scan_n<const N: usize>( &mut self ) -> Result<(Vec<AccessPointInfo, N>, usize), Self::Error>

source§

fn scan(&mut self) -> Result<Vec<AccessPointInfo>, Self::Error>

source§

impl<'d> Send for WifiDriver<'d>

Auto Trait Implementations§

§

impl<'d> !RefUnwindSafe for WifiDriver<'d>

§

impl<'d> !Sync for WifiDriver<'d>

§

impl<'d> Unpin for WifiDriver<'d>

§

impl<'d> !UnwindSafe for WifiDriver<'d>

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.