From a0f7f8c045b46844310a7ca2d527591f9a157bbe Mon Sep 17 00:00:00 2001 From: Mikhail Modin Date: Mon, 10 Jun 2024 19:56:55 +0100 Subject: [PATCH 1/7] Update for esp32s3, add web server to example --- .cargo/config.toml | 55 --------- .gitignore | 3 +- README.md | 2 + examples/camera-example/.cargo/config.toml | 12 +- examples/camera-example/Cargo.toml | 25 ++-- examples/camera-example/README.md | 15 ++- examples/camera-example/sdkconfig.defaults | 9 +- examples/camera-example/src/main.rs | 135 ++++++++++++--------- sdkconfig.defaults | 1 - src/lib.rs | 8 +- 10 files changed, 128 insertions(+), 137 deletions(-) delete mode 100644 .cargo/config.toml delete mode 100644 sdkconfig.defaults diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 8762107..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,55 +0,0 @@ -[build] -# Uncomment the relevant target for your chip here (ESP32, ESP32-S2, ESP32-S3 or ESP32-C3) -target = "xtensa-esp32-espidf" -#target = "xtensa-esp32s2-espidf" -#target = "xtensa-esp32s3-espidf" -#target = "riscv32imc-esp-espidf" - -[target.xtensa-esp32-espidf] -linker = "ldproxy" -# Uncomment for ESP-IDF 5 and later. Don't forget to also uncomment the `ESP_IDF_VERSION = "release/v5.0"`parameter in the `[env]` section below -#rustflags = ["--cfg", "espidf_time64"] - -[target.xtensa-esp32s2-espidf] -linker = "ldproxy" -# Uncomment for ESP-IDF 5 and later. Don't forget to also uncomment the `ESP_IDF_VERSION = "release/v5.0"`parameter in the `[env]` section below -#rustflags = ["--cfg", "espidf_time64"] - -[target.xtensa-esp32s3-espidf] -linker = "ldproxy" -# Uncomment for ESP-IDF 5 and later. Don't forget to also uncomment the `ESP_IDF_VERSION = "release/v5.0"`parameter in the `[env]` section below -#rustflags = ["--cfg", "espidf_time64"] - -[target.riscv32imc-esp-espidf] -linker = "ldproxy" -# Future - necessary for the experimental "native build" of esp-idf-sys with ESP32C3 -# See also https://github.com/ivmarkov/embuild/issues/16 -rustflags = ["-C", "default-linker-libraries"] -# Uncomment for ESP-IDF 5 and later. Don't forget to also uncomment the `ESP_IDF_VERSION = "release/v5.0"`parameter in the `[env]` section below -#rustflags = ["--cfg", "espidf_time64", "-C", "default-linker-libraries"] - -[unstable] -build-std = ["std", "panic_abort"] -#build-std-features = ["panic_immediate_abort"] # Only necessary if building against ESP-IDF tag `v4.3.2` (the minimum supported version) - -[env] -# Select ESP IDF version in embuild's format described here: -# https://github.com/esp-rs/esp-idf-sys/blob/master/README.md#esp_idf_version-esp_idf_version-native-builder-only -# -# Uncomment this to build against ESP-IDF master (currently unreleased ESP IDF 5.1) -#ESP_IDF_VERSION = "master" -# Don't forget to uncomment also the `rustflags` parameter in your "target" section above -# -# Uncomment this to build against ESP-IDF 5.0 -# Don't forget to uncomment also the `rustflags` parameter in your "target" section above -#ESP_IDF_VERSION = "release/v5.0" -# -# Comment out this when using the PlatformIO build, i.e. `cargo build --features pio` (it only supports `v4.3.2`) -ESP_IDF_VERSION = "release/v4.4" - -# These configurations will pick up your custom "sdkconfig.release", "sdkconfig.debug" or "sdkconfig.defaults[.*]" files -# that you might put in the root of the project -# The easiest way to generate a full "sdkconfig" configuration (as opposed to manually enabling only the necessary flags via "sdkconfig.defaults[.*]" -# is by running "cargo pio espidf menuconfig" (that is, if using the pio builder) -#ESP_IDF_SDKCONFIG = "sdkconfig.release;sdkconfig.debug" -ESP_IDF_SDKCONFIG_DEFAULTS = "sdkconfig.defaults;sdkconfig.defaults.esp32;sdkconfig.defaults.esp32s2" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 101a548..352ddc5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target /Cargo.lock -/.embuild \ No newline at end of file +/.embuild +components_esp32s3.lock diff --git a/README.md b/README.md index c0db308..52c9cea 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # esp-camera-rs Rust wrapper library to interface with the ESP32 camera + +See [examples/camera-example/README.md](examples/camera-example/README.md) for usage details. diff --git a/examples/camera-example/.cargo/config.toml b/examples/camera-example/.cargo/config.toml index 058f7f5..e92f9b9 100644 --- a/examples/camera-example/.cargo/config.toml +++ b/examples/camera-example/.cargo/config.toml @@ -1,17 +1,21 @@ [build] -target = "xtensa-esp32-espidf" +target = "xtensa-esp32s3-espidf" -[target.xtensa-esp32-espidf] +[target.xtensa-esp32s3-espidf] linker = "ldproxy" # runner = "espflash --monitor" # Select this runner for espflash v1.x.x -runner = "espflash flash --monitor" # Select this runner for espflash v2.x.x +runner = "espflash flash --monitor -T target/xtensa-esp32s3-espidf/release/partition-table.bin" # Select this runner for espflash v2.x.x rustflags = [ "--cfg", "espidf_time64"] # Extending time_t for ESP IDF 5: https://github.com/esp-rs/rust/issues/110 [unstable] build-std = ["std", "panic_abort"] [env] -MCU="esp32" +MCU="esp32s3" # Note: this variable is not used by the pio builder (`cargo build --features pio`) ESP_IDF_VERSION = "v5.1.3" +# Workaround for https://github.com/esp-rs/esp-idf-template/issues/174 until +# https://github.com/esp-rs/esp-idf-hal/pull/387 gets released and the template +# updated. +CRATE_CC_NO_DEFAULTS = "1" diff --git a/examples/camera-example/Cargo.toml b/examples/camera-example/Cargo.toml index 5d0d52b..4b66ff7 100644 --- a/examples/camera-example/Cargo.toml +++ b/examples/camera-example/Cargo.toml @@ -3,6 +3,7 @@ name = "camera-example" version = "0.1.0" authors = ["Mathias Pius "] edition = "2021" +resolver = "2" rust-version = "1.71" [profile.release] @@ -12,15 +13,25 @@ opt-level = "s" debug = true # Symbols are nice and they don't increase the size on Flash opt-level = "z" +[features] +default = ["std", "embassy", "esp-idf-svc/native"] + +pio = ["esp-idf-svc/pio"] +std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"] +alloc = ["esp-idf-svc/alloc"] +nightly = ["esp-idf-svc/nightly"] +experimental = ["esp-idf-svc/experimental"] +embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"] + [dependencies] log = { version = "0.4", default-features = false } -anyhow = "1.0.82" -esp-idf-svc = { version = "0.48", default-features = false, features = [ - "binstart", - "std", -] } -esp-idf-sys = { version = "0.34.1" } -esp-camera-rs = { git = "https://github.com/MathiasPius/esp-camera-rs.git" } +anyhow = "1.0" +esp-idf-svc = { version = "0.48", default-features = false } +esp-idf-sys = "0.34" +embedded-svc = "0.27" + +#esp-camera-rs = { git = "https://github.com/MathiasPius/esp-camera-rs.git" } +esp-camera-rs = { path = "../../" } [build-dependencies] embuild = "0.31.3" diff --git a/examples/camera-example/README.md b/examples/camera-example/README.md index 13b5f2e..aa3656d 100644 --- a/examples/camera-example/README.md +++ b/examples/camera-example/README.md @@ -1,12 +1,11 @@ -This example assumes you have already set up all the tools necessary to compile Rust for ESP32. +This example assumes you have already set up all the tools necessary to compile Rust for ESP32. Follow [The Rust on ESP Book](https://docs.esp-rs.org/book/) for setup steps. -When run using `cargo run`, it will compile and flash the program to an ESP32-CAM mounted on an -ESP32-CAM-MB board connected via USB to the host machine. +When you need to export `WIFI_SSID` and `WIFI_PASS` environment variables and run the example by using `cargo run -r`, it will compile and flash the program to an ESP32S3 with a camera. The pins are set up for this [Freenove board](https://github.com/Freenove/Freenove_ESP32_S3_WROOM_Board). The program will: -1. Initialize the onboard OV2640 camera as well as the bright white LED (flash). -2. Turn on the flash. -3. Take a jpeg-encoded picture using the camera. -4. Print information about the image: width, height and size in bytes. -5. Enter deep sleep for 60 seconds, after which the device starts the process. \ No newline at end of file +1. Connect to your WiFi. +1. Initialize the onboard OV2640 camera as well as a LED. +1. Start HTTP server. +1. Take a jpeg-encoded picture using the camera for each GET on `/` url and send it. +1. Print trace information about each step and action. diff --git a/examples/camera-example/sdkconfig.defaults b/examples/camera-example/sdkconfig.defaults index c073e82..247670f 100644 --- a/examples/camera-example/sdkconfig.defaults +++ b/examples/camera-example/sdkconfig.defaults @@ -1,5 +1,8 @@ -# I think larger stack size is required for rust? Not sure where I got this info +# 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=8000 -# Enable PSRAM, which allows us to store larger images -CONFIG_ESP32_SPIRAM_SUPPORT=y \ No newline at end of file +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_LWIP_LOCAL_HOSTNAME="esp-cam" +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y + diff --git a/examples/camera-example/src/main.rs b/examples/camera-example/src/main.rs index a5b9267..8414d8f 100644 --- a/examples/camera-example/src/main.rs +++ b/examples/camera-example/src/main.rs @@ -1,76 +1,103 @@ +use embedded_svc::http::Method; +use embedded_svc::io::Write; +use embedded_svc::wifi::{AuthMethod, ClientConfiguration, Configuration}; +use esp_idf_svc::eventloop::EspSystemEventLoop; use esp_idf_svc::hal::{gpio::PinDriver, peripherals::Peripherals}; -use esp_idf_sys::esp_deep_sleep; -use log::info; +use esp_idf_svc::http::server::{Configuration as HttpServerConfig, EspHttpServer}; +use esp_idf_svc::nvs::EspDefaultNvsPartition; +use esp_idf_svc::wifi::{BlockingWifi, EspWifi}; +use log::{error, info}; use std::time::Duration; fn main() -> anyhow::Result<()> { - // 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(); - info!("initializing camera and flash"); + info!("initializing peripherals"); let peripherals = Peripherals::take().unwrap(); + let sysloop = EspSystemEventLoop::take()?; + let nvs = EspDefaultNvsPartition::take()?; + + info!("initializing WiFi"); + let mut wifi = BlockingWifi::wrap( + EspWifi::new(peripherals.modem, sysloop.clone(), Some(nvs))?, + sysloop, + )?; + + wifi.set_configuration(&Configuration::Client(ClientConfiguration { + ssid: env!("WIFI_SSID").try_into().unwrap(), + bssid: None, + auth_method: AuthMethod::None, + password: env!("WIFI_PASS").try_into().unwrap(), + channel: None, + }))?; - // ESP32-CAM has an onboard Flash LED addressed at GPIO-4 - let mut flash = PinDriver::output(peripherals.pins.gpio4)?; - flash.set_low()?; + wifi.start()?; + wifi.connect()?; + wifi.wait_netif_up()?; + info!( + "Wifi is ready, ip {:?}", + wifi.wifi().sta_netif().get_ip_info()? + ); - // Initialize the camera + let mut led = PinDriver::output(peripherals.pins.gpio2)?; + led.set_low()?; + + info!("Initialize the camera"); let camera = esp_camera_rs::Camera::new( - peripherals.pins.gpio32, - peripherals.pins.gpio0, - peripherals.pins.gpio5, + None, + peripherals.pins.gpio15, + peripherals.pins.gpio11, + peripherals.pins.gpio9, + peripherals.pins.gpio8, + peripherals.pins.gpio10, + peripherals.pins.gpio12, peripherals.pins.gpio18, - peripherals.pins.gpio19, - peripherals.pins.gpio21, - peripherals.pins.gpio36, - peripherals.pins.gpio39, - peripherals.pins.gpio34, - peripherals.pins.gpio35, - peripherals.pins.gpio25, - peripherals.pins.gpio23, - peripherals.pins.gpio22, - peripherals.pins.gpio26, - peripherals.pins.gpio27, + peripherals.pins.gpio17, + peripherals.pins.gpio16, + peripherals.pins.gpio6, + peripherals.pins.gpio7, + peripherals.pins.gpio13, + peripherals.pins.gpio4, + peripherals.pins.gpio5, esp_idf_sys::camera::pixformat_t_PIXFORMAT_JPEG, esp_idf_sys::camera::framesize_t_FRAMESIZE_UXGA, esp_idf_sys::camera::camera_fb_location_t_CAMERA_FB_IN_PSRAM, )?; - info!("initialization complete!"); + info!("initializing http servert"); + + let state = std::sync::Arc::new(std::sync::Mutex::new((led, camera))); - // Turn on the flash and take a picture. - // You probably want to keep it on for a while and adjust - // the camera exposure to get a good image, but this is - // mainly here to show that the program is working. - info!("taking a picture"); - flash.set_high()?; - let framebuffer = camera.get_framebuffer(); - flash.set_low()?; + let mut httpserver = EspHttpServer::new(&HttpServerConfig::default())?; + info!("preocessing http requests"); - if let Some(framebuffer) = framebuffer { - info!( - "took picture: {width}x{height} {size} bytes", - width = framebuffer.width(), - height = framebuffer.height(), - size = framebuffer.data().len(), - ); + httpserver.fn_handler("/", Method::Get, |request| { + info!("taking a picture"); + let (ref mut led, camera) = &mut *state.lock().unwrap(); - // TODO: Do something with the framebuffer. - // the JPEG-encoded byte data is in framebuffer.data() - // so you can just dump this to a file or send it over - // the network as "image.jpeg" and it should work. - } else { - panic!("failed to take image"); - }; + led.set_high()?; + let framebuffer = camera.get_framebuffer(); + led.set_low()?; + if let Some(framebuffer) = framebuffer { + info!( + "took picture: {width}x{height} {size} bytes", + width = framebuffer.width(), + height = framebuffer.height(), + size = framebuffer.data().len(), + ); + let mut response = + request.into_response(200, Some("Ok"), &[("Content-Type", "image/jpeg")])?; + response.write_all(framebuffer.data()) + } else { + error!("failed to take image"); + let mut response = request.into_status_response(500)?; + response.write_all(b"camera failed") + } + .map(|_| ()) + })?; - // Send the board into deep sleep. This will basically turn off everything - // and consume very little power, and then "reboot" the device, restarting - // the pin initialization and taking another picture. - let delay = Duration::from_secs(60); - info!("finished, entering deep sleep for {delay:#?}"); - unsafe { esp_deep_sleep(delay.as_micros() as u64) } + loop { + std::thread::sleep(Duration::from_millis(1000)); + } } diff --git a/sdkconfig.defaults b/sdkconfig.defaults deleted file mode 100644 index 753473e..0000000 --- a/sdkconfig.defaults +++ /dev/null @@ -1 +0,0 @@ -CONFIG_ESP32_SPIRAM_SUPPORT=y \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index a5f4ec9..ae0024b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -225,7 +225,7 @@ pub struct Camera<'a> { impl<'a> Camera<'a> { pub fn new( - pin_pwdn: impl Peripheral

