Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for WPS #331

Merged
merged 9 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/configs/sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y

# Examples often require a larger than the default stack size for the main thread.
CONFIG_ESP_MAIN_TASK_STACK_SIZE=10000
CONFIG_ESP_MAIN_TASK_STACK_SIZE=12000

# Go figure...
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=4096
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096

# Enable WS support
CONFIG_HTTPD_WS_SUPPORT=y
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [?.??.?] - ????-??-??
* #316 - BREAKING CHANGE addressing a typo - `http::server::Configuration::max_resp_handlers` renamed to `http::server::Configuration::max_resp_headers`
* #319 - Set default TTL in `EspPing` to 64
* #322 - Fix MQTT PSK code (did not compile)
* #323 - ETH example with a statically configured IP
* #324 - New methods in `EspWifi` to swap STA and AP netifs separately from each other
* #326 - logging from multiple threads in Rust/ESP-IDF no longer results in intermixed logs
* #331 - Add support for WPS

## [0.47.3] - 2023-11-12
* BREAKING CHANGE IN A PATCH RELEASE DUE TO DISCOVERED UB: All constructors and methods in the Classic BT services, as well as in
Expand Down
82 changes: 82 additions & 0 deletions examples/wps.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//! Example of using blocking WPS.

use embedded_svc::wifi::{AuthMethod, ClientConfiguration, Configuration};

use esp_idf_svc::hal::prelude::Peripherals;
use esp_idf_svc::log::EspLogger;
use esp_idf_svc::wifi::{BlockingWifi, EspWifi};
use esp_idf_svc::wifi::{WpsConfig, WpsFactoryInfo, WpsStatus, WpsType};
use esp_idf_svc::{eventloop::EspSystemEventLoop, nvs::EspDefaultNvsPartition};

use log::info;

const WPS_CONFIG: WpsConfig = WpsConfig {
wps_type: WpsType::Pbc,
factory_info: WpsFactoryInfo {
manufacturer: "ESPRESSIF",
model_number: "esp32",
model_name: "ESPRESSIF IOT",
device_name: "ESP DEVICE",
},
};

fn main() -> anyhow::Result<()> {
esp_idf_svc::sys::link_patches();
EspLogger::initialize_default();

let peripherals = Peripherals::take()?;
let sys_loop = EspSystemEventLoop::take()?;
let nvs = EspDefaultNvsPartition::take()?;

let mut wifi = BlockingWifi::wrap(
EspWifi::new(peripherals.modem, sys_loop.clone(), Some(nvs))?,
sys_loop,
)?;

wifi.start()?;
info!("Wifi started");

match wifi.start_wps(&WPS_CONFIG)? {
WpsStatus::SuccessConnected => (),
WpsStatus::SuccessMultipleAccessPoints(credentials) => {
log::info!("received multiple credentials, connecting to first one:");
for i in &credentials {
log::info!(" - ssid: {}", i.ssid);
}
let wifi_configuration: Configuration = Configuration::Client(ClientConfiguration {
ssid: credentials[0].ssid.clone(),
bssid: None,
auth_method: AuthMethod::WPA2Personal,
password: credentials[1].passphrase.clone(),
channel: None,
});
wifi.set_configuration(&wifi_configuration)?;
}
WpsStatus::Failure => anyhow::bail!("WPS failure"),
WpsStatus::Timeout => anyhow::bail!("WPS timeout"),
WpsStatus::Pin(_) => anyhow::bail!("WPS pin"),
WpsStatus::PbcOverlap => anyhow::bail!("WPS PBC overlap"),
}

match wifi.get_configuration()? {
Configuration::Client(config) => {
info!("Successfully connected to {} using WPS", config.ssid)
}
_ => anyhow::bail!("Not in station mode"),
};

wifi.connect()?;
info!("Wifi connected");

wifi.wait_netif_up()?;
info!("Wifi netif up");

let ip_info = wifi.wifi().sta_netif().get_ip_info()?;
info!("Wifi DHCP info: {:?}", ip_info);

info!("Shutting down in 5s...");

std::thread::sleep(core::time::Duration::from_secs(5));

Ok(())
}
93 changes: 93 additions & 0 deletions examples/wps_async.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//! Example of using async WPS.

use embedded_svc::wifi::{AuthMethod, ClientConfiguration, Configuration};

use esp_idf_svc::hal::prelude::Peripherals;
use esp_idf_svc::log::EspLogger;
use esp_idf_svc::timer::EspTaskTimerService;
use esp_idf_svc::wifi::{AsyncWifi, EspWifi};
use esp_idf_svc::wifi::{WpsConfig, WpsFactoryInfo, WpsStatus, WpsType};
use esp_idf_svc::{eventloop::EspSystemEventLoop, nvs::EspDefaultNvsPartition};

use futures::executor::block_on;

use log::info;

const WPS_CONFIG: WpsConfig = WpsConfig {
wps_type: WpsType::Pbc,
factory_info: WpsFactoryInfo {
manufacturer: "ESPRESSIF",
model_number: "esp32",
model_name: "ESPRESSIF IOT",
device_name: "ESP DEVICE",
},
};

fn main() -> anyhow::Result<()> {
esp_idf_svc::sys::link_patches();
EspLogger::initialize_default();

let peripherals = Peripherals::take()?;
let sys_loop = EspSystemEventLoop::take()?;
let timer_service = EspTaskTimerService::new()?;
let nvs = EspDefaultNvsPartition::take()?;

let mut wifi = AsyncWifi::wrap(
EspWifi::new(peripherals.modem, sys_loop.clone(), Some(nvs))?,
sys_loop,
timer_service,
)?;

block_on(connect_wps(&mut wifi))?;

let ip_info = wifi.wifi().sta_netif().get_ip_info()?;
info!("Wifi DHCP info: {:?}", ip_info);

info!("Shutting down in 5s...");

std::thread::sleep(core::time::Duration::from_secs(5));

Ok(())
}

async fn connect_wps(wifi: &mut AsyncWifi<EspWifi<'static>>) -> anyhow::Result<()> {
wifi.start().await?;
info!("Wifi started");

match wifi.start_wps(&WPS_CONFIG).await? {
WpsStatus::SuccessConnected => (),
WpsStatus::SuccessMultipleAccessPoints(credentials) => {
log::info!("received multiple credentials, connecting to first one:");
for i in &credentials {
log::info!(" - ssid: {}", i.ssid);
}
let wifi_configuration: Configuration = Configuration::Client(ClientConfiguration {
ssid: credentials[0].ssid.clone(),
bssid: None,
auth_method: AuthMethod::WPA2Personal,
password: credentials[1].passphrase.clone(),
channel: None,
});
wifi.set_configuration(&wifi_configuration)?;
}
WpsStatus::Failure => anyhow::bail!("WPS failure"),
WpsStatus::Timeout => anyhow::bail!("WPS timeout"),
WpsStatus::Pin(_) => anyhow::bail!("WPS pin"),
WpsStatus::PbcOverlap => anyhow::bail!("WPS PBC overlap"),
}

match wifi.get_configuration()? {
Configuration::Client(config) => {
info!("Successfully connected to {} using WPS", config.ssid)
}
_ => anyhow::bail!("Not in station mode"),
};

wifi.connect().await?;
info!("Wifi connected");

wifi.wait_netif_up().await?;
info!("Wifi netif up");

Ok(())
}
18 changes: 12 additions & 6 deletions src/private/cstr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,22 @@ use core::str::Utf8Error;

use crate::sys::{EspError, ESP_ERR_INVALID_SIZE};

#[cfg(feature = "alloc")]
pub fn set_str(buf: &mut [u8], s: &str) -> Result<(), crate::sys::EspError> {
assert!(s.len() < buf.len());
let cs = to_cstring_arg(s)?;
let ss: &[u8] = cs.as_bytes_with_nul();
buf[..ss.len()].copy_from_slice(ss);
pub fn set_str(buf: &mut [u8], s: &str) -> Result<(), EspError> {
if s.len() >= buf.len() {
return Err(EspError::from_infallible::<ESP_ERR_INVALID_SIZE>());
}

buf[..s.len()].copy_from_slice(s.as_bytes());
buf[s.len()] = 0;

Ok(())
}

pub fn c_char_to_u8_slice_mut(s: &mut [c_char]) -> &mut [u8] {
let s_ptr = unsafe { s.as_mut_ptr() as *mut u8 };
unsafe { core::slice::from_raw_parts_mut(s_ptr, s.len()) }
}

pub unsafe fn from_cstr_ptr<'a>(ptr: *const c_char) -> &'a str {
CStr::from_ptr(ptr).to_str().unwrap()
}
Expand Down
Loading