苏兮博客-记录学习经验 - rust
type: channel
link: https://www.suxii.cn/tag/rust/
items: ESP32C3使用Slint渲染TFT屏幕
items: ESP32C3驱动TFT屏幕
items: ESP32C3使用Slint渲染OLED屏幕
items: ESP32C3引入Slint: 解决依赖冲突
items: ESP32C3使用BLE
items: rust裸机开发esp32c3
items: rust开发esp32c3驱动oled屏幕
items: Rust 与 Kotlin：优雅的数据传输与多态序列化实践
items: 安卓使用rust构建so
items: esp32c3自动配网

ESP32C3使用Slint渲染TFT屏幕
type: item
date: 2025-05-10T20:02:12+08:00
description: 这个教程算是在st7789屏幕没有买之前就已经开始打算了，之前的使用slint驱动oled也算是为这个打下基础吧创建新项目可以参考 ESP32C3使用Slint渲染OLED屏幕 引入slint依赖，创建跟配置slint跟这篇文章一样，引入的依赖基本上大差不差，只不过这个项目还需要引入st7789屏幕的相关依赖。然后在Cargo.toml中添加依赖 [dependencies] # 基础依赖 critical-section = "1.2.0" esp-hal = { version = "1.0.0-beta.0", features = ["esp32c3","unstable"] } esp-alloc = "0.7.0" esp-println = { version = "0.13.1",features = ["esp32c3","log"] } log = "0.4.27" esp-backtrace = { version = "0.15.1" ,features = ["esp32c3","println","panic-handler"]} # 图形相关 embedded-hal = "1.0.0" embedded-graphics-core = "0.4.0" embedded-graphics = "0.8.1" embedded-graphics-framebuf = "0.5.0" display-interface = "0.5.0" display-interface-spi = "0.5.0" mipidsi = "0.9.0" embedded-hal-bus = "0.3.0" # 异步 esp-hal-embassy = { version = "0.7.0", features = ["esp32c3"] } embassy-time = { version = "0.4.0", features = ["generic-queue-8"] } embassy-executor = { version = "0.7.0",features = ["task-arena-size-20480","executor-thread"] } #embassy-futures = "0.1.1" static_cell = { version = "2.1.0", features = ["nightly"] } tinygif = "0.0.4" [dependencies.slint] git = "https://github.com/slint-ui/slint" rev = "29168bc89270798f6075a0a729c14a3f011ceb4f" # 修复提交的哈希 default-features = false features = [ "compat-1-2", "unsafe-single-threaded", # 启用单线程模式 "libm", "renderer-software", ] [build-dependencies] slint-build = {git = "https://github.com/slint-ui/slint",rev = "29168bc89270798f6075a0a729c14a3f011ceb4f"} 创建ui文件创建 ui/main.slint 文件，作为程序的入口文件import { System,LocalTime,Route , Setting} from "./global.slint"; import { HomePage } from "./page/home_page.slint"; import { SettingPage } from "./page/setting_page.slint"; // 导出给rust代码调用 export { System,LocalTime,Setting } export component MainView inherits Window { background: black; width: System.screen_width; height: System.screen_height; default-font-family: "黑体"; // 简单实现路由 if System.route==Route.HomePage: HomePage{} if System.route==Route.SettingPage: SettingPage{} // 显示帧率 if Setting.fps == true:Rectangle { padding: 2px; x:0…