+ 'a, + pin_pwdn: Option, pin_xclk: impl Peripheral

+ 'a, pin_d0: impl Peripheral

+ 'a, pin_d1: impl Peripheral

+ 'a, @@ -245,13 +245,13 @@ impl<'a> Camera<'a> { fb_location: camera::camera_fb_location_t, ) -> Result { esp_idf_hal::into_ref!( - pin_pwdn, pin_xclk, pin_d0, pin_d1, pin_d2, pin_d3, pin_d4, pin_d5, pin_d6, pin_d7, + pin_xclk, pin_d0, pin_d1, pin_d2, pin_d3, pin_d4, pin_d5, pin_d6, pin_d7, pin_vsync, pin_href, pin_pclk, pin_sda, pin_scl ); let config = camera::camera_config_t { - pin_pwdn: pin_pwdn.pin(), + pin_pwdn: pin_pwdn.map(|p| p.into_ref().pin()).unwrap_or(-1), pin_xclk: pin_xclk.pin(), - pin_reset: 0xff, + pin_reset: -1, pin_d0: pin_d0.pin(), pin_d1: pin_d1.pin(), From ef2e1005010429b6351104ac8a3a49701ab86274 Mon Sep 17 00:00:00 2001 From: Mikhail Modin Date: Mon, 10 Jun 2024 20:01:35 +0100 Subject: [PATCH 2/7] update lib path --- examples/camera-example/Cargo.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/camera-example/Cargo.toml b/examples/camera-example/Cargo.toml index 4b66ff7..c79f3eb 100644 --- a/examples/camera-example/Cargo.toml +++ b/examples/camera-example/Cargo.toml @@ -30,8 +30,10 @@ esp-idf-svc = { version = "0.48", default-features = false } esp-idf-sys = "0.34" embedded-svc = "0.27" -#esp-camera-rs = { git = "https://github.com/MathiasPius/esp-camera-rs.git" } -esp-camera-rs = { path = "../../" } +esp-camera-rs = { git = "https://github.com/mikhail-m1/esp-camera-rs.git" } +# Uncomment next string to use local version of the lib. +# You also need to run `git submodule init` and `git submodule update` +#esp-camera-rs = { path = "../../" } [build-dependencies] embuild = "0.31.3" From b3fda590b7ef6733d72e4c333b7297766c04a303 Mon Sep 17 00:00:00 2001 From: Mikhail Modin Date: Tue, 9 Jul 2024 19:12:54 +0100 Subject: [PATCH 3/7] Rework new to config, add getters --- Cargo.toml | 1 + README.md | 3 +- examples/camera-example/README.md | 4 +- examples/camera-example/src/main.rs | 40 ++- src/lib.rs | 384 +++++++++++++++------------- 5 files changed, 226 insertions(+), 206 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4c7c915..bd38fd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] esp-idf-hal = "0.43.1" esp-idf-sys = "0.34.1" +concat-idents = "1.1.5" [patch.crates-io] esp-idf-sys = { git = "https://github.com/esp-rs/esp-idf-sys", branch = "master" } diff --git a/README.md b/README.md index 52c9cea..85b9482 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # esp-camera-rs -Rust wrapper library to interface with the ESP32 camera +Rust wrapper library to interface with the ESP32 and ESP32 S3 cameras. The way to define configuration +for camera was reworked, get methods added and set methods rewrote to use macro. See [examples/camera-example/README.md](examples/camera-example/README.md) for usage details. diff --git a/examples/camera-example/README.md b/examples/camera-example/README.md index aa3656d..06f3271 100644 --- a/examples/camera-example/README.md +++ b/examples/camera-example/README.md @@ -1,4 +1,6 @@ -This example assumes you have already set up all the tools necessary to compile Rust for ESP32. Follow [The Rust on ESP Book](https://docs.esp-rs.org/book/) for setup steps. +This example is set up for ESP32S3, but you can run it on other ESP32 chips by changing `.cargo/config.toml` and `sdkconfig.defaults` the camera's pins should be changed as well. + +To build and run the example you need to set up all the tools necessary to compile Rust for ESP32. Follow [The Rust on ESP Book](https://docs.esp-rs.org/book/) for setup steps. When you need to export `WIFI_SSID` and `WIFI_PASS` environment variables and run the example by using `cargo run -r`, it will compile and flash the program to an ESP32S3 with a camera. The pins are set up for this [Freenove board](https://github.com/Freenove/Freenove_ESP32_S3_WROOM_Board). diff --git a/examples/camera-example/src/main.rs b/examples/camera-example/src/main.rs index 8414d8f..5ca2b15 100644 --- a/examples/camera-example/src/main.rs +++ b/examples/camera-example/src/main.rs @@ -14,7 +14,7 @@ fn main() -> anyhow::Result<()> { esp_idf_svc::log::EspLogger::initialize_default(); info!("initializing peripherals"); - let peripherals = Peripherals::take().unwrap(); + let mut peripherals = Peripherals::take().unwrap(); let sysloop = EspSystemEventLoop::take()?; let nvs = EspDefaultNvsPartition::take()?; @@ -44,26 +44,24 @@ fn main() -> anyhow::Result<()> { led.set_low()?; info!("Initialize the camera"); - let camera = esp_camera_rs::Camera::new( - None, - peripherals.pins.gpio15, - peripherals.pins.gpio11, - peripherals.pins.gpio9, - peripherals.pins.gpio8, - peripherals.pins.gpio10, - peripherals.pins.gpio12, - peripherals.pins.gpio18, - peripherals.pins.gpio17, - peripherals.pins.gpio16, - peripherals.pins.gpio6, - peripherals.pins.gpio7, - peripherals.pins.gpio13, - peripherals.pins.gpio4, - peripherals.pins.gpio5, - esp_idf_sys::camera::pixformat_t_PIXFORMAT_JPEG, - esp_idf_sys::camera::framesize_t_FRAMESIZE_UXGA, - esp_idf_sys::camera::camera_fb_location_t_CAMERA_FB_IN_PSRAM, - )?; + + let camera_params = esp_camera_rs::CameraParams::new() + .set_clock_pin(&mut peripherals.pins.gpio15) + .set_d0_pin(&mut peripherals.pins.gpio11) + .set_d1_pin(&mut peripherals.pins.gpio9) + .set_d2_pin(&mut peripherals.pins.gpio8) + .set_d3_pin(&mut peripherals.pins.gpio10) + .set_d4_pin(&mut peripherals.pins.gpio12) + .set_d5_pin(&mut peripherals.pins.gpio18) + .set_d6_pin(&mut peripherals.pins.gpio17) + .set_d7_pin(&mut peripherals.pins.gpio16) + .set_vertical_sync_pin(&mut peripherals.pins.gpio6) + .set_horizontal_reference_pin(&mut peripherals.pins.gpio7) + .set_pixel_clock_pin(&mut peripherals.pins.gpio13) + .set_sda_pin(&mut peripherals.pins.gpio4) + .set_scl_pin(&mut peripherals.pins.gpio5); + + let camera = esp_camera_rs::Camera::new(&camera_params)?; info!("initializing http servert"); diff --git a/src/lib.rs b/src/lib.rs index ae0024b..5396159 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,82 @@ // code updated from https://github.com/Kezii/esp32cam_rs/blob/master/src/espcam.rs +use std::ffi::c_int; use std::marker::PhantomData; use esp_idf_hal::gpio::*; use esp_idf_hal::peripheral::Peripheral; use esp_idf_sys::*; +impl<'a> Camera<'a> { + pub fn new(params: &CameraParams) -> Result { + let config = camera::camera_config_t { + pin_pwdn: params.power, + pin_xclk: params.clock, + pin_reset: -1, + pin_d0: params.d0, + pin_d1: params.d1, + pin_d2: params.d2, + pin_d3: params.d3, + pin_d4: params.d4, + pin_d5: params.d5, + pin_d6: params.d6, + pin_d7: params.d7, + pin_vsync: params.vertical_sync, + pin_href: params.horizontal_reference, + pin_pclk: params.pixel_clock, + + xclk_freq_hz: 20_000_000, + ledc_timer: esp_idf_sys::ledc_timer_t_LEDC_TIMER_0, + ledc_channel: esp_idf_sys::ledc_channel_t_LEDC_CHANNEL_0, + + pixel_format: params.pixel_format, + frame_size: params.frame_size, + + jpeg_quality: 12, + fb_count: 1, + grab_mode: camera::camera_grab_mode_t_CAMERA_GRAB_WHEN_EMPTY, + + fb_location: params.fb_location, + + __bindgen_anon_1: camera::camera_config_t__bindgen_ty_1 { + pin_sccb_sda: params.sda, + }, + __bindgen_anon_2: camera::camera_config_t__bindgen_ty_2 { + pin_sccb_scl: params.scl, + }, + ..Default::default() + }; + + esp_idf_sys::esp!(unsafe { camera::esp_camera_init(&config) })?; + Ok(Self { _p: PhantomData }) + } + + pub fn get_framebuffer(&self) -> Option { + let fb = unsafe { camera::esp_camera_fb_get() }; + if fb.is_null() { + None + } else { + Some(FrameBuffer { + fb, + _p: PhantomData, + }) + } + } + + pub fn sensor(&self) -> CameraSensor<'a> { + CameraSensor { + sensor: unsafe { camera::esp_camera_sensor_get() }, + _p: PhantomData, + } + } +} + +impl<'a> Drop for Camera<'a> { + fn drop(&mut self) { + esp!(unsafe { camera::esp_camera_deinit() }).expect("error during esp_camera_deinit") + } +} + pub struct FrameBuffer<'a> { fb: *mut camera::camera_fb_t, _p: PhantomData<&'a camera::camera_fb_t>, @@ -48,6 +119,33 @@ pub struct CameraSensor<'a> { _p: PhantomData<&'a camera::sensor_t>, } +macro_rules! define_set_function { + ( $set_name: ident, bool) => { + pub fn $set_name(&self, enable: bool) -> Result<(), EspError> { + esp!(unsafe { (*self.sensor).$set_name.unwrap()(self.sensor, enable as i32) }) + } + }; + ( $set_name: ident, $type: ty) => { + pub fn $set_name(&self, level: $type) -> Result<(), EspError> { + esp!(unsafe { (*self.sensor).$set_name.unwrap()(self.sensor, level) }) + } + }; +} +macro_rules! define_get_set_function { + ($name:ident, $set_name: ident, bool) => { + pub fn $name(&self) -> bool { + unsafe { (*self.sensor).status.$name != 0 } + } + define_set_function!($set_name, bool); + }; + ($name:ident, $set_name: ident, $type: ty) => { + pub fn $name(&self) -> $type { + unsafe { (*self.sensor).status.$name as $type } + } + define_set_function!($set_name, $type); + }; +} + impl<'a> CameraSensor<'a> { pub fn init_status(&self) -> Result<(), EspError> { esp!(unsafe { (*self.sensor).init_status.unwrap()(self.sensor) }) @@ -55,101 +153,34 @@ impl<'a> CameraSensor<'a> { pub fn reset(&self) -> Result<(), EspError> { esp!(unsafe { (*self.sensor).reset.unwrap()(self.sensor) }) } - pub fn set_pixformat(&self, format: camera::pixformat_t) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_pixformat.unwrap()(self.sensor, format) }) - } - pub fn set_framesize(&self, framesize: camera::framesize_t) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_framesize.unwrap()(self.sensor, framesize) }) - } - pub fn set_contrast(&self, level: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_contrast.unwrap()(self.sensor, level) }) - } - pub fn set_brightness(&self, level: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_brightness.unwrap()(self.sensor, level) }) - } - pub fn set_saturation(&self, level: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_saturation.unwrap()(self.sensor, level) }) - } - pub fn set_sharpness(&self, level: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_sharpness.unwrap()(self.sensor, level) }) - } - pub fn set_denoise(&self, level: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_denoise.unwrap()(self.sensor, level) }) - } - pub fn set_gainceiling(&self, gainceiling: camera::gainceiling_t) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_gainceiling.unwrap()(self.sensor, gainceiling) }) - } - pub fn set_quality(&self, quality: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_quality.unwrap()(self.sensor, quality) }) - } - pub fn set_colorbar(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { - (*self.sensor).set_colorbar.unwrap()(self.sensor, if enable { 1 } else { 0 }) - }) - } - pub fn set_whitebal(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { - (*self.sensor).set_whitebal.unwrap()(self.sensor, if enable { 1 } else { 0 }) - }) - } - pub fn set_gain_ctrl(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { - (*self.sensor).set_gain_ctrl.unwrap()(self.sensor, if enable { 1 } else { 0 }) - }) - } - pub fn set_exposure_ctrl(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { - (*self.sensor).set_exposure_ctrl.unwrap()(self.sensor, if enable { 1 } else { 0 }) - }) - } - pub fn set_hmirror(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { - (*self.sensor).set_hmirror.unwrap()(self.sensor, if enable { 1 } else { 0 }) - }) - } - pub fn set_vflip(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_vflip.unwrap()(self.sensor, if enable { 1 } else { 0 }) }) - } - pub fn set_aec2(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_aec2.unwrap()(self.sensor, if enable { 1 } else { 0 }) }) - } - pub fn set_awb_gain(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { - (*self.sensor).set_awb_gain.unwrap()(self.sensor, if enable { 1 } else { 0 }) - }) - } - pub fn set_agc_gain(&self, gain: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_agc_gain.unwrap()(self.sensor, gain) }) - } - pub fn set_aec_value(&self, gain: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_aec_value.unwrap()(self.sensor, gain) }) - } - pub fn set_special_effect(&self, effect: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_special_effect.unwrap()(self.sensor, effect) }) - } - pub fn set_wb_mode(&self, mode: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_wb_mode.unwrap()(self.sensor, mode) }) - } - pub fn set_ae_level(&self, level: i32) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_ae_level.unwrap()(self.sensor, level) }) - } - pub fn set_dcw(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_dcw.unwrap()(self.sensor, if enable { 1 } else { 0 }) }) - } - pub fn set_bpc(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_bpc.unwrap()(self.sensor, if enable { 1 } else { 0 }) }) - } - pub fn set_wpc(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_wpc.unwrap()(self.sensor, if enable { 1 } else { 0 }) }) - } - pub fn set_raw_gma(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { - (*self.sensor).set_raw_gma.unwrap()(self.sensor, if enable { 1 } else { 0 }) - }) - } - pub fn set_lenc(&self, enable: bool) -> Result<(), EspError> { - esp!(unsafe { (*self.sensor).set_lenc.unwrap()(self.sensor, if enable { 1 } else { 0 }) }) - } + define_get_set_function!(framesize, set_framesize, camera::framesize_t); + define_set_function!(set_pixformat, camera::pixformat_t); + define_get_set_function!(contrast, set_contrast, i32); + define_get_set_function!(brightness, set_brightness, i32); + define_get_set_function!(saturation, set_saturation, i32); + define_get_set_function!(sharpness, set_sharpness, i32); + define_get_set_function!(denoise, set_denoise, i32); + define_get_set_function!(gainceiling, set_gainceiling, u32); + define_get_set_function!(quality, set_quality, i32); + define_get_set_function!(colorbar, set_colorbar, bool); + define_set_function!(set_whitebal, bool); + define_set_function!(set_gain_ctrl, bool); + define_set_function!(set_exposure_ctrl, bool); + define_get_set_function!(hmirror, set_hmirror, bool); + define_get_set_function!(vflip, set_vflip, bool); + define_get_set_function!(aec2, set_aec2, bool); + define_get_set_function!(awb_gain, set_awb_gain, bool); + define_get_set_function!(agc_gain, set_agc_gain, bool); + define_get_set_function!(aec_value, set_aec_value, bool); + define_get_set_function!(special_effect, set_special_effect, i32); + define_get_set_function!(wb_mode, set_wb_mode, i32); + define_get_set_function!(ae_level, set_ae_level, i32); + define_get_set_function!(dcw, set_dcw, bool); + define_get_set_function!(bpc, set_bpc, bool); + define_get_set_function!(wpc, set_wpc, bool); + define_get_set_function!(raw_gma, set_raw_gma, bool); + define_get_set_function!(lenc, set_lenc, bool); + pub fn get_reg(&self, reg: i32, mask: i32) -> Result<(), EspError> { esp!(unsafe { (*self.sensor).get_reg.unwrap()(self.sensor, reg, mask) }) } @@ -223,98 +254,85 @@ pub struct Camera<'a> { _p: PhantomData<&'a ()>, } -impl<'a> Camera<'a> { - pub fn new( - pin_pwdn: Option, - pin_xclk: impl Peripheral

+ 'a, - pin_d0: impl Peripheral

+ 'a, - pin_d1: impl Peripheral

+ 'a, - pin_d2: impl Peripheral

+ 'a, - pin_d3: impl Peripheral

+ 'a, - pin_d4: impl Peripheral

+ 'a, - pin_d5: impl Peripheral

+ 'a, - pin_d6: impl Peripheral

+ 'a, - pin_d7: impl Peripheral

+ 'a, - pin_vsync: impl Peripheral

+ 'a, - pin_href: impl Peripheral

+ 'a, - pin_pclk: impl Peripheral

+ 'a, - pin_sda: impl Peripheral

+ 'a, - pin_scl: impl Peripheral

+ 'a, - pixel_format: camera::pixformat_t, - frame_size: camera::framesize_t, - fb_location: camera::camera_fb_location_t, - ) -> Result { - esp_idf_hal::into_ref!( - pin_xclk, pin_d0, pin_d1, pin_d2, pin_d3, pin_d4, pin_d5, pin_d6, pin_d7, - pin_vsync, pin_href, pin_pclk, pin_sda, pin_scl - ); - let config = camera::camera_config_t { - pin_pwdn: pin_pwdn.map(|p| p.into_ref().pin()).unwrap_or(-1), - pin_xclk: pin_xclk.pin(), - pin_reset: -1, - - pin_d0: pin_d0.pin(), - pin_d1: pin_d1.pin(), - pin_d2: pin_d2.pin(), - pin_d3: pin_d3.pin(), - pin_d4: pin_d4.pin(), - pin_d5: pin_d5.pin(), - pin_d6: pin_d6.pin(), - pin_d7: pin_d7.pin(), - pin_vsync: pin_vsync.pin(), - pin_href: pin_href.pin(), - pin_pclk: pin_pclk.pin(), - - xclk_freq_hz: 20000000, - ledc_timer: esp_idf_sys::ledc_timer_t_LEDC_TIMER_0, - ledc_channel: esp_idf_sys::ledc_channel_t_LEDC_CHANNEL_0, - - pixel_format, - frame_size, - - jpeg_quality: 12, - fb_count: 1, - grab_mode: camera::camera_grab_mode_t_CAMERA_GRAB_WHEN_EMPTY, - - fb_location, - - __bindgen_anon_1: camera::camera_config_t__bindgen_ty_1 { - pin_sccb_sda: pin_sda.pin(), - }, - __bindgen_anon_2: camera::camera_config_t__bindgen_ty_2 { - pin_sccb_scl: pin_scl.pin(), - }, - - ..Default::default() - }; - - esp_idf_sys::esp!(unsafe { camera::esp_camera_init(&config) })?; - Ok(Self { _p: PhantomData }) - } - - pub fn get_framebuffer(&self) -> Option { - let fb = unsafe { camera::esp_camera_fb_get() }; - if fb.is_null() { - //unsafe { camera::esp_camera_fb_return(fb); } - None - } else { - Some(FrameBuffer { - fb, - _p: PhantomData, - }) - } - } +pub struct CameraParams<'a> { + power: c_int, + clock: c_int, + d0: c_int, + d1: c_int, + d2: c_int, + d3: c_int, + d4: c_int, + d5: c_int, + d6: c_int, + d7: c_int, + vertical_sync: c_int, + horizontal_reference: c_int, + pixel_clock: c_int, + sda: c_int, + scl: c_int, + pixel_format: camera::pixformat_t, + frame_size: camera::framesize_t, + fb_location: camera::camera_fb_location_t, + _p: PhantomData<&'a ()>, +} - pub fn sensor(&self) -> CameraSensor<'a> { - CameraSensor { - sensor: unsafe { camera::esp_camera_sensor_get() }, +impl CameraParams<'static> { + pub fn new() -> CameraParams<'static> { + Self { + power: -1, + clock: -1, + d0: -1, + d1: -1, + d2: -1, + d3: -1, + d4: -1, + d5: -1, + d6: -1, + d7: -1, + vertical_sync: -1, + horizontal_reference: -1, + pixel_clock: -1, + sda: -1, + scl: -1, + pixel_format: camera::pixformat_t_PIXFORMAT_JPEG, + frame_size: camera::framesize_t_FRAMESIZE_UXGA, + fb_location: camera::camera_fb_location_t_CAMERA_FB_IN_PSRAM, _p: PhantomData, } } } -impl<'a> Drop for Camera<'a> { - fn drop(&mut self) { - esp!(unsafe { camera::esp_camera_deinit() }).expect("error during esp_camera_deinit") - } +macro_rules! define_set_pin_function { + ($name:ident, $direction:ty) => { + concat_idents::concat_idents!( + fn_name = set_, + $name, + _pin { + pub fn fn_name(self, p: impl Peripheral

+ 'a) -> CameraParams<'a> { + CameraParams { + $name: p.into_ref().pin(), + _p: PhantomData, + ..self + } + } + }); + }; +} + +impl<'a> CameraParams<'a> { + define_set_pin_function!(power, OutputPin); + define_set_pin_function!(clock, OutputPin); + define_set_pin_function!(d0, IOPin); + define_set_pin_function!(d1, IOPin); + define_set_pin_function!(d2, IOPin); + define_set_pin_function!(d3, IOPin); + define_set_pin_function!(d4, IOPin); + define_set_pin_function!(d5, IOPin); + define_set_pin_function!(d6, IOPin); + define_set_pin_function!(d7, IOPin); + define_set_pin_function!(vertical_sync, IOPin); + define_set_pin_function!(horizontal_reference, IOPin); + define_set_pin_function!(pixel_clock, IOPin); + define_set_pin_function!(sda, IOPin); + define_set_pin_function!(scl, OutputPin); } From f2da38f83dff544f9f95ea737f406dd0b00fb611 Mon Sep 17 00:00:00 2001 From: Mikhail Modin Date: Fri, 18 Oct 2024 20:10:30 +0100 Subject: [PATCH 4/7] Update source, add more parameters to new --- Cargo.toml | 7 +++---- README.md | 2 ++ esp32-camera | 2 +- src/lib.rs | 33 +++++++++++++++++++++++++++------ 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bd38fd1..747c5fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,11 +3,10 @@ name = "esp-camera-rs" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -esp-idf-hal = "0.43.1" -esp-idf-sys = "0.34.1" +esp-idf-hal = "0.44.1" +esp-idf-sys = "0.35" + concat-idents = "1.1.5" [patch.crates-io] diff --git a/README.md b/README.md index 85b9482..bb53efe 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,5 @@ Rust wrapper library to interface with the ESP32 and ESP32 S3 cameras. The way t for camera was reworked, get methods added and set methods rewrote to use macro. See [examples/camera-example/README.md](examples/camera-example/README.md) for usage details. + +Do not runt cargo build in this directory, run it in the example dir! diff --git a/esp32-camera b/esp32-camera index bae46be..0054ab7 160000 --- a/esp32-camera +++ b/esp32-camera @@ -1 +1 @@ -Subproject commit bae46be5eb126c46c692a29a953991117f68336b +Subproject commit 0054ab76046d2879ca9682edb2419b0613b06acd diff --git a/src/lib.rs b/src/lib.rs index 5396159..2de8265 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,8 +32,8 @@ impl<'a> Camera<'a> { pixel_format: params.pixel_format, frame_size: params.frame_size, - jpeg_quality: 12, - fb_count: 1, + jpeg_quality: params.jpeg_quality, + fb_count: params.fb_count, grab_mode: camera::camera_grab_mode_t_CAMERA_GRAB_WHEN_EMPTY, fb_location: params.fb_location, @@ -154,7 +154,7 @@ impl<'a> CameraSensor<'a> { esp!(unsafe { (*self.sensor).reset.unwrap()(self.sensor) }) } define_get_set_function!(framesize, set_framesize, camera::framesize_t); - define_set_function!(set_pixformat, camera::pixformat_t); + //define_set_function!(set_pixformat, camera::pixformat_t); // doesn't work on my board define_get_set_function!(contrast, set_contrast, i32); define_get_set_function!(brightness, set_brightness, i32); define_get_set_function!(saturation, set_saturation, i32); @@ -273,6 +273,8 @@ pub struct CameraParams<'a> { pixel_format: camera::pixformat_t, frame_size: camera::framesize_t, fb_location: camera::camera_fb_location_t, + jpeg_quality: i32, + fb_count: usize, _p: PhantomData<&'a ()>, } @@ -297,6 +299,8 @@ impl CameraParams<'static> { pixel_format: camera::pixformat_t_PIXFORMAT_JPEG, frame_size: camera::framesize_t_FRAMESIZE_UXGA, fb_location: camera::camera_fb_location_t_CAMERA_FB_IN_PSRAM, + jpeg_quality: 12, + fb_count: 1, _p: PhantomData, } } @@ -305,9 +309,7 @@ impl CameraParams<'static> { macro_rules! define_set_pin_function { ($name:ident, $direction:ty) => { concat_idents::concat_idents!( - fn_name = set_, - $name, - _pin { + fn_name = set_, $name, _pin { pub fn fn_name(self, p: impl Peripheral

+ 'a) -> CameraParams<'a> { CameraParams { $name: p.into_ref().pin(), @@ -319,6 +321,20 @@ macro_rules! define_set_pin_function { }; } +macro_rules! define_set_plain_function { + ($name:ident, $type:ty) => { + concat_idents::concat_idents!( + fn_name = set_, $name { + pub fn fn_name(self, value: $type) -> Self { + CameraParams { + $name: value, + ..self + } + } + }); + }; +} + impl<'a> CameraParams<'a> { define_set_pin_function!(power, OutputPin); define_set_pin_function!(clock, OutputPin); @@ -335,4 +351,9 @@ impl<'a> CameraParams<'a> { define_set_pin_function!(pixel_clock, IOPin); define_set_pin_function!(sda, IOPin); define_set_pin_function!(scl, OutputPin); + define_set_plain_function!(pixel_format, camera::pixformat_t); + define_set_plain_function!(frame_size, camera::framesize_t); + define_set_plain_function!(fb_location, camera::camera_fb_location_t); + define_set_plain_function!(jpeg_quality, i32); + define_set_plain_function!(fb_count, usize); } From 1dce4c74653ad19608dd53a8c79ba589696200d6 Mon Sep 17 00:00:00 2001 From: Mikhail Modin Date: Sat, 19 Oct 2024 16:47:17 +0100 Subject: [PATCH 5/7] Fix example build --- examples/camera-example/Cargo.toml | 21 +++++++-------------- examples/camera-example/src/main.rs | 6 ++++-- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/examples/camera-example/Cargo.toml b/examples/camera-example/Cargo.toml index c79f3eb..631ddb5 100644 --- a/examples/camera-example/Cargo.toml +++ b/examples/camera-example/Cargo.toml @@ -13,22 +13,15 @@ opt-level = "s" debug = true # Symbols are nice and they don't increase the size on Flash opt-level = "z" -[features] -default = ["std", "embassy", "esp-idf-svc/native"] - -pio = ["esp-idf-svc/pio"] -std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"] -alloc = ["esp-idf-svc/alloc"] -nightly = ["esp-idf-svc/nightly"] -experimental = ["esp-idf-svc/experimental"] -embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"] - [dependencies] log = { version = "0.4", default-features = false } anyhow = "1.0" -esp-idf-svc = { version = "0.48", default-features = false } -esp-idf-sys = "0.34" -embedded-svc = "0.27" +esp-idf-svc = { version = "0.49.1", default-features = false, features = [ + "binstart", + "std", +] } +esp-idf-sys = "0.35" +embedded-svc = "0.28" esp-camera-rs = { git = "https://github.com/mikhail-m1/esp-camera-rs.git" } # Uncomment next string to use local version of the lib. @@ -36,4 +29,4 @@ esp-camera-rs = { git = "https://github.com/mikhail-m1/esp-camera-rs.git" } #esp-camera-rs = { path = "../../" } [build-dependencies] -embuild = "0.31.3" +embuild = "0.32" diff --git a/examples/camera-example/src/main.rs b/examples/camera-example/src/main.rs index 5ca2b15..5240c84 100644 --- a/examples/camera-example/src/main.rs +++ b/examples/camera-example/src/main.rs @@ -5,7 +5,7 @@ use esp_idf_svc::eventloop::EspSystemEventLoop; use esp_idf_svc::hal::{gpio::PinDriver, peripherals::Peripherals}; use esp_idf_svc::http::server::{Configuration as HttpServerConfig, EspHttpServer}; use esp_idf_svc::nvs::EspDefaultNvsPartition; -use esp_idf_svc::wifi::{BlockingWifi, EspWifi}; +use esp_idf_svc::wifi::{BlockingWifi, EspWifi, PmfConfiguration, ScanMethod}; use log::{error, info}; use std::time::Duration; @@ -30,6 +30,8 @@ fn main() -> anyhow::Result<()> { auth_method: AuthMethod::None, password: env!("WIFI_PASS").try_into().unwrap(), channel: None, + pmf_cfg: PmfConfiguration::Capable { required: true}, + scan_method: ScanMethod::FastScan, }))?; wifi.start()?; @@ -70,7 +72,7 @@ fn main() -> anyhow::Result<()> { let mut httpserver = EspHttpServer::new(&HttpServerConfig::default())?; info!("preocessing http requests"); - httpserver.fn_handler("/", Method::Get, |request| { + httpserver.fn_handler("/", Method::Get, move |request| { info!("taking a picture"); let (ref mut led, camera) = &mut *state.lock().unwrap(); From f1b342b03b14588854e894429277d9c12f855c6a Mon Sep 17 00:00:00 2001 From: Mikhail Modin Date: Mon, 4 Nov 2024 20:38:40 +0000 Subject: [PATCH 6/7] One more parameter, fix example --- examples/camera-example/Cargo.toml | 2 +- examples/camera-example/src/main.rs | 37 ++++++++++++++--------------- src/lib.rs | 14 +++++++---- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/examples/camera-example/Cargo.toml b/examples/camera-example/Cargo.toml index 631ddb5..a50eb55 100644 --- a/examples/camera-example/Cargo.toml +++ b/examples/camera-example/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "camera-example" version = "0.1.0" -authors = ["Mathias Pius "] +authors = ["Mikhail Modin "] edition = "2021" resolver = "2" rust-version = "1.71" diff --git a/examples/camera-example/src/main.rs b/examples/camera-example/src/main.rs index 5240c84..c582da1 100644 --- a/examples/camera-example/src/main.rs +++ b/examples/camera-example/src/main.rs @@ -14,7 +14,7 @@ fn main() -> anyhow::Result<()> { esp_idf_svc::log::EspLogger::initialize_default(); info!("initializing peripherals"); - let mut peripherals = Peripherals::take().unwrap(); + let peripherals = Peripherals::take().unwrap(); let sysloop = EspSystemEventLoop::take()?; let nvs = EspDefaultNvsPartition::take()?; @@ -30,7 +30,7 @@ fn main() -> anyhow::Result<()> { auth_method: AuthMethod::None, password: env!("WIFI_PASS").try_into().unwrap(), channel: None, - pmf_cfg: PmfConfiguration::Capable { required: true}, + pmf_cfg: PmfConfiguration::Capable { required: true }, scan_method: ScanMethod::FastScan, }))?; @@ -48,30 +48,29 @@ fn main() -> anyhow::Result<()> { info!("Initialize the camera"); let camera_params = esp_camera_rs::CameraParams::new() - .set_clock_pin(&mut peripherals.pins.gpio15) - .set_d0_pin(&mut peripherals.pins.gpio11) - .set_d1_pin(&mut peripherals.pins.gpio9) - .set_d2_pin(&mut peripherals.pins.gpio8) - .set_d3_pin(&mut peripherals.pins.gpio10) - .set_d4_pin(&mut peripherals.pins.gpio12) - .set_d5_pin(&mut peripherals.pins.gpio18) - .set_d6_pin(&mut peripherals.pins.gpio17) - .set_d7_pin(&mut peripherals.pins.gpio16) - .set_vertical_sync_pin(&mut peripherals.pins.gpio6) - .set_horizontal_reference_pin(&mut peripherals.pins.gpio7) - .set_pixel_clock_pin(&mut peripherals.pins.gpio13) - .set_sda_pin(&mut peripherals.pins.gpio4) - .set_scl_pin(&mut peripherals.pins.gpio5); + .set_clock_pin(peripherals.pins.gpio15) + .set_d0_pin(peripherals.pins.gpio11) + .set_d1_pin(peripherals.pins.gpio9) + .set_d2_pin(peripherals.pins.gpio8) + .set_d3_pin(peripherals.pins.gpio10) + .set_d4_pin(peripherals.pins.gpio12) + .set_d5_pin(peripherals.pins.gpio18) + .set_d6_pin(peripherals.pins.gpio17) + .set_d7_pin(peripherals.pins.gpio16) + .set_vertical_sync_pin(peripherals.pins.gpio6) + .set_horizontal_reference_pin(peripherals.pins.gpio7) + .set_pixel_clock_pin(peripherals.pins.gpio13) + .set_sda_pin(peripherals.pins.gpio4) + .set_scl_pin(peripherals.pins.gpio5); let camera = esp_camera_rs::Camera::new(&camera_params)?; info!("initializing http servert"); - + //It's better to use camera from main loop, but for simplicity it is passed it to handler let state = std::sync::Arc::new(std::sync::Mutex::new((led, camera))); - let mut httpserver = EspHttpServer::new(&HttpServerConfig::default())?; - info!("preocessing http requests"); + info!("preocessing http requests"); httpserver.fn_handler("/", Method::Get, move |request| { info!("taking a picture"); let (ref mut led, camera) = &mut *state.lock().unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 2de8265..da939fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -// code updated from https://github.com/Kezii/esp32cam_rs/blob/master/src/espcam.rs - use std::ffi::c_int; use std::marker::PhantomData; @@ -8,7 +6,7 @@ use esp_idf_hal::peripheral::Peripheral; use esp_idf_sys::*; impl<'a> Camera<'a> { - pub fn new(params: &CameraParams) -> Result { + pub fn new(params: &CameraParams<'a>) -> Result { let config = camera::camera_config_t { pin_pwdn: params.power, pin_xclk: params.clock, @@ -25,7 +23,8 @@ impl<'a> Camera<'a> { pin_href: params.horizontal_reference, pin_pclk: params.pixel_clock, - xclk_freq_hz: 20_000_000, + xclk_freq_hz: params.xclk_freq_hz, + ledc_timer: esp_idf_sys::ledc_timer_t_LEDC_TIMER_0, ledc_channel: esp_idf_sys::ledc_channel_t_LEDC_CHANNEL_0, @@ -87,6 +86,10 @@ impl<'a> FrameBuffer<'a> { unsafe { std::slice::from_raw_parts((*self.fb).buf, (*self.fb).len) } } + pub fn data_mut(&mut self) -> &'a mut [u8] { + unsafe { std::slice::from_raw_parts_mut((*self.fb).buf, (*self.fb).len) } + } + pub fn width(&self) -> usize { unsafe { (*self.fb).width } } @@ -268,6 +271,7 @@ pub struct CameraParams<'a> { vertical_sync: c_int, horizontal_reference: c_int, pixel_clock: c_int, + xclk_freq_hz: c_int, sda: c_int, scl: c_int, pixel_format: camera::pixformat_t, @@ -294,6 +298,7 @@ impl CameraParams<'static> { vertical_sync: -1, horizontal_reference: -1, pixel_clock: -1, + xclk_freq_hz: 16_000_000, // It's a magic value on ESP32-S2 or ESP32-S3 to enable EDMA mode sda: -1, scl: -1, pixel_format: camera::pixformat_t_PIXFORMAT_JPEG, @@ -356,4 +361,5 @@ impl<'a> CameraParams<'a> { define_set_plain_function!(fb_location, camera::camera_fb_location_t); define_set_plain_function!(jpeg_quality, i32); define_set_plain_function!(fb_count, usize); + define_set_plain_function!(xclk_freq_hz, i32); } From 204a2ea31c8122400e71161eb52a6eedef7743db Mon Sep 17 00:00:00 2001 From: Mikhail Modin Date: Mon, 4 Nov 2024 20:40:02 +0000 Subject: [PATCH 7/7] add Cargo.lock for example --- examples/camera-example/.gitignore | 1 - examples/camera-example/Cargo.lock | 1537 ++++++++++++++++++++++++++++ 2 files changed, 1537 insertions(+), 1 deletion(-) create mode 100644 examples/camera-example/Cargo.lock diff --git a/examples/camera-example/.gitignore b/examples/camera-example/.gitignore index 7c18138..4514c9a 100644 --- a/examples/camera-example/.gitignore +++ b/examples/camera-example/.gitignore @@ -1,4 +1,3 @@ .embuild/ target/ components_esp32.lock -Cargo.lock \ No newline at end of file diff --git a/examples/camera-example/Cargo.lock b/examples/camera-example/Cargo.lock new file mode 100644 index 0000000..7a6ffcd --- /dev/null +++ b/examples/camera-example/Cargo.lock @@ -0,0 +1,1537 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377e4c0ba83e4431b10df45c1d4666f178ea9c552cac93e60c3a88bf32785923" +dependencies = [ + "as-slice", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.79", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bstr" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "build-time" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1219c19fc29b7bfd74b7968b420aff5bc951cf517800176e795d6b2300dd382" +dependencies = [ + "chrono", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "camera-example" +version = "0.1.0" +dependencies = [ + "anyhow", + "embedded-svc", + "embuild", + "esp-camera-rs", + "esp-idf-svc", + "esp-idf-sys", + "log", +] + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +dependencies = [ + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-targets", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cmake" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +dependencies = [ + "cc", +] + +[[package]] +name = "concat-idents" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" +dependencies = [ + "quote", + "syn 2.0.79", +] + +[[package]] +name = "const_format" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "cvt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ae9bf77fbf2d39ef573205d554d87e86c12f1994e9ea335b0651b9b278bcf1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "embassy-futures" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" + +[[package]] +name = "embassy-sync" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3e0c49ff02ebe324faf3a8653ba91582e2d0a7fdef5bc88f449d5aa1bfcc05c" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async", + "futures-util", + "heapless", +] + +[[package]] +name = "embedded-can" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d2e857f87ac832df68fa498d18ddc679175cf3d2e4aa893988e5601baf9438" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "embedded-io", +] + +[[package]] +name = "embedded-svc" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b85590a7a120e370bed5b6bc2b399b345c60d4c749d3bc06039472da37b9893" +dependencies = [ + "defmt", + "embedded-io", + "embedded-io-async", + "enumset", + "heapless", + "log", + "num_enum", + "serde", + "strum 0.25.0", + "strum_macros 0.25.3", +] + +[[package]] +name = "embuild" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6e3e470e31fd4cae065d37f7cad56d42861ba1f9a35aa277694dee3d6b357c4" +dependencies = [ + "anyhow", + "bindgen", + "bitflags 1.3.2", + "cmake", + "filetime", + "globwalk", + "home", + "log", + "regex", + "remove_dir_all", + "serde", + "serde_json", + "shlex", + "strum 0.24.1", + "tempfile", + "thiserror", + "which", +] + +[[package]] +name = "enumset" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" +dependencies = [ + "enumset_derive", + "serde", +] + +[[package]] +name = "enumset_derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "envy" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" +dependencies = [ + "serde", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "esp-camera-rs" +version = "0.1.0" +dependencies = [ + "concat-idents", + "esp-idf-hal", + "esp-idf-sys", +] + +[[package]] +name = "esp-idf-hal" +version = "0.44.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa893ab84c4a7db5ca42ab45e2e09942412976fe3100a9dd72e56ba0a9a58b4" +dependencies = [ + "atomic-waker", + "embassy-sync", + "embedded-can", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io", + "embedded-io-async", + "embuild", + "enumset", + "esp-idf-sys", + "heapless", + "log", + "nb 1.1.0", + "num_enum", +] + +[[package]] +name = "esp-idf-svc" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac42f9303792348e3217c570b0f0d8280a381d053bcb730c3018ec6873928513" +dependencies = [ + "embassy-futures", + "embedded-hal-async", + "embedded-svc", + "embuild", + "enumset", + "esp-idf-hal", + "heapless", + "log", + "num_enum", + "uncased", +] + +[[package]] +name = "esp-idf-sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb97e3800686a4d64f3c0a9998be3d6f16c903bca2a425746e97f00ed28cde5e" +dependencies = [ + "anyhow", + "bindgen", + "build-time", + "cargo_metadata", + "const_format", + "embuild", + "envy", + "libc", + "regex", + "serde", + "strum 0.24.1", + "which", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fs_at" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14af6c9694ea25db25baa2a1788703b9e7c6648dcaeeebeb98f7561b5384c036" +dependencies = [ + "aligned", + "cfg-if", + "cvt", + "libc", + "nix", + "windows-sys 0.52.0", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "globset" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags 1.3.2", + "ignore", + "walkdir", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "ignore" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "normpath" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "prettyplease" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +dependencies = [ + "proc-macro2", + "syn 2.0.79", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "regex" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "remove_dir_all" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a694f9e0eb3104451127f6cc1e5de55f59d3b1fc8c5ddfaeb6f1e716479ceb4a" +dependencies = [ + "cfg-if", + "cvt", + "fs_at", + "libc", + "normpath", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "serde_json" +version = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67d42a0bd4ac281beff598909bb56a86acaf979b84483e1c79c10dcaf98f8cf3" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros 0.24.3", +] + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros 0.25.3", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.79", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "uncased" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +]