首页
苏兮影视
随笔记
壁纸
更多
直播
时光轴
友联
关于
统计
Search
1
软件添加id功能按钮
708 阅读
2
v2ray节点搭建
508 阅读
3
typecho非常有特色的模块
460 阅读
4
QQxml消息卡片生成源码
421 阅读
5
Linux下提权常用小命令
366 阅读
谈天说地
建站源码
经验教程
资源分享
动漫美图
登录
Search
标签搜索
java
flutter
springboot
rust
安卓
linux
vue
docker
joe
快捷键
git
fish shell
maven
redis
netty
dart
groovy
js
设计模式
rpc
尽意
累计撰写
95
篇文章
累计收到
38
条评论
首页
栏目
谈天说地
建站源码
经验教程
资源分享
动漫美图
页面
苏兮影视
随笔记
壁纸
直播
时光轴
友联
关于
统计
搜索到
1
篇与
的结果
2024-11-06
esp32c3自动配网
在 esp32-c3 rust使用docker编译 新建项目的基础上,引入必要的依赖Cargo.toml[dependencies] log = { version = "0.4", default-features = false } esp-idf-svc = { version = "0.49", default-features = false } # 添加http的依赖 anyhow = "=1.0.86" embedded-svc = "=0.28.0" # json处理 serde = { version = "1.0", features = ["derive"] } # 序列化,支持多种,xml,json等 serde_json = "1.0" # 专门处理json格式 新建一个跟main.rs同级的配网文件,auto_set_wifi.rs然后在main.rs文件中引用mod auto_set_wifi;编写自动配网rust代码 // 引入配网页面的html文件 static INDEX_HTML: &str = include_str!("../index.html"); // 设置nvs存储的参数 static WIFI_INFO_KEY: &str = "WIFI_INFO"; static NAME_SPACE: &str = "ESP_WIFI"; // 默认ap模式下的配置信息 static AP_WIFO_INFO: WifiInfo<'static> = WifiInfo { ssid: "esp32_c3_wifi", password: "00000000", }; #[derive(Debug, Deserialize, Serialize)] struct WifiInfo<'a> { ssid: &'a str, password: &'a str, } pub fn start_auto_wifi() -> anyhow::Result<()> { // 自动配网,需要先开启ap模式,让手机连上esp32的热点 let peripherals = Peripherals::take()?; let sysloop = EspEventLoop::take()?; let nvs = EspDefaultNvsPartition::take()?; let mut wifi = BlockingWifi::wrap( EspWifi::new(peripherals.modem, sysloop.clone(), Some(nvs.clone()))?, sysloop.clone(), )?; wifi.set_configuration(&esp_idf_svc::wifi::Configuration::AccessPoint( AccessPointConfiguration { ssid: AP_WIFO_INFO.ssid.try_into().unwrap(), password: AP_WIFO_INFO.password.try_into().unwrap(), auth_method: esp_idf_svc::wifi::AuthMethod::WPA2Personal, ..Default::default() }, ))?; // 由于wifi,跟nvs在后面的函数也需要被调用,所有权不能丢弃,需要用安全的智能指针进行接管 let wifi = Arc::new(Mutex::new(wifi)); let nvs = Arc::new(Mutex::new(EspNvs::new(nvs, NAME_SPACE, true)?)); let temp_wifi = wifi.clone(); let temp_nvs = nvs.clone(); let mut buf = [0;128]; log::warn!("正在查找是否存在配网信息..."); if let Err(_) = nvs.lock().unwrap().get_raw(WIFI_INFO_KEY, &mut buf) { log::info!("不存在配网信息,开启ap模式"); let mut temp_wifi = temp_wifi.lock().unwrap(); temp_wifi.start()?; log::info!("开启wifi"); temp_wifi.wait_netif_up()?; log::info!("等待底层网络分配"); log::info!("WiFi信息为:{:?}", temp_wifi.wifi().ap_netif().get_ip_info()); } else { log::info!("存在配网信息,开启混合模式"); let _ = std::thread::spawn(|| start_muxt_mode(temp_wifi, temp_nvs)); } // 配网页面路由 let temp_nvs = nvs.clone(); let mut server = EspHttpServer::new(&ServerConfig::default())?; server.fn_handler("/", esp_idf_svc::http::Method::Get, |request| { request .into_ok_response() .unwrap() .write_all(INDEX_HTML.as_bytes()) })?; // 提交配网的表单信息 server.fn_handler( "/wifi", esp_idf_svc::http::Method::Post, move |mut request| { let len = request.content_len().unwrap() as usize; let mut buf = vec![0; len]; request.read_exact(&mut buf).unwrap(); let temp_nvs = temp_nvs.clone(); let mut response = request.into_ok_response().unwrap(); let raw = temp_nvs.lock().unwrap().set_raw(WIFI_INFO_KEY, &buf); if let true = raw.unwrap_or(false) { response.write_all(b"{\"msg\":\"success\"}").unwrap(); } else { response.write_all(b"{\"msg\":\"faiture\"}").unwrap(); } response.flush().unwrap(); Ok(()) }, )?; // 查看nvs里保存的配网信息 let temp_nvs = nvs.clone(); server.fn_handler("/nvs", esp_idf_svc::http::Method::Get, move |request| { let temp_nvs = temp_nvs.clone(); let mut buf = [0; 128]; let mut response = request.into_ok_response().unwrap(); if let Option::None = temp_nvs .lock() .unwrap() .get_raw(WIFI_INFO_KEY, &mut buf) .unwrap_or(Option::None) { response.write_all(b"{\"msg\":\"faiure\"}").unwrap(); } else { let end = buf.iter().position(|&x| x == 0).unwrap_or(buf.len()); let res = String::from_utf8_lossy(&buf[..end]); let wifi_info = serde_json::from_slice::<WifiInfo>(&buf[..end]).unwrap(); log::error!("WiFi信息为:{:?}", wifi_info); response.write_all(res.as_bytes()).unwrap(); } response.flush() })?; // 开启混合模式路由 let temp_wifi = wifi.clone(); let temp_nvs = nvs.clone(); server.fn_handler("/muxt", esp_idf_svc::http::Method::Get, move |request| { request.into_ok_response().unwrap().write(b"okk").unwrap(); let (temp_wifi, temp_nvs) = (temp_wifi.clone(), temp_nvs.clone()); let _ = std::thread::spawn(|| start_muxt_mode(temp_wifi, temp_nvs)); Ok(()) })?; // 删除nvs的配置信息 let temp_nvs = nvs.clone(); server.fn_handler("/del", esp_idf_svc::http::Method::Get, move |request| { let mut response = request.into_ok_response().unwrap(); let mut temp_nvs = temp_nvs.lock().unwrap(); if let Err(e) = temp_nvs.remove(WIFI_INFO_KEY) { response.write_all(format!("delete faiure,{e}").as_bytes()) }else{ response.write_all(b"delete success") } })?; forget(server); forget(wifi); Ok(()) } pub fn start_muxt_mode( wifi: Arc<Mutex<BlockingWifi<EspWifi>>>, nvs: Arc<Mutex<EspNvs<NvsDefault>>> )-> anyhow::Result<()> { // 启动混合模式 log::info!("延迟500毫秒执行"); FreeRtos::delay_ms(500); log::info!("开始配置"); let mut wifi = wifi.lock().unwrap(); let nvs = nvs.lock().unwrap(); // 重试连接的次数 let mut retry = 5; loop { if retry < 0 { log::error!("尝试剩余{retry}次后,连接失败"); break; } if wifi.is_started()? { if let Err(_) = wifi.stop() { log::error!("断开wifi连接失败,剩余{}次重试",retry); retry-=1; continue; } log::info!("断开wifi"); } let mut buf = [0; 128]; if let Option::None = nvs.get_raw(WIFI_INFO_KEY, &mut buf).unwrap_or(Option::None) { log::error!("获取WiFi信息失败,剩余{}次重试",retry); } let end = buf.iter().position(|&x| x == 0).unwrap_or(buf.len()); let wifi_info = serde_json::from_slice::<WifiInfo>(&buf[..end]).unwrap(); log::warn!("WiFi信息为:{:?}", wifi_info); let client_config = ClientConfiguration { ssid: wifi_info.ssid.try_into().unwrap(), password: wifi_info.password.try_into().unwrap(), ..Default::default() }; let ap_config = AccessPointConfiguration { ssid: AP_WIFO_INFO.ssid.try_into().unwrap(), password: AP_WIFO_INFO.password.try_into().unwrap(), auth_method: esp_idf_svc::wifi::AuthMethod::WPA2Personal, ..Default::default() }; wifi.set_configuration(&esp_idf_svc::wifi::Configuration::Mixed( client_config, ap_config, ))?; log::info!("启动wifi"); wifi.start()?; log::info!("等待网络连接"); if let Err(e) = wifi.connect() { log::error!("连接失败:{e},剩余{}次连接尝试", retry); retry -= 1; continue; } log::info!("等待底层网络驱动处理"); if let Err(e) = wifi.wait_netif_up() { log::error!("等待底层网络驱动处理失败,{e},剩余{}次重试",retry); } break; } log::info!("Ap模式信息为:{:?}", wifi.wifi().ap_netif().get_ip_info()); log::info!("Ip信息为:{:?}", wifi.wifi().sta_netif().get_ip_info()); Ok(()) } 在main.rs中调用fn main() { // It is necessary to call this function once. Otherwise some patches to the runtime // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71 esp_idf_svc::sys::link_patches(); // Bind the log crate to the ESP Logging facilities esp_idf_svc::log::EspLogger::initialize_default(); start_auto_wifi().unwrap(); }配网的html页面代码<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>esp32配网页面</title> <style> body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f4f4f9; } .login-container { width: 300px; padding: 20px; background-color: #fff; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); border-radius: 8px; } .login-container h2 { text-align: center; margin-bottom: 20px; color: #333; } .login-container input { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } .login-container button { width: 100%; padding: 10px; background-color: #4CAF50; border: none; color: #fff; border-radius: 4px; cursor: pointer; font-size: 16px; } .login-container button:hover { background-color: #45a049; } </style> </head> <body> <div class="login-container"> <h2>配网页面</h2> <form id="loginForm"> <input type="text" id="username" placeholder="ssid" required> <input type="password" id="password" placeholder="密码" required> <button type="button" onclick="submitForm()">提交</button> </form> </div> <script> function submitForm() { const ssid = document.getElementById('username').value; const password = document.getElementById('password').value; fetch(window.location.origin + '/wifi', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ssid, password }) }) .then(response => response.json()) .then(data => { // 在此处理响应数据 alert(data.msg); if (data.msg === "success"){ fetch(window.location.origin + '/muxt'); } console.log('成功:', data); }) .catch(error => { console.error('错误:', error); }); } </script> </body> </html>
2024年11月06日
37 阅读
0 评论
3 点赞