ESP32C3驱动TFT屏幕
type: item
date: 2025-05-09T14:56:00+08:00
description: 因为使用的是新版esp-generate创建的项目，很多api的使用都大改了，网上能搜到的类似的教程也都完全没法用，这个教程是使用最新版esp-hal基于rust开发esp32c3驱动st7789屏幕。看网上有些项目叫MOSI，MISO的，也有叫SDI，SDO，这两个本质就是一个东西，在不同协议叫法不同。SPI 协议中大家都喜欢叫 MOSI / MISO，有些芯片厂商文档上写的是 SDI / SDO；MOSI == SDI（对于从机）：表示“数据输入”MISO == SDO（对于从机）：表示“数据输出”项目创建在 rust裸机开发esp32c3 的基础上，先新建一个最基础的环境引入依赖[dependencies] critical-section = "1.2.0" esp-hal = { version = "1.0.0-beta.0", features = ["esp32c3","unstable"] } esp-println = { version = "0.13.1",features = ["esp32c3","log"] } log = "0.4.27" # 图形相关 embedded-hal = "1.0.0" embedded-graphics-core = "0.4.0" embedded-graphics = "0.8.1" embedded-graphics-framebuf = "0.5.0" display-interface = "0.5.0" display-interface-spi = "0.5.0" mipidsi = "0.9.0" embedded-hal-bus = "0.3.0" 编写main.rs代码#![no_std] #![no_main] use embedded_graphics::Drawable; use embedded_graphics::image::{Image, ImageRawLE}; use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::prelude::{DrawTarget, Point, Primitive, RgbColor}; use embedded_graphics::primitives::PrimitiveStyle; use embedded_graphics_core::prelude::Size; use embedded_graphics_core::primitives::Rectangle; use embedded_hal::delay::DelayNs; use embedded_hal::digital::ErrorType; use embedded_hal_bus::spi::ExclusiveDevice; use esp_hal::clock::CpuClock; use esp_hal::delay::Delay; use esp_hal::gpio::{Level, Output, OutputConfig}; use esp_hal::main; use esp_hal::spi::master::{Config, Spi}; use esp_hal::spi::Mode; use esp_hal::time::{Duration, Instant, Rate}; use esp_println::logger::init_logger; use esp_println::println; use log::{error, LevelFilter}; use mipidsi::_mock::MockSpi; use mipidsi::models::ST7789; use mipidsi::Builder; use mipidsi::interface::SpiInterface; use mipidsi::options::Orientation; #[panic_handler] fn panic(e: &core::panic::PanicInfo) -> ! { println!("{}",e); loop { } } #[main] fn main() -> ! { // generator version: 0.3.1 let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); init_logger(LevelFilter::Debug); let peripherals = esp_hal::init(config); let…

ESP32C3使用Slint渲染OLED屏幕
type: item
date: 2025-05-05T18:59:05+08:00
description: 前言：说一下为什么要用slint，既然都选择用rust开发嵌入式了避免不了要折腾，也是为后续驱动st7789做铺垫吧。而其实对应OLED屏幕已经有一个很好用的库了embedded-graphics，几乎能满足OLED屏幕的全部需求了，但是slint有动画，定时器，声明式，这些优势，再嵌入式开发再合适不过了。在写这个的时候也遇到不少坑，所以记录一下吧创建项目引入库编译问题已经在 ESP32C3引入Slint 文章解决了先创建一个最基础的esp32c3的项目然后再Cargo.toml中添加依赖# 基础依赖 critical-section = "1.2.0" esp-hal = { version = "1.0.0-beta.0", features = ["esp32c3","unstable"] } esp-alloc = "0.7.0" esp-println = { version = "0.13.1",features = ["esp32c3","log"] } log = "0.4.27" esp-backtrace = { version = "0.15.1" ,features = ["esp32c3","println","panic-handler"]} # 图形相关 embedded-hal = "0.2.7" embedded-graphics-core = "0.4.0" embedded-graphics = "0.8.1" embedded-graphics-framebuf = "0.5.0" ssd1306 = { version = "0.10.0" ,features = ["graphics"]} # 异步 esp-hal-embassy = { version = "0.7.0", features = ["esp32c3"] } embassy-time = { version = "0.4.0", features = ["generic-queue-8"] } embassy-executor = { version = "0.7.0",features = ["task-arena-size-20480"] } static_cell = { version = "2.1.0", features = ["nightly"] } [dependencies.slint] git = "https://github.com/slint-ui/slint" rev = "29168bc89270798f6075a0a729c14a3f011ceb4f" # 修复提交的哈希 default-features = false features = [ "compat-1-2", "unsafe-single-threaded", # 启用单线程模式 "libm", "renderer-software", ] [build-dependencies] slint-build = {git = "https://github.com/slint-ui/slint",rev = "29168bc89270798f6075a0a729c14a3f011ceb4f"} 配置Slint我们使用slint的ui跟代码分离的模式，修改build.rs新增一个build_slint函数，然后在main函数中调用它 fn main(){ build_slint(); ... } fn build_slint(){ slint_build::compile_with_config( "ui/MainView.slint", slint_build::CompilerConfiguration::new() .embed_resources(slint_build::EmbedResourcesKind::EmbedForSoftwareRenderer) ).unwrap() }创建UI文件在项目根目录下创建 ui/MainView.slint 文件，定义 UI 界面// 由于是在no_std的环境下，没有默认字体，使用需要引入自定义的字体 import "./fonts/simhei.ttf"; // 这里定义了一个全局的状态，用于在rust代码里进行修改ui状态 export global MyState { in-out property <bool> is_show : true; } export component MainView inherits Window { default-font-family: "黑体"; width: 128px; height: 64px; Rectangle …

ESP32C3引入Slint: 解决依赖冲突
type: item
date: 2025-05-03T16:50:07+08:00
description: 为什么要折腾这个？想在 ESP32-C3 开发板上实现一个酷炫的 UI 界面，选了 Rust 生态的 Slint 框架。结果刚加上依赖就报错：error: 不能同时启用 critical-section 和 portable_atomic_unsafe_assume_single_core这两个特性不能同时存在解决问题过程第一步：创建最小测试项目# 生成纯净的 ESP32-C3 项目骨架 esp-generate --chip=esp32c3 slint_demo此时项目仅包含最基础的硬件驱动，编译一次成功：cargo build Compiling slint_demo v0.1.0 Finished dev [optimized] target(s)第二步：引入 Slint 引爆问题按官方文档添加依赖：cargo add slint@1.10.0 --no-default-features --features "compat-1-2 unsafe-single-threaded libm renderer-software"再次编译立刻报错：error: critical-section 与 portable_atomic_unsafe_assume_single_core 冲突第三步：定位问题注释 Slint 保留 ESP-HAL → 编译成功注释 ESP-HAL 保留 Slint → 依然报错Slint 的依赖树里藏了冲突的组件第四步：解决问题搜索 slint critical-section site:github.com锁定关键讨论：Issue #5057发现修复补丁：Commit 29168bc核心修改点：# Slint 内部配置调整 - portable-atomic = { features = ["critical-section"] } + portable-atomic = {} # 解除强制依赖最终配置方案关键依赖声明 (Cargo.toml)[dependencies] # 硬件抽象层 esp-hal = { version = "1.0.0-beta.0", default-features = false, features = ["esp32c3"] # 注意关闭默认特性 } # UI 框架 [dependencies.slint] git = "https://github.com/slint-ui/slint" rev = "29168bc89270798f6075a0a729c14a3f011ceb4f" # 锁定修复版本 default-features = false features = [ "compat-1-2", # 兼容旧版 API "unsafe-single-threaded", # 单核模式 "libm", # 数学库支持 "renderer-software" # 软件渲染 ] # 内存分配器 esp-alloc = "0.7.0"内存管理配置 (main.rs)// 初始化堆内存（72KB 用于 UI） #[main] fn main() -> ! { let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let _peripherals = esp_hal::init(config); esp_alloc::heap_allocator!(size: 72 * 1024); }经验总结依赖管理铁律用 cargo tree -e features 查看依赖关系通过 default-features = false 精准控制特性版本锁定技巧使用 rev = "commit_hash" 锁定特定修复版本定期检查 GitHub Issues 跟踪问题进展

