Rust嵌入式WiFi开发库esp-wifi-sys的使用:ESP32/ESP8266低层WiFi驱动与系统集成
Rust嵌入式WiFi开发库esp-wifi-sys的使用:ESP32/ESP8266低层WiFi驱动与系统集成
简介
esp-wifi-sys 是用于Wi-Fi/蓝牙LE无线电所需的二进制blob的低级不安全绑定。这些库和头文件来自ESP-IDF,绑定是通过bindgen生成的。
许可证
该库采用双许可证:
- Apache License, Version 2.0
- MIT license
您可以任选其一使用。
安装
在项目目录中运行以下Cargo命令:
cargo add esp-wifi-sys
或在Cargo.toml中添加以下行:
esp-wifi-sys = "0.7.1"
使用示例
以下是一个完整的示例代码,展示如何使用esp-wifi-sys库进行基本的WiFi初始化:
use esp_wifi_sys as sys;
fn main() {
// 初始化WiFi底层驱动
unsafe {
// 初始化TCP/IP协议栈
sys::esp_netif_init();
// 创建默认事件循环
sys::esp_event_loop_create_default();
// 初始化WiFi
let ret = sys::esp_wifi_init(&sys::wifi_init_config_t {
// 配置参数
event_handler: Some(wifi_event_handler),
osi_funcs: std::ptr::null_mut(),
wpa_crypto_funcs: std::ptr::null_mut(),
static_rx_buf_num: 16,
dynamic_rx_buf_num: 32,
tx_buf_type: 1,
static_tx_buf_num: 16,
dynamic_tx_buf_num: 32,
cache_tx_buf_num: 16,
csi_enable: 0,
ampdu_rx_enable: 1,
ampdu_tx_enable: 1,
nvs_enable: 1,
nano_enable: 1,
rx_ba_win: 6,
wifi_task_core_id: 0,
beacon_max_len: 0,
mgmt_sbuf_num: 32,
feature_caps: sys::CONFIG_FEATURE_CACHE_TX_BUF_BIT,
magic: sys::WIFI_INIT_CONFIG_MAGIC,
});
if ret != sys::ESP_OK as i32 {
panic!("Failed to initialize WiFi");
}
// 设置WiFi为STA模式
sys::esp_wifi_set_mode(sys::wifi_mode_t_WIFI_MODE_STA);
// 启动WiFi
sys::esp_wifi_start();
}
}
// WiFi事件处理回调函数
extern "C" fn wifi_event_handler(
ctx: *mut std::ffi::c_void,
event: sys::system_event_t,
) {
match event.event_id {
sys::SYSTEM_EVENT_WIFI_READY => {
println!("WiFi ready");
}
sys::SYSTEM_EVENT_STA_START => {
println!("STA start");
}
sys::SYSTEM_EVENT_STA_CONNECTED => {
println!("STA connected");
}
sys::SYSTEM_EVENT_STA_GOT_IP => {
println!("STA got IP");
}
_ => {}
}
}
完整示例demo
以下是一个更完整的示例,展示如何使用esp-wifi-sys连接WiFi网络:
use esp_wifi_sys as sys;
use std::ffi::CString;
fn main() {
unsafe {
// 1. 初始化网络堆栈和事件循环
sys::esp_netif_init();
sys::esp_event_loop_create_default();
// 2. 初始化WiFi
let ret = sys::esp_wifi_init(&sys::wifi_init_config_t {
event_handler: Some(wifi_event_handler),
osi_funcs: std::ptr::null_mut(),
wpa_crypto_funcs: std::ptr::null_mut(),
static_rx_buf_num: 16,
dynamic_rx_buf_num: 32,
tx_buf_type: 1,
static_tx_buf_num: 16,
dynamic_tx_buf_num: 32,
cache_tx_buf_num: 16,
csi_enable: 0,
ampdu_rx_enable: 1,
ampdu_tx_enable: 1,
nvs_enable: 1,
nano_enable: 1,
rx_ba_win: 6,
wifi_task_core_id: 0,
beacon_max_len: 0,
mgmt_sbuf_num: 32,
feature_caps: sys::CONFIG_FEATURE_CACHE_TX_BUF_BIT,
magic: sys::WIFI_INIT_CONFIG_MAGIC,
});
if ret != sys::ESP_OK as i32 {
panic!("Failed to initialize WiFi");
}
// 3. 配置WiFi为STA模式
sys::esp_wifi_set_mode(sys::wifi_mode_t_WIFI_MODE_STA);
// 4. 配置WiFi连接参数
let ssid = CString::new("YourSSID").unwrap();
let password = CString::new("YourPassword").unwrap();
let wifi_config = sys::wifi_config_t {
sta: sys::wifi_sta_config_t {
ssid: [0; 32],
password: [0; 64],
scan_method: sys::WIFI_FAST_SCAN,
bssid_set: 0,
bssid: [0; 6],
channel: 0,
listen_interval: 0,
sort_method: sys::WIFI_CONNECT_AP_BY_SIGNAL,
threshold: sys::wifi_scan_threshold_t {
rssi: 0,
authmode: sys::WIFI_AUTH_WPA2_PSK as u8,
},
..Default::default()
},
};
// 复制SSID和密码到配置结构体
std::ptr::copy_nonoverlapping(
ssid.as_ptr(),
wifi_config.sta.ssid.as_mut_ptr(),
ssid.as_bytes().len(),
);
std::ptr::copy_nonoverlapping(
password.as_ptr(),
wifi_config.sta.password.as_mut_ptr(),
password.as_bytes().len(),
);
// 5. 设置WiFi配置
sys::esp_wifi_set_config(sys::wifi_interface_t_WIFI_IF_STA, &wifi_config);
// 6. 启动WiFi
sys::esp_wifi_start();
// 7. 连接WiFi网络
sys::esp_wifi_connect();
// 主循环
loop {
// 保持程序运行
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
}
// WiFi事件处理回调函数
extern "C" fn wifi_event_handler(
ctx: *mut std::ffi::c_void,
event: sys::system_event_t,
) {
match event.event_id {
sys::SYSTEM_EVENT_WIFI_READY => println!("WiFi ready"),
sys::SYSTEM_EVENT_STA_START => println!("STA started"),
sys::SYSTEM_EVENT_STA_CONNECTED => println!("Connected to AP"),
sys::SYSTEM_EVENT_STA_GOT_IP => {
let event_info = unsafe { event.event_info };
let ip_info = unsafe { event_info.got_ip.ip_info };
println!(
"Got IP: {}.{}.{}.{}",
(ip_info.ip.addr >> 0) & 0xff,
(ip_info.ip.addr >> 8) & 0xff,
(ip_info.ip.addr >> 16) & 0xff,
(ip_info.ip.addr >> 24) & 0xff
);
}
sys::SYSTEM_EVENT_STA_DISCONNECTED => {
println!("Disconnected from AP, attempting to reconnect...");
unsafe { sys::esp_wifi_connect() };
}
_ => {}
}
}
注意事项
- 该库提供的是低级不安全绑定,使用时需要特别注意内存安全和线程安全
- 使用时需要依赖ESP-IDF提供的二进制blob
- 所有操作都需要在unsafe块中进行
- 需要正确配置ESP32/ESP8266的开发环境
贡献
除非您明确声明,否则任何有意提交的作品都将按照Apache-2.0许可证双重许可,如上所述,没有任何附加条款或条件。
适用领域
该库适用于:
- 无标准库环境(No standard library)
- 嵌入式开发(Embedded development)
- 硬件支持(Hardware support)
1 回复
Rust嵌入式WiFi开发库esp-wifi-sys的使用指南
完整示例Demo
下面是一个结合STA模式连接、AP模式创建和WiFi事件处理的完整示例:
use esp_wifi_sys::{
wifi_init_config_t, wifi_config_t, wifi_mode_t,
esp_wifi_init, esp_wifi_set_mode, esp_wifi_set_config,
esp_wifi_start, esp_wifi_connect, esp_wifi_scan_start,
esp_event_base_t, system_event_t, esp_event_handler_register,
WIFI_EVENT, IP_EVENT, WIFI_EVENT_STA_START,
WIFI_EVENT_STA_CONNECTED, WIFI_EVENT_STA_DISCONNECTED,
IP_EVENT_STA_GOT_IP, wifi_scan_config_t
};
// WiFi事件处理回调函数
unsafe extern "C" fn wifi_event_handler(
_arg: *mut core::ffi::c_void,
event_base: esp_event_base_t,
event_id: i32,
event_data: *mut core::ffi::c_void,
) {
match (event_base, event_id) {
(WIFI_EVENT, WIFI_EVENT_STA_START) => {
println!("[事件] WiFi STA模式已启动");
}
(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED) => {
println!("[事件] 已连接到AP");
}
(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED) => {
println!("[事件] 从AP断开连接");
// 这里可以添加重连逻辑
}
(IP_EVENT, IP_EVENT_STA_GOT_IP) => {
let event = &*(event_data as *const system_event_t);
println!("[事件] 获取到IP: {:?}", event.event_info.got_ip.ip_info.ip);
}
_ => {}
}
}
// 初始化WiFi并注册事件处理器
fn init_wifi() {
// 初始化默认配置
let init_config = wifi_init_config_t::default();
unsafe {
esp_wifi_init(&init_config).unwrap();
}
// 注册WiFi事件处理器
unsafe {
esp_event_handler_register(
WIFI_EVENT,
esp_wifi_sys::ESP_EVENT_ANY_ID,
Some(wifi_event_handler),
core::ptr::null_mut(),
).unwrap();
esp_event_handler_register(
IP_EVENT,
IP_EVENT_STA_GOT_IP,
Some(wifi_event_handler),
core::ptr::null_mut(),
).unwrap();
}
}
// 连接到指定WiFi网络
fn connect_to_wifi(ssid: &str, password: &str) {
// 设置为STA模式
unsafe {
esp_wifi_set_mode(wifi_mode_t::WIFI_MODE_STA).unwrap();
}
// 配置网络参数
let mut wifi_config = wifi_config_t::default();
let ssid_slice = ssid.as_bytes();
let pass_slice = password.as_bytes();
// 复制SSID和密码到配置结构
wifi_config.sta.ssid[..ssid_slice.len()].copy_from_slice(ssid_slice);
wifi_config.sta.password[..pass_slice.len()].copy_from_slice(pass_slice);
// 设置配置并启动WiFi
unsafe {
esp_wifi_set_config(wifi_mode_t::WIFI_MODE_STA, &wifi_config).unwrap();
esp_wifi_start().unwrap();
esp_wifi_connect().unwrap();
}
}
// 创建AP热点
fn create_ap(ssid: &str, password: Option<&str>) {
// 设置为AP模式
unsafe {
esp_wifi_set_mode(wifi_mode_t::WIFI_MODE_AP).unwrap();
}
let mut wifi_config = wifi_config_t::default();
let ssid_slice = ssid.as_bytes();
wifi_config.ap.ssid[..ssid_slice.len()].copy_from_slice(ssid_slice);
wifi_config.ap.ssid_len = ssid_slice.len() as u8;
// 设置密码或开放网络
if let Some(pass) = password {
let pass_slice = pass.as_bytes();
wifi_config.ap.password[..pass_slice.len()].copy_from_slice(pass_slice);
wifi_config.ap.authmode = wifi_auth_mode_t::WIFI_AUTH_WPA2_PSK;
} else {
wifi_config.ap.authmode = wifi_auth_mode_t::WIFI_AUTH_OPEN;
}
unsafe {
esp_wifi_set_config(wifi_mode_t::WIFI_MODE_AP, &wifi_config).unwrap();
esp_wifi_start().unwrap();
}
}
// 扫描附近WiFi网络
fn scan_networks() {
let scan_config = wifi_scan_config_t {
ssid: None,
bssid: None,
channel: 0,
show_hidden: true,
scan_type: wifi_scan_type_t::WIFI_SCAN_TYPE_ACTIVE,
scan_time: wifi_scan_time_t::default(),
};
unsafe {
println!("开始扫描WiFi网络...");
esp_wifi_scan_start(&scan_config, true).unwrap();
let mut ap_num = 0;
esp_wifi_scan_get_ap_num(&mut ap_num).unwrap();
println!("发现 {} 个网络", ap_num);
let mut ap_records = vec![wifi_ap_record_t::default(); ap_num as usize];
esp_wifi_scan_get_ap_records(&mut ap_num, ap_records.as_mut_ptr()).unwrap();
for (i, record) in ap_records.iter().enumerate() {
let ssid = core::str::from_utf8(&record.ssid).unwrap_or("[无效SSID]");
println!("{}. SSID: {}, 信号强度: {}dBm, 信道: {}",
i+1, ssid, record.rssi, record.primary);
}
}
}
fn main() {
// 初始化WiFi
init_wifi();
// 示例1: 连接到WiFi网络
println!("正在连接到WiFi网络...");
connect_to_wifi("your_ssid", "your_password");
// 等待连接完成
std::thread::sleep(std::time::Duration::from_secs(5));
// 示例2: 扫描附近网络
scan_networks();
// 示例3: 创建AP热点
println!("正在创建AP热点...");
create_ap("MyESP32AP", Some("ap_password"));
// 保持程序运行
loop {
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
代码说明
- 事件处理:通过
wifi_event_handler
函数处理各种WiFi事件,如连接、断开、获取IP等 - STA模式:
connect_to_wifi
函数实现了连接到指定WiFi网络的功能 - AP模式:
create_ap
函数创建了一个WiFi热点,支持设置密码或开放网络 - 网络扫描:
scan_networks
函数扫描并显示附近的WiFi网络信息 - 初始化:
init_wifi
函数初始化WiFi驱动并注册事件处理器
使用建议
- 在实际应用中,应该添加更完善的错误处理
- 对于嵌入式设备,考虑添加看门狗定时器防止程序卡死
- 可以根据需要扩展事件处理逻辑,如自动重连机制
- 生产环境中应该避免硬编码WiFi凭据,建议使用配置系统
这个完整示例展示了esp-wifi-sys
库的主要功能,包括STA和AP模式的操作、网络扫描以及事件处理,可以作为开发嵌入式WiFi应用的起点。