ESP32C3使用BLE
type: item
date: 2025-05-01T16:36:00+08:00
description: 初始化项目参考 项目创建 新建一个基于std的新项目在Cargo.toml添加必要的依赖[package] name = "esp32c3-ble-demo" version = "0.1.0" authors = ["suxii <m@suxii.cn>"] edition = "2021" resolver = "2" rust-version = "1.77" bin name = "esp32c3-ble-demo" harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors [features] default = [] experimental = ["esp-idf-svc/experimental"] [dependencies] log = "0.4" esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync","experimental","std"] } futures = "0.3.31" anyhow = "1.0.98" enumset = "1.1.5" heapless = "0.8.0" esp-idf-sys = "0.36.1" esp-idf-hal = "0.45.2" # 处理序列化，反序列化 serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" [build-dependencies] embuild = "0.33" 开启BLE功能将sdkconfig.defaults 文件替换成# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) CONFIG_ESP_MAIN_TASK_STACK_SIZE=7000 CONFIG_BT_BLUEDROID_ENABLED=y CONFIG_BT_ENABLED=y CONFIG_BT_BLE_ENABLED=y CONFIG_BT_GATTS_ENABLE=y CONFIG_BT_BLE_SMP_ENABLE=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=y CONFIG_BT_BTC_TASK_STACK_SIZE=7000 CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y CONFIG_BT_CTRL_BLE_MAX_ACT=10 CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=10 CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0 CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 CONFIG_BT_CTRL_BLE_SCAN_DUPL=y # Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). # This allows to use 1 ms granuality for thread sleeps (10 ms by default). #CONFIG_FREERTOS_HZ=1000 # Workaround for https://github.com/espressif/esp-idf/issues/7631 #CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n #CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n并且在同级目录新建一个 sdkconfig.esp32c3文件# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) CONFIG_ESP_MAIN_TASK_STACK_SIZE=7000 CONFIG_BT_ENABLED=y CONFIG_BT_BLE_ENAB…

rust裸机开发esp32c3
type: item
date: 2025-04-30T01:03:45+08:00
description: 安装esp-generate# 安装新版生成工具 cargo install esp-generate # 安装依赖工具链 cargo install espup espup install激活环境变量source $HOME/export-esp.sh # linuxWindows用户默认在C:\Users\HOME目录下有一个 export-esp.ps1文件，双击执行激活环境变量使用esp-genertate 创建新项目esp-generate --chip=esp32c3 demo这个项目是个hello world项目，不需要额外的配置，接着按s创建项目添加依赖在Cargo.toml的[dependencies]添加println依赖esp-println = { version = "0.13.1",features = ["esp32c3","log"] }点亮LED修改mian.rs点亮一个led#![no_std] #![no_main] use esp_hal::clock::CpuClock; use esp_hal::gpio::{Level, Output, OutputConfig}; use esp_hal::main; use esp_hal::time::{Duration, Instant}; use esp_println::println; #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } #[main] fn main() -> ! { // generator version: 0.3.1 let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals = esp_hal::init(config); let mut led = Output::new(peripherals.GPIO9, Level::Low, OutputConfig::default()); let mut count = 0; loop { let delay_start = Instant::now(); led.toggle(); println!("第{count}次数改变led状态"); count+=1; while delay_start.elapsed() < Duration::from_millis(1500) {} } // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.0.0-beta.0/examples/src/bin } 成功打印日志

rust开发esp32c3驱动oled屏幕
type: item
date: 2025-04-27T22:49:55+08:00
description: 使用的是 I2C SSD1306 0.96寸的OLED屏幕1.在Cargo.toml中添加图形库依赖# 处理ssd1306屏幕 ssd1306 = {version = "0.10.0",features = ["graphics"]} embedded-graphics = "0.8.1"完整配置 Cargo.toml[package] name = "esp32c3-oled-demo" version = "0.1.0" authors = ["suxii <m@suxii.cn>"] edition = "2021" resolver = "2" rust-version = "1.77" bin name = "esp32c3-oled-demo" harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors [features] default = [] experimental = ["esp-idf-svc/experimental"] [dependencies] log = "0.4" esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync","experimental","std"] } futures = "0.3.31" anyhow = "1.0.98" esp-idf-hal = "0.45.2" # 处理ssd1306屏幕 ssd1306 = {version = "0.10.0",features = ["graphics"]} embedded-graphics = "0.8.1" [build-dependencies] embuild = "0.33" 2.在main.rs中编写rust代码use esp_idf_hal::{ delay::FreeRtos, i2c::*, peripherals::Peripherals, prelude::*, }; use embedded_graphics::{ mono_font::{ascii::FONT_6X10, MonoTextStyle}, pixelcolor::BinaryColor, prelude::*, primitives::{Circle, Line, PrimitiveStyle, Rectangle}, text::Text }; use ssd1306::{I2CDisplayInterface, Ssd1306, prelude::*, size::DisplaySize128x64}; fn main() -> anyhow::Result<()> { esp_idf_hal::sys::link_patches(); // 初始化外设 let peripherals = Peripherals::take()?; // 配置I2C let i2c = peripherals.i2c0; let sda = peripherals.pins.gpio5; let scl = peripherals.pins.gpio6; let config = I2cConfig::new().baudrate(400.kHz().into()); let i2c = I2cDriver::new(i2c, sda, scl, &config)?; // 创建SSD1306接口 let interface = I2CDisplayInterface::new(i2c); let mut display = Ssd1306::new( interface, DisplaySize128x64, DisplayRotation::Rotate0 ).into_buffered_graphics_mode(); // 初始化显示屏 display.init().expect("SSD1306 init failed"); display.flush().expect("Failed to flush display"); // 创建图形样式 let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On); let line_style = PrimitiveStyle::with_stroke(BinaryColor::On, 1); let mut run_x = 64; loop {…

Rust 与 Kotlin：优雅的数据传输与多态序列化实践
type: item
date: 2025-04-26T15:29:00+08:00
description: 在现代软件开发中，尤其是在系统编程和移动应用领域，实现不同语言之间的数据交换至关重要。Rust 和 Kotlin 都以其高性能和安全性著称，提供了强大的多态序列化机制，能够确保数据结构在不同语言间的一致性和可维护性。本文将通过一个示例，展示如何在 Rust 和 Kotlin 中定义和处理多态消息，确保它们之间的无缝互操作。定义消息结构我们希望构建一个多态消息系统，包含两种类型的消息：LedMessage：控制 LED 的整数值。TextMessage：发送一条文本消息。Rust 实现Rust 使用 serde 库进行序列化和反序列化。通过使用 #[serde(tag = "type")] 属性，我们可以根据 type 字段区分不同的消息类型。use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] #[serde(tag = "type")] enum Message { #[serde(rename = "led")] Led(LedMessage), #[serde(rename = "text")] Text(TextMessage), #[serde(other)] Unknown, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct LedMessage { value: i32, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct TextMessage { text: String, } impl Message { fn to_json(&self) -> serde_json::Result<String> { serde_json::to_string(self) } fn from_str(src: &str) -> serde_json::Result<Self> { serde_json::from_str(src) } } fn test() { let led_message = Message::Led(LedMessage { value: 33 }); let encoded = led_message.to_json().unwrap(); println!("{}", encoded); match Message::from_str("{\"text\":\"hello text\",\"type\":\"text\"}").unwrap() { Message::Led(led_message) => { println!("收到 LedMessage：{}", led_message.value) } Message::Text(text_message) => { println!("收到 TextMessage：{}", text_message.text) } Message::Unknown => { println!("未知的消息类型") } } }在这个实现中，type 字段用于区分不同的消息类型，serde 会根据该字段自动选择合适的枚举变体进行反序列化。Kotlin 实现Kotlin 使用 kotlinx.serialization 库处理多态序列化。通过自定义序列化器，我们可以根据 type 字段动态选择合适的反序列化器。import kotlinx.serialization.* import kotlinx.serialization.json.* object MessageSerializer : JsonContentPolymorphicSerializer<Message>(Message::class) { override fun selectDeserializer(element: JsonElement): DeserializationStrategy<Message> { val type = element.jsonObject["type"]!!.jsonPrimitive.content return when (type) { "led" -> Message.LedMessage.serializer() "text" -> Message.TextMessage.serializer() else -> throw SerializationException("未知类型：$type") } } …

安卓使用rust构建so
type: item
date: 2025-03-20T17:06:12+08:00
description: 1. 下载和配置 NDK首先，从 Android NDK 下载页面 下载并安装最新版本的 Android NDK。在安装完成后，确保能够找到 NDK 的安装路径并配置工具链。您将使用这个工具链来交叉编译 Rust 代码为 Android 的本地库。2. 创建 Rust 库项目使用以下命令在命令行中创建一个新的 Rust 库项目：cargo new android_test_lib --lib此命令会生成一个新的 Rust 项目目录 android_test_lib，并包含一个简单的库文件结构。3. 配置 Cargo.toml编辑项目中的 Cargo.toml 文件，指定该库的构建类型，并添加依赖项：[package] name = "android_lib_test" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] jni = "0.21.1"解释：[lib] 中的 crate-type = ["cdylib"] 指定 Rust 将构建一个 C 兼容的动态库，以便 Android 使用。jni = "0.21.1" 是用于与 Java 进行交互的 JNI 库，允许我们在 Rust 中调用 JNI 方法。4. 配置 .cargo/config.toml在项目根目录下创建 .cargo 文件夹，并在其中添加 config.toml 文件，配置 Android 的交叉编译工具链：mkdir .cargo touch .cargo/config.toml目录结构编辑 config.toml 文件，指定交叉编译时使用的工具链路径：[target.aarch64-linux-android] linker = "D:/android-ndk-r27c/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang.cmd" # 注意文件路径解释：这里的 linker 配置项指定了 Android NDK 中 clang 编译器的位置，您需要根据自己的实际路径进行修改。5. 添加目标平台支持在命令行中运行以下命令，确保您的 Rust 环境支持目标架构：rustup target list如果 aarch64-linux-android 目标没有显示为已安装，使用以下命令安装：rustup target add aarch64-linux-android6. 编写 Rust 代码编辑 src/lib.rs 文件，编写您的 Rust 代码并实现 JNI 接口：use jni::JNIEnv; use jni::objects::{JClass, JString}; use jni::sys::jstring; #[no_mangle] pub extern "system" fn Java_com_suxii_myapplicationrust_Hello_say( mut env: JNIEnv, class: JClass, input: JString, ) -> jstring { let world: String = env.get_string(&input).expect("invalid pattern string").into(); let output = env.new_string(format!("Hello, {}! this is rust", world)).expect("Couldn't create java string!"); output.into_raw() }解释：#[no_mangle]：防止 Rust 编译器对函数名进行修改，以保证 JNI 函数名称与 Java 端的声明一致。extern "system" fn Java_com_suxii_myapplicationrust_Hello_say：JNI 函数，名称必须符合 Java_包名_类名_方法名 的格式。env.get_string(&input).expect("invalid pattern string").into();：将 Java 字符串转换为 Rust 字符串。env.new_string(format!("Hello, {}! this is rust", world))：创建一个新的 Java 字符串并返回给 Java。7. 编译 Rust 库使用以下命令为 Android 构建 release 版本的动态库：cargo build --target aarch64-linux-android --release编译完成…

esp32c3自动配网
type: item
date: 2024-11-06T16:38:45+08:00
description: 在 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_in…