diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml new file mode 100644 index 0000000..dd8219a --- /dev/null +++ b/.github/workflows/build-and-release.yml @@ -0,0 +1,119 @@ +name: Build nad Release the OpenIris bin files + +on: + workflow_dispatch: + push: + tags: + - "*.*.*" + branches: + - "main" + - "beta" + pull_request: + types: + - opened + - reopened + - synchronize + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +permissions: + contents: write + deployments: write + +jobs: + setup: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - id: set-matrix + run: echo "matrix={\"firmware_config\":[{\"board_name\":\"esp32AIThinker\", \"target\":\"esp32\"}, {\"board_name\":\"esp32M5Stack\", \"target\":\"esp32\"}, {\"board_name\":\"esp32cam\", \"target\":\"esp32\"}, {\"board_name\":\"esp_eye\", \"target\":\"esp32s3\"}, {\"board_name\":\"facefocusvr_eye_L\", \"target\":\"esp32s3\"}, {\"board_name\":\"facefocusvr_eye_R\", \"target\":\"esp32s3\"}, {\"board_name\":\"facefocusvr_face\", \"target\":\"esp32s3\"}, {\"board_name\":\"project_babble\", \"target\":\"esp32s3\"}, {\"board_name\":\"seed_studio_xiao_esp32s3\", \"target\":\"esp32s3\"}, {\"board_name\":\"wrooms3\", \"target\":\"esp32s3\"}, {\"board_name\":\"wrooms3QIO\", \"target\":\"esp32s3\"}, {\"board_name\":\"wrover\", \"target\":\"esp32s3\"}]}" >> $GITHUB_OUTPUT + + build: + needs: setup + permissions: + contents: write + strategy: + fail-fast: false + matrix: ${{fromJson(needs.setup.outputs.matrix)}} + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v5 + with: + submodules: "recursive" + + - name: Setup UV + uses: astral-sh/setup-uv@v6 + + - name: Set up Python + run: uv python install + + - name: Setup SDKConfig + run: uv run ./tools/switchBoardType.py --board ${{ matrix.firmware_config.board_name }} --diff + + - name: Show SDKConfig + run: cat ./sdkconfig + + - name: Build + uses: espressif/esp-idf-ci-action@v1 + with: + esp_idf_version: v5.4.2 + target: ${{ matrix.firmware_config.target }} + path: ./ + + - name: Merge bins + uses: espressif/esp-idf-ci-action@v1 + with: + esp_idf_version: v5.4.2 + target: ${{ matrix.firmware_config.target }} + path: ./ + command: idf.py merge-bin -f raw + + - name: Zip the resulting bin + run: zip -r ${{matrix.firmware_config.board_name}}.zip build/merged-binary.bin + + - name: Archive Firmware binaries + uses: actions/upload-artifact@v4 + with: + name: ${{matrix.firmware_config.board_name}}-firmware + path: ./${{matrix.firmware_config.board_name}}.zip + retention-days: 5 + if-no-files-found: error + + release: + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout repo + uses: actions/checkout@v5 + + - name: Prepare directory + run: mkdir -p build + + - name: Download firmware builds + uses: actions/download-artifact@v4 + with: + path: build/ + + - name: Make Release + uses: softprops/action-gh-release@v2 + if: github.ref_type == 'tag' + with: + files: build/*.zip + prerelease: ${{contains(github.ref_type, 'rc')}} + + cleanup: + needs: [setup, release] + strategy: + fail-fast: false + matrix: ${{fromJson(needs.setup.outputs.matrix)}} + name: Cleanup actions + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: "♻️ remove build artifacts" + uses: geekyeggo/delete-artifact@v5 + with: + name: ${{matrix.firmware_config.board_name}}-firmware diff --git a/.gitignore b/.gitignore index 21f60c1..856858c 100644 --- a/.gitignore +++ b/.gitignore @@ -90,11 +90,12 @@ sdkconfig # Local History for Visual Studio Code .history/ - +tests/.env # Built Visual Studio Code Extensions *.vsix ### VisualStudioCode Patch ### # Ignore all local history of files .history -.ionide \ No newline at end of file +.ionide +*\__pycache__ \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a1066c..ace098a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,3 @@ -# The following five lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) set(EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_LIST_DIR}/components) diff --git a/README.md b/README.md index 28a8e4f..c51ac2f 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,12 @@ Firmware and tools for OpenIris — Wi‑Fi, UVC streaming, and a Python setup C - Python tools for setup over USB serial: - `tools/switchBoardType.py` — choose a board profile (builds the right sdkconfig) - `tools/setup_openiris.py` — interactive CLI for Wi‑Fi, MDNS/Name, Mode, LED PWM, Logs, and a Settings Summary - - Composite USB (UVC + CDC) when UVC mode is enabled (`GENERAL_INCLUDE_UVC_MODE`) for simultaneous video streaming and command channel - - LED current monitoring (if enabled via `MONITORING_LED_CURRENT`) with filtered mA readings - - Configurable debug LED + external IR LED control with optional error mirroring (`LED_DEBUG_ENABLE`, `LED_EXTERNAL_AS_DEBUG`) - - Auto‑discovered per‑board configuration overlays under `boards/` - - Command framework (JSON over serial / CDC / REST) for mode switching, Wi‑Fi config, OTA credentials, LED brightness, info & monitoring - - Single source advertised name (`CONFIG_GENERAL_ADVERTISED_NAME`) used for both UVC device name and mDNS hostname (unless overridden at runtime) +- Composite USB (UVC + CDC) when UVC mode is enabled (`GENERAL_INCLUDE_UVC_MODE`) for simultaneous video streaming and command channel +- LED current monitoring (if enabled via `MONITORING_LED_CURRENT`) with filtered mA readings +- Configurable debug LED + external IR LED control with optional error mirroring (`LED_DEBUG_ENABLE`, `LED_EXTERNAL_AS_DEBUG`) +- Auto‑discovered per‑board configuration overlays under `boards/` +- Command framework (JSON over serial / CDC / REST) for mode switching, Wi‑Fi config, OTA credentials, LED brightness, info & monitoring +- Single source advertised name (`CONFIG_GENERAL_ADVERTISED_NAME`) used for both UVC device name and mDNS hostname (unless overridden at runtime) --- @@ -63,23 +63,32 @@ After this, you’re ready for the Quick start below. ## Quick start +### 1) Grab UV. + +We're using UV to manage our tools, grab and install it from [here](https://docs.astral.sh/uv/getting-started/installation/). + +Once installed, you'll be able to just run the commands below and UV will take care of setting up everything. + ### 1) Pick your board (loads the default configuration) + Boards are auto‑discovered from the `boards/` directory. First list them, then pick one: Windows (cmd): ```cmd -python .\tools\switchBoardType.py --list -python .\tools\switchBoardType.py --board seed_studio_xiao_esp32s3 --diff +uv run .\tools\switchBoardType.py --list +uv run .\tools\switchBoardType.py --board seed_studio_xiao_esp32s3 --diff ``` macOS/Linux (bash): ```bash -python3 ./tools/switchBoardType.py --list -python3 ./tools/switchBoardType.py --board seed_studio_xiao_esp32s3 --diff +uv run ./tools/switchBoardType.py --list +uv run ./tools/switchBoardType.py --board seed_studio_xiao_esp32s3 --diff ``` + Notes: + - Use `--list` to see all detected board keys. - Board key = relative path under `boards/` with `/` replaced by `_` (and duplicate tail segments collapsed, e.g. `project_babble/project_babble` -> `project_babble`). - `--diff` shows what will change vs the current `sdkconfig`. @@ -89,8 +98,8 @@ Notes: - Set the target (e.g., ESP32‑S3). - Build, flash, and open the serial monitor. - - (Optional) For UVC mode ensure `GENERAL_INCLUDE_UVC_MODE=y`. If you want device to boot directly into UVC: also set `START_IN_UVC_MODE=y`. - - Disable Wi‑Fi services for pure wired builds: `GENERAL_ENABLE_WIRELESS=n`. +- (Optional) For UVC mode ensure `GENERAL_INCLUDE_UVC_MODE=y`. If you want device to boot directly into UVC: also set `START_IN_UVC_MODE=y`. +- Disable Wi‑Fi services for pure wired builds: `GENERAL_ENABLE_WIRELESS=n`. ### 3) Use the Python setup CLI (recommended) @@ -99,19 +108,18 @@ Configure the device over USB serial. Before you run it: - If you still have the serial monitor open, close it (the port must be free). -- In VS Code, open the sidebar “ESP‑IDF: Explorer” and click “Open ESP‑IDF Terminal”. We’ll run the CLI there so Python and packages are in the right environment. Then run: ```cmd -python .\tools\setup_openiris.py --port COMxx +uv run .\tools\setup_openiris.py --port COMxx ``` Examples: -- Windows: `python .\tools\setup_openiris.py --port COM69`, … -- macOS: idk -- Linux: idk +- Windows: `uv run .\tools\setup_openiris.py --port COM69`, … +- macOS: `uv run .\tools\setup_openiris.py --port \dev\tty` +- Linux: `uv run .\tools\setup_openiris.py --port \dev\tty` What the CLI can do: @@ -131,7 +139,9 @@ What the CLI can do: - The UVC device name is based on the MDNS hostname. ## Advertised Name (UVC + mDNS) + `CONFIG_GENERAL_ADVERTISED_NAME` (Kconfig) defines the base name announced over: + - USB UVC descriptor (appears in OS camera list) - mDNS hostname / service name @@ -144,10 +154,10 @@ Runtime override: If the setup CLI (or a JSON command) provides a new device nam - Fast Wi‑Fi setup: in the CLI, go to “Wi‑Fi settings” → “Automatic setup”, then check “status”. - Change name/MDNS: set the device name in the CLI, then replug USB — UVC will show the new name. - Adjust brightness/LED: set LED PWM in the CLI. - - Switch to UVC mode over commands (CDC/serial): - `{"commands":[{"command":"switch_mode","data":{"mode":"uvc"}}]}` then reboot. - - Read filtered LED current (if enabled): - `{"commands":[{"command":"get_led_current"}]}` +- Switch to UVC mode over commands (CDC/serial): + `{"commands":[{"command":"switch_mode","data":{"mode":"uvc"}}]}` then reboot. +- Read filtered LED current (if enabled): + `{"commands":[{"command":"get_led_current"}]}` --- @@ -156,19 +166,62 @@ Runtime override: If the setup CLI (or a JSON command) provides a new device nam - `main/` — entry point - `components/` — modules (Camera, WiFi, UVC, CommandManager, …) - `tools/` — Python helper tools (board switch, setup CLI, scanner) - -If you want to dig deeper: commands are mapped via the `CommandManager` under `components/CommandManager/...`. +- `tests/` - Hardware in the loop tests, with support for different boards and automatic skips if a board can't perform a given test + If you want to dig deeper: commands are mapped via the `CommandManager` under `components/CommandManager/...`. --- +## Running Hardware In The Loop Tests + +In order to run the tests, you'll need to setup a couple of things: + +- copy the `.env.example` file in `/tests/` and rename it to `.env`. Then, open it and fill out the network details - SSID and Password. +- plug in your board to your pc and wait for it to boot. +- open the terminal (`ctrl/cmd + j` in VSC) and head over to `/tests/` directory. + +Once there, you can invoke the tests with `UV` like so: + +```cmd +uv run pytest --board= --connection=COM +``` + +This will auto select every test we have, connect to your board automatically and have pytest skip tests that don't fit your board. +For example, tests involving switching modes to UVC and testing commands over there are disabled for esp32 based boards as only esp32s3 can do it. Same goes for WiFi for FaceFocus Boards. + +If you see any fails, you can try rerunning them one by one with: + +```cmd +uv run pytest --board= --connection=COM -k name_of_the_test +``` + +Or rerun every single failed test like so: + +```cmd +uv run pytest --board= --connection=COM --lf +``` + +Sometimes tests will fail due to timeouts, this is normal. + +You should see the tests starting to go off, with any luck - all of them passing, your board should also start reacting to the changes - reboots, blinking lights etc are **expected** as we're performing hardware in the loop tests. + +### Warning: + + After the testing session ends **WE WILL RESET THE BOARD**, any changes you've made yourself to it will be lost. This is done to ensure that the test we perform are unaffected by any changes done by said tests. + If we skipped that, tests involving adding fake networks would break some that rely on the board connecting to real ones in a timely manner, for example. + + There is currently no way to skip that behavior. + ## Troubleshooting ### USB Composite (UVC + CDC) + When UVC support is compiled in, the device enumerates as a composite USB device: + - UVC interface: video streaming (JPEG frames) - CDC (virtual COM): command channel accepting newline‑terminated JSON objects Example newline‑terminated JSON commands over CDC (one per line): + ``` {"commands":[{"command":"ping"}]} {"commands":[{"command":"get_who_am_i"}]} @@ -176,59 +229,68 @@ Example newline‑terminated JSON commands over CDC (one per line): ``` Chained commands in a single request (processed in order): + ``` {"commands":[ {"command":"set_mdns","data":{"hostname":"tracker"}}, {"command":"set_wifi","data":{"name":"main","ssid":"your_network","password":"password","channel":0,"power":0}} ]} ``` + Responses are JSON blobs flushed immediately. --- ### Monitoring (LED Current) + Enabled with `MONITORING_LED_CURRENT=y` plus shunt/gain settings. The task samples every `CONFIG_MONITORING_LED_INTERVAL_MS` ms and maintains a filtered moving average over `CONFIG_MONITORING_LED_SAMPLES` samples. Use `get_led_current` command to query. ### Debug & External LED Configuration -| Kconfig | Effect | -|---------|--------| -| LED_DEBUG_ENABLE | Enables/disables discrete status LED GPIO init & drive | -| LED_EXTERNAL_CONTROL | Enables PWM control for IR / external LED | -| LED_EXTERNAL_PWM_DUTY_CYCLE | Default duty % applied at boot (0–100) | -| LED_EXTERNAL_AS_DEBUG | Mirrors only error patterns onto external LED (0%/50%) when debug LED absent or also for redundancy | + +| Kconfig | Effect | +| --------------------------- | --------------------------------------------------------------------------------------------------- | +| LED_DEBUG_ENABLE | Enables/disables discrete status LED GPIO init & drive | +| LED_EXTERNAL_CONTROL | Enables PWM control for IR / external LED | +| LED_EXTERNAL_PWM_DUTY_CYCLE | Default duty % applied at boot (0–100) | +| LED_EXTERNAL_AS_DEBUG | Mirrors only error patterns onto external LED (0%/50%) when debug LED absent or also for redundancy | ### Board Profiles + Each file under `boards/` overlays `sdkconfig.base_defaults`. The merge order: base → board file → (optional) dynamic Wi‑Fi overrides via `switchBoardType.py` flags. Duplicate trailing segment directories collapse to unique keys. - UVC doesn’t appear on the host? - Switch mode to UVC via CLI tool, replug USB and wait 20s. ### Adding a new board configuration + 1. Create a new config file under `boards/` (you can nest folders): for example `boards/my_family/my_variant`. 2. Populate it with only the `CONFIG_...` lines that differ from the shared defaults. Shared baseline lives in `boards/sdkconfig.base_defaults` and is always merged first. 3. The board key the script accepts will be the relative path with `/` turned into `_` (example: `boards/my_family/my_variant` -> `my_family_my_variant`). -4. Run `python tools/switchBoardType.py --list` to verify it’s detected, then switch using `-b my_family_my_variant`. +4. Run `uv run tools/switchBoardType.py --list` to verify it’s detected, then switch using `-b my_family_my_variant`. 5. If you accidentally create two files that collapse to the same key the last one found wins—rename to keep keys unique. Tips: + - Use `--diff` after adding a board to sanity‑check only the intended keys change. - For Wi‑Fi overrides on first flash: add none—pass `--ssid` / `--password` when switching if needed. --- ## Troubleshooting + ### LED Status / Error Patterns + The firmware uses a small set of LED patterns to indicate status and blocking errors. When `LED_DEBUG_ENABLE` is disabled and `LED_EXTERNAL_AS_DEBUG` is enabled the external IR LED mirrors ONLY error patterns (0%/50% duty). Non‑error patterns are not mirrored. -| State | Visual | Category | Timing Pattern (ms) | Meaning | -|-------|--------|----------|---------------------|---------| -| LedStateNone | ![idle](docs/led_patterns/idle.svg) | idle | (off) | No activity / heartbeat window waiting | -| LedStateStreaming | ![stream](docs/led_patterns/streaming.svg) | active | steady on | Streaming running (UVC or Wi‑Fi) | -| LedStateStoppedStreaming | ![stopped](docs/led_patterns/stopped.svg) | inactive | steady off | Streaming intentionally stopped | -| CameraError | ![camera error](docs/led_patterns/camera_error.svg) | error | 300/300 300/700 (loop) | Camera init/runtime failure (check sensor, ribbon, power) | -| WiFiStateConnecting | ![wifi connecting](docs/led_patterns/wifi_connecting.svg) | transitional | 400/400 (loop) | Wi‑Fi associating / DHCP pending | -| WiFiStateConnected | ![wifi connected](docs/led_patterns/wifi_connected.svg) | notification | 150/150×3 then 600 off | Wi‑Fi connected successfully | -| WiFiStateError | ![wifi error](docs/led_patterns/wifi_error.svg) | error | 200/100 500/300 (loop) | Wi‑Fi failed (auth timeout or no AP) | +| State | Visual | Category | Timing Pattern (ms) | Meaning | +| ------------------------ | --------------------------------------------------------- | ------------ | ---------------------- | --------------------------------------------------------- | +| LedStateNone | ![idle](docs/led_patterns/idle.svg) | idle | (off) | No activity / heartbeat window waiting | +| LedStateStreaming | ![stream](docs/led_patterns/streaming.svg) | active | steady on | Streaming running (UVC or Wi‑Fi) | +| LedStateStoppedStreaming | ![stopped](docs/led_patterns/stopped.svg) | inactive | steady off | Streaming intentionally stopped | +| CameraError | ![camera error](docs/led_patterns/camera_error.svg) | error | 300/300 300/700 (loop) | Camera init/runtime failure (check sensor, ribbon, power) | +| WiFiStateConnecting | ![wifi connecting](docs/led_patterns/wifi_connecting.svg) | transitional | 400/400 (loop) | Wi‑Fi associating / DHCP pending | +| WiFiStateConnected | ![wifi connected](docs/led_patterns/wifi_connected.svg) | notification | 150/150×3 then 600 off | Wi‑Fi connected successfully | +| WiFiStateError | ![wifi error](docs/led_patterns/wifi_error.svg) | error | 200/100 500/300 (loop) | Wi‑Fi failed (auth timeout or no AP) | --- diff --git a/boards/esp32AIThinker/esp32AIThinker b/boards/esp32AIThinker/esp32AIThinker new file mode 100644 index 0000000..b0b5dc3 --- /dev/null +++ b/boards/esp32AIThinker/esp32AIThinker @@ -0,0 +1,63 @@ +CONFIG_IDF_TARGET="esp32" +# CONFIG_IDF_TARGET_ESP32S3 is not set +# CONFIG_WIRED_MODE is not set +CONFIG_LED_DEBUG_GPIO=33 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240 is not set +# CONFIG_ESP32S3_SPIRAM_SUPPORT is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +# Camera sensor pinout configuration +CONFIG_CAMERA_MODULE_NAME="ESP32AITHINKER" +CONFIG_PWDN_GPIO_NUM=32 +CONFIG_RESET_GPIO_NUM=-1 +CONFIG_XCLK_GPIO_NUM=0 +CONFIG_SIOD_GPIO_NUM=26 +CONFIG_SIOC_GPIO_NUM=27 +CONFIG_Y9_GPIO_NUM=35 +CONFIG_Y8_GPIO_NUM=34 +CONFIG_Y7_GPIO_NUM=39 +CONFIG_Y6_GPIO_NUM=36 +CONFIG_Y5_GPIO_NUM=21 +CONFIG_Y4_GPIO_NUM=19 +CONFIG_Y3_GPIO_NUM=18 +CONFIG_Y2_GPIO_NUM=5 +CONFIG_VSYNC_GPIO_NUM=25 +CONFIG_HREF_GPIO_NUM=23 +CONFIG_PCLK_GPIO_NUM=22 +# end of Camera sensor pinout configuration +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +CONFIG_SPIRAM_MODE_QUAD=y +# CONFIG_SPIRAM_MODE_OCT is not set +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_SPEED_120M is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set + +# +# OpenIris: Serial Communication Settings +# +CONFIG_UART_PORT_NUMBER=0 +CONFIG_UART_RX_PIN=3 +CONFIG_UART_TX_PIN=1 + +# end of OpenIris: Serial Communication Settings + +# CONFIG_MONITORING_LED_CURRENT is not set \ No newline at end of file diff --git a/boards/esp32Cam/esp32Cam b/boards/esp32Cam/esp32Cam new file mode 100644 index 0000000..3ff820e --- /dev/null +++ b/boards/esp32Cam/esp32Cam @@ -0,0 +1,62 @@ +CONFIG_IDF_TARGET="esp32" +# CONFIG_IDF_TARGET_ESP32S3 is not set +# CONFIG_WIRED_MODE is not set +CONFIG_LED_DEBUG_GPIO=33 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240 is not set +# CONFIG_ESP32S3_SPIRAM_SUPPORT is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +# Camera sensor pinout configuration +CONFIG_CAMERA_MODULE_NAME="ESP32CAM" +CONFIG_PWDN_GPIO_NUM=32 +CONFIG_RESET_GPIO_NUM=33 +CONFIG_XCLK_GPIO_NUM=4 +CONFIG_SIOD_GPIO_NUM=18 +CONFIG_SIOC_GPIO_NUM=23 +CONFIG_Y9_GPIO_NUM=36 +CONFIG_Y8_GPIO_NUM=19 +CONFIG_Y7_GPIO_NUM=21 +CONFIG_Y6_GPIO_NUM=39 +CONFIG_Y5_GPIO_NUM=35 +CONFIG_Y4_GPIO_NUM=14 +CONFIG_Y3_GPIO_NUM=13 +CONFIG_Y2_GPIO_NUM=34 +CONFIG_VSYNC_GPIO_NUM=5 +CONFIG_HREF_GPIO_NUM=27 +CONFIG_PCLK_GPIO_NUM=25 +# end of Camera sensor pinout configuration +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +CONFIG_SPIRAM_MODE_QUAD=y +# CONFIG_SPIRAM_MODE_OCT is not set +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_SPEED_120M is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set + +# +# OpenIris: Serial Communication Settings +# +CONFIG_UART_PORT_NUMBER=0 +CONFIG_UART_RX_PIN=3 +CONFIG_UART_TX_PIN=1 + +# end of OpenIris: Serial Communication Settings +# CONFIG_MONITORING_LED_CURRENT is not set \ No newline at end of file diff --git a/boards/esp32M5Stack/esp32M5Stack b/boards/esp32M5Stack/esp32M5Stack new file mode 100644 index 0000000..184094f --- /dev/null +++ b/boards/esp32M5Stack/esp32M5Stack @@ -0,0 +1,64 @@ +# TODO test out on real hardware +CONFIG_IDF_TARGET="esp32" +# CONFIG_IDF_TARGET_ESP32S3 is not set +# CONFIG_WIRED_MODE is not set +CONFIG_LED_DEBUG_GPIO=33 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240 is not set +# CONFIG_ESP32S3_SPIRAM_SUPPORT is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +# Camera sensor pinout configuration +CONFIG_CAMERA_MODULE_NAME="ESP32M5STACK" +CONFIG_PWDN_GPIO_NUM=-1 +CONFIG_RESET_GPIO_NUM=15 +CONFIG_XCLK_GPIO_NUM=27 +CONFIG_SIOD_GPIO_NUM=25 +CONFIG_SIOC_GPIO_NUM=23 +CONFIG_Y9_GPIO_NUM=19 +CONFIG_Y8_GPIO_NUM=36 +CONFIG_Y7_GPIO_NUM=18 +CONFIG_Y6_GPIO_NUM=39 +CONFIG_Y5_GPIO_NUM=5 +CONFIG_Y4_GPIO_NUM=34 +CONFIG_Y3_GPIO_NUM=35 +CONFIG_Y2_GPIO_NUM=17 +CONFIG_VSYNC_GPIO_NUM=22 +CONFIG_HREF_GPIO_NUM=26 +CONFIG_PCLK_GPIO_NUM=21 +# end of Camera sensor pinout configuration +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +CONFIG_SPIRAM_MODE_QUAD=y +# CONFIG_SPIRAM_MODE_OCT is not set +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_SPEED_120M is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set + +# +# OpenIris: Serial Communication Settings +# +CONFIG_UART_PORT_NUMBER=0 +CONFIG_UART_RX_PIN=3 +CONFIG_UART_TX_PIN=1 + +# end of OpenIris: Serial Communication Settings + +# CONFIG_MONITORING_LED_CURRENT is not set \ No newline at end of file diff --git a/boards/esp_eye/esp_eye b/boards/esp_eye/esp_eye new file mode 100644 index 0000000..83467e1 --- /dev/null +++ b/boards/esp_eye/esp_eye @@ -0,0 +1,52 @@ +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_WIRED_MODE=y +CONFIG_BLINK_GPIO=38 # todo check this +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +# Camera sensor pinout configuration +CONFIG_CAMERA_MODULE_NAME="ESP322ESP_EYE" +CONFIG_PWDN_GPIO_NUM=-1 +CONFIG_RESET_GPIO_NUM=-1 +CONFIG_XCLK_GPIO_NUM=4 +CONFIG_SIOD_GPIO_NUM=18 +CONFIG_SIOC_GPIO_NUM=23 +CONFIG_Y9_GPIO_NUM=36 +CONFIG_Y8_GPIO_NUM=37 +CONFIG_Y7_GPIO_NUM=38 +CONFIG_Y6_GPIO_NUM=39 +CONFIG_Y5_GPIO_NUM=14 +CONFIG_Y4_GPIO_NUM=19 +CONFIG_Y3_GPIO_NUM=13 +CONFIG_Y2_GPIO_NUM=34 +CONFIG_VSYNC_GPIO_NUM=5 +CONFIG_HREF_GPIO_NUM=27 +CONFIG_PCLK_GPIO_NUM=25 +# end of Camera sensor pinout configuration +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +CONFIG_SPIRAM_MODE_QUAD=y +# CONFIG_SPIRAM_MODE_OCT is not set +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_SPEED_120M is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set \ No newline at end of file diff --git a/boards/facefocusvr/face b/boards/facefocusvr/face index e51b9e7..aca01d7 100644 --- a/boards/facefocusvr/face +++ b/boards/facefocusvr/face @@ -68,4 +68,4 @@ CONFIG_GENERAL_BOARD="facefocusvr_face" # CONFIG_GENERAL_ENABLE_WIRELESS is not set # CONFIG_LED_DEBUG_ENABLE is not set CONFIG_LED_EXTERNAL_AS_DEBUG=y -CONFIG_GENERAL_ADVERTISED_NAME="FFVR Face" \ No newline at end of file +CONFIG_GENERAL_ADVERTISED_NAME="FFVR Face" diff --git a/boards/project_babble/project_babble b/boards/project_babble/project_babble index 507ffbe..db3e3a8 100644 --- a/boards/project_babble/project_babble +++ b/boards/project_babble/project_babble @@ -1,3 +1,5 @@ +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y CONFIG_LED_DEBUG_GPIO=38 CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32S3_SPIRAM_SUPPORT=y diff --git a/boards/sdkconfig.base_defaults b/boards/sdkconfig.base_defaults index 71ea29d..a624d2a 100644 --- a/boards/sdkconfig.base_defaults +++ b/boards/sdkconfig.base_defaults @@ -2228,7 +2228,6 @@ CONFIG_TUSB_PID=0x8000 CONFIG_TUSB_MANUFACTURER="ETVR" CONFIG_TUSB_PRODUCT="OpenIris Camera" CONFIG_TUSB_SERIAL_NUM="12345678" -# CONFIG_UVC_SUPPORT_TWO_CAM is not set # # USB Cam1 Config diff --git a/boards/seed_studio/xiao_esp32s3 b/boards/seed_studio/xiao_esp32s3 index 98da3bb..c3a29cb 100644 --- a/boards/seed_studio/xiao_esp32s3 +++ b/boards/seed_studio/xiao_esp32s3 @@ -1,3 +1,5 @@ +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y CONFIG_LED_DEBUG_GPIO=21 CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y diff --git a/boards/wrooms3/wrooms3 b/boards/wrooms3/wrooms3 new file mode 100644 index 0000000..92fe98a --- /dev/null +++ b/boards/wrooms3/wrooms3 @@ -0,0 +1,51 @@ +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_WIRED_MODE=y +CONFIG_BLINK_GPIO=38 +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="8MB" +# Camera sensor pinout configuration +CONFIG_CAMERA_MODULE_NAME="WROOMS3" +CONFIG_PWDN_GPIO_NUM=-1 +CONFIG_RESET_GPIO_NUM=-1 +CONFIG_XCLK_GPIO_NUM=15 +CONFIG_SIOD_GPIO_NUM=4 +CONFIG_SIOC_GPIO_NUM=5 +CONFIG_Y9_GPIO_NUM=16 +CONFIG_Y8_GPIO_NUM=17 +CONFIG_Y7_GPIO_NUM=18 +CONFIG_Y6_GPIO_NUM=12 +CONFIG_Y5_GPIO_NUM=10 +CONFIG_Y4_GPIO_NUM=8 +CONFIG_Y3_GPIO_NUM=9 +CONFIG_Y2_GPIO_NUM=11 +CONFIG_VSYNC_GPIO_NUM=6 +CONFIG_HREF_GPIO_NUM=7 +CONFIG_PCLK_GPIO_NUM=13 +# end of Camera sensor pinout configuration +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +CONFIG_SPIRAM_MODE_QUAD=y +# CONFIG_SPIRAM_MODE_OCT is not set +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_SPEED_120M is not set +CONFIG_SPIRAM_SPEED_80M=y \ No newline at end of file diff --git a/boards/wrooms3QIO/wrooms3QIO b/boards/wrooms3QIO/wrooms3QIO new file mode 100644 index 0000000..02bb83b --- /dev/null +++ b/boards/wrooms3QIO/wrooms3QIO @@ -0,0 +1,52 @@ +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_WIRED_MODE=y +CONFIG_BLINK_GPIO=38 +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="8MB" +# Camera sensor pinout configuration +CONFIG_CAMERA_MODULE_NAME="WROOMS3" +CONFIG_PWDN_GPIO_NUM=-1 +CONFIG_RESET_GPIO_NUM=-1 +CONFIG_XCLK_GPIO_NUM=15 +CONFIG_SIOD_GPIO_NUM=4 +CONFIG_SIOC_GPIO_NUM=5 +CONFIG_Y9_GPIO_NUM=16 +CONFIG_Y8_GPIO_NUM=17 +CONFIG_Y7_GPIO_NUM=18 +CONFIG_Y6_GPIO_NUM=12 +CONFIG_Y5_GPIO_NUM=10 +CONFIG_Y4_GPIO_NUM=8 +CONFIG_Y3_GPIO_NUM=9 +CONFIG_Y2_GPIO_NUM=11 +CONFIG_VSYNC_GPIO_NUM=6 +CONFIG_HREF_GPIO_NUM=7 +CONFIG_PCLK_GPIO_NUM=13 +# end of Camera sensor pinout configuration +CONFIG_FLASHMODE_QIO = y +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +CONFIG_SPIRAM_MODE_QUAD=y +# CONFIG_SPIRAM_MODE_OCT is not set +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_SPEED_120M is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set \ No newline at end of file diff --git a/boards/wrover/wrover b/boards/wrover/wrover new file mode 100644 index 0000000..2cbcaee --- /dev/null +++ b/boards/wrover/wrover @@ -0,0 +1,52 @@ +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_WIRED_MODE=y +CONFIG_BLINK_GPIO=38 +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +# Camera sensor pinout configuration +CONFIG_CAMERA_MODULE_NAME="WROVER" +CONFIG_PWDN_GPIO_NUM=-1 +CONFIG_RESET_GPIO_NUM=-1 +CONFIG_XCLK_GPIO_NUM=21 +CONFIG_SIOD_GPIO_NUM=26 +CONFIG_SIOC_GPIO_NUM=27 +CONFIG_Y9_GPIO_NUM=35 +CONFIG_Y8_GPIO_NUM=34 +CONFIG_Y7_GPIO_NUM=39 +CONFIG_Y6_GPIO_NUM=36 +CONFIG_Y5_GPIO_NUM=19 +CONFIG_Y4_GPIO_NUM=18 +CONFIG_Y3_GPIO_NUM=5 +CONFIG_Y2_GPIO_NUM=4 +CONFIG_VSYNC_GPIO_NUM=25 +CONFIG_HREF_GPIO_NUM=23 +CONFIG_PCLK_GPIO_NUM=22 +# end of Camera sensor pinout configuration +CONFIG_FLASHMODE_QIO=y +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +CONFIG_SPIRAM_MODE_QUAD=y +# CONFIG_SPIRAM_MODE_OCT is not set +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_SPEED_120M is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SUPPORTS_EXTERNAL_LED_CONTROL is not set \ No newline at end of file diff --git a/components/CameraManager/CameraManager/CameraManager.cpp b/components/CameraManager/CameraManager/CameraManager.cpp index 555313a..50bab34 100644 --- a/components/CameraManager/CameraManager/CameraManager.cpp +++ b/components/CameraManager/CameraManager/CameraManager.cpp @@ -75,33 +75,16 @@ void CameraManager::setupCameraPinout() .ledc_timer = LEDC_TIMER_0, .ledc_channel = LEDC_CHANNEL_0, - // this causes problems .pixel_format = PIXFORMAT_JPEG, // YUV422,GRAYSCALE,RGB565,JPEG .frame_size = FRAMESIZE_240X240, // QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates. - .jpeg_quality = 8, // 0-63, for OV series camera sensors, lower number means higher quality // Below 6 stability problems - .fb_count = 2, // When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode. - .fb_location = CAMERA_FB_IN_DRAM, - .grab_mode = CAMERA_GRAB_WHEN_EMPTY, // was CAMERA_GRAB_LATEST; new mode reduces frame skips at cost of minor latency + .jpeg_quality = 8, // 0-63, for OV series camera sensors, lower number means higher quality // Below 6 stability problems + .fb_count = 2, // When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode. + .fb_location = CAMERA_FB_IN_DRAM, + .grab_mode = CAMERA_GRAB_WHEN_EMPTY, // was CAMERA_GRAB_LATEST; new mode reduces frame skips at cost of minor latency }; } -void CameraManager::setupBasicResolution() -{ - - if (!esp_psram_is_initialized()) - { - ESP_LOGE(CAMERA_MANAGER_TAG, "PSRAM not initialized!"); - ESP_LOGD(CAMERA_MANAGER_TAG, "Setting fb_location to CAMERA_FB_IN_DRAM with lower picture quality"); - config.fb_location = CAMERA_FB_IN_DRAM; - config.jpeg_quality = 7; - config.fb_count = 2; - return; - } - - ESP_LOGI(CAMERA_MANAGER_TAG, "PSRAM size: %u", esp_psram_get_size()); -} - void CameraManager::setupCameraSensor() { ESP_LOGI(CAMERA_MANAGER_TAG, "Setting up camera sensor"); @@ -137,8 +120,8 @@ void CameraManager::setupCameraSensor() // automatic gain control gain, controls by how much the resulting image // should be amplified - camera_sensor->set_agc_gain(camera_sensor, 2); // 0 to 30 - camera_sensor->set_gainceiling(camera_sensor, (gainceiling_t)6); // 0 to 6 + camera_sensor->set_agc_gain(camera_sensor, 2); // 0 to 30 + camera_sensor->set_gainceiling(camera_sensor, static_cast(6)); // 0 to 6 // black and white pixel correction, averages the white and black spots camera_sensor->set_bpc(camera_sensor, 1); // 0 = disable , 1 = enable @@ -170,9 +153,6 @@ bool CameraManager::setupCamera() { ESP_LOGI(CAMERA_MANAGER_TAG, "Setting up camera pinout"); this->setupCameraPinout(); - ESP_LOGI(CAMERA_MANAGER_TAG, "Setting up camera with resolution"); - // this->setupBasicResolution(); - ESP_LOGI(CAMERA_MANAGER_TAG, "Initializing camera..."); if (auto const hasCameraBeenInitialized = esp_camera_init(&config); hasCameraBeenInitialized == ESP_OK) @@ -212,7 +192,6 @@ bool CameraManager::setupCamera() #endif this->setupCameraSensor(); - // this->loadConfigData(); // move this to update method once implemented return true; } diff --git a/components/CameraManager/CameraManager/CameraManager.hpp b/components/CameraManager/CameraManager/CameraManager.hpp index 0034691..390cfcf 100644 --- a/components/CameraManager/CameraManager/CameraManager.hpp +++ b/components/CameraManager/CameraManager/CameraManager.hpp @@ -36,7 +36,6 @@ private: void loadConfigData(); void setupCameraPinout(); void setupCameraSensor(); - void setupBasicResolution(); }; #endif // CAMERAMANAGER_HPP \ No newline at end of file diff --git a/components/CommandManager/CommandManager/CommandManager.cpp b/components/CommandManager/CommandManager/CommandManager.cpp index b666029..f2bb174 100644 --- a/components/CommandManager/CommandManager/CommandManager.cpp +++ b/components/CommandManager/CommandManager/CommandManager.cpp @@ -26,7 +26,7 @@ std::unordered_map commandTypeMap = { {"get_led_duty_cycle", CommandType::GET_LED_DUTY_CYCLE}, {"get_serial", CommandType::GET_SERIAL}, {"get_led_current", CommandType::GET_LED_CURRENT}, - {"get_who_am_i", CommandType::GET_WHO_AM_I}, + {"get_who_am_i", CommandType::GET_WHO_AM_I}, }; std::function CommandManager::createCommand(const CommandType type, const nlohmann::json &json) const @@ -161,5 +161,5 @@ CommandManagerResponse CommandManager::executeFromType(const CommandType type, c return CommandManagerResponse({{"command", type}, {"error", "Unknown command"}}); } - return CommandManagerResponse({"result", command()}); + return CommandManagerResponse(nlohmann::json{{"result", command()}}); } \ No newline at end of file diff --git a/components/CommandManager/CommandManager/commands/wifi_commands.cpp b/components/CommandManager/CommandManager/commands/wifi_commands.cpp index db81371..f99b517 100644 --- a/components/CommandManager/CommandManager/commands/wifi_commands.cpp +++ b/components/CommandManager/CommandManager/commands/wifi_commands.cpp @@ -5,7 +5,7 @@ CommandResult setWiFiCommand(std::shared_ptr registry, const nlohmann::json &json) { #if !CONFIG_GENERAL_ENABLE_WIRELESS - return CommandResult::getErrorResult("Not supported by current firmware"); + return CommandResult::getErrorResult("Not supported by current firmware"); #endif auto payload = json.get(); @@ -33,7 +33,7 @@ CommandResult setWiFiCommand(std::shared_ptr registry, const CommandResult deleteWiFiCommand(std::shared_ptr registry, const nlohmann::json &json) { #if !CONFIG_GENERAL_ENABLE_WIRELESS - return CommandResult::getErrorResult("Not supported by current firmware"); + return CommandResult::getErrorResult("Not supported by current firmware"); #endif const auto payload = json.get(); @@ -49,7 +49,7 @@ CommandResult deleteWiFiCommand(std::shared_ptr registry, co CommandResult updateWiFiCommand(std::shared_ptr registry, const nlohmann::json &json) { #if !CONFIG_GENERAL_ENABLE_WIRELESS - return CommandResult::getErrorResult("Not supported by current firmware"); + return CommandResult::getErrorResult("Not supported by current firmware"); #endif auto payload = json.get(); @@ -82,7 +82,7 @@ CommandResult updateWiFiCommand(std::shared_ptr registry, co CommandResult updateAPWiFiCommand(std::shared_ptr registry, const nlohmann::json &json) { #if !CONFIG_GENERAL_ENABLE_WIRELESS - return CommandResult::getErrorResult("Not supported by current firmware"); + return CommandResult::getErrorResult("Not supported by current firmware"); #endif const auto payload = json.get(); diff --git a/components/Monitoring/CMakeLists.txt b/components/Monitoring/CMakeLists.txt index fd6f78f..bd394ff 100644 --- a/components/Monitoring/CMakeLists.txt +++ b/components/Monitoring/CMakeLists.txt @@ -1,6 +1,34 @@ -idf_component_register(SRCS - "Monitoring/CurrentMonitor.cpp" - "Monitoring/MonitoringManager.cpp" - INCLUDE_DIRS "Monitoring" - REQUIRES driver esp_adc Helpers +set( + requires + Helpers ) + +if ("$ENV{IDF_TARGET}" STREQUAL "esp32s3") +list(APPEND requires + driver + esp_adc +) +endif() + +set( + source_files + "" +) + +if ("$ENV{IDF_TARGET}" STREQUAL "esp32s3") +list(APPEND source_files + "Monitoring/CurrentMonitor_esp32s3.cpp" + "Monitoring/MonitoringManager_esp32s3.cpp" +) +else() +list(APPEND source_files + "Monitoring/CurrentMonitor_esp32.cpp" + "Monitoring/MonitoringManager_esp32.cpp" +) +endif() + + +idf_component_register(SRCS ${source_files} + INCLUDE_DIRS "Monitoring" + REQUIRES ${requires} +) \ No newline at end of file diff --git a/components/Monitoring/Monitoring/CurrentMonitor.hpp b/components/Monitoring/Monitoring/CurrentMonitor.hpp index d1163d3..f61fa01 100644 --- a/components/Monitoring/Monitoring/CurrentMonitor.hpp +++ b/components/Monitoring/Monitoring/CurrentMonitor.hpp @@ -6,7 +6,8 @@ #include #include "sdkconfig.h" -class CurrentMonitor { +class CurrentMonitor +{ public: CurrentMonitor(); ~CurrentMonitor() = default; @@ -25,15 +26,15 @@ public: // Whether monitoring is enabled by Kconfig static constexpr bool isEnabled() { - #ifdef CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT return true; - #else +#else return false; - #endif +#endif } private: -#if CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT void init_adc(); int read_mv_once(); int gpio_to_adc_channel(int gpio); diff --git a/components/Monitoring/Monitoring/CurrentMonitor_esp32.cpp b/components/Monitoring/Monitoring/CurrentMonitor_esp32.cpp new file mode 100644 index 0000000..be2d090 --- /dev/null +++ b/components/Monitoring/Monitoring/CurrentMonitor_esp32.cpp @@ -0,0 +1,42 @@ +#include "CurrentMonitor.hpp" +#include + +static const char *TAG_CM = "[CurrentMonitor]"; + +CurrentMonitor::CurrentMonitor() +{ + // empty as esp32 doesn't support this + // but without a separate implementation, the linker will complain :c +} + +void CurrentMonitor::setup() +{ + ESP_LOGI(TAG_CM, "LED current monitoring disabled"); +} + +float CurrentMonitor::getCurrentMilliAmps() const +{ + return 0.0f; +} + +float CurrentMonitor::pollAndGetMilliAmps() +{ + sampleOnce(); + return getCurrentMilliAmps(); +} + +void CurrentMonitor::sampleOnce() +{ + (void)0; +} + +#ifdef CONFIG_MONITORING_LED_CURRENT +void CurrentMonitor::init_adc() +{ +} + +int CurrentMonitor::read_mv_once() +{ + return 0; +} +#endif \ No newline at end of file diff --git a/components/Monitoring/Monitoring/CurrentMonitor.cpp b/components/Monitoring/Monitoring/CurrentMonitor_esp32s3.cpp similarity index 95% rename from components/Monitoring/Monitoring/CurrentMonitor.cpp rename to components/Monitoring/Monitoring/CurrentMonitor_esp32s3.cpp index 024d767..478a7ce 100644 --- a/components/Monitoring/Monitoring/CurrentMonitor.cpp +++ b/components/Monitoring/Monitoring/CurrentMonitor_esp32s3.cpp @@ -2,7 +2,7 @@ #include #include -#if CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT #include "esp_adc/adc_oneshot.h" #include "esp_adc/adc_cali.h" #include "esp_adc/adc_cali_scheme.h" @@ -12,14 +12,14 @@ static const char *TAG_CM = "[CurrentMonitor]"; CurrentMonitor::CurrentMonitor() { -#if CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT samples_.assign(CONFIG_MONITORING_LED_SAMPLES, 0); #endif } void CurrentMonitor::setup() { -#if CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT init_adc(); #else ESP_LOGI(TAG_CM, "LED current monitoring disabled"); @@ -28,7 +28,7 @@ void CurrentMonitor::setup() float CurrentMonitor::getCurrentMilliAmps() const { -#if CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT const int shunt_milliohm = CONFIG_MONITORING_LED_SHUNT_MILLIOHM; // mΩ if (shunt_milliohm <= 0) return 0.0f; @@ -48,7 +48,7 @@ float CurrentMonitor::pollAndGetMilliAmps() void CurrentMonitor::sampleOnce() { -#if CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT int mv = read_mv_once(); // Divide by analog gain/divider factor to get shunt voltage if (CONFIG_MONITORING_LED_GAIN > 0) @@ -76,7 +76,7 @@ void CurrentMonitor::sampleOnce() #endif } -#if CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT static adc_oneshot_unit_handle_t s_adc_handle = nullptr; static adc_cali_handle_t s_cali_handle = nullptr; diff --git a/components/Monitoring/Monitoring/MonitoringManager.hpp b/components/Monitoring/Monitoring/MonitoringManager.hpp index 3e7a6c2..7fb6e78 100644 --- a/components/Monitoring/Monitoring/MonitoringManager.hpp +++ b/components/Monitoring/Monitoring/MonitoringManager.hpp @@ -4,9 +4,9 @@ #include #include "CurrentMonitor.hpp" -class MonitoringManager { +class MonitoringManager +{ public: - void setup(); void start(); void stop(); @@ -15,7 +15,7 @@ public: float getCurrentMilliAmps() const { return last_current_ma_.load(); } private: - static void taskEntry(void* arg); + static void taskEntry(void *arg); void run(); TaskHandle_t task_{nullptr}; diff --git a/components/Monitoring/Monitoring/MonitoringManager_esp32.cpp b/components/Monitoring/Monitoring/MonitoringManager_esp32.cpp new file mode 100644 index 0000000..e9c4adf --- /dev/null +++ b/components/Monitoring/Monitoring/MonitoringManager_esp32.cpp @@ -0,0 +1,25 @@ +#include "MonitoringManager.hpp" +#include + +static const char *TAG_MM = "[MonitoringManager]"; + +void MonitoringManager::setup() +{ + ESP_LOGI(TAG_MM, "Monitoring disabled by Kconfig"); +} + +void MonitoringManager::start() +{ +} + +void MonitoringManager::stop() +{ +} + +void MonitoringManager::taskEntry(void *arg) +{ +} + +void MonitoringManager::run() +{ +} diff --git a/components/Monitoring/Monitoring/MonitoringManager.cpp b/components/Monitoring/Monitoring/MonitoringManager_esp32s3.cpp similarity index 80% rename from components/Monitoring/Monitoring/MonitoringManager.cpp rename to components/Monitoring/Monitoring/MonitoringManager_esp32s3.cpp index 1a371b5..2eec518 100644 --- a/components/Monitoring/Monitoring/MonitoringManager.cpp +++ b/components/Monitoring/Monitoring/MonitoringManager_esp32s3.cpp @@ -2,11 +2,11 @@ #include #include "sdkconfig.h" -static const char* TAG_MM = "[MonitoringManager]"; +static const char *TAG_MM = "[MonitoringManager]"; void MonitoringManager::setup() { -#if CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT cm_.setup(); ESP_LOGI(TAG_MM, "Monitoring enabled. Interval=%dms, Samples=%d, Gain=%d, R=%dmΩ", CONFIG_MONITORING_LED_INTERVAL_MS, @@ -20,7 +20,7 @@ void MonitoringManager::setup() void MonitoringManager::start() { -#if CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT if (task_ == nullptr) { xTaskCreate(&MonitoringManager::taskEntry, "MonitoringTask", 2048, this, 1, &task_); @@ -38,14 +38,14 @@ void MonitoringManager::stop() } } -void MonitoringManager::taskEntry(void* arg) +void MonitoringManager::taskEntry(void *arg) { - static_cast(arg)->run(); + static_cast(arg)->run(); } void MonitoringManager::run() { -#if CONFIG_MONITORING_LED_CURRENT +#ifdef CONFIG_MONITORING_LED_CURRENT while (true) { float ma = cm_.pollAndGetMilliAmps(); diff --git a/components/ProjectConfig/ProjectConfig/Models.hpp b/components/ProjectConfig/ProjectConfig/Models.hpp index 448f625..8561dad 100644 --- a/components/ProjectConfig/ProjectConfig/Models.hpp +++ b/components/ProjectConfig/ProjectConfig/Models.hpp @@ -35,14 +35,14 @@ struct DeviceMode_t : BaseConfigModel void load() { - // Default mode can be controlled via sdkconfig: - // - If CONFIG_START_IN_UVC_MODE is enabled, default to UVC - // - Otherwise default to SETUP + // Default mode can be controlled via sdkconfig: + // - If CONFIG_START_IN_UVC_MODE is enabled, default to UVC + // - Otherwise default to SETUP int default_mode = #if CONFIG_START_IN_UVC_MODE static_cast(StreamingMode::UVC); #else - static_cast(StreamingMode::SETUP); + static_cast(StreamingMode::SETUP); #endif int stored_mode = this->pref->getInt("mode", default_mode); @@ -103,14 +103,8 @@ struct MDNSConfig_t : BaseConfigModel void load() { - // Default hostname comes from GENERAL_ADVERTISED_NAME (unified advertised name) - std::string default_hostname = -#ifdef CONFIG_GENERAL_ADVERTISED_NAME - CONFIG_GENERAL_ADVERTISED_NAME; -#else - "openiristracker"; -#endif - + // Default hostname comes from GENERAL_ADVERTISED_NAME (unified advertised name) + std::string default_hostname = CONFIG_GENERAL_ADVERTISED_NAME; if (default_hostname.empty()) { default_hostname = "openiristracker"; @@ -146,7 +140,7 @@ struct CameraConfig_t : BaseConfigModel { this->vflip = this->pref->getInt("vflip", 0); this->href = this->pref->getInt("href", 0); - this->framesize = this->pref->getInt("framesize", 4); + this->framesize = this->pref->getInt("framesize", 5); this->quality = this->pref->getInt("quality", 7); this->brightness = this->pref->getInt("brightness", 2); }; @@ -331,14 +325,11 @@ public: { for (auto i = 0; i < this->networks.size() - 1; i++) { - printf("we're at %d while networks size is %d ", i, this->networks.size() - 2); WifiConfigRepresentation += Helpers::format_string("%s, ", this->networks[i].toRepresentation().c_str()); } } WifiConfigRepresentation += Helpers::format_string("%s", this->networks[networks.size() - 1].toRepresentation().c_str()); - printf(WifiConfigRepresentation.c_str()); - printf("\n"); } return Helpers::format_string( diff --git a/components/RestAPI/RestAPI/RestAPI.cpp b/components/RestAPI/RestAPI/RestAPI.cpp index de002df..e1655f2 100644 --- a/components/RestAPI/RestAPI/RestAPI.cpp +++ b/components/RestAPI/RestAPI/RestAPI.cpp @@ -2,7 +2,10 @@ #include +#define PATCH_METHOD "PATCH" #define POST_METHOD "POST" +#define GET_METHOD "GET" +#define DELETE_METHOD "DELETE" bool getIsSuccess(const nlohmann::json &response) { @@ -19,27 +22,55 @@ bool getIsSuccess(const nlohmann::json &response) RestAPI::RestAPI(std::string url, std::shared_ptr commandManager) : command_manager(commandManager) { + // until we stumble on a simpler way to handle the commands over the rest api + // the formula will be like this: + // each command gets its own endpoint + // each endpoint must include the action it performs in its path + // for example + // /get/ for getters + // /set/ for posts + // /delete/ for deletes + // /update/ for updates + // additional actions on the resource should be appended after the resource name + // like for example /api/set/config/save/ + // + // one endpoint must not contain more than one action + this->url = std::move(url); - // updates - routes.emplace("/api/update/wifi/", &RestAPI::handle_update_wifi); - routes.emplace("/api/update/device/", &RestAPI::handle_update_device); - routes.emplace("/api/update/camera/", &RestAPI::handle_update_camera); + // updates via PATCH + routes.emplace("/api/update/wifi/", RequestBaseData(PATCH_METHOD, CommandType::UPDATE_WIFI, 200, 400)); + routes.emplace("/api/update/device/mode/", RequestBaseData(PATCH_METHOD, CommandType::SWITCH_MODE, 200, 400)); + routes.emplace("/api/update/camera/", RequestBaseData(PATCH_METHOD, CommandType::UPDATE_CAMERA, 200, 400)); + routes.emplace("/api/update/ota/credentials", RequestBaseData(PATCH_METHOD, CommandType::UPDATE_OTA_CREDENTIALS, 200, 400)); + routes.emplace("/api/update/ap/", RequestBaseData(PATCH_METHOD, CommandType::UPDATE_AP_WIFI, 200, 400)); + routes.emplace("/api/update/led_duty_cycle/", RequestBaseData(PATCH_METHOD, CommandType::SET_LED_DUTY_CYCLE, 200, 400)); - // post will reset it - // resets - routes.emplace("/api/reset/config/", &RestAPI::handle_reset_config); - // gets - routes.emplace("/api/get/config/", &RestAPI::handle_get_config); + // POST will set the data + routes.emplace("/api/set/pause/", RequestBaseData(POST_METHOD, CommandType::PAUSE, 200, 400)); + routes.emplace("/api/set/wifi/", RequestBaseData(POST_METHOD, CommandType::SET_WIFI, 200, 400)); + routes.emplace("/api/set/mdns/", RequestBaseData(POST_METHOD, CommandType::SET_MDNS, 200, 400)); + routes.emplace("/api/set/config/save/", RequestBaseData(POST_METHOD, CommandType::SAVE_CONFIG, 200, 400)); + routes.emplace("/api/set/wifi/connect/", RequestBaseData(POST_METHOD, CommandType::CONNECT_WIFI, 200, 400)); - // reboots - routes.emplace("/api/reboot/device/", &RestAPI::handle_reboot); - routes.emplace("/api/reboot/camera/", &RestAPI::handle_camera_reboot); + // resets via POST as well + routes.emplace("/api/reset/config/", RequestBaseData(POST_METHOD, CommandType::RESET_CONFIG, 200, 400)); - // heartbeat - routes.emplace("/api/ping/", &RestAPI::pong); + // gets via GET + routes.emplace("/api/get/config/", RequestBaseData(GET_METHOD, CommandType::GET_CONFIG, 200, 400)); + routes.emplace("/api/get/mdns/", RequestBaseData(GET_METHOD, CommandType::GET_MDNS_NAME, 200, 400)); + routes.emplace("/api/get/led_duty_cycle/", RequestBaseData(GET_METHOD, CommandType::GET_LED_DUTY_CYCLE, 200, 400)); + routes.emplace("/api/get/serial_number/", RequestBaseData(GET_METHOD, CommandType::GET_SERIAL, 200, 400)); + routes.emplace("/api/get/led_current/", RequestBaseData(GET_METHOD, CommandType::GET_LED_CURRENT, 200, 400)); + routes.emplace("/api/get/who_am_i/", RequestBaseData(GET_METHOD, CommandType::GET_WHO_AM_I, 200, 400)); - // special - routes.emplace("/api/save/", &RestAPI::handle_save); + // deletes via DELETE + routes.emplace("/api/delete/wifi", RequestBaseData(DELETE_METHOD, CommandType::DELETE_NETWORK, 200, 400)); + + // reboots via POST + routes.emplace("/api/reboot/device/", RequestBaseData(GET_METHOD, CommandType::RESTART_DEVICE, 200, 500)); + + // heartbeat via GET + routes.emplace("/api/ping/", RequestBaseData(GET_METHOD, CommandType::PING, 200, 400)); } void RestAPI::begin() @@ -58,19 +89,24 @@ void RestAPI::handle_request(struct mg_connection *connection, int event, void * auto const *message = static_cast(event_data); auto const uri = std::string(message->uri.buf, message->uri.len); - if (auto const handler = this->routes[uri]) - { - auto *context = new RequestContext{ - .connection = connection, - .method = std::string(message->method.buf, message->method.len), - .body = std::string(message->body.buf, message->body.len), - }; - (*this.*handler)(context); - } - else + if (this->routes.find(uri) == this->routes.end()) { mg_http_reply(connection, 404, "", "Wrong URL"); + return; } + + auto const base_request_params = this->routes.at(uri); + + auto *context = new RequestContext{ + .connection = connection, + .method = std::string(message->method.buf, message->method.len), + .body = std::string(message->body.buf, message->body.len), + }; + this->handle_endpoint_command(context, + base_request_params.allowed_method, + base_request_params.command_type, + base_request_params.success_code, + base_request_params.error_code); } } @@ -95,97 +131,16 @@ void HandleRestAPIPollTask(void *pvParameter) } } -// COMMANDS -// updates -void RestAPI::handle_update_wifi(RequestContext *context) +void RestAPI::handle_endpoint_command(RequestContext *context, std::string allowed_method, CommandType command_type, int success_code, int error_code) { - if (context->method != POST_METHOD) + + if (context->method != allowed_method) { mg_http_reply(context->connection, 401, JSON_RESPONSE, "{%m:%m}", MG_ESC("error"), "Method not allowed"); return; } - const nlohmann::json result = command_manager->executeFromType(CommandType::UPDATE_WIFI, context->body); - const auto code = getIsSuccess(result) ? 200 : 400; + const nlohmann::json result = command_manager->executeFromType(command_type, context->body); + const auto code = getIsSuccess(result) ? success_code : error_code; mg_http_reply(context->connection, code, JSON_RESPONSE, result.dump().c_str()); -} - -void RestAPI::handle_update_device(RequestContext *context) -{ - if (context->method != POST_METHOD) - { - mg_http_reply(context->connection, 401, JSON_RESPONSE, "{%m:%m}", MG_ESC("error"), "Method not allowed"); - return; - } - - const nlohmann::json result = command_manager->executeFromType(CommandType::UPDATE_OTA_CREDENTIALS, context->body); - const auto code = getIsSuccess(result) ? 200 : 500; - mg_http_reply(context->connection, code, JSON_RESPONSE, result.dump().c_str()); -} - -void RestAPI::handle_update_camera(RequestContext *context) -{ - if (context->method != POST_METHOD) - { - mg_http_reply(context->connection, 401, JSON_RESPONSE, "{%m:%m}", MG_ESC("error"), "Method not allowed"); - return; - } - - const nlohmann::json result = command_manager->executeFromType(CommandType::UPDATE_CAMERA, context->body); - const auto code = getIsSuccess(result) ? 200 : 500; - mg_http_reply(context->connection, code, JSON_RESPONSE, result.dump().c_str()); -} - -// gets - -void RestAPI::handle_get_config(RequestContext *context) -{ - auto const result = this->command_manager->executeFromType(CommandType::GET_CONFIG, ""); - const nlohmann::json jsonResult = result; - mg_http_reply(context->connection, 200, JSON_RESPONSE, "{%m:%m}", MG_ESC("result"), jsonResult.dump().c_str()); -} - -// resets - -void RestAPI::handle_reset_config(RequestContext *context) -{ - if (context->method != POST_METHOD) - { - mg_http_reply(context->connection, 401, JSON_RESPONSE, "{%m:%m}", MG_ESC("error"), "Method not allowed"); - return; - } - - const nlohmann::json result = this->command_manager->executeFromType(CommandType::RESET_CONFIG, "{\"section\": \"all\"}"); - const auto code = getIsSuccess(result) ? 200 : 500; - mg_http_reply(context->connection, code, JSON_RESPONSE, "{%m:%m}", MG_ESC("result"), result.dump().c_str()); -} - -// reboots -void RestAPI::handle_reboot(RequestContext *context) -{ - const auto result = this->command_manager->executeFromType(CommandType::RESTART_DEVICE, ""); - mg_http_reply(context->connection, 200, JSON_RESPONSE, "{%m:%m}", MG_ESC("result"), "Ok"); -} - -void RestAPI::handle_camera_reboot(RequestContext *context) -{ - mg_http_reply(context->connection, 200, JSON_RESPONSE, "{%m:%m}", MG_ESC("result"), "Ok"); -} - -// heartbeat - -void RestAPI::pong(RequestContext *context) -{ - const nlohmann::json result = this->command_manager->executeFromType(CommandType::PING, ""); - const auto code = getIsSuccess(result) ? 200 : 500; - mg_http_reply(context->connection, code, JSON_RESPONSE, result.dump().c_str()); -} - -// special - -void RestAPI::handle_save(RequestContext *context) -{ - const nlohmann::json result = this->command_manager->executeFromType(CommandType::SAVE_CONFIG, ""); - const auto code = getIsSuccess(result) ? 200 : 500; - mg_http_reply(context->connection, code, JSON_RESPONSE, result.dump().c_str()); -} +} \ No newline at end of file diff --git a/components/RestAPI/RestAPI/RestAPI.hpp b/components/RestAPI/RestAPI/RestAPI.hpp index 49aab3e..0768b83 100644 --- a/components/RestAPI/RestAPI/RestAPI.hpp +++ b/components/RestAPI/RestAPI/RestAPI.hpp @@ -18,10 +18,18 @@ struct RequestContext std::string body; }; +struct RequestBaseData +{ + std::string allowed_method; + CommandType command_type; + int success_code; + int error_code; + RequestBaseData(std::string allowed_method, CommandType command_type, int success_code, int error_code) : allowed_method(allowed_method), command_type(command_type), success_code(success_code), error_code(error_code) {}; +}; + class RestAPI { - using route_handler = void (RestAPI::*)(RequestContext *); - typedef std::unordered_map route_map; + typedef std::unordered_map route_map; std::string url; route_map routes; @@ -29,26 +37,7 @@ class RestAPI std::shared_ptr command_manager; private: - // updates - void handle_update_wifi(RequestContext *context); - void handle_update_device(RequestContext *context); - void handle_update_camera(RequestContext *context); - - // gets - void handle_get_config(RequestContext *context); - - // resets - void handle_reset_config(RequestContext *context); - - // reboots - void handle_reboot(RequestContext *context); - void handle_camera_reboot(RequestContext *context); - - // heartbeat - void pong(RequestContext *context); - - // special - void handle_save(RequestContext *context); + void handle_endpoint_command(RequestContext *context, std::string allowed_method, CommandType command_type, int success_code, int error_code); public: // this will also need command manager diff --git a/components/SerialManager/CMakeLists.txt b/components/SerialManager/CMakeLists.txt index 41c18ab..cf72e7e 100644 --- a/components/SerialManager/CMakeLists.txt +++ b/components/SerialManager/CMakeLists.txt @@ -1,4 +1,32 @@ -idf_component_register(SRCS "SerialManager/SerialManager.cpp" - INCLUDE_DIRS "SerialManager" - REQUIRES esp_driver_uart CommandManager ProjectConfig tinyusb +set ( + requires + esp_driver_uart + CommandManager + ProjectConfig +) + +if ("$ENV{IDF_TARGET}" STREQUAL "esp32s3") +list(APPEND requires + tinyusb +) +endif() + +set ( + source_files + "SerialManager/SerialManager.cpp" +) + +if ("$ENV{IDF_TARGET}" STREQUAL "esp32s3" ) +list(APPEND source_files + "SerialManager/SerialManager_esp32s3.cpp" +) +else() +list(APPEND source_files + "SerialManager/SerialManager_esp32.cpp" +) +endif() + +idf_component_register(SRCS ${source_files} + INCLUDE_DIRS "SerialManager" + REQUIRES ${requires} ) \ No newline at end of file diff --git a/components/SerialManager/SerialManager/SerialManager.cpp b/components/SerialManager/SerialManager/SerialManager.cpp index 90ac55c..adc1a19 100644 --- a/components/SerialManager/SerialManager/SerialManager.cpp +++ b/components/SerialManager/SerialManager/SerialManager.cpp @@ -1,9 +1,6 @@ #include "SerialManager.hpp" #include "esp_log.h" #include "main_globals.hpp" -#include "tusb.h" - -#define BUF_SIZE (1024) SerialManager::SerialManager(std::shared_ptr commandManager, esp_timer_handle_t *timerHandle) : commandManager(commandManager), timerHandle(timerHandle) @@ -12,62 +9,6 @@ SerialManager::SerialManager(std::shared_ptr commandManager, esp this->temp_data = static_cast(malloc(256)); } -void SerialManager::setup() -{ - usb_serial_jtag_driver_config_t usb_serial_jtag_config; - usb_serial_jtag_config.rx_buffer_size = BUF_SIZE; - usb_serial_jtag_config.tx_buffer_size = BUF_SIZE; - usb_serial_jtag_driver_install(&usb_serial_jtag_config); -} - -void SerialManager::try_receive() -{ - static auto current_position = 0; - int len = usb_serial_jtag_read_bytes(this->temp_data, 256, 1000 / 20); - - // If driver is uninstalled or an error occurs, abort read gracefully - if (len < 0) - { - return; - } - - if (len > 0) - { - // Notify main that a command was received during startup - notify_startup_command_received(); - } - - // since we've got something on the serial port - // we gotta keep reading until we've got the whole message - // we will submit the command once we get a newline, a return or the buffer is full - for (auto i = 0; i < len; i++) - { - this->data[current_position++] = this->temp_data[i]; - // if we're at the end of the buffer, try to process the command anyway - // if we've got a new line, we've finished sending the commands, process them - if (current_position >= BUF_SIZE || this->data[current_position - 1] == '\n' || this->data[current_position - 1] == '\r') - { - data[current_position] = '\0'; - current_position = 0; - - const nlohmann::json result = this->commandManager->executeFromJson(std::string_view(reinterpret_cast(this->data))); - const auto resultMessage = result.dump(); - usb_serial_jtag_write_bytes_chunked(resultMessage.c_str(), resultMessage.length(), 1000 / 20); - } - } -} - -void SerialManager::usb_serial_jtag_write_bytes_chunked(const char *data, size_t len, size_t timeout) -{ - while (len > 0) - { - auto to_write = len > BUF_SIZE ? BUF_SIZE : len; - auto written = usb_serial_jtag_write_bytes(data, to_write, timeout); - data += written; - len -= written; - } -} - // Function to notify that a command was received during startup void SerialManager::notify_startup_command_received() { @@ -83,21 +24,6 @@ void SerialManager::notify_startup_command_received() } } -void SerialManager::shutdown() -{ - // Stop heartbeats; timer will be deleted by main if needed. - // Uninstall the USB Serial JTAG driver to free the internal USB for TinyUSB. - esp_err_t err = usb_serial_jtag_driver_uninstall(); - if (err == ESP_OK) - { - ESP_LOGI("[SERIAL]", "usb_serial_jtag driver uninstalled"); - } - else if (err != ESP_ERR_INVALID_STATE) - { - ESP_LOGW("[SERIAL]", "usb_serial_jtag_driver_uninstall returned %s", esp_err_to_name(err)); - } -} - // we can cancel this task once we're in cdc void HandleSerialManagerTask(void *pvParameters) { @@ -107,72 +33,3 @@ void HandleSerialManagerTask(void *pvParameters) serialManager->try_receive(); } } - -void HandleCDCSerialManagerTask(void *pvParameters) -{ - auto const commandManager = static_cast(pvParameters); - static char buffer[BUF_SIZE]; - auto idx = 0; - - cdc_command_packet_t packet; - while (true) - { - if (xQueueReceive(cdcMessageQueue, &packet, portMAX_DELAY) == pdTRUE) - { - for (auto i = 0; i < packet.len; i++) - { - buffer[idx++] = packet.data[i]; - // if we're at the end of the buffer, try to process the command anyway - // if we've got a new line, we've finished sending the commands, process them - if (idx >= BUF_SIZE || buffer[idx - 1] == '\n' || buffer[idx - 1] == '\r') - { - buffer[idx - 1] = '\0'; - const nlohmann::json result = commandManager->executeFromJson(std::string_view(reinterpret_cast(buffer))); - const auto resultMessage = result.dump(); - tud_cdc_write(resultMessage.c_str(), resultMessage.length()); - tud_cdc_write_flush(); - idx = 0; - } - } - } - } -} - -// tud_cdc_rx_cb is defined as TU_ATTR_WEAK so we can override it, we will be called back if we get some data -// but we don't want to do any processing here since we don't want to risk blocking -// grab the data and send it to a queue, a special task will process it and handle with the command manager -extern "C" void tud_cdc_rx_cb(uint8_t itf) -{ - // we can void the interface number - (void)itf; - cdc_command_packet_t packet; - auto len = tud_cdc_available(); - - if (len > 0) - { - auto read = tud_cdc_read(packet.data, sizeof(packet.data)); - if (read > 0) - { - // we should be safe here, given that the max buffer size is 64 - packet.len = static_cast(read); - xQueueSend(cdcMessageQueue, &packet, 1); - } - } -} - -extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) -{ - (void)itf; - (void)dtr; - (void)rts; - - ESP_LOGI("[SERIAL]", "CDC line state changed: DTR=%d, RTS=%d", dtr, rts); -} - -void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) -{ - (void)itf; - ESP_LOGI("[SERIAL]", "CDC line coding: %" PRIu32 " bps, %d stop bits, %d parity, %d data bits", - p_line_coding->bit_rate, p_line_coding->stop_bits, - p_line_coding->parity, p_line_coding->data_bits); -} \ No newline at end of file diff --git a/components/SerialManager/SerialManager/SerialManager.hpp b/components/SerialManager/SerialManager/SerialManager.hpp index 5124dc2..f48e6b8 100644 --- a/components/SerialManager/SerialManager/SerialManager.hpp +++ b/components/SerialManager/SerialManager/SerialManager.hpp @@ -10,14 +10,16 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" -#include "driver/uart.h" +#include "sdkconfig.h" #include "esp_log.h" #include "driver/gpio.h" -#include "driver/usb_serial_jtag.h" -#include "esp_vfs_usb_serial_jtag.h" #include "esp_vfs_dev.h" #include "esp_mac.h" +#ifndef BUF_SIZE +#define BUF_SIZE (1024) +#endif + extern "C" void tud_cdc_rx_cb(uint8_t itf); extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); @@ -39,8 +41,6 @@ public: void shutdown(); private: - void usb_serial_jtag_write_bytes_chunked(const char *data, size_t len, size_t timeout); - std::shared_ptr commandManager; esp_timer_handle_t *timerHandle; uint8_t *data; diff --git a/components/SerialManager/SerialManager/SerialManager_esp32.cpp b/components/SerialManager/SerialManager/SerialManager_esp32.cpp new file mode 100644 index 0000000..4ec64c3 --- /dev/null +++ b/components/SerialManager/SerialManager/SerialManager_esp32.cpp @@ -0,0 +1,102 @@ +#include "SerialManager.hpp" +#include "esp_log.h" +#include "main_globals.hpp" +#include "driver/uart.h" + +void SerialManager::setup() +{ + uart_config_t uart_config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + }; + + const auto uart_num = static_cast(CONFIG_UART_PORT_NUMBER); + + uart_driver_install(uart_num, BUF_SIZE, BUF_SIZE, 0, NULL, 0); + uart_param_config(uart_num, &uart_config); + + uart_set_pin(uart_num, + CONFIG_UART_TX_PIN, + CONFIG_UART_RX_PIN, + UART_PIN_NO_CHANGE, + UART_PIN_NO_CHANGE); + + gpio_set_pull_mode(static_cast(CONFIG_UART_RX_PIN), GPIO_PULLDOWN_ONLY); + + // ----- Startup Flush ----- + uart_flush(uart_num); + + uint8_t dump_buf[256]; + // clean up initial onslaught of logs + while (uart_read_bytes(uart_num, dump_buf, sizeof(dump_buf), 10 / portTICK_PERIOD_MS) > 0) + { + } +} + +void uart_write_bytes_chunked(uart_port_t uart_num, const void *src, size_t size) +{ + while (size > 0) + { + auto to_write = size > BUF_SIZE ? BUF_SIZE : size; + auto written = uart_write_bytes(uart_num, src, to_write); + src += written; + size -= written; + } +} + +void SerialManager::try_receive() +{ + static auto current_position = 0; + const auto uart_num = static_cast(CONFIG_UART_PORT_NUMBER); + int len = uart_read_bytes(uart_num, this->temp_data, BUF_SIZE, 1000 / 20); + + // If driver is uninstalled or an error occurs, abort read gracefully + if (len <= 0) + { + return; + } + + if (len > 0) + { + notify_startup_command_received(); + } + + // since we've got something on the serial port + // we gotta keep reading until we've got the whole message + // we will submit the command once we get a newline, a return or the buffer is full + for (auto i = 0; i < len; i++) + { + this->data[current_position++] = this->temp_data[i]; + // if we're at the end of the buffer, try to process the command anyway + // if we've got a new line, we've finished sending the commands, process them + if (current_position >= BUF_SIZE || this->data[current_position - 1] == '\n' || this->data[current_position - 1] == '\r') + { + data[current_position] = '\0'; + current_position = 0; + + const nlohmann::json result = this->commandManager->executeFromJson(std::string_view(reinterpret_cast(this->data))); + const auto resultMessage = result.dump(); + // todo check if this works + // uart_write_bytes_chunked(uart_num, resultMessage.c_str(), resultMessage.length())s + uart_write_bytes(uart_num, resultMessage.c_str(), resultMessage.length()); + } + } +} + +void SerialManager::shutdown() +{ + // Uninstall the UART driver to free the internal to keep compatibility with JTAG implementation. + const auto uart_num = static_cast(CONFIG_UART_PORT_NUMBER); + esp_err_t err = uart_driver_delete(uart_num); + if (err == ESP_OK) + { + ESP_LOGI("[SERIAL]", "usb_serial_jtag driver uninstalled"); + } + else if (err != ESP_ERR_INVALID_STATE) + { + ESP_LOGW("[SERIAL]", "usb_serial_jtag_driver_uninstall returned %s", esp_err_to_name(err)); + } +} diff --git a/components/SerialManager/SerialManager/SerialManager_esp32s3.cpp b/components/SerialManager/SerialManager/SerialManager_esp32s3.cpp new file mode 100644 index 0000000..4e66f99 --- /dev/null +++ b/components/SerialManager/SerialManager/SerialManager_esp32s3.cpp @@ -0,0 +1,152 @@ +#include "SerialManager.hpp" +#include "esp_log.h" +#include "main_globals.hpp" +#include "driver/usb_serial_jtag.h" +#include "esp_vfs_usb_serial_jtag.h" + +#include "tusb.h" + +void SerialManager::setup() +{ +#ifndef CONFIG_USE_UART_FOR_COMMUNICATION + usb_serial_jtag_driver_config_t usb_serial_jtag_config; + usb_serial_jtag_config.rx_buffer_size = BUF_SIZE; + usb_serial_jtag_config.tx_buffer_size = BUF_SIZE; + usb_serial_jtag_driver_install(&usb_serial_jtag_config); +#endif +} + +void usb_serial_jtag_write_bytes_chunked(const char *data, size_t len, size_t timeout) +{ +#ifndef CONFIG_USE_UART_FOR_COMMUNICATION + while (len > 0) + { + auto to_write = len > BUF_SIZE ? BUF_SIZE : len; + auto written = usb_serial_jtag_write_bytes(data, to_write, timeout); + data += written; + len -= written; + } +#endif +} + +void SerialManager::try_receive() +{ + static auto current_position = 0; + int len = usb_serial_jtag_read_bytes(this->temp_data, 256, 1000 / 20); + + // If driver is uninstalled or an error occurs, abort read gracefully + if (len < 0) + { + return; + } + + if (len > 0) + { + // Notify main that a command was received during startup + notify_startup_command_received(); + } + + // since we've got something on the serial port + // we gotta keep reading until we've got the whole message + // we will submit the command once we get a newline, a return or the buffer is full + for (auto i = 0; i < len; i++) + { + this->data[current_position++] = this->temp_data[i]; + // if we're at the end of the buffer, try to process the command anyway + // if we've got a new line, we've finished sending the commands, process them + if (current_position >= BUF_SIZE || this->data[current_position - 1] == '\n' || this->data[current_position - 1] == '\r') + { + data[current_position] = '\0'; + current_position = 0; + + const nlohmann::json result = this->commandManager->executeFromJson(std::string_view(reinterpret_cast(this->data))); + const auto resultMessage = result.dump(); + usb_serial_jtag_write_bytes_chunked(resultMessage.c_str(), resultMessage.length(), 1000 / 20); + } + } +} + +void SerialManager::shutdown() +{ + // Uninstall the USB Serial JTAG driver to free the internal USB for TinyUSB. + esp_err_t err = usb_serial_jtag_driver_uninstall(); + if (err == ESP_OK) + { + ESP_LOGI("[SERIAL]", "usb_serial_jtag driver uninstalled"); + } + else if (err != ESP_ERR_INVALID_STATE) + { + ESP_LOGW("[SERIAL]", "usb_serial_jtag_driver_uninstall returned %s", esp_err_to_name(err)); + } +} + +void HandleCDCSerialManagerTask(void *pvParameters) +{ +#ifndef CONFIG_USE_UART_FOR_COMMUNICATION + auto const commandManager = static_cast(pvParameters); + static char buffer[BUF_SIZE]; + auto idx = 0; + + cdc_command_packet_t packet; + while (true) + { + if (xQueueReceive(cdcMessageQueue, &packet, portMAX_DELAY) == pdTRUE) + { + for (auto i = 0; i < packet.len; i++) + { + buffer[idx++] = packet.data[i]; + // if we're at the end of the buffer, try to process the command anyway + // if we've got a new line, we've finished sending the commands, process them + if (idx >= BUF_SIZE || buffer[idx - 1] == '\n' || buffer[idx - 1] == '\r') + { + buffer[idx - 1] = '\0'; + const nlohmann::json result = commandManager->executeFromJson(std::string_view(reinterpret_cast(buffer))); + const auto resultMessage = result.dump(); + tud_cdc_write(resultMessage.c_str(), resultMessage.length()); + tud_cdc_write_flush(); + idx = 0; + } + } + } + } +#endif +} + +// tud_cdc_rx_cb is defined as TU_ATTR_WEAK so we can override it, we will be called back if we get some data +// but we don't want to do any processing here since we don't want to risk blocking +// grab the data and send it to a queue, a special task will process it and handle with the command manager +extern "C" void tud_cdc_rx_cb(uint8_t itf) +{ + // we can void the interface number + (void)itf; + cdc_command_packet_t packet; + auto len = tud_cdc_available(); + + if (len > 0) + { + auto read = tud_cdc_read(packet.data, sizeof(packet.data)); + if (read > 0) + { + // we should be safe here, given that the max buffer size is 64 + packet.len = static_cast(read); + xQueueSend(cdcMessageQueue, &packet, 1); + } + } +} + +extern "C" void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) +{ + (void)itf; + (void)dtr; + (void)rts; + + ESP_LOGI("[SERIAL]", "CDC line state changed: DTR=%d, RTS=%d", dtr, rts); +} + +void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding) +{ + (void)itf; + ESP_LOGI("[SERIAL]", "CDC line coding: %" PRIu32 " bps, %d stop bits, %d parity, %d data bits", + p_line_coding->bit_rate, p_line_coding->stop_bits, + p_line_coding->parity, p_line_coding->data_bits); +} \ No newline at end of file diff --git a/components/StreamServer/StreamServer/StreamServer.cpp b/components/StreamServer/StreamServer/StreamServer.cpp index 5908452..de448e7 100644 --- a/components/StreamServer/StreamServer/StreamServer.cpp +++ b/components/StreamServer/StreamServer/StreamServer.cpp @@ -74,10 +74,11 @@ esp_err_t StreamHelpers::stream(httpd_req_t *req) } if (response != ESP_OK) break; - + // Only log every 100 frames to reduce overhead static int frame_count = 0; - if (++frame_count % 100 == 0) { + if (++frame_count % 100 == 0) + { long request_end = Helpers::getTimeInMillis(); long latency = (request_end - last_request_time); last_request_time = request_end; @@ -98,13 +99,12 @@ esp_err_t StreamServer::startStreamServer() { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); config.stack_size = 20480; - // todo bring this back to 1 once we're done with logs over websockets config.max_uri_handlers = 10; config.server_port = STREAM_SERVER_PORT; config.ctrl_port = STREAM_SERVER_PORT; - config.recv_wait_timeout = 5; // 5 seconds for receiving - config.send_wait_timeout = 5; // 5 seconds for sending - config.lru_purge_enable = true; // Enable LRU purge for better connection handling + config.recv_wait_timeout = 5; // 5 seconds for receiving + config.send_wait_timeout = 5; // 5 seconds for sending + config.lru_purge_enable = true; // Enable LRU purge for better connection handling httpd_uri_t stream_page = { .uri = "/", @@ -139,7 +139,6 @@ esp_err_t StreamServer::startStreamServer() httpd_register_uri_handler(camera_stream, &stream_page); ESP_LOGI(STREAM_SERVER_TAG, "Stream server started on port %d", STREAM_SERVER_PORT); - // todo add printing IP addr here return ESP_OK; } \ No newline at end of file diff --git a/components/UVCStream/CMakeLists.txt b/components/UVCStream/CMakeLists.txt index 8deee2a..2afdb16 100644 --- a/components/UVCStream/CMakeLists.txt +++ b/components/UVCStream/CMakeLists.txt @@ -1,4 +1,19 @@ +set ( + requires + esp_timer + esp32-camera + StateManager + CameraManager + Helpers +) + +if ("$ENV{IDF_TARGET}" STREQUAL "esp32s3") +list(APPEND requires + usb_device_uvc +) +endif() + idf_component_register(SRCS "UVCStream/UVCStream.cpp" INCLUDE_DIRS "UVCStream" - REQUIRES esp_timer esp32-camera StateManager usb_device_uvc CameraManager Helpers + REQUIRES ${requires} ) \ No newline at end of file diff --git a/components/UVCStream/UVCStream/UVCStream.cpp b/components/UVCStream/UVCStream/UVCStream.cpp index a1b931c..5a55416 100644 --- a/components/UVCStream/UVCStream/UVCStream.cpp +++ b/components/UVCStream/UVCStream/UVCStream.cpp @@ -1,8 +1,9 @@ #include "UVCStream.hpp" + +#ifdef CONFIG_GENERAL_INCLUDE_UVC_MODE #include // for snprintf #include "freertos/FreeRTOS.h" #include "freertos/task.h" -// no deps on main globals here; handover is performed in main before calling setup when needed static const char *UVC_STREAM_TAG = "[UVC DEVICE]"; @@ -94,10 +95,10 @@ static uvc_fb_t *UVCStreamHelpers::camera_fb_get_cb(void *cb_ctx) // to the underlying camera buffer was overwritten before TinyUSB returned it. // --- Frame pacing BEFORE grabbing a new camera frame --- - static int64_t next_deadline_us = 0; // next permitted capture time - static int rem_acc = 0; // fractional remainder accumulator - static const int target_fps = 60; // desired FPS - static const int64_t us_per_sec = 1000000; // 1e6 microseconds + static int64_t next_deadline_us = 0; // next permitted capture time + static int rem_acc = 0; // fractional remainder accumulator + static const int target_fps = 60; // desired FPS + static const int64_t us_per_sec = 1000000; // 1e6 microseconds static const int base_interval_us = us_per_sec / target_fps; // 16666 static const int rem_us = us_per_sec % target_fps; // 40 (distributed) @@ -167,12 +168,6 @@ static void UVCStreamHelpers::camera_fb_return_cb(uvc_fb_t *fb, void *cb_ctx) esp_err_t UVCStreamManager::setup() { - -#ifndef CONFIG_GENERAL_INCLUDE_UVC_MODE - ESP_LOGE(UVC_STREAM_TAG, "The board does not support UVC, please, setup WiFi connection."); - return ESP_FAIL; -#endif - ESP_LOGI(UVC_STREAM_TAG, "Setting up UVC Stream"); // Allocate a fixed-size transfer buffer (compile-time constant) uvc_buffer_size = UVCStreamManager::UVC_MAX_FRAMESIZE_SIZE; @@ -218,4 +213,6 @@ esp_err_t UVCStreamManager::start() ESP_LOGI(UVC_STREAM_TAG, "Starting UVC streaming"); // UVC device is already initialized in setup(), just log that we're starting return ESP_OK; -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/components/UVCStream/UVCStream/UVCStream.hpp b/components/UVCStream/UVCStream/UVCStream.hpp index b0dfb43..46f3068 100644 --- a/components/UVCStream/UVCStream/UVCStream.hpp +++ b/components/UVCStream/UVCStream/UVCStream.hpp @@ -1,6 +1,10 @@ #pragma once #ifndef UVCSTREAM_HPP #define UVCSTREAM_HPP + +#include "sdkconfig.h" + +#ifdef CONFIG_GENERAL_INCLUDE_UVC_MODE #include "esp_timer.h" #include "esp_mac.h" #include "esp_camera.h" @@ -33,8 +37,6 @@ extern QueueHandle_t eventQueue; namespace UVCStreamHelpers { - // TODO move the camera handling code to the camera manager and have the uvc manager initialize it in wired mode - typedef struct { camera_fb_t *cam_fb_p; @@ -64,3 +66,4 @@ public: }; #endif // UVCSTREAM_HPP +#endif \ No newline at end of file diff --git a/components/usb_device_uvc/tusb/uvc_frame_config.h b/components/usb_device_uvc/tusb/uvc_frame_config.h index 556223f..f4061c1 100644 --- a/components/usb_device_uvc/tusb/uvc_frame_config.h +++ b/components/usb_device_uvc/tusb/uvc_frame_config.h @@ -8,69 +8,51 @@ #include "sdkconfig.h" #ifdef CONFIG_FORMAT_MJPEG_CAM1 -#define FORMAT_MJPEG_CAM1 1 +#define FORMAT_MJPEG_CAM1 1 #endif #ifdef CONFIG_UVC_CAM1_MULTI_FRAMESIZE -//If enable, add VGA and HVGA to list -#define UVC_CAM1_FRAME_MULTI 1 +// If enable, add VGA and HVGA to list +#define UVC_CAM1_FRAME_MULTI 1 #endif -#define UVC_CAM1_FRAME_WIDTH CONFIG_UVC_CAM1_FRAMESIZE_WIDTH -#define UVC_CAM1_FRAME_HEIGHT CONFIG_UVC_CAM1_FRAMESIZE_HEIGT -#define UVC_CAM1_FRAME_RATE CONFIG_UVC_CAM1_FRAMERATE +#define UVC_CAM1_FRAME_WIDTH CONFIG_UVC_CAM1_FRAMESIZE_WIDTH +#define UVC_CAM1_FRAME_HEIGHT CONFIG_UVC_CAM1_FRAMESIZE_HEIGT +#define UVC_CAM1_FRAME_RATE CONFIG_UVC_CAM1_FRAMERATE #ifdef CONFIG_UVC_MODE_BULK_CAM1 #define UVC_CAM1_BULK_MODE #endif -#if CONFIG_UVC_SUPPORT_TWO_CAM -#ifdef CONFIG_FORMAT_MJPEG_CAM2 -#define FORMAT_MJPEG_CAM2 1 -#endif - -#ifdef CONFIG_UVC_CAM2_MULTI_FRAMESIZE -//If enable, add VGA and HVGA to list -#define UVC_CAM2_FRAME_MULTI 1 -#endif - -#define UVC_CAM2_FRAME_WIDTH CONFIG_UVC_CAM2_FRAMESIZE_WIDTH -#define UVC_CAM2_FRAME_HEIGHT CONFIG_UVC_CAM2_FRAMESIZE_HEIGT -#define UVC_CAM2_FRAME_RATE CONFIG_UVC_CAM2_FRAMERATE - -#ifdef CONFIG_UVC_MODE_BULK_CAM2 -#define UVC_CAM2_BULK_MODE -#endif -#endif - #ifndef UVC_CAM2_FRAME_WIDTH -#define UVC_CAM2_FRAME_WIDTH UVC_CAM1_FRAME_WIDTH +#define UVC_CAM2_FRAME_WIDTH UVC_CAM1_FRAME_WIDTH #endif #ifndef UVC_CAM2_FRAME_HEIGHT -#define UVC_CAM2_FRAME_HEIGHT UVC_CAM1_FRAME_HEIGHT +#define UVC_CAM2_FRAME_HEIGHT UVC_CAM1_FRAME_HEIGHT #endif #ifndef UVC_CAM2_FRAME_RATE -#define UVC_CAM2_FRAME_RATE UVC_CAM1_FRAME_RATE +#define UVC_CAM2_FRAME_RATE UVC_CAM1_FRAME_RATE #endif -static const struct { +static const struct +{ int width; int height; int rate; } UVC_FRAMES_INFO[][4] = {{ - {UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE}, - {CONFIG_UVC_MULTI_FRAME_WIDTH_1, CONFIG_UVC_MULTI_FRAME_HEIGHT_1, CONFIG_UVC_MULTI_FRAME_FPS_1}, - {CONFIG_UVC_MULTI_FRAME_WIDTH_2, CONFIG_UVC_MULTI_FRAME_HEIGHT_2, CONFIG_UVC_MULTI_FRAME_FPS_2}, - {CONFIG_UVC_MULTI_FRAME_WIDTH_3, CONFIG_UVC_MULTI_FRAME_HEIGHT_3, CONFIG_UVC_MULTI_FRAME_FPS_3}, - }, { - {UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE}, - {CONFIG_UVC_MULTI_FRAME_WIDTH_1, CONFIG_UVC_MULTI_FRAME_HEIGHT_1, CONFIG_UVC_MULTI_FRAME_FPS_1}, - {CONFIG_UVC_MULTI_FRAME_WIDTH_2, CONFIG_UVC_MULTI_FRAME_HEIGHT_2, CONFIG_UVC_MULTI_FRAME_FPS_2}, - {CONFIG_UVC_MULTI_FRAME_WIDTH_3, CONFIG_UVC_MULTI_FRAME_HEIGHT_3, CONFIG_UVC_MULTI_FRAME_FPS_3}, - } -}; + {UVC_CAM1_FRAME_WIDTH, UVC_CAM1_FRAME_HEIGHT, UVC_CAM1_FRAME_RATE}, + {CONFIG_UVC_MULTI_FRAME_WIDTH_1, CONFIG_UVC_MULTI_FRAME_HEIGHT_1, CONFIG_UVC_MULTI_FRAME_FPS_1}, + {CONFIG_UVC_MULTI_FRAME_WIDTH_2, CONFIG_UVC_MULTI_FRAME_HEIGHT_2, CONFIG_UVC_MULTI_FRAME_FPS_2}, + {CONFIG_UVC_MULTI_FRAME_WIDTH_3, CONFIG_UVC_MULTI_FRAME_HEIGHT_3, CONFIG_UVC_MULTI_FRAME_FPS_3}, + }, + { + {UVC_CAM2_FRAME_WIDTH, UVC_CAM2_FRAME_HEIGHT, UVC_CAM2_FRAME_RATE}, + {CONFIG_UVC_MULTI_FRAME_WIDTH_1, CONFIG_UVC_MULTI_FRAME_HEIGHT_1, CONFIG_UVC_MULTI_FRAME_FPS_1}, + {CONFIG_UVC_MULTI_FRAME_WIDTH_2, CONFIG_UVC_MULTI_FRAME_HEIGHT_2, CONFIG_UVC_MULTI_FRAME_FPS_2}, + {CONFIG_UVC_MULTI_FRAME_WIDTH_3, CONFIG_UVC_MULTI_FRAME_HEIGHT_3, CONFIG_UVC_MULTI_FRAME_FPS_3}, + }}; #define UVC_FRAME_NUM (sizeof(UVC_FRAMES_INFO[0]) / sizeof(UVC_FRAMES_INFO[0][0])) _Static_assert(UVC_FRAME_NUM == 4, "UVC_FRAME_NUM must be 4"); diff --git a/components/usb_device_uvc/usb_device_uvc.c b/components/usb_device_uvc/usb_device_uvc.c index fe793a6..0d939b1 100644 --- a/components/usb_device_uvc/usb_device_uvc.c +++ b/components/usb_device_uvc/usb_device_uvc.c @@ -20,11 +20,7 @@ static const char *TAG = "usbd_uvc"; -#if CONFIG_UVC_SUPPORT_TWO_CAM -#define UVC_CAM_NUM 2 -#else #define UVC_CAM_NUM 1 -#endif typedef struct { @@ -85,12 +81,6 @@ void tud_suspend_cb(bool remote_wakeup_en) { s_uvc_device.user_config[0].stop_cb(s_uvc_device.user_config[0].cb_ctx); } -#if CONFIG_UVC_SUPPORT_TWO_CAM - if (s_uvc_device.user_config[1].stop_cb) - { - s_uvc_device.user_config[1].stop_cb(s_uvc_device.user_config[1].cb_ctx); - } -#endif ESP_LOGI(TAG, "Suspend"); } @@ -178,82 +168,6 @@ static void video_task(void *arg) } } -#if CONFIG_UVC_SUPPORT_TWO_CAM -static void video_task2(void *arg) -{ - uint32_t start_ms = 0; - uint32_t frame_num = 0; - uint32_t frame_len = 0; - uint32_t already_start = 0; - uint32_t tx_busy = 0; - uint8_t *uvc_buffer = s_uvc_device.user_config[1].uvc_buffer; - uint32_t uvc_buffer_size = s_uvc_device.user_config[1].uvc_buffer_size; - uvc_fb_t *pic = NULL; - - while (1) - { - if (!tud_video_n_streaming(1, 0)) - { - already_start = 0; - frame_num = 0; - tx_busy = 0; - vTaskDelay(1); - continue; - } - - if (!already_start) - { - already_start = 1; - start_ms = get_time_millis(); - } - - uint32_t cur = get_time_millis(); - if (cur - start_ms < s_uvc_device.interval_ms[1]) - { - vTaskDelay(1); - continue; - } - - if (tx_busy) - { - uint32_t xfer_done = ulTaskNotifyTake(pdTRUE, 1); - if (xfer_done == 0) - { - continue; - } - ++frame_num; - tx_busy = 0; - } - - start_ms += s_uvc_device.interval_ms[1]; - ESP_LOGD(TAG, "frame %" PRIu32 " taking picture...", frame_num); - pic = s_uvc_device.user_config[1].fb_get_cb(s_uvc_device.user_config[1].cb_ctx); - if (pic) - { - ESP_LOGD(TAG, "Picture taken! Its size was: %zu bytes", pic->len); - } - else - { - ESP_LOGE(TAG, "Failed to capture picture"); - continue; - } - - if (pic->len > uvc_buffer_size) - { - ESP_LOGW(TAG, "frame size is too big, dropping frame"); - s_uvc_device.user_config[1].fb_return_cb(pic, s_uvc_device.user_config[1].cb_ctx); - continue; - } - frame_len = pic->len; - memcpy(uvc_buffer, pic->buf, frame_len); - s_uvc_device.user_config[1].fb_return_cb(pic, s_uvc_device.user_config[1].cb_ctx); - tx_busy = 1; - tud_video_n_frame_xfer(1, 0, (void *)uvc_buffer, frame_len); - ESP_LOGD(TAG, "frame %" PRIu32 " transfer start, size %" PRIu32, frame_num, frame_len); - } -} -#endif - void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { (void)ctl_idx; @@ -307,20 +221,11 @@ esp_err_t uvc_device_config(int index, uvc_device_config_t *config) esp_err_t uvc_device_init(void) { ESP_RETURN_ON_FALSE(s_uvc_device.uvc_init[0], ESP_ERR_INVALID_STATE, TAG, "uvc device 0 not init"); -#if CONFIG_UVC_SUPPORT_TWO_CAM - ESP_RETURN_ON_FALSE(s_uvc_device.uvc_init[1], ESP_ERR_INVALID_STATE, TAG, "uvc device 1 not init, if not use, please disable CONFIG_UVC_SUPPORT_TWO_CAM"); -#endif #ifdef CONFIG_FORMAT_MJPEG_CAM1 s_uvc_device.format[0] = UVC_FORMAT_JPEG; #endif -#if CONFIG_UVC_SUPPORT_TWO_CAM -#ifdef CONFIG_FORMAT_MJPEG_CAM2 - s_uvc_device.format[1] = UVC_FORMAT_JPEG; -#endif -#endif - // init device stack on configured roothub port usb_phy_init(); bool usb_init = tusb_init(); @@ -335,10 +240,6 @@ esp_err_t uvc_device_init(void) #if (CFG_TUD_VIDEO) core_id = (CONFIG_UVC_CAM1_TASK_CORE < 0) ? tskNO_AFFINITY : CONFIG_UVC_CAM1_TASK_CORE; xTaskCreatePinnedToCore(video_task, "UVC", 4096, NULL, CONFIG_UVC_CAM1_TASK_PRIORITY, &s_uvc_device.uvc_task_hdl[0], core_id); -#if CONFIG_UVC_SUPPORT_TWO_CAM - core_id = (CONFIG_UVC_CAM2_TASK_CORE < 0) ? tskNO_AFFINITY : CONFIG_UVC_CAM2_TASK_CORE; - xTaskCreatePinnedToCore(video_task2, "UVC2", 4096, NULL, CONFIG_UVC_CAM2_TASK_PRIORITY, &s_uvc_device.uvc_task_hdl[1], core_id); -#endif #endif ESP_LOGI(TAG, "UVC Device Start, Version: %d.%d.%d", USB_DEVICE_UVC_VER_MAJOR, USB_DEVICE_UVC_VER_MINOR, USB_DEVICE_UVC_VER_PATCH); return ESP_OK; diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 064f8e0..be12760 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -107,6 +107,28 @@ menu "OpenIris: WiFi Configuration" endmenu +menu "OpenIris: Serial Communication Settings" + config UART_PORT_NUMBER + int "UART Port number" + default 0 + range 0 4 + help + The UART port to use for communication + + config UART_RX_PIN + int "UART RX PIN number" + default -1 + help + The UART RX pin to use for communication. If set to -1 we won't override it. It will be treated as NO_CHANGE + + config UART_TX_PIN + int "UART TX PIN number" + default -1 + help + The UART TX pin to use for communication. If set to -1 we won't override it. It will be treated as NO_CHANGE + +endmenu + menu "OpenIris: LED Configuration" config LED_DEBUG_ENABLE diff --git a/main/openiris_main.cpp b/main/openiris_main.cpp index 75ba6e2..95fae32 100644 --- a/main/openiris_main.cpp +++ b/main/openiris_main.cpp @@ -22,7 +22,10 @@ #include #include #include + +#ifdef CONFIG_MONITORING_LED_CURRENT #include +#endif #ifdef CONFIG_GENERAL_INCLUDE_UVC_MODE #include @@ -36,7 +39,7 @@ #define BLINK_GPIO (gpio_num_t) CONFIG_LED_DEBUG_GPIO #else // Use an invalid / unused GPIO when debug LED disabled to avoid accidental toggles -#define BLINK_GPIO (gpio_num_t) - 1 +#define BLINK_GPIO (gpio_num_t)(-1) #endif #define CONFIG_LED_C_PIN_GPIO (gpio_num_t) CONFIG_LED_EXTERNAL_GPIO @@ -61,14 +64,18 @@ MDNSManager mdnsManager(deviceConfig, eventQueue); std::shared_ptr cameraHandler = std::make_shared(deviceConfig, eventQueue); StreamServer streamServer(80, stateManager); -auto *restAPI = new RestAPI("http://0.0.0.0:81", commandManager); +std::shared_ptr restAPI = std::make_shared("http://0.0.0.0:81", commandManager); #ifdef CONFIG_GENERAL_INCLUDE_UVC_MODE UVCStreamManager uvcStream; #endif auto ledManager = std::make_shared(BLINK_GPIO, CONFIG_LED_C_PIN_GPIO, ledStateQueue, deviceConfig); + +#ifdef CONFIG_MONITORING_LED_CURRENT std::shared_ptr monitoringManager = std::make_shared(); +#endif + auto *serialManager = new SerialManager(commandManager, &timerHandle); void startWiFiMode(); @@ -165,7 +172,6 @@ void startWiredMode(bool shouldCloseSerialManager) #ifndef CONFIG_GENERAL_INCLUDE_UVC_MODE ESP_LOGE("[MAIN]", "UVC mode selected but the board likely does not support it."); ESP_LOGI("[MAIN]", "Falling back to WiFi mode if credentials available"); - deviceMode = StreamingMode::WIFI; startWiFiMode(); #else ESP_LOGI("[MAIN]", "Starting UVC streaming mode."); @@ -216,6 +222,7 @@ void startWiFiMode() mdnsManager.start(); restAPI->begin(); StreamingMode mode = deviceConfig->getDeviceMode(); + // don't enable in SETUP mode if (mode == StreamingMode::WIFI) { streamServer.startStreamServer(); @@ -223,8 +230,8 @@ void startWiFiMode() xTaskCreate( HandleRestAPIPollTask, "HandleRestAPIPollTask", - 1024 * 2, - restAPI, + 2024 * 2, + restAPI.get(), 1, // it's the rest API, we only serve commands over it so we don't really need a higher priority nullptr); #else @@ -265,18 +272,23 @@ extern "C" void app_main(void) dependencyRegistry->registerService(DependencyType::wifi_manager, wifiManager); #endif dependencyRegistry->registerService(DependencyType::led_manager, ledManager); + +#ifdef CONFIG_MONITORING_LED_CURRENT dependencyRegistry->registerService(DependencyType::monitoring_manager, monitoringManager); +#endif // add endpoint to check firmware version - // setup CI and building for other boards // esp_log_set_vprintf(&websocket_logger); Logo::printASCII(); initNVSStorage(); deviceConfig->load(); ledManager->setup(); + +#ifdef CONFIG_MONITORING_LED_CURRENT monitoringManager->setup(); monitoringManager->start(); +#endif xTaskCreate( HandleStateManagerTask, diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d98617f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,36 @@ +[project] +name = "blink" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "pyserial>=3.5", + "pytest>=9.0.1", + "python-dotenv>=1.2.1", +] + +[dependency-groups] +dev = [ + "bumpver>=2025.1131", +] + +[bumpver] +current_version = "0.1.0" +version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]" +commit = true +tag = true +push = false + +[bumpver.file_patterns] +"pyproject.toml" = [ + 'version = "{version}"', +] +"sdkconfig" = [ + 'CONFIG_GENERAL_VERSION="{version}"', +] + +[tool.pytest] +testpaths = [ + "tests" +] diff --git a/pytest_blink.py b/pytest_blink.py deleted file mode 100644 index 8df33cf..0000000 --- a/pytest_blink.py +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: CC0-1.0 -import logging -import os - -import pytest -from pytest_embedded_idf.dut import IdfDut - - -@pytest.mark.supported_targets -@pytest.mark.generic -def test_blink(dut: IdfDut) -> None: - # check and log bin size - binary_file = os.path.join(dut.app.binary_path, 'blink.bin') - bin_size = os.path.getsize(binary_file) - logging.info('blink_bin_size : {}KB'.format(bin_size // 1024)) diff --git a/sdkconfig b/sdkconfig index ce3f32c..f11818e 100644 --- a/sdkconfig +++ b/sdkconfig @@ -595,6 +595,14 @@ CONFIG_WIFI_AP_SSID="EyeTrackVR" CONFIG_WIFI_AP_PASSWORD="12345678" # end of OpenIris: WiFi Configuration +# +# OpenIris: Serial Communication Settings +# +CONFIG_UART_PORT_NUMBER=0 +CONFIG_UART_RX_PIN=-1 +CONFIG_UART_TX_PIN=-1 +# end of OpenIris: Serial Communication Settings + # # OpenIris: LED Configuration # diff --git a/sdkconfig.old b/sdkconfig.old new file mode 100644 index 0000000..62657d0 --- /dev/null +++ b/sdkconfig.old @@ -0,0 +1,2057 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) 5.4.2 Project Configuration +CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000 +CONFIG_SOC_MPU_REGIONS_MAX_NUM=8 +CONFIG_SOC_ADC_SUPPORTED=y +CONFIG_SOC_UART_SUPPORTED=y +CONFIG_SOC_PCNT_SUPPORTED=y +CONFIG_SOC_PHY_SUPPORTED=y +CONFIG_SOC_WIFI_SUPPORTED=y +CONFIG_SOC_TWAI_SUPPORTED=y +CONFIG_SOC_GDMA_SUPPORTED=y +CONFIG_SOC_AHB_GDMA_SUPPORTED=y +CONFIG_SOC_GPTIMER_SUPPORTED=y +CONFIG_SOC_LCDCAM_SUPPORTED=y +CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y +CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y +CONFIG_SOC_MCPWM_SUPPORTED=y +CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y +CONFIG_SOC_CACHE_SUPPORT_WRAP=y +CONFIG_SOC_ULP_SUPPORTED=y +CONFIG_SOC_ULP_FSM_SUPPORTED=y +CONFIG_SOC_RISCV_COPROC_SUPPORTED=y +CONFIG_SOC_BT_SUPPORTED=y +CONFIG_SOC_USB_OTG_SUPPORTED=y +CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y +CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y +CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED=y +CONFIG_SOC_SUPPORTS_SECURE_DL_MODE=y +CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD=y +CONFIG_SOC_EFUSE_SUPPORTED=y +CONFIG_SOC_SDMMC_HOST_SUPPORTED=y +CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED=y +CONFIG_SOC_RTC_MEM_SUPPORTED=y +CONFIG_SOC_PSRAM_DMA_CAPABLE=y +CONFIG_SOC_XT_WDT_SUPPORTED=y +CONFIG_SOC_I2S_SUPPORTED=y +CONFIG_SOC_RMT_SUPPORTED=y +CONFIG_SOC_SDM_SUPPORTED=y +CONFIG_SOC_GPSPI_SUPPORTED=y +CONFIG_SOC_LEDC_SUPPORTED=y +CONFIG_SOC_I2C_SUPPORTED=y +CONFIG_SOC_SYSTIMER_SUPPORTED=y +CONFIG_SOC_SUPPORT_COEXISTENCE=y +CONFIG_SOC_TEMP_SENSOR_SUPPORTED=y +CONFIG_SOC_AES_SUPPORTED=y +CONFIG_SOC_MPI_SUPPORTED=y +CONFIG_SOC_SHA_SUPPORTED=y +CONFIG_SOC_HMAC_SUPPORTED=y +CONFIG_SOC_DIG_SIGN_SUPPORTED=y +CONFIG_SOC_FLASH_ENC_SUPPORTED=y +CONFIG_SOC_SECURE_BOOT_SUPPORTED=y +CONFIG_SOC_MEMPROT_SUPPORTED=y +CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y +CONFIG_SOC_BOD_SUPPORTED=y +CONFIG_SOC_CLK_TREE_SUPPORTED=y +CONFIG_SOC_MPU_SUPPORTED=y +CONFIG_SOC_WDT_SUPPORTED=y +CONFIG_SOC_SPI_FLASH_SUPPORTED=y +CONFIG_SOC_RNG_SUPPORTED=y +CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y +CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y +CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y +CONFIG_SOC_PM_SUPPORTED=y +CONFIG_SOC_SIMD_INSTRUCTION_SUPPORTED=y +CONFIG_SOC_XTAL_SUPPORT_40M=y +CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y +CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_ARBITER_SUPPORTED=y +CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED=y +CONFIG_SOC_ADC_MONITOR_SUPPORTED=y +CONFIG_SOC_ADC_DMA_SUPPORTED=y +CONFIG_SOC_ADC_PERIPH_NUM=2 +CONFIG_SOC_ADC_MAX_CHANNEL_NUM=10 +CONFIG_SOC_ADC_ATTEN_NUM=4 +CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=2 +CONFIG_SOC_ADC_PATT_LEN_MAX=24 +CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_RESULT_BYTES=4 +CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM=2 +CONFIG_SOC_ADC_DIGI_MONITOR_NUM=2 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=83333 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=611 +CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED=y +CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED=y +CONFIG_SOC_ADC_SHARED_POWER=y +CONFIG_SOC_APB_BACKUP_DMA=y +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y +CONFIG_SOC_CACHE_WRITEBACK_SUPPORTED=y +CONFIG_SOC_CACHE_FREEZE_SUPPORTED=y +CONFIG_SOC_CPU_CORES_NUM=2 +CONFIG_SOC_CPU_INTR_NUM=32 +CONFIG_SOC_CPU_HAS_FPU=y +CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y +CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=64 +CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16 +CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 +CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 +CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100 +CONFIG_SOC_AHB_GDMA_VERSION=1 +CONFIG_SOC_GDMA_NUM_GROUPS_MAX=1 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP=5 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX=5 +CONFIG_SOC_AHB_GDMA_SUPPORT_PSRAM=y +CONFIG_SOC_GPIO_PORT=1 +CONFIG_SOC_GPIO_PIN_COUNT=49 +CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER=y +CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB=y +CONFIG_SOC_GPIO_SUPPORT_RTC_INDEPENDENT=y +CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y +CONFIG_SOC_GPIO_VALID_GPIO_MASK=0x1FFFFFFFFFFFF +CONFIG_SOC_GPIO_IN_RANGE_MAX=48 +CONFIG_SOC_GPIO_OUT_RANGE_MAX=48 +CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x0001FFFFFC000000 +CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y +CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y +CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_OUT_AUTO_ENABLE=y +CONFIG_SOC_I2C_NUM=2 +CONFIG_SOC_HP_I2C_NUM=2 +CONFIG_SOC_I2C_FIFO_LEN=32 +CONFIG_SOC_I2C_CMD_REG_NUM=8 +CONFIG_SOC_I2C_SUPPORT_SLAVE=y +CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS=y +CONFIG_SOC_I2C_SUPPORT_XTAL=y +CONFIG_SOC_I2C_SUPPORT_RTC=y +CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS=y +CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE=y +CONFIG_SOC_I2S_NUM=2 +CONFIG_SOC_I2S_HW_VERSION_2=y +CONFIG_SOC_I2S_SUPPORTS_XTAL=y +CONFIG_SOC_I2S_SUPPORTS_PLL_F160M=y +CONFIG_SOC_I2S_SUPPORTS_PCM=y +CONFIG_SOC_I2S_SUPPORTS_PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y +CONFIG_SOC_I2S_PDM_MAX_TX_LINES=2 +CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y +CONFIG_SOC_I2S_PDM_MAX_RX_LINES=4 +CONFIG_SOC_I2S_SUPPORTS_TDM=y +CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y +CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_LEDC_TIMER_NUM=4 +CONFIG_SOC_LEDC_CHANNEL_NUM=8 +CONFIG_SOC_LEDC_TIMER_BIT_WIDTH=14 +CONFIG_SOC_LEDC_SUPPORT_FADE_STOP=y +CONFIG_SOC_MCPWM_GROUPS=2 +CONFIG_SOC_MCPWM_TIMERS_PER_GROUP=3 +CONFIG_SOC_MCPWM_OPERATORS_PER_GROUP=3 +CONFIG_SOC_MCPWM_COMPARATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GENERATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_TRIGGERS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GPIO_FAULTS_PER_GROUP=3 +CONFIG_SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP=y +CONFIG_SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER=3 +CONFIG_SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP=3 +CONFIG_SOC_MCPWM_SWSYNC_CAN_PROPAGATE=y +CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=1 +CONFIG_SOC_MMU_PERIPH_NUM=1 +CONFIG_SOC_PCNT_GROUPS=1 +CONFIG_SOC_PCNT_UNITS_PER_GROUP=4 +CONFIG_SOC_PCNT_CHANNELS_PER_UNIT=2 +CONFIG_SOC_PCNT_THRES_POINT_PER_UNIT=2 +CONFIG_SOC_RMT_GROUPS=1 +CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_CHANNELS_PER_GROUP=8 +CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48 +CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y +CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION=y +CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO=y +CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY=y +CONFIG_SOC_RMT_SUPPORT_XTAL=y +CONFIG_SOC_RMT_SUPPORT_RC_FAST=y +CONFIG_SOC_RMT_SUPPORT_APB=y +CONFIG_SOC_RMT_SUPPORT_DMA=y +CONFIG_SOC_LCD_I80_SUPPORTED=y +CONFIG_SOC_LCD_RGB_SUPPORTED=y +CONFIG_SOC_LCD_I80_BUSES=1 +CONFIG_SOC_LCD_RGB_PANELS=1 +CONFIG_SOC_LCD_I80_BUS_WIDTH=16 +CONFIG_SOC_LCD_RGB_DATA_WIDTH=16 +CONFIG_SOC_LCD_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_LCDCAM_I80_NUM_BUSES=1 +CONFIG_SOC_LCDCAM_I80_BUS_WIDTH=16 +CONFIG_SOC_LCDCAM_RGB_NUM_PANELS=1 +CONFIG_SOC_LCDCAM_RGB_DATA_WIDTH=16 +CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=549 +CONFIG_SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTCIO_PIN_COUNT=22 +CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y +CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y +CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y +CONFIG_SOC_SDM_GROUPS=y +CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 +CONFIG_SOC_SDM_CLK_SUPPORT_APB=y +CONFIG_SOC_SPI_PERIPH_NUM=3 +CONFIG_SOC_SPI_MAX_CS_NUM=6 +CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 +CONFIG_SOC_SPI_SUPPORT_DDRCLK=y +CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS=y +CONFIG_SOC_SPI_SUPPORT_CD_SIG=y +CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS=y +CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y +CONFIG_SOC_SPI_SUPPORT_CLK_APB=y +CONFIG_SOC_SPI_SUPPORT_CLK_XTAL=y +CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT=y +CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y +CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16 +CONFIG_SOC_SPI_SUPPORT_OCT=y +CONFIG_SOC_SPI_SCT_SUPPORTED=y +CONFIG_SOC_SPI_SCT_REG_NUM=14 +CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX=y +CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX=0x3FFFA +CONFIG_SOC_MEMSPI_SRC_FREQ_120M=y +CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y +CONFIG_SOC_SPIRAM_SUPPORTED=y +CONFIG_SOC_SPIRAM_XIP_SUPPORTED=y +CONFIG_SOC_SYSTIMER_COUNTER_NUM=2 +CONFIG_SOC_SYSTIMER_ALARM_NUM=3 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI=20 +CONFIG_SOC_SYSTIMER_FIXED_DIVIDER=y +CONFIG_SOC_SYSTIMER_INT_LEVEL=y +CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE=y +CONFIG_SOC_TIMER_GROUPS=2 +CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 +CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54 +CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y +CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y +CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 +CONFIG_SOC_TOUCH_SENSOR_VERSION=2 +CONFIG_SOC_TOUCH_SENSOR_NUM=15 +CONFIG_SOC_TOUCH_SUPPORT_SLEEP_WAKEUP=y +CONFIG_SOC_TOUCH_SUPPORT_WATERPROOF=y +CONFIG_SOC_TOUCH_SUPPORT_PROX_SENSING=y +CONFIG_SOC_TOUCH_PROXIMITY_CHANNEL_NUM=3 +CONFIG_SOC_TOUCH_PROXIMITY_MEAS_DONE_SUPPORTED=y +CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 +CONFIG_SOC_TWAI_CONTROLLER_NUM=1 +CONFIG_SOC_TWAI_CLK_SUPPORT_APB=y +CONFIG_SOC_TWAI_BRP_MIN=2 +CONFIG_SOC_TWAI_BRP_MAX=16384 +CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS=y +CONFIG_SOC_UART_NUM=3 +CONFIG_SOC_UART_HP_NUM=3 +CONFIG_SOC_UART_FIFO_LEN=128 +CONFIG_SOC_UART_BITRATE_MAX=5000000 +CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND=y +CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y +CONFIG_SOC_UART_SUPPORT_APB_CLK=y +CONFIG_SOC_UART_SUPPORT_RTC_CLK=y +CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y +CONFIG_SOC_USB_OTG_PERIPH_NUM=1 +CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968 +CONFIG_SOC_SHA_SUPPORT_DMA=y +CONFIG_SOC_SHA_SUPPORT_RESUME=y +CONFIG_SOC_SHA_GDMA=y +CONFIG_SOC_SHA_SUPPORT_SHA1=y +CONFIG_SOC_SHA_SUPPORT_SHA224=y +CONFIG_SOC_SHA_SUPPORT_SHA256=y +CONFIG_SOC_SHA_SUPPORT_SHA384=y +CONFIG_SOC_SHA_SUPPORT_SHA512=y +CONFIG_SOC_SHA_SUPPORT_SHA512_224=y +CONFIG_SOC_SHA_SUPPORT_SHA512_256=y +CONFIG_SOC_SHA_SUPPORT_SHA512_T=y +CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 +CONFIG_SOC_MPI_OPERATIONS_NUM=3 +CONFIG_SOC_RSA_MAX_BIT_LEN=4096 +CONFIG_SOC_AES_SUPPORT_DMA=y +CONFIG_SOC_AES_GDMA=y +CONFIG_SOC_AES_SUPPORT_AES_128=y +CONFIG_SOC_AES_SUPPORT_AES_256=y +CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT1_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_BT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_CPU_PD=y +CONFIG_SOC_PM_SUPPORT_TAGMEM_PD=y +CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y +CONFIG_SOC_PM_SUPPORT_RC_FAST_PD=y +CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD=y +CONFIG_SOC_PM_SUPPORT_MAC_BB_PD=y +CONFIG_SOC_PM_SUPPORT_MODEM_PD=y +CONFIG_SOC_CONFIGURABLE_VDDSDIO_SUPPORTED=y +CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY=y +CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL=y +CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA=y +CONFIG_SOC_PM_MODEM_PD_BY_SW=y +CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256=y +CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION=y +CONFIG_SOC_CLK_XTAL32K_SUPPORTED=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_DCACHE=y +CONFIG_SOC_EFUSE_HARD_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_USB_JTAG=y +CONFIG_SOC_EFUSE_SOFT_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT=y +CONFIG_SOC_EFUSE_DIS_ICACHE=y +CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK=y +CONFIG_SOC_SECURE_BOOT_V2_RSA=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 +CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=64 +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_OPTIONS=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_256=y +CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE=256 +CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +CONFIG_SOC_MAC_BB_PD_MEM_SIZE=192 +CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH=12 +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME=y +CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_OPI_MODE=y +CONFIG_SOC_SPI_MEM_SUPPORT_TIMING_TUNING=y +CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y +CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y +CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY=y +CONFIG_SOC_MEMSPI_CORE_CLK_SHARED_WITH_PSRAM=y +CONFIG_SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP=y +CONFIG_SOC_COEX_HW_PTI=y +CONFIG_SOC_EXTERNAL_COEX_LEADER_TX_LINE=y +CONFIG_SOC_SDMMC_USE_GPIO_MATRIX=y +CONFIG_SOC_SDMMC_NUM_SLOTS=2 +CONFIG_SOC_SDMMC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_SDMMC_DELAY_PHASE_NUM=4 +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y +CONFIG_SOC_WIFI_HW_TSF=y +CONFIG_SOC_WIFI_FTM_SUPPORT=y +CONFIG_SOC_WIFI_GCMP_SUPPORT=y +CONFIG_SOC_WIFI_WAPI_SUPPORT=y +CONFIG_SOC_WIFI_CSI_SUPPORT=y +CONFIG_SOC_WIFI_MESH_SUPPORT=y +CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND=y +CONFIG_SOC_BLE_SUPPORTED=y +CONFIG_SOC_BLE_MESH_SUPPORTED=y +CONFIG_SOC_BLE_50_SUPPORTED=y +CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y +CONFIG_SOC_BLUFI_SUPPORTED=y +CONFIG_SOC_ULP_HAS_ADC=y +CONFIG_SOC_PHY_COMBO_MODULE=y +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TOOLCHAIN="gcc" +CONFIG_IDF_TOOLCHAIN_GCC=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET_ARCH="xtensa" +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_INIT_VERSION="$IDF_INIT_VERSION" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# Build type +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# CONFIG_APP_REPRODUCIBLE_BUILD is not set +# CONFIG_APP_NO_BLOBS is not set +# end of Build type +# Bootloader config +# Bootloader manager +CONFIG_BOOTLOADER_COMPILE_TIME_DATE=y +CONFIG_BOOTLOADER_PROJECT_VER=1 +# end of Bootloader manager +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# Log +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +# Format +# CONFIG_BOOTLOADER_LOG_COLORS is not set +CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS=y +# end of Format +# end of Log +# Serial Flash Configurations +# CONFIG_BOOTLOADER_FLASH_DC_AWARE is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Serial Flash Configurations +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config +# Security features +CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED=y +CONFIG_SECURE_BOOT_V2_PREFERRED=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +CONFIG_SECURE_ROM_DL_MODE_ENABLED=y +# end of Security features +# Application manager +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=9 +# end of Application manager +CONFIG_ESP_ROM_HAS_CRC_LE=y +CONFIG_ESP_ROM_HAS_CRC_BE=y +CONFIG_ESP_ROM_HAS_MZ_CRC32=y +CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +CONFIG_ESP_ROM_UART_CLK_IS_XTAL=y +CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING=y +CONFIG_ESP_ROM_USB_OTG_NUM=3 +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=4 +CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG=y +CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV=y +CONFIG_ESP_ROM_GET_CLK_FREQ=y +CONFIG_ESP_ROM_HAS_HAL_WDT=y +CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y +CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y +CONFIG_ESP_ROM_HAS_SPI_FLASH=y +CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y +CONFIG_ESP_ROM_HAS_NEWLIB=y +CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y +CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME=y +CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y +CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y +CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG=y +CONFIG_ESP_ROM_HAS_SW_FLOAT=y +CONFIG_ESP_ROM_HAS_VERSION=y +CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB=y +CONFIG_ESP_ROM_HAS_OUTPUT_PUTC_FUNC=y +# Boot ROM Behavior +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior +# Serial flasher config +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=y +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +# CONFIG_ESPTOOLPY_FLASHMODE_DIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config +# Partition Table +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="min_spiffs.csv" +CONFIG_PARTITION_TABLE_FILENAME="min_spiffs.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table +# ENV_Caps +CONFIG_ENV_GPIO_RANGE_MIN=0 +CONFIG_ENV_GPIO_RANGE_MAX=48 +CONFIG_ENV_GPIO_IN_RANGE_MAX=48 +CONFIG_ENV_GPIO_OUT_RANGE_MAX=48 +# end of ENV_Caps +# OpenIris: General Configuration +# CONFIG_GENERAL_INCLUDE_UVC_MODE is not set +# CONFIG_START_IN_UVC_MODE is not set +# CONFIG_GENERAL_STARTUP_DELAY is not set +CONFIG_GENERAL_VERSION="0.0.1" +# end of OpenIris: General Configuration +# OpenIris: Camera Configuration +CONFIG_CAMERA_USB_XCLK_FREQ=23000000 +CONFIG_CAMERA_WIFI_XCLK_FREQ=16500000 +# end of OpenIris: Camera Configuration +# OpenIris: WiFi Configuration +CONFIG_WIFI_MDNS_HOSTNAME="openiristracker" +CONFIG_WIFI_SSID="" +CONFIG_WIFI_PASSWORD="" +CONFIG_WIFI_AP_SSID="EyeTrackVR" +CONFIG_WIFI_AP_PASSWORD="12345678" +# end of OpenIris: WiFi Configuration +# OpenIris: LED Configuration +CONFIG_LED_DEBUG_GPIO=38 +CONFIG_LED_EXTERNAL_GPIO=1 +CONFIG_LED_EXTERNAL_CONTROL=y +CONFIG_LED_EXTERNAL_PWM_FREQ=5000 +CONFIG_LED_EXTERNAL_PWM_DUTY_CYCLE=100 +# end of OpenIris: LED Configuration +# Camera sensor pinout configuration +CONFIG_CAMERA_MODULE_NAME="SWROOM_BABBLE_S3" +CONFIG_PWDN_GPIO_NUM=-1 +CONFIG_RESET_GPIO_NUM=-1 +CONFIG_XCLK_GPIO_NUM=4 +CONFIG_SIOD_GPIO_NUM=48 +CONFIG_SIOC_GPIO_NUM=47 +CONFIG_Y9_GPIO_NUM=13 +CONFIG_Y8_GPIO_NUM=5 +CONFIG_Y7_GPIO_NUM=6 +CONFIG_Y6_GPIO_NUM=15 +CONFIG_Y5_GPIO_NUM=17 +CONFIG_Y4_GPIO_NUM=8 +CONFIG_Y3_GPIO_NUM=18 +CONFIG_Y2_GPIO_NUM=16 +CONFIG_VSYNC_GPIO_NUM=21 +CONFIG_HREF_GPIO_NUM=14 +CONFIG_PCLK_GPIO_NUM=7 +# end of Camera sensor pinout configuration +# Compiler options +# CONFIG_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +CONFIG_COMPILER_OPTIMIZATION_PERF=y +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE=y +CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_NO_MERGE_CONSTANTS is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS=y +# CONFIG_COMPILER_DISABLE_GCC12_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC13_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC14_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +CONFIG_COMPILER_RT_LIB_GCCLIB=y +CONFIG_COMPILER_RT_LIB_NAME="gcc" +# CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING is not set +CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE=y +# CONFIG_COMPILER_STATIC_ANALYZER is not set +# end of Compiler options +# Component config +# Application Level Tracing +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +# CONFIG_APPTRACE_DEST_UART1 is not set +# CONFIG_APPTRACE_DEST_UART2 is not set +# CONFIG_APPTRACE_DEST_USB_CDC is not set +CONFIG_APPTRACE_DEST_UART_NONE=y +CONFIG_APPTRACE_UART_TASK_PRIO=1 +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing +# Bluetooth +# CONFIG_BT_ENABLED is not set +# Common Options +# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set +# end of Common Options +# end of Bluetooth +# Console Library +# CONFIG_CONSOLE_SORTED_HELP is not set +# end of Console Library +# Driver Configurations +# TWAI Configuration +# CONFIG_TWAI_ISR_IN_IRAM is not set +CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y +# end of TWAI Configuration +# Legacy ADC Driver Configuration +# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set +# Legacy ADC Calibration Configuration +# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set +# end of Legacy ADC Calibration Configuration +# end of Legacy ADC Driver Configuration +# Legacy MCPWM Driver Configurations +# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy MCPWM Driver Configurations +# Legacy Timer Group Driver Configurations +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Timer Group Driver Configurations +# Legacy RMT Driver Configurations +# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy RMT Driver Configurations +# Legacy I2S Driver Configurations +# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2S Driver Configurations +# Legacy I2C Driver Configurations +# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2C Driver Configurations +# Legacy PCNT Driver Configurations +# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy PCNT Driver Configurations +# Legacy SDM Driver Configurations +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy SDM Driver Configurations +# Legacy Temperature Sensor Driver Configurations +# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Temperature Sensor Driver Configurations +# end of Driver Configurations +# eFuse Bit Manager +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager +# ESP-TLS +CONFIG_ESP_TLS_USING_MBEDTLS=y +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set +# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS +# ADC and ADC Calibration +# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set +# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set +# CONFIG_ADC_ENABLE_DEBUG_LOG is not set +# end of ADC and ADC Calibration +# Wireless Coexistence +CONFIG_ESP_COEX_ENABLED=y +# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_ESP_COEX_GPIO_DEBUG is not set +# end of Wireless Coexistence +# Common ESP-related +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related +# ESP-Driver:GPIO Configurations +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:GPIO Configurations +# ESP-Driver:GPTimer Configurations +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +CONFIG_GPTIMER_OBJ_CACHE_SAFE=y +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:GPTimer Configurations +# ESP-Driver:I2C Configurations +# CONFIG_I2C_ISR_IRAM_SAFE is not set +# CONFIG_I2C_ENABLE_DEBUG_LOG is not set +# CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 is not set +# end of ESP-Driver:I2C Configurations +# ESP-Driver:I2S Configurations +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:I2S Configurations +# ESP-Driver:LEDC Configurations +# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:LEDC Configurations +# ESP-Driver:MCPWM Configurations +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:MCPWM Configurations +# ESP-Driver:PCNT Configurations +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:PCNT Configurations +# ESP-Driver:RMT Configurations +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:RMT Configurations +# ESP-Driver:Sigma Delta Modulator Configurations +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Sigma Delta Modulator Configurations +# ESP-Driver:SPI Configurations +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of ESP-Driver:SPI Configurations +# ESP-Driver:Touch Sensor Configurations +# CONFIG_TOUCH_CTRL_FUNC_IN_IRAM is not set +# CONFIG_TOUCH_ISR_IRAM_SAFE is not set +# CONFIG_TOUCH_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Touch Sensor Configurations +# ESP-Driver:Temperature Sensor Configurations +# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Temperature Sensor Configurations +# ESP-Driver:UART Configurations +# CONFIG_UART_ISR_IN_IRAM is not set +# end of ESP-Driver:UART Configurations +# ESP-Driver:USB Serial/JTAG Configuration +CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y +# end of ESP-Driver:USB Serial/JTAG Configuration +# Ethernet +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# CONFIG_ETH_TRANSMIT_MUTEX is not set +# end of Ethernet +# Event Loop Library +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library +# GDB Stub +CONFIG_ESP_GDBSTUB_ENABLED=y +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y +CONFIG_ESP_GDBSTUB_MAX_TASKS=32 +# end of GDB Stub +# ESP HID +CONFIG_ESPHID_TASK_SIZE_BT=2048 +CONFIG_ESPHID_TASK_SIZE_BLE=4096 +# end of ESP HID +# ESP HTTP client +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT is not set +CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTP client +# HTTP Server +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +CONFIG_HTTPD_WS_SUPPORT=y +# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set +CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT=2000 +# end of HTTP Server +# ESP HTTPS OTA +# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set +# CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set +CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTPS OTA +# ESP HTTPS server +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTPS server +# Hardware Settings +# Chip revision +CONFIG_ESP32S3_REV_MIN_0=y +# CONFIG_ESP32S3_REV_MIN_1 is not set +# CONFIG_ESP32S3_REV_MIN_2 is not set +CONFIG_ESP32S3_REV_MIN_FULL=0 +CONFIG_ESP_REV_MIN_FULL=0 +# Maximum Supported ESP32-S3 Revision (Rev v0.99) +CONFIG_ESP32S3_REV_MAX_FULL=99 +CONFIG_ESP_REV_MAX_FULL=99 +CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL=0 +CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=199 +# Maximum Supported ESP32-S3 eFuse Block Revision (eFuse Block Rev v1.99) +# end of Chip revision +# MAC Config +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC is not set +# end of MAC Config +# Sleep Config +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY=2000 +# CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is not set +# CONFIG_ESP_SLEEP_DEBUG is not set +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=y +# end of Sleep Config +# RTC Clock Config +CONFIG_RTC_CLK_SRC_INT_RC=y +# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_RTC_CLK_CAL_CYCLES=1024 +# end of RTC Clock Config +# Peripheral Control +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y +# end of Peripheral Control +# GDMA Configurations +CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y +CONFIG_GDMA_ISR_HANDLER_IN_IRAM=y +CONFIG_GDMA_OBJ_DRAM_SAFE=y +# CONFIG_GDMA_ENABLE_DEBUG_LOG is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configurations +# Main XTAL Config +CONFIG_XTAL_FREQ_40=y +CONFIG_XTAL_FREQ=40 +# end of Main XTAL Config +CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y +# end of Hardware Settings +# ESP-Driver:LCD Controller Configurations +# CONFIG_LCD_ENABLE_DEBUG_LOG is not set +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# CONFIG_LCD_RGB_RESTART_IN_VSYNC is not set +# end of ESP-Driver:LCD Controller Configurations +# ESP-MM: Memory Management Configurations +# CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS is not set +# end of ESP-MM: Memory Management Configurations +# ESP NETIF Adapter +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +# CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION is not set +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y +CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC=y +# CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS is not set +# CONFIG_ESP_NETIF_L2_TAP is not set +# CONFIG_ESP_NETIF_BRIDGE_EN is not set +# CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF is not set +# end of ESP NETIF Adapter +# Partition API Configuration +# end of Partition API Configuration +# PHY +CONFIG_ESP_PHY_ENABLED=y +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +# CONFIG_ESP_PHY_REDUCE_TX_POWER is not set +CONFIG_ESP_PHY_ENABLE_USB=y +# CONFIG_ESP_PHY_ENABLE_CERT_TEST is not set +CONFIG_ESP_PHY_RF_CAL_PARTIAL=y +# CONFIG_ESP_PHY_RF_CAL_NONE is not set +# CONFIG_ESP_PHY_RF_CAL_FULL is not set +CONFIG_ESP_PHY_CALIBRATION_MODE=0 +# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set +# CONFIG_ESP_PHY_RECORD_USED_TIME is not set +# end of PHY +# Power Management +# CONFIG_PM_ENABLE is not set +# CONFIG_PM_SLP_IRAM_OPT is not set +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP=y +# end of Power Management +# ESP PSRAM +CONFIG_SPIRAM=y +# SPI RAM config +CONFIG_SPIRAM_MODE_QUAD=y +# CONFIG_SPIRAM_MODE_OCT is not set +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +# CONFIG_SPIRAM_SPEED_120M is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SPIRAM_SPEED_40M is not set +CONFIG_SPIRAM_SPEED=80 +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION=y +# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set +# CONFIG_SPIRAM_USE_MEMMAP is not set +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=32768 +# CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is not set +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 +# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set +# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set +# end of SPI RAM config +# end of ESP PSRAM +# ESP Ringbuf +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf +# ESP Security Specific +# end of ESP Security Specific +# ESP System Settings +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 +# Cache config +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# end of Cache config +# Memory +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of Memory +# Trace memory +# CONFIG_ESP32S3_TRAX is not set +CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 +# end of Trace memory +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS=0 +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y +# Memory protection +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +# end of Memory protection +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_DEBUG_OCDAWARE=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +# Brownout Detector +CONFIG_ESP_BROWNOUT_DET=y +CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP_BROWNOUT_DET_LVL=7 +# end of Brownout Detector +CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y +CONFIG_ESP_SYSTEM_BBPLL_RECALIB=y +# end of ESP System Settings +# IPC (Inter-Processor Call) +CONFIG_ESP_IPC_TASK_STACK_SIZE=1280 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) +# ESP Timer (High Resolution Timer) +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set +CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 +CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of ESP Timer (High Resolution Timer) +# Wi-Fi +CONFIG_ESP_WIFI_ENABLED=y +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y +# CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER is not set +CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y +# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set +CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0 +CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5 +# CONFIG_ESP_WIFI_CSI_ENABLED is not set +CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP_WIFI_TX_BA_WIN=6 +CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP_WIFI_RX_BA_WIN=6 +CONFIG_ESP_WIFI_NVS_ENABLED=y +CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP_WIFI_IRAM_OPT=y +# CONFIG_ESP_WIFI_EXTRA_IRAM_OPT is not set +CONFIG_ESP_WIFI_RX_IRAM_OPT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP_WIFI_ENABLE_SAE_PK=y +CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50 +CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10 +CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15 +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +CONFIG_ESP_WIFI_GMAC_SUPPORT=y +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +CONFIG_ESP_WIFI_MBEDTLS_CRYPTO=y +CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y +# CONFIG_ESP_WIFI_WAPI_PSK is not set +# CONFIG_ESP_WIFI_SUITE_B_192 is not set +# CONFIG_ESP_WIFI_11KV_SUPPORT is not set +# CONFIG_ESP_WIFI_MBO_SUPPORT is not set +# CONFIG_ESP_WIFI_DPP_SUPPORT is not set +# CONFIG_ESP_WIFI_11R_SUPPORT is not set +# CONFIG_ESP_WIFI_WPS_SOFTAP_REGISTRAR is not set +# WPS Configuration Options +# CONFIG_ESP_WIFI_WPS_STRICT is not set +# CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set +# end of WPS Configuration Options +# CONFIG_ESP_WIFI_DEBUG_PRINT is not set +# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set +CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y +# CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set +# end of Wi-Fi +# Core dump +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump +# FAT Filesystem support +CONFIG_FATFS_VOLUME_COUNT=2 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +# CONFIG_FATFS_SECTOR_512 is not set +CONFIG_FATFS_SECTOR_4096=y +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y +# CONFIG_FATFS_USE_FASTSEEK is not set +CONFIG_FATFS_USE_STRFUNC_NONE=y +# CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV is not set +# CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV is not set +CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 +# CONFIG_FATFS_IMMEDIATE_FSYNC is not set +# CONFIG_FATFS_USE_LABEL is not set +CONFIG_FATFS_LINK_LOCK=y +# CONFIG_FATFS_USE_DYN_BUFFERS is not set +# File system free space calculation behavior +CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 +CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 +# end of File system free space calculation behavior +# end of FAT Filesystem support +# FreeRTOS +# Kernel +# CONFIG_FREERTOS_SMP is not set +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_HZ=1000 +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +# CONFIG_FREERTOS_USE_IDLE_HOOK is not set +# CONFIG_FREERTOS_USE_TICK_HOOK is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +CONFIG_FREERTOS_USE_TIMERS=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc" +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1 is not set +CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set +# end of Kernel +# Port +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y +# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# end of Port +# Extra +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y +# end of Extra +CONFIG_FREERTOS_PORT=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y +CONFIG_FREERTOS_NUMBER_OF_CORES=2 +# end of FreeRTOS +# Hardware Abstraction Layer (HAL) and Low Level (LL) +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_WDT_USE_ROM_IMPL=y +CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y +CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) +# Heap memory debugging +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_USE_HOOKS is not set +# CONFIG_HEAP_TASK_TRACKING is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH is not set +# end of Heap memory debugging +# Log Level +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +# CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT is not set +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE=y +CONFIG_LOG_MAXIMUM_LEVEL=5 +# Level Settings +# CONFIG_LOG_MASTER_LEVEL is not set +CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=y +# CONFIG_LOG_TAG_LEVEL_IMPL_NONE is not set +# CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST is not set +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST=y +# CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY is not set +CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP=y +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31 +# end of Level Settings +# end of Log Level +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# LWIP +CONFIG_LWIP_ENABLE=y +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +# CONFIG_LWIP_NETIF_API is not set +CONFIG_LWIP_TCPIP_TASK_PRIO=18 +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +# CONFIG_LWIP_CHECK_THREAD_SAFETY is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +# CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_ND6=y +# CONFIG_LWIP_FORCE_ROUTER_FORWARDING is not set +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_DEFAULT_TTL=64 +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +CONFIG_LWIP_IP_REASS_MAX_PBUFS=10 +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_ESP_MLDV6_REPORT=y +CONFIG_LWIP_MLDV6_TMR_INTERVAL=40 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DOES_ACD_CHECK is not set +# CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 +CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 +# DHCP server +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_DHCPS_STATIC_ENTRIES=y +CONFIG_LWIP_DHCPS_ADD_DNS=y +# end of DHCP server +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV4=y +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# TCP +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760 +CONFIG_LWIP_TCP_WND_DEFAULT=5760 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 +CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4 +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP +# UDP +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP +# Checksums +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 +CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 +CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 +# CONFIG_LWIP_PPP_SUPPORT is not set +# CONFIG_LWIP_SLIP_SUPPORT is not set +# ICMP +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP +# LWIP RAW API +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API +# SNTP +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +CONFIG_LWIP_SNTP_STARTUP_DELAY=y +CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY=5000 +# end of SNTP +# DNS +CONFIG_LWIP_DNS_MAX_HOST_IP=1 +CONFIG_LWIP_DNS_MAX_SERVERS=3 +# CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set +# CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF is not set +# end of DNS +CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 +CONFIG_LWIP_ESP_LWIP_ASSERT=y +# Hooks +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE=y +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_INPUT_NONE=y +# CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set +# end of Hooks +# CONFIG_LWIP_DEBUG is not set +# end of LWIP +# mbedTLS +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC is not set +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set +# mbedTLS v3.x related +# CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 is not set +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +CONFIG_MBEDTLS_PKCS7_C=y +# end of mbedTLS v3.x related +# Certificate Bundle +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA1_C=y +CONFIG_MBEDTLS_SHA512_C=y +# CONFIG_MBEDTLS_SHA3_C is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y +# TLS Key Exchange Methods +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y +# Symmetric Ciphers +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers +# CONFIG_MBEDTLS_RIPEMD160_C is not set +# Certificates +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y +CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED=y +# CONFIG_MBEDTLS_DHM_C is not set +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +CONFIG_MBEDTLS_ERROR_STRINGS=y +CONFIG_MBEDTLS_FS_IO=y +# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set +# end of mbedTLS +# ESP-MQTT Configurations +CONFIG_MQTT_PROTOCOL_311=y +# CONFIG_MQTT_PROTOCOL_5 is not set +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations +# Newlib +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y +# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set +# end of Newlib +CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND=y +# NVS +# CONFIG_NVS_ENCRYPTION is not set +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY is not set +# CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM is not set +# end of NVS +# OpenThread +# CONFIG_OPENTHREAD_ENABLED is not set +# OpenThread Spinel +# CONFIG_OPENTHREAD_SPINEL_ONLY is not set +# end of OpenThread Spinel +# end of OpenThread +# Protocomm +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y +# end of Protocomm +# PThreads +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads +# MMU Config +CONFIG_MMU_PAGE_SIZE_64KB=y +CONFIG_MMU_PAGE_MODE="64KB" +CONFIG_MMU_PAGE_SIZE=0x10000 +# end of MMU Config +# Main Flash configuration +# SPI Flash behavior when brownout +CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC=y +CONFIG_SPI_FLASH_BROWNOUT_RESET=y +# end of SPI Flash behavior when brownout +# Optional and Experimental Features (READ DOCS FIRST) +# Features here require specific hardware (READ DOCS FIRST!) +# CONFIG_SPI_FLASH_HPM_ENA is not set +CONFIG_SPI_FLASH_HPM_AUTO=y +# CONFIG_SPI_FLASH_HPM_DIS is not set +CONFIG_SPI_FLASH_HPM_ON=y +CONFIG_SPI_FLASH_HPM_DC_AUTO=y +# CONFIG_SPI_FLASH_HPM_DC_DISABLE is not set +# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set +CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 +# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set +# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set +# end of Optional and Experimental Features (READ DOCS FIRST) +# end of Main Flash configuration +# SPI Flash driver +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set +# Auto-detect flash chips +CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_TH_SUPPORTED=y +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver +# SPIFFS Configuration +CONFIG_SPIFFS_MAX_PARTITIONS=3 +# SPIFFS Cache Configuration +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y +# Debug Configuration +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration +# TCP Transport +# Websocket +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# CONFIG_WS_DYNAMIC_BUFFER is not set +# end of Websocket +# end of TCP Transport +# Ultra Low Power (ULP) Co-processor +# CONFIG_ULP_COPROC_ENABLED is not set +# ULP Debugging Options +# end of ULP Debugging Options +# end of Ultra Low Power (ULP) Co-processor +# Unity unit testing library +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library +# USB-OTG +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set +# Hub Driver Configuration +# Root Port configuration +CONFIG_USB_HOST_DEBOUNCE_DELAY_MS=250 +CONFIG_USB_HOST_RESET_HOLD_MS=30 +CONFIG_USB_HOST_RESET_RECOVERY_MS=30 +CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS=10 +# end of Root Port configuration +# CONFIG_USB_HOST_HUBS_SUPPORTED is not set +# end of Hub Driver Configuration +# CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK is not set +CONFIG_USB_OTG_SUPPORTED=y +# end of USB-OTG +# Virtual file system +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_VFS_SELECT_IN_RAM is not set +CONFIG_VFS_SUPPORT_TERMIOS=y +CONFIG_VFS_MAX_COUNT=8 +# Host File System I/O (Semihosting) +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) +CONFIG_VFS_INITIALIZE_DEV_NULL=y +# end of Virtual file system +# Wear Levelling +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling +# Wi-Fi Provisioning Manager +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y +# CONFIG_WIFI_PROV_STA_FAST_SCAN is not set +# end of Wi-Fi Provisioning Manager +# USB Device UVC +CONFIG_TUSB_VID=0x303A +CONFIG_TUSB_PID=0x8000 +CONFIG_TUSB_MANUFACTURER="ETVR" +CONFIG_TUSB_PRODUCT="OpenIris Camera" +CONFIG_TUSB_SERIAL_NUM="12345678" +# USB Cam1 Config +CONFIG_FORMAT_MJPEG_CAM1=y +# CONFIG_FORMAT_H264_CAM1 is not set +# CONFIG_FORMAT_UNCOMPR_CAM1 is not set +# CONFIG_UVC_MODE_ISOC_CAM1 is not set +CONFIG_UVC_MODE_BULK_CAM1=y +CONFIG_FRAMESIZE_QVGA=y +# CONFIG_FRAMESIZE_HVGA is not set +# CONFIG_FRAMESIZE_VGA is not set +# CONFIG_FRAMESIZE_SVGA is not set +# CONFIG_FRAMESIZE_HD is not set +# CONFIG_FRAMESIZE_FHD is not set +CONFIG_UVC_CAM1_FRAMERATE=60 +CONFIG_UVC_CAM1_FRAMESIZE_WIDTH=240 +CONFIG_UVC_CAM1_FRAMESIZE_HEIGT=240 +CONFIG_UVC_CAM1_MULTI_FRAMESIZE=y +# end of USB Cam1 Config +# UVC_MULTI_FRAME_CONFIG +# FRAME_SIZE_1 +CONFIG_UVC_MULTI_FRAME_WIDTH_1=240 +CONFIG_UVC_MULTI_FRAME_HEIGHT_1=240 +CONFIG_UVC_MULTI_FRAME_FPS_1=60 +# end of FRAME_SIZE_1 +# FRAME_SIZE_2 +CONFIG_UVC_MULTI_FRAME_WIDTH_2=240 +CONFIG_UVC_MULTI_FRAME_HEIGHT_2=240 +CONFIG_UVC_MULTI_FRAME_FPS_2=60 +# end of FRAME_SIZE_2 +# FRAME_SIZE_3 +CONFIG_UVC_MULTI_FRAME_WIDTH_3=240 +CONFIG_UVC_MULTI_FRAME_HEIGHT_3=240 +CONFIG_UVC_MULTI_FRAME_FPS_3=60 +# end of FRAME_SIZE_3 +# end of UVC_MULTI_FRAME_CONFIG +# UVC Task Config +CONFIG_UVC_TINYUSB_TASK_PRIORITY=4 +CONFIG_UVC_TINYUSB_TASK_CORE=-1 +CONFIG_UVC_CAM1_TASK_PRIORITY=3 +CONFIG_UVC_CAM1_TASK_CORE=-1 +# end of UVC Task Config +# end of USB Device UVC +# CMake Utilities +# CONFIG_CU_RELINKER_ENABLE is not set +# CONFIG_CU_DIAGNOSTICS_COLOR_NEVER is not set +CONFIG_CU_DIAGNOSTICS_COLOR_ALWAYS=y +# CONFIG_CU_DIAGNOSTICS_COLOR_AUTO is not set +# CONFIG_CU_GCC_LTO_ENABLE is not set +# CONFIG_CU_GCC_STRING_1BYTE_ALIGN is not set +# end of CMake Utilities +# Camera configuration +# CONFIG_OV7670_SUPPORT is not set +# CONFIG_OV7725_SUPPORT is not set +# CONFIG_NT99141_SUPPORT is not set +CONFIG_OV2640_SUPPORT=y +CONFIG_OV3660_SUPPORT=y +CONFIG_OV5640_SUPPORT=y +# CONFIG_GC2145_SUPPORT is not set +# CONFIG_GC032A_SUPPORT is not set +# CONFIG_GC0308_SUPPORT is not set +# CONFIG_BF3005_SUPPORT is not set +# CONFIG_BF20A6_SUPPORT is not set +# CONFIG_SC101IOT_SUPPORT is not set +# CONFIG_SC030IOT_SUPPORT is not set +# CONFIG_SC031GS_SUPPORT is not set +CONFIG_MEGA_CCM_SUPPORT=y +# CONFIG_SCCB_HARDWARE_I2C_PORT0 is not set +CONFIG_SCCB_HARDWARE_I2C_PORT1=y +CONFIG_SCCB_CLK_FREQ=100000 +CONFIG_CAMERA_TASK_STACK_SIZE=30720 +CONFIG_CAMERA_CORE0=y +# CONFIG_CAMERA_CORE1 is not set +# CONFIG_CAMERA_NO_AFFINITY is not set +CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX=32768 +CONFIG_CAMERA_JPEG_MODE_FRAME_SIZE_AUTO=y +# CONFIG_CAMERA_JPEG_MODE_FRAME_SIZE_CUSTOM is not set +# CONFIG_CAMERA_CONVERTER_ENABLED is not set +# CONFIG_LCD_CAM_ISR_IRAM_SAFE is not set +# end of Camera configuration +# mDNS +CONFIG_MDNS_MAX_INTERFACES=3 +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_ACTION_QUEUE_LEN=16 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 +# MDNS Memory Configuration +# CONFIG_MDNS_TASK_CREATE_FROM_SPIRAM is not set +CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL=y +# CONFIG_MDNS_MEMORY_ALLOC_SPIRAM is not set +CONFIG_MDNS_MEMORY_ALLOC_INTERNAL=y +# CONFIG_MDNS_MEMORY_CUSTOM_IMPL is not set +# end of MDNS Memory Configuration +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +# CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES is not set +# CONFIG_MDNS_ENABLE_DEBUG_PRINTS is not set +CONFIG_MDNS_ENABLE_CONSOLE_CLI=y +# CONFIG_MDNS_RESPOND_REVERSE_QUERIES is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y +# MDNS Predefined interfaces +CONFIG_MDNS_PREDEF_NETIF_STA=y +CONFIG_MDNS_PREDEF_NETIF_AP=y +CONFIG_MDNS_PREDEF_NETIF_ETH=y +# end of MDNS Predefined interfaces +# end of mDNS +# end of Component config +# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set +# Deprecated options for backward compatibility +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +CONFIG_FLASHMODE_QIO=y +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_MONITOR_BAUD=115200 +# CONFIG_OPTIMIZATION_LEVEL_DEBUG is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set +# CONFIG_COMPILER_OPTIMIZATION_DEFAULT is not set +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +# CONFIG_EXTERNAL_COEX_ENABLE is not set +# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_MCPWM_ISR_IN_IRAM is not set +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_GDBSTUB_SUPPORT_TASKS=y +CONFIG_GDBSTUB_MAX_TASKS=32 +# CONFIG_OTA_ALLOW_HTTP is not set +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_REDUCE_PHY_TX_POWER is not set +# CONFIG_ESP32_REDUCE_PHY_TX_POWER is not set +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP32S3_DEBUG_OCDAWARE=y +CONFIG_BROWNOUT_DET=y +CONFIG_ESP32S3_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_7=y +CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S3_BROWNOUT_DET_LVL=7 +CONFIG_IPC_TASK_STACK_SIZE=1280 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +# CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y +CONFIG_WPA_MBEDTLS_CRYPTO=y +CONFIG_WPA_MBEDTLS_TLS_CLIENT=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# CONFIG_WPA_11R_SUPPORT is not set +# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_L2_TO_L3_COPY is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5760 +CONFIG_TCP_WND_DEFAULT=5760 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_SYSTIMER=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_SYSTIMER is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options +CONFIG_GENERAL_INCLUDE_UVC_MODE=y +# CONFIG_MONITORING_LED_CURRENT is not set +CONFIG_GENERAL_BOARD="project_babble" +CONFIG_GENERAL_ENABLE_WIRELESS=y diff --git a/tests/.env.example b/tests/.env.example new file mode 100644 index 0000000..d59b7c2 --- /dev/null +++ b/tests/.env.example @@ -0,0 +1,5 @@ +WIFI_SSID= +WIFI_PASS= +SWITCH_MODE_REBOOT_TIME=5 +WIFI_CONNECTION_TIMEOUT=5 +INVALID_WIFI_CONNECTION_TIMEOUT=30 \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..2a5a485 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,217 @@ +from dataclasses import dataclass +import dotenv +import pytest +import time + +from tests.utils import ( + OpenIrisDeviceManager, + has_command_failed, + get_current_ports, + get_new_port, +) + +board_capabilities = { + "esp_eye": ["wired", "wireless"], + "esp32AIThinker": ["wireless"], + "esp32Cam": ["wireless"], + "esp32M5Stack": ["wireless"], + "facefocusvr_eye_L": ["wired", "measure_current"], + "facefocusvr_eye_R": ["wired", "measure_current"], + "facefocusvr_face": ["wired", "measure_current"], + "project_babble": ["wireless", "wired"], + "seed_studio": ["wireless", "wired"], + "wrooms3": ["wireless", "wired"], + "wrooms3QIO": ["wireless", "wired"], + "wrover": ["wireless", "wired"], +} + + +def pytest_addoption(parser): + parser.addoption("--board", action="store") + parser.addoption( + "--connection", + action="store", + help="Defines how to connect to the given board, wireless by ip/mdns or wired by com/cdc", + ) + + +def pytest_configure(config): + config.addinivalue_line( + "markers", "has_capability(caps): skip if the board does not have the capability" + ) + config.addinivalue_line( + "markers", "lacks_capability(caps): skip if the board DOES have the capability" + ) + + +@pytest.fixture(autouse=True) +def check_capability_marker(request, board_lacks_capability): + """ + Autorun on each test, checks if the board we started with, has the required capability + + This lets us skip tests that are impossible to run on some boards - like for example: + + It's impossible to run wired tests on a wireless board + It's impossible to run tests for measuring current on boards without this feature + """ + if marker := request.node.get_closest_marker("has_capability"): + if not len(marker.args): + raise ValueError( + "has_capability marker must be provided with a capability to check" + ) + + for capability in marker.args: + if board_lacks_capability(capability): + pytest.skip(f"Board does not have capability {capability}") + + +@pytest.fixture(autouse=True) +def check_lacks_capability_marker(request, board_lacks_capability): + if lacks_capability_marker := request.node.get_closest_marker("lacks_capability"): + if not len(lacks_capability_marker.args): + raise ValueError( + "lacks_capability marker must be provided with a capability to check" + ) + + for capability in lacks_capability_marker.args: + if not board_lacks_capability(capability): + pytest.skip( + "The board supports given capability: {required_capability}, skipping" + ) + + +@pytest.fixture(scope="session", autouse=True) +def board_name(request): + board_name = request.config.getoption("--board") + if not board_name: + raise ValueError("No board defined") + + yield board_name + + +@pytest.fixture() +def board_lacks_capability(board_name): + def func(capability: str): + if board_name: + if board_name not in board_capabilities: + raise ValueError(f"Unknown board {board_name}") + + return capability not in board_capabilities[board_name] + return True + + return func + + +@pytest.fixture(scope="session", autouse=True) +def board_connection(request): + """ + Grabs the specified connection connection method, to be used ONLY for the initial connection. Everything after it HAS to be handled via Device Manager. + Ports WILL change throughout the tests, device manager can keep track of that and reconnect the board as needed. + """ + board_connection = request.config.getoption("--connection") + + if not board_connection: + raise ValueError("No connection method defined") + + yield board_connection + + +@dataclass +class TestConfig: + WIFI_SSID: str + WIFI_PASS: str + SWITCH_MODE_REBOOT_TIME: int + WIFI_CONNECTION_TIMEOUT: int + INVALID_WIFI_CONNECTION_TIMEOUT: int + + def __init__( + self, + WIFI_SSID: str, + WIFI_PASS: str, + SWITCH_MODE_REBOOT_TIME: int, + WIFI_CONNECTION_TIMEOUT: int, + INVALID_WIFI_CONNECTION_TIMEOUT: int, + ): + self.WIFI_SSID = WIFI_SSID + self.WIFI_PASS = WIFI_PASS + self.SWITCH_MODE_REBOOT_TIME = int(SWITCH_MODE_REBOOT_TIME) + self.WIFI_CONNECTION_TIMEOUT = int(WIFI_CONNECTION_TIMEOUT) + self.INVALID_WIFI_CONNECTION_TIMEOUT = int(INVALID_WIFI_CONNECTION_TIMEOUT) + + +@pytest.fixture(scope="session") +def config(): + config = TestConfig(**dotenv.dotenv_values()) + yield config + + +@pytest.fixture(scope="session") +def openiris_device_manager(board_connection, config): + manager = OpenIrisDeviceManager() + manager.get_device(board_connection, config) + yield manager + + if manager._device: + manager._device.disconnect() + + +@pytest.fixture() +def get_openiris_device(openiris_device_manager, config): + def func(port: str | None = None, _config: dict | None = None): + return openiris_device_manager.get_device(port, config or _config) + + return func + + +@pytest.fixture() +def ensure_board_in_mode(openiris_device_manager, config): + """ + Given the OpenIrisDevice manager, grabs the current device and ensures it's in the required mode + + if not, sends the command to switch and attempts reconnection if necessary, returning the device back + """ + supported_modes = ["wifi", "uvc"] + + def func(mode, device): + if mode not in supported_modes: + raise ValueError(f"{mode} is not a supported mode") + + command_result = device.send_command("get_device_mode") + if has_command_failed(command_result): + raise ValueError(f"Failed to get device mode, error: {command_result}") + + current_mode = command_result["results"][0]["result"]["data"]["mode"].lower() + if mode == current_mode: + return device + + old_ports = get_current_ports() + command_result = device.send_command("switch_mode", {"mode": mode}) + if has_command_failed(command_result): + raise ValueError("Failed to switch mode, rerun the tests") + + print("Rebooting the board after changing mode") + device.send_command("restart_device") + + sleep_timeout = int(config.SWITCH_MODE_REBOOT_TIME) + print( + f"Sleeping for {sleep_timeout} seconds to allow the device to switch modes and boot up" + ) + time.sleep(sleep_timeout) + new_ports = get_current_ports() + + new_device = openiris_device_manager.get_device( + get_new_port(old_ports, new_ports), config + ) + return new_device + + return func + + +@pytest.fixture(scope="session", autouse=True) +def after_session_cleanup(openiris_device_manager, config): + yield + + print("Cleanup: Resetting the config and restarting device") + device = openiris_device_manager.get_device(config=config) + device.send_command("reset_config", {"section": "all"}) + device.send_command("restart_device") diff --git a/tests/test_commands.py b/tests/test_commands.py new file mode 100644 index 0000000..886432c --- /dev/null +++ b/tests/test_commands.py @@ -0,0 +1,543 @@ +import time +from tests.utils import has_command_failed, DetectPortChange +import pytest + + +def test_sending_invalid_command(get_openiris_device): + device = get_openiris_device() + command_result = device.send_command("some_invalid_command") + assert has_command_failed(command_result) + + +def test_sending_invalid_command_with_payload(get_openiris_device): + device = get_openiris_device() + command_result = device.send_command("some_invalid_command", {"param": "invalid"}) + assert has_command_failed(command_result) + + +def test_ping_wired(get_openiris_device): + device = get_openiris_device() + + command_result = device.send_command("ping") + assert not has_command_failed(command_result) + + +@pytest.mark.has_capability("wired", "wireless") +def test_changing_mode_to_wired(get_openiris_device, ensure_board_in_mode, config): + device = get_openiris_device() + + # let's make sure we're in the wireless mode first, if we're going to try changing it + device = ensure_board_in_mode("wifi", device) + with DetectPortChange() as port_selector: + command_result = device.send_command("switch_mode", {"mode": "uvc"}) + assert not has_command_failed(command_result) + device.send_command("restart_device") + time.sleep(config.SWITCH_MODE_REBOOT_TIME) + + # and since we've changed the ports + device = get_openiris_device(port_selector.get_new_port()) + # initial read to flush the logs first + device.send_command("get_device_mode") + result = device.send_command("get_device_mode") + assert not has_command_failed(result) + + +def test_changing_mode_same_mode(get_openiris_device): + device = get_openiris_device() + result = device.send_command("get_device_mode") + current_mode = result["results"][0]["result"]["data"]["mode"].lower() + command_result = device.send_command("switch_mode", {"mode": current_mode}) + assert not has_command_failed(command_result) + + result = device.send_command("get_device_mode") + assert not has_command_failed(result) + assert result["results"][0]["result"]["data"]["mode"].lower() == current_mode + + +def test_changing_mode_invalid_mode(get_openiris_device): + device = get_openiris_device() + command_result = device.send_command("switch_mode", {"mode": "NOT SUPPORTED"}) + assert has_command_failed(command_result) + + +def test_setting_mdns_name(get_openiris_device, ensure_board_in_mode, config): + def check_mdns_name(name: str): + command_result = device.send_command("get_mdns_name") + assert not has_command_failed(command_result) + assert command_result["results"][0]["result"]["data"]["hostname"] == name + + device = get_openiris_device() + device = ensure_board_in_mode("wifi", device) + first_name = "testname1" + second_name = "testname2" + # try setting the test mdns name first, just so we know the commands pass + command_result = device.send_command("set_mdns", {"hostname": first_name}) + assert not has_command_failed(command_result) + + check_mdns_name(first_name) + + command_result = device.send_command("set_mdns", {"hostname": second_name}) + assert not has_command_failed(command_result) + + device.send_command("restart_device") + # let the board boot, wait till it connects + time.sleep(config.SWITCH_MODE_REBOOT_TIME) + check_mdns_name(second_name) + + +@pytest.mark.parametrize("payload", [{"name": "awd"}, {}]) +def test_setting_mdns_name_invalid_payload(get_openiris_device, payload): + device = get_openiris_device() + command_result = device.send_command("set_mdns", payload) + assert has_command_failed(command_result) + + +@pytest.mark.has_capability("wired", "wireless") +# make this to be has_capabilities instead +def test_reboot_command(get_openiris_device, ensure_board_in_mode, config): + device = ensure_board_in_mode("wifi", get_openiris_device()) + + command_result = device.send_command("switch_mode", {"mode": "uvc"}) + assert not has_command_failed(command_result) + + # we're testing if rebooting actually triggers reboot + # so to be 100% sure of that, we're changing the mode to UVC and looking for new port + # which might be a little overkill kill and won't work on boards not supporting both modes + with DetectPortChange() as port_selector: + device.send_command("restart_device") + time.sleep(config.SWITCH_MODE_REBOOT_TIME) + + assert port_selector.get_new_port() + + +def test_get_serial(get_openiris_device): + device = get_openiris_device() + command_result = device.send_command("get_serial") + assert not has_command_failed(command_result) + # test for response integrity as well to uphold the contract + assert "mac" in command_result["results"][0]["result"]["data"] + assert "serial" in command_result["results"][0]["result"]["data"] + + +def test_get_who_am_i(get_openiris_device): + device = get_openiris_device() + command_result = device.send_command("get_who_am_i") + assert not has_command_failed(command_result) + # test for response integrity as well to uphold the contract + assert "version" in command_result["results"][0]["result"]["data"] + assert "who_am_i" in command_result["results"][0]["result"]["data"] + + +@pytest.mark.has_capability("measure_current") +def test_get_led_current_supported(get_openiris_device): + device = get_openiris_device() + command_result = device.send_command("get_led_current") + assert not has_command_failed(command_result) + assert "led_current_ma" in command_result["results"][0]["result"]["data"] + + +@pytest.mark.lacks_capability("measure_current") +def test_get_led_current_unsupported(get_openiris_device): + device = get_openiris_device() + command_result = device.send_command("get_led_current") + assert has_command_failed(command_result) + + +def test_get_led_duty_cycle(get_openiris_device): + device = get_openiris_device() + command_result = device.send_command("get_led_duty_cycle") + assert not has_command_failed(command_result) + assert ( + "led_external_pwm_duty_cycle" in command_result["results"][0]["result"]["data"] + ) + + +def test_set_led_duty_cycle(get_openiris_device): + device = get_openiris_device() + command_result = device.send_command("set_led_duty_cycle", {"dutyCycle": 0}) + assert not has_command_failed(command_result) + + command_result = device.send_command("get_led_duty_cycle") + assert not has_command_failed(command_result) + assert ( + command_result["results"][0]["result"]["data"]["led_external_pwm_duty_cycle"] + == 0 + ) + + command_result = device.send_command("set_led_duty_cycle", {"dutyCycle": 100}) + assert not has_command_failed(command_result) + + command_result = device.send_command("get_led_duty_cycle") + assert not has_command_failed(command_result) + assert ( + command_result["results"][0]["result"]["data"]["led_external_pwm_duty_cycle"] + == 100 + ) + + +@pytest.mark.parametrize( + "payload", + [ + {}, + {"dutyCycle": -1}, + {"dutyCycle": 1.5}, + {"dutyCycle": 150}, + {"awd": 21}, + {"dutyCycle": "21"}, + ], +) +def test_set_led_duty_cycle_invalid_payload(get_openiris_device, payload): + device = get_openiris_device() + command_result = device.send_command("set_led_duty_cycle", payload) + assert has_command_failed(command_result) + + +@pytest.mark.has_capability("wireless") +def test_check_wifi_status(get_openiris_device, ensure_board_in_mode): + device = ensure_board_in_mode("wifi", get_openiris_device()) + command_result = device.send_command("get_wifi_status") + assert not has_command_failed(command_result) + + +@pytest.mark.has_capability("wireless") +def test_scan_networks(get_openiris_device, ensure_board_in_mode, config): + # this test might run after some tests that affect the network on the device + # which might prevent us from scanning and thus make the test fail, so we reset the config + device = get_openiris_device() + reset_command = device.send_command("reset_config", {"section": "all"}) + assert not has_command_failed(reset_command) + + with DetectPortChange() as port_selector: + device.send_command("restart_device") + time.sleep(config.SWITCH_MODE_REBOOT_TIME) + + device = ensure_board_in_mode( + "wifi", get_openiris_device(port_selector.get_new_port()) + ) + command_result = device.send_command("scan_networks") + assert not has_command_failed(command_result) + assert len(command_result["results"][0]["result"]["data"]["networks"]) != 0 + + +def test_get_config(get_openiris_device): + device = get_openiris_device() + command_result = device.send_command("get_config") + assert not has_command_failed(command_result) + + +def test_reset_config_invalid_payload(get_openiris_device): + # to test the config, we can do two things. Set the mdns, get the config, reset it, get it again and compare + device = get_openiris_device() + reset_command = device.send_command("reset_config") + assert has_command_failed(reset_command) + + +def test_reset_config(get_openiris_device, config): + device = get_openiris_device() + command_result = device.send_command("set_mdns", {"hostname": "somedifferentname"}) + assert not has_command_failed(command_result) + + current_config = device.send_command("get_config") + assert not has_command_failed(current_config) + + reset_command = device.send_command("reset_config", {"section": "all"}) + assert not has_command_failed(reset_command) + + # since the config was reset, but the data will still be held in memory, we need to reboot the device + with DetectPortChange(): + device.send_command("restart_device") + time.sleep(config.SWITCH_MODE_REBOOT_TIME) + + new_config = device.send_command("get_config") + assert not has_command_failed(new_config) + + assert not new_config == current_config + + +@pytest.mark.has_capability("wireless") +def test_set_wifi(get_openiris_device, ensure_board_in_mode, config): + # since we want to test actual connection to the network, let's reset the device and reboot it + device = get_openiris_device() + reset_command = device.send_command("reset_config", {"section": "all"}) + assert not has_command_failed(reset_command) + + with DetectPortChange(): + device.send_command("restart_device") + time.sleep(config.SWITCH_MODE_REBOOT_TIME) + + # now that the config is clear, let's try setting the wifi + device = ensure_board_in_mode("wifi", device) + params = { + "name": "main", + "ssid": config.WIFI_SSID, + "password": config.WIFI_PASS, + "channel": 0, + "power": 0, + } + set_wifi_result = device.send_command("set_wifi", params) + assert not has_command_failed(set_wifi_result) + + # now, let's force connection and check if it worked + connect_wifi_result = device.send_command("connect_wifi") + assert not -has_command_failed(connect_wifi_result) + time.sleep(config.WIFI_CONNECTION_TIMEOUT) # and let it try to for some time + + wifi_status_command = device.send_command("get_wifi_status") + assert not has_command_failed(wifi_status_command) + assert wifi_status_command["results"][0]["result"]["data"]["status"] == "connected" + + +@pytest.mark.has_capability("wireless") +def test_set_wifi_invalid_network(get_openiris_device, ensure_board_in_mode, config): + device = ensure_board_in_mode("wifi", get_openiris_device()) + params = { + "name": "main", + "ssid": "PleaseDontBeARealNetwork", + "password": "AndThePasswordIsFake", + "channel": 0, + "power": 0, + } + set_wifi_result = device.send_command("set_wifi", params) + # even if the network is fake, we should not fail to set it + assert not has_command_failed(set_wifi_result) + + device.send_command("connect_wifi") + + time.sleep( + config.INVALID_WIFI_CONNECTION_TIMEOUT + ) # and let it try to for some time + + wifi_status_command = device.send_command("get_wifi_status") + # the command should not fail as well, but we should get an error result + assert not has_command_failed(wifi_status_command) + assert wifi_status_command["results"][0]["result"]["data"]["status"] == "error" + # and not to break other tests, clean up + device.send_command("reset_config", {"section": "all"}) + device.send_command("restart_device") + + +@pytest.mark.has_capability("wireless") +@pytest.mark.parametrize( + "payload", + ( + {}, + { + "ssid": "PleaseDontBeARealNetwork", + "password": "AndThePasswordIsFake", + "channel": 0, + "power": 0, + }, + { + "name": "IaintGotNoNameAndIMustConnect", + "password": "AndThePasswordIsFake", + "channel": 0, + "power": 0, + }, + ), +) +def test_set_wifi_invalid_payload(ensure_board_in_mode, get_openiris_device, payload): + device = ensure_board_in_mode("wifi", get_openiris_device()) + set_wifi_result = device.send_command("set_wifi", payload) + # even if the network is fake, we should not fail to set it + assert has_command_failed(set_wifi_result) + # and not to break other tests, clean up + device.send_command("reset_config", {"section": "all"}) + device.send_command("restart_device") + + +def test_update_main_wifi_network(ensure_board_in_mode, get_openiris_device, config): + # now that the config is clear, let's try setting the wifi + device = ensure_board_in_mode("wifi", get_openiris_device()) + params1 = { + "name": "main", + "ssid": "Nada", + "password": "Nuuh", + "channel": 0, + "power": 0, + } + + params2 = { + **params1, + "ssid": config.WIFI_SSID, + "password": config.WIFI_PASS, + } + + set_wifi_result = device.send_command("set_wifi", params1) + assert not has_command_failed(set_wifi_result) + + set_wifi_result = device.send_command("set_wifi", params2) + assert not has_command_failed(set_wifi_result) + # and not to break other tests, clean up + device.send_command("reset_config", {"section": "all"}) + device.send_command("restart_device") + + +def test_set_wifi_add_another_network(ensure_board_in_mode, get_openiris_device): + device = ensure_board_in_mode("wifi", get_openiris_device()) + params = { + "name": "anotherNetwork", + "ssid": "PleaseDontBeARealNetwork", + "password": "AndThePassowrdIsFake", + "channel": 0, + "power": 0, + } + set_wifi_result = device.send_command("set_wifi", params) + assert not has_command_failed(set_wifi_result) + # and not to break other tests, clean up + device.send_command("reset_config", {"section": "all"}) + device.send_command("restart_device") + + +@pytest.mark.parametrize( + "payload", + ( + { + "ssid": "testAP", + "password": "12345678", + "channel": 0, + }, + { + "ssid": "testAP", + "channel": 0, + }, + { + "ssid": "testAP", + "password": "12345678", + }, + { + "ssid": "testAP", + }, + { + "password": "12345678", + }, + ), +) +def test_update_ap_wifi(ensure_board_in_mode, get_openiris_device, payload): + device = ensure_board_in_mode("wifi", get_openiris_device()) + result = device.send_command("update_ap_wifi", payload) + assert not has_command_failed(result) + # and not to break other tests, clean up + device.send_command("reset_config", {"section": "all"}) + device.send_command("restart_device") + + +@pytest.mark.parametrize( + "payload", + ( + {}, # completely empty payload + { + "channel": 2 + }, # technically valid payload, but we're missing the network name, + { + "name": "IAMNOTTHERE", + "channel": 2, + }, # None-existent network + ), +) +@pytest.mark.has_capability("wireless") +def test_update_wifi_command_fail(ensure_board_in_mode, get_openiris_device, payload): + device = ensure_board_in_mode("wifi", get_openiris_device()) + result = device.send_command("update_wifi", payload) + assert has_command_failed(result) + + +@pytest.mark.parametrize( + "payload", + ( + { + "name": "anotherNetwork", + "ssid": "WEUPDATEDTHESSID", + "password": "ACOMPLETELYDIFFERENTPASS", + "channel": 1, + "power": 2, + }, + { + "name": "anotherNetwork", + "password": "ACOMPLETELYDIFFERENTPASS", + }, + { + "name": "anotherNetwork", + "ssid": "WEUPDATEDTHESSID", + }, + { + "name": "anotherNetwork", + "channel": 1, + }, + { + "name": "anotherNetwork", + "power": 2, + }, + ), +) +@pytest.mark.has_capability("wireless") +def test_update_wifi_command(ensure_board_in_mode, get_openiris_device, payload): + device = ensure_board_in_mode("wifi", get_openiris_device()) + params = { + "name": "anotherNetwork", + "ssid": "PleaseDontBeARealNetwork", + "password": "AndThePasswordIsFake", + "channel": 0, + "power": 0, + } + set_wifi_result = device.send_command("set_wifi", params) + assert not has_command_failed(set_wifi_result) + + device = ensure_board_in_mode("wifi", get_openiris_device()) + result = device.send_command("update_wifi", payload) + assert not has_command_failed(result) + + +@pytest.mark.parametrize( + "payload", + ( + {}, + {"name": ""}, + ), +) +@pytest.mark.has_capability("wireless") +def test_delete_network_fail(ensure_board_in_mode, get_openiris_device, payload): + device = ensure_board_in_mode("wifi", get_openiris_device()) + result = device.send_command("delete_network", payload) + assert has_command_failed(result) + + +@pytest.mark.parametrize("payload", ({"name": "main"}, {"name": "NOTANETWORK"})) +@pytest.mark.has_capability("wireless") +def test_delete_network(ensure_board_in_mode, get_openiris_device, payload): + device = ensure_board_in_mode("wifi", get_openiris_device()) + result = device.send_command("delete_network", payload) + assert not has_command_failed(result) + + +@pytest.mark.parametrize( + "payload", + ( + {}, + { + "vlip": 0, + "hflip": 0, + "framesize": 5, + "quality": 7, + "brightness": 2, + }, + { + "vlip": 0, + }, + { + "hflip": 0, + }, + { + "framesize": 5, + }, + { + "quality": 7, + }, + { + "brightness": 2, + }, + ), +) +def test_update_camera(get_openiris_device, payload): + device = get_openiris_device() + result = device.send_command("update_camera", payload) + assert not has_command_failed(result) diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..3b28856 --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,78 @@ +import time +import serial.tools.list_ports +from tools.openiris_device import OpenIrisDevice + +OPENIRIS_DEVICE = None + + +class OpenIrisDeviceManager: + def __init__(self): + self._device: OpenIrisDevice | None = None + self.stored_ports = [] + self._current_port: str | None = None + + def get_device(self, port: str | None = None, config=None) -> OpenIrisDevice: + """ + Returns the current OpenIrisDevice connection helper + + if the port changed from the one given previously, it will attempt to reconnect + if no device exists, we will create one and try to connect + + This helper is designed to be used within a session long fixture + """ + if not port and not self._device: + raise ValueError("No device connected yet, provide a port first") + + # I'm not sure if I like this approach + # maybe I need to rethink this fixture + current_ports = get_current_ports() + new_port = get_new_port(self.stored_ports, current_ports) + if new_port is not None: + self.stored_ports = current_ports + + if not port: + port = new_port + + if port and port != self._current_port: + print(f"Port changed from {self._current_port} to {port}, reconnecting...") + self._current_port = port + + if self._device: + self._device.disconnect() + self._device = None + + self._device = OpenIrisDevice(port, False, False) + self._device.connect() + time.sleep(config.SWITCH_MODE_REBOOT_TIME) + + return self._device + + +def has_command_failed(result) -> bool: + return "error" in result or result["results"][0]["result"]["status"] != "success" + + +def get_current_ports() -> list[str]: + return [port.name for port in serial.tools.list_ports.comports()] + + +def get_new_port(old_ports, new_ports) -> str: + if ports_diff := list(set(new_ports) - set(old_ports)): + return ports_diff[0] + return None + + +class DetectPortChange: + def __init__(self): + self.old_ports = [] + self.new_ports = [] + + def __enter__(self, *args, **kwargs): + self.old_ports = get_current_ports() + return self + + def __exit__(self, *args, **kwargs): + self.new_ports = get_current_ports() + + def get_new_port(self): + return get_new_port(self.old_ports, self.new_ports) diff --git a/tools/__init__.py b/tools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tools/openiris_device.py b/tools/openiris_device.py new file mode 100644 index 0000000..f54c5d8 --- /dev/null +++ b/tools/openiris_device.py @@ -0,0 +1,143 @@ +import time +import json +import serial + + +class OpenIrisDevice: + def __init__(self, port: str, debug: bool, debug_commands: bool): + self.port = port + self.debug = debug + self.debug_commands = debug_commands + self.connection: serial.Serial | None = None + self.connected = False + + def __enter__(self): + self.connected = self.__connect() + return self + + def __exit__(self, type, value, traceback): + self.__disconnect() + self.connected = False + + def connect(self): + self.connected = self.__connect() + + def disconnect(self): + self.__disconnect() + self.connected = False + + def __connect(self) -> bool: + print(f"📡 Connecting directly to {self.port}...") + + try: + self.connection = serial.Serial( + port=self.port, baudrate=115200, timeout=1, write_timeout=1 + ) + self.connection.dtr = False + self.connection.rts = False + print(f"✅ Connected to the device on {self.port}") + return True + except Exception as e: + print(f"❌ Failed to connect to {self.port}: {e}") + return False + + def __disconnect(self): + if self.connection and self.connection.is_open: + self.connection.close() + print(f"🔌 Disconnected from {self.port}") + + def __check_if_response_is_complete(self, response) -> dict | None: + try: + if self.debug: + print(f"\nCHECKING: {response} \n") + return json.loads(response) + except ValueError: + if self.debug: + print("\nCHECK FAILED\n") + return None + + def __read_response(self, timeout: int | None = None) -> dict | None: + # we can try and retrieve the response now. + # it should be more or less immediate, but some commands may take longer + # so we gotta timeout + timeout = timeout if timeout is not None else 15 + start_time = time.time() + response_buffer = "" + while time.time() - start_time < timeout: + if self.connection.in_waiting: + packet = self.connection.read_all().decode("utf-8", errors="ignore") + if self.debug and packet.strip(): + print(f"Received: {packet}") + print("-" * 10) + print(f"Current buffer: {response_buffer}") + print("-" * 10) + + # we can't rely on new lines to detect if we're done + # nor can we assume that we're always gonna get valid json response + # but we can assume that if we're to get a valid response, it's gonna be json + # so we can start actually building the buffer only when + # some part of the packet starts with "{", and start building from there + # we can assume that no further data will be returned, so we can validate + # right after receiving the last packet + if (not response_buffer and "{" in packet) or response_buffer: + # assume we just started building the buffer and we've received the first packet + + # alternative approach in case this doesn't work - we're always sending a valid json + # so we can start building the buffer from the first packet and keep trying to find the + # starting and ending brackets, extract that part and validate, if the message is complete, return + if not response_buffer: + starting_idx = packet.find("{") + response_buffer = packet[starting_idx:] + else: + response_buffer += packet + + # and once we get something, we can validate if it's a valid json + if parsed_response := self.__check_if_response_is_complete( + response_buffer + ): + return parsed_response + else: + # if it's not a valid response just yet, + # we might've stumbled a case where we got a valid response + # but to the end of it, we've got some leftovers attached + # so, we can try and find the ending + ending_idx = response_buffer[::-1].find("}") + if reparsed_response := self.__check_if_response_is_complete( + response_buffer[: len(response_buffer) - ending_idx] + ): + return reparsed_response + else: + time.sleep(0.1) + return None + + def is_connected(self) -> bool: + return self.connected + + def send_command( + self, command: str, params: dict | None = None, timeout: int | None = None + ) -> dict: + if not self.connection or not self.connection.is_open: + return {"error": "Device Not Connected"} + + cmd_obj = {"commands": [{"command": command}]} + if params: + cmd_obj["commands"][0]["data"] = params + + # we're expecting the json string to end with a new line + # to signify we've finished sending the command + cmd_str = json.dumps(cmd_obj) + "\n" + try: + # clean it out first, just to be sure we're starting fresh + self.connection.reset_input_buffer() + if self.debug or self.debug_commands: + print(f"Sending command: {cmd_str}") + self.connection.write(cmd_str.encode()) + response = self.__read_response(timeout) + + if self.debug: + print(f"Received response: {response}") + + return response or {"error": "Command timeout"} + + except Exception as e: + return {"error": f"Communication error: {e}"} diff --git a/tools/setup_openiris.py b/tools/setup_openiris.py index c8caa89..3e40872 100644 --- a/tools/setup_openiris.py +++ b/tools/setup_openiris.py @@ -5,14 +5,14 @@ # /// -import json import time import argparse import sys -import serial import string from dataclasses import dataclass +from openiris_device import OpenIrisDevice + def is_back(choice: str): return choice.lower() in ["back", "b", "exit"] @@ -79,122 +79,6 @@ class Menu(SubMenu): super().__init__(title, context, parent_menu) -class OpenIrisDevice: - def __init__(self, port: str, debug: bool, debug_commands: bool): - self.port = port - self.debug = debug - self.debug_commands = debug_commands - self.connection: serial.Serial | None = None - self.connected = False - - def __enter__(self): - self.connected = self.__connect() - return self - - def __exit__(self, type, value, traceback): - self.__disconnect() - - def __connect(self) -> bool: - print(f"📡 Connecting directly to {self.port}...") - - try: - self.connection = serial.Serial( - port=self.port, baudrate=115200, timeout=1, write_timeout=1 - ) - print(f"✅ Connected to the device on {self.port}") - return True - except Exception as e: - print(f"❌ Failed to connect to {self.port}: {e}") - return False - - def __disconnect(self): - if self.connection and self.connection.is_open: - self.connection.close() - print(f"🔌 Disconnected from {self.port}") - - def __check_if_response_is_complete(self, response) -> dict | None: - try: - return json.loads(response) - except ValueError: - return None - - def __read_response(self, timeout: int | None = None) -> dict | None: - # we can try and retrieve the response now. - # it should be more or less immediate, but some commands may take longer - # so we gotta timeout - timeout = timeout if timeout is not None else 15 - start_time = time.time() - response_buffer = "" - while time.time() - start_time < timeout: - if self.connection.in_waiting: - packet = self.connection.read_all().decode("utf-8", errors="ignore") - if self.debug and packet.strip(): - print(f"Received: {packet}") - print("-" * 10) - print(f"Current buffer: {response_buffer}") - print("-" * 10) - - # we can't rely on new lines to detect if we're done - # nor can we assume that we're always gonna get valid json response - # but we can assume that if we're to get a valid response, it's gonna be json - # so we can start actually building the buffer only when - # some part of the packet starts with "{", and start building from there - # we can assume that no further data will be returned, so we can validate - # right after receiving the last packet - if (not response_buffer and "{" in packet) or response_buffer: - # assume we just started building the buffer and we've received the first packet - - # alternative approach in case this doesn't work - we're always sending a valid json - # so we can start building the buffer from the first packet and keep trying to find the - # starting and ending brackets, extract that part and validate, if the message is complete, return - if not response_buffer: - starting_idx = packet.find("{") - response_buffer = packet[starting_idx:] - else: - response_buffer += packet - - # and once we get something, we can validate if it's a valid json - if parsed_response := self.__check_if_response_is_complete( - response_buffer - ): - return parsed_response - else: - time.sleep(0.1) - return None - - def is_connected(self) -> bool: - return self.connected - - def send_command( - self, command: str, params: dict | None = None, timeout: int | None = None - ) -> dict: - if not self.connection or not self.connection.is_open: - return {"error": "Device Not Connected"} - - cmd_obj = {"commands": [{"command": command}]} - if params: - cmd_obj["commands"][0]["data"] = params - - # we're expecting the json string to end with a new line - # to signify we've finished sending the command - cmd_str = json.dumps(cmd_obj) + "\n" - try: - # clean it out first, just to be sure we're starting fresh - self.connection.reset_input_buffer() - if self.debug or self.debug_commands: - print(f"Sending command: {cmd_str}") - self.connection.write(cmd_str.encode()) - response = self.__read_response(timeout) - - if self.debug: - print(f"Received response: {response}") - - return response or {"error": "Command timeout"} - - except Exception as e: - return {"error": f"Communication error: {e}"} - - @dataclass class WiFiNetwork: ssid: str @@ -314,14 +198,18 @@ def get_serial_info(device: OpenIrisDevice) -> dict: "mac": response["results"][0]["result"]["data"]["mac"], } + def get_device_info(device: OpenIrisDevice) -> dict: response = device.send_command("get_who_am_i") if has_command_failed(response): print(f"❌ Failed to get device info: {response['error']}") return {"who_am_i": None, "version": None} - - return {"who_am_i": response["results"][0]["result"]["data"]["who_am_i"], "version": response["results"][0]["result"]["data"]["version"]} + + return { + "who_am_i": response["results"][0]["result"]["data"]["who_am_i"], + "version": response["results"][0]["result"]["data"]["version"], + } def get_wifi_status(device: OpenIrisDevice) -> dict: @@ -339,7 +227,9 @@ def get_led_current(device: OpenIrisDevice) -> dict: print(f"❌ Failed to get LED current: {response}") return {"led_current_ma": "unknown"} - return {"led_current_ma": response["results"][0]["result"]["data"]["led_current_ma"]} + return { + "led_current_ma": response["results"][0]["result"]["data"]["led_current_ma"] + } def configure_device_name(device: OpenIrisDevice, *args, **kwargs): @@ -462,11 +352,11 @@ def get_settings_summary(device: OpenIrisDevice, *args, **kwargs): print(f"🔑 Serial: {summary['Identity']}") print(f"💡 LED PWM Duty: {summary['LED']['duty_cycle']}%") print(f"🎚️ Mode: {summary['Mode']['mode']}") - + current_section = summary.get("Current", {}) led_current_ma = current_section.get("led_current_ma") print(f"🔌 LED Current: {led_current_ma} mA") - + advertised_name_data = summary.get("AdvertisedName", {}) advertised_name = advertised_name_data.get("name") print(f"📛 Name: {advertised_name}") @@ -479,7 +369,6 @@ def get_settings_summary(device: OpenIrisDevice, *args, **kwargs): if ver: print(f"🧭 Version: {ver}") - wifi = summary.get("WiFi", {}).get("wifi_status", {}) if wifi: status = wifi.get("status", "unknown") @@ -487,6 +376,7 @@ def get_settings_summary(device: OpenIrisDevice, *args, **kwargs): configured = wifi.get("networks_configured", 0) print(f"📶 WiFi: {status} | IP: {ip} | Networks configured: {configured}") + def restart_device_command(device: OpenIrisDevice, *args, **kwargs): print("🔄 Restarting device...") response = device.send_command("restart_device") @@ -497,6 +387,7 @@ def restart_device_command(device: OpenIrisDevice, *args, **kwargs): print("✅ Device restart command sent successfully") print("💡 Please wait a few seconds for the device to reboot") + def scan_networks(wifi_scanner: WiFiScanner, *args, **kwargs): use_custom_timeout = ( input("Should we use a custom scan timeout? (y/n)\n>> ").strip().lower() == "y" @@ -626,7 +517,7 @@ def automatic_wifi_configuration( ip = None last_status = None while time.time() - start < timeout_s: - status = get_wifi_status(device).get("wifi_status", {}) + status = get_wifi_status(device).get("wifi_status") or {} last_status = status ip = status.get("ip_address") if ip and ip not in ("0.0.0.0", "", None): @@ -654,7 +545,7 @@ def attempt_wifi_connection(device: OpenIrisDevice, *args, **kwargs): def check_wifi_status(device: OpenIrisDevice, *args, **kwargs): - status = get_wifi_status(device).get("wifi_status") + status = get_wifi_status(device).get("wifi_status") or {} print(f"📶 WiFi Status: {status.get('status', 'Unknown')}") if ip_address := status.get("ip_address"): print(f"🌐 IP Address: {ip_address}") diff --git a/tools/switchBoardType.py b/tools/switchBoardType.py index 0ff17f6..3764d66 100644 --- a/tools/switchBoardType.py +++ b/tools/switchBoardType.py @@ -1,221 +1,331 @@ import os import difflib +import shutil import argparse from typing import Dict, Optional, List HEADER_COLOR = "\033[95m" -OKGREEN = '\033[92m' -WARNING = '\033[93m' -OKBLUE = '\033[94m' -ENDC = '\033[0m' +OKGREEN = "\033[92m" +WARNING = "\033[93m" +OKBLUE = "\033[94m" +ENDC = "\033[0m" BOARDS_DIR_NAME = "boards" SDKCONFIG_DEFAULTS_FILENAME = "sdkconfig.base_defaults" + +# some components are super platform specific. +# to a point where building them with esp32 will fail every single time due to depndencies not supporting it +# with our own components, we can ship some shims to keep things clean +# but with those, unless we roll our own somehow, we're out of luck. +# So, to make things simpler, when selecting for which board to build, we're gonna reconfigure the components +# on the fly. +PLATFORM_SPECIFIC_COMPONENTS = {"esp32s3": ["usb_device_uvc"]} +PLATFORM_SPECIFIC_COMPONENTS_DIRS = {"esp32s3": "esp32s3"} + + def get_root_path() -> str: - return os.path.split(os.path.dirname(os.path.realpath(__file__)))[0] + return os.path.split(os.path.dirname(os.path.realpath(__file__)))[0] def get_boards_root() -> str: - return os.path.join(get_root_path(), BOARDS_DIR_NAME) + return os.path.join(get_root_path(), BOARDS_DIR_NAME) + + +def get_config_platform(_parsed_config: dict) -> str: + # 1:-1 to strip quotes + return _parsed_config["CONFIG_IDF_TARGET"][1:-1] def enumerate_board_configs() -> Dict[str, str]: - """Walk the boards directory and build a mapping of board names to absolute file paths. + """Walk the boards directory and build a mapping of board names to absolute file paths. - Naming strategy: - - Relative path from boards/ to file with path separators replaced by '_'. - - If the last two path segments are identical (e.g. project_babble/project_babble) collapse to a single segment. - - For facefocusvr eye boards we keep eye_L / eye_R suffix to distinguish configs even though WHO_AM_I is same. - """ - boards_dir = get_boards_root() - mapping: Dict[str, str] = {} - if not os.path.isdir(boards_dir): + Naming strategy: + - Relative path from boards/ to file with path separators replaced by '_'. + - If the last two path segments are identical (e.g. project_babble/project_babble) collapse to a single segment. + - For facefocusvr eye boards we keep eye_L / eye_R suffix to distinguish configs even though WHO_AM_I is same. + """ + boards_dir = get_boards_root() + mapping: Dict[str, str] = {} + if not os.path.isdir(boards_dir): + return mapping + for root, _dirs, files in os.walk(boards_dir): + for f in files: + if f == SDKCONFIG_DEFAULTS_FILENAME: + continue + rel_path = os.path.relpath(os.path.join(root, f), boards_dir) + parts = rel_path.split(os.sep) + if len(parts) >= 2 and parts[-1] == parts[-2]: # collapse duplicate tail + parts = parts[:-1] + board_key = "_".join(parts) + mapping[board_key] = os.path.join(root, f) return mapping - for root, _dirs, files in os.walk(boards_dir): - for f in files: - if f == SDKCONFIG_DEFAULTS_FILENAME: - continue - rel_path = os.path.relpath(os.path.join(root, f), boards_dir) - parts = rel_path.split(os.sep) - if len(parts) >= 2 and parts[-1] == parts[-2]: # collapse duplicate tail - parts = parts[:-1] - board_key = "_".join(parts) - mapping[board_key] = os.path.join(root, f) - return mapping BOARD_CONFIGS = enumerate_board_configs() + def build_arg_parser() -> argparse.ArgumentParser: - p = argparse.ArgumentParser() - p.add_argument("-b", "--board", help="Board name (run with --list to see options). Flexible: accepts path-like or partial if unique.") - p.add_argument("--list", help="List discovered boards and exit", action="store_true") - p.add_argument("--dry-run", help="Dry run, won't modify files", action="store_true") - p.add_argument("--diff", help="Show the difference between base config and selected board", action="store_true") - p.add_argument("--ssid", help="Set the WiFi SSID", type=str, default="") - p.add_argument("--password", help="Set the WiFi password", type=str, default="") - p.add_argument("--clear-wifi", help="Clear WiFi credentials", action="store_true") - return p + p = argparse.ArgumentParser() + p.add_argument( + "-b", + "--board", + help="Board name (run with --list to see options). Flexible: accepts path-like or partial if unique.", + ) + p.add_argument( + "--list", help="List discovered boards and exit", action="store_true" + ) + p.add_argument("--dry-run", help="Dry run, won't modify files", action="store_true") + p.add_argument( + "--diff", + help="Show the difference between base config and selected board", + action="store_true", + ) + p.add_argument("--ssid", help="Set the WiFi SSID", type=str, default="") + p.add_argument("--password", help="Set the WiFi password", type=str, default="") + p.add_argument("--clear-wifi", help="Clear WiFi credentials", action="store_true") + return p + def list_boards(): - print("Discovered boards:") - width = max((len(k) for k in BOARD_CONFIGS), default=0) - for name, path in sorted(BOARD_CONFIGS.items()): - print(f" {name.ljust(width)} -> {os.path.relpath(path, get_root_path())}") + print("Discovered boards:") + width = max((len(k) for k in BOARD_CONFIGS), default=0) + for name, path in sorted(BOARD_CONFIGS.items()): + print(f" {name.ljust(width)} -> {os.path.relpath(path, get_root_path())}") + def _suggest_boards(partial: str) -> List[str]: - if not partial: - return [] - partial_low = partial.lower() - contains = [b for b in BOARD_CONFIGS if partial_low in b.lower()] - if contains: - return contains[:10] - # fallback to fuzzy matching using difflib - choices = list(BOARD_CONFIGS.keys()) - return difflib.get_close_matches(partial, choices, n=5, cutoff=0.4) + if not partial: + return [] + partial_low = partial.lower() + contains = [b for b in BOARD_CONFIGS if partial_low in b.lower()] + if contains: + return contains[:10] + # fallback to fuzzy matching using difflib + choices = list(BOARD_CONFIGS.keys()) + return difflib.get_close_matches(partial, choices, n=5, cutoff=0.4) + def normalize_board_name(raw: Optional[str]) -> Optional[str]: - if raw is None: + if raw is None: + return None + candidate = raw.strip() + if not candidate: + return None + candidate = candidate.replace("\\", "/").rstrip("/") + # strip leading folders like tools/, boards/ + parts = [ + p + for p in candidate.split("/") + if p not in (".", "") and p not in ("tools", "boards") + ] + if parts: + candidate = parts[-1] if len(parts) == 1 else "_".join(parts) + candidate = candidate.replace("-", "_") + # exact match + if candidate in BOARD_CONFIGS: + return candidate + # try ending match + endings = [b for b in BOARD_CONFIGS if b.endswith(candidate)] + if len(endings) == 1: + return endings[0] + if len(endings) > 1: + print(f"Ambiguous board '{raw}'. Could be: {', '.join(endings)}") + return None + # attempt case-insensitive + lower_map = {b.lower(): b for b in BOARD_CONFIGS} + if candidate.lower() in lower_map: + return lower_map[candidate.lower()] return None - candidate = raw.strip() - if not candidate: - return None - candidate = candidate.replace('\\', '/').rstrip('/') - # strip leading folders like tools/, boards/ - parts = [p for p in candidate.split('/') if p not in ('.', '') and p not in ('tools', 'boards')] - if parts: - candidate = parts[-1] if len(parts) == 1 else "_".join(parts) - candidate = candidate.replace('-', '_') - # exact match - if candidate in BOARD_CONFIGS: - return candidate - # try ending match - endings = [b for b in BOARD_CONFIGS if b.endswith(candidate)] - if len(endings) == 1: - return endings[0] - if len(endings) > 1: - print(f"Ambiguous board '{raw}'. Could be: {', '.join(endings)}") - return None - # attempt case-insensitive - lower_map = {b.lower(): b for b in BOARD_CONFIGS} - if candidate.lower() in lower_map: - return lower_map[candidate.lower()] - return None def get_main_config_path() -> str: - return os.path.join(get_root_path(), "sdkconfig") + return os.path.join(get_root_path(), "sdkconfig") def get_board_config_path(board_key: str) -> str: - return BOARD_CONFIGS[board_key] + return BOARD_CONFIGS[board_key] def get_base_config_path() -> str: - # base defaults moved under boards directory - return os.path.join(get_boards_root(), SDKCONFIG_DEFAULTS_FILENAME) + # base defaults moved under boards directory + return os.path.join(get_boards_root(), SDKCONFIG_DEFAULTS_FILENAME) def parse_config(config_file) -> dict: - config = {} - for line in config_file: - line = line.strip().split("=") - if len(line) == 2: - config[line[0]] = line[1] - else: - # lines without value are usually comments, we're safe to store empty string there - config[line[0]] = "" - return config + config = {} + for line in config_file: + line = line.strip().split("=") + if len(line) == 2: + config[line[0]] = line[1] + else: + # lines without value are usually comments, we're safe to store empty string there + config[line[0]] = "" + return config def handle_wifi_config(_new_config: dict, _main_config: dict, _args) -> dict: - if _args.ssid: - _new_config["CONFIG_WIFI_SSID"] = f"\"{_args.ssid}\"" - _new_config["CONFIG_WIFI_PASSWORD"] = f"\"{_args.password}\"" - else: - if "CONFIG_WIFI_SSID" in _main_config: - _new_config["CONFIG_WIFI_SSID"] = _main_config["CONFIG_WIFI_SSID"] - if "CONFIG_WIFI_PASSWORD" in _main_config: - _new_config["CONFIG_WIFI_PASSWORD"] = _main_config["CONFIG_WIFI_PASSWORD"] + if _args.ssid: + _new_config["CONFIG_WIFI_SSID"] = f'"{_args.ssid}"' + _new_config["CONFIG_WIFI_PASSWORD"] = f'"{_args.password}"' + else: + if "CONFIG_WIFI_SSID" in _main_config: + _new_config["CONFIG_WIFI_SSID"] = _main_config["CONFIG_WIFI_SSID"] + if "CONFIG_WIFI_PASSWORD" in _main_config: + _new_config["CONFIG_WIFI_PASSWORD"] = _main_config["CONFIG_WIFI_PASSWORD"] - if _args.clear_wifi: - _new_config["CONFIG_WIFI_SSID"] = "\"\"" - _new_config["CONFIG_WIFI_PASSWORD"] = "\"\"" - return _new_config + if _args.clear_wifi: + _new_config["CONFIG_WIFI_SSID"] = '""' + _new_config["CONFIG_WIFI_PASSWORD"] = '""' + return _new_config def compute_diff(_parsed_base_config: dict, _parsed_board_config: dict) -> dict: - _diff = {} - for _key in _parsed_board_config: - if _key not in _parsed_base_config: - if _parsed_board_config[_key] != "": - _diff[_key] = f"{OKGREEN}+{ENDC} {_parsed_board_config[_key]}" - else: - if _parsed_board_config[_key] != _parsed_base_config[_key]: - _diff[_key] = f"{OKGREEN}{_parsed_base_config[_key]}{ENDC} -> {OKBLUE}{_parsed_board_config[_key]}{ENDC}" - return _diff + _diff = {} + for _key in _parsed_board_config: + if _key not in _parsed_base_config: + if _parsed_board_config[_key] != "": + _diff[_key] = f"{OKGREEN}+{ENDC} {_parsed_board_config[_key]}" + else: + if _parsed_board_config[_key] != _parsed_base_config[_key]: + _diff[_key] = ( + f"{OKGREEN}{_parsed_base_config[_key]}{ENDC} -> {OKBLUE}{_parsed_board_config[_key]}{ENDC}" + ) + return _diff + + +def _move_directories(component: str, destination_path: str): + if os.path.exists(component): + shutil.move(component, destination_path) + + +def handle_extra_components(old_platform: str, new_platform: str, dry_run: bool): + print( + f"{OKGREEN}Switching components configuration from platform:{ENDC} {OKBLUE}{old_platform}{ENDC} {OKGREEN}to platform:{ENDC} {OKBLUE}{new_platform}{ENDC}" + ) + + if old_platform == new_platform: + print(f"{OKGREEN}The platform is the same. Nothing to do here.{ENDC}") + return + + old_platform_components = PLATFORM_SPECIFIC_COMPONENTS.get(old_platform, []) + new_platform_components = PLATFORM_SPECIFIC_COMPONENTS.get(new_platform, []) + if dry_run: + print(f"{OKGREEN}Would remove: {ENDC}") + for component in old_platform_components: + print(f"{OKBLUE}- {component} {ENDC}") + + print(f"{OKGREEN}Would add: {ENDC}") + for component in new_platform_components: + print(f"{OKBLUE}- {component} {ENDC}") + + return + + components_path = os.path.join(get_root_path(), "components") + + if old_base_dir := PLATFORM_SPECIFIC_COMPONENTS_DIRS.get(old_platform): + old_extra_components_path = os.path.join( + os.path.join(get_root_path(), "extra_components"), old_base_dir + ) + for component in old_platform_components: + component_path = os.path.join(components_path, component) + print( + f"{OKGREEN}Moving:{ENDC}{OKBLUE} {component}{ENDC} to {OKBLUE}{old_extra_components_path}{ENDC}" + ) + _move_directories(component_path, old_extra_components_path) + + if new_base_dir := PLATFORM_SPECIFIC_COMPONENTS_DIRS.get(new_platform): + new_extra_components_path = os.path.join( + os.path.join(get_root_path(), "extra_components"), new_base_dir + ) + for component in new_platform_components: + component_path = os.path.join(new_extra_components_path, component) + print( + f"{OKGREEN}Moving:{ENDC}{OKBLUE} {component}{ENDC} to {OKBLUE}{components_path}{ENDC}" + ) + _move_directories(component_path, components_path) def main(): - parser = build_arg_parser() - args = parser.parse_args() + parser = build_arg_parser() + args = parser.parse_args() - if args.list: - list_boards() - return + if args.list: + list_boards() + return - board_input = args.board - if not board_input: - parser.error("--board is required (or use --list)") - normalized = normalize_board_name(board_input) - if not normalized: - print(f"{WARNING}Unknown board '{board_input}'.") - suggestions = _suggest_boards(board_input) - if suggestions: - print("Did you mean: " + ", ".join(suggestions)) - print("Use --list to see all boards.") - raise SystemExit(2) + board_input = args.board + if not board_input: + parser.error("--board is required (or use --list)") + normalized = normalize_board_name(board_input) + if not normalized: + print(f"{WARNING}Unknown board '{board_input}'.") + suggestions = _suggest_boards(board_input) + if suggestions: + print("Did you mean: " + ", ".join(suggestions)) + print("Use --list to see all boards.") + raise SystemExit(2) - if not os.path.isfile(get_base_config_path()): - raise SystemExit(f"Base defaults file not found: {get_base_config_path()}") + if not os.path.isfile(get_base_config_path()): + raise SystemExit(f"Base defaults file not found: {get_base_config_path()}") - print(f"{OKGREEN}Switching configuration to board:{ENDC} {OKBLUE}{normalized}{ENDC}") - print(f"{OKGREEN}Using defaults from :{ENDC} {get_base_config_path()}") - print(f"{OKGREEN}Using board config from :{ENDC} {get_board_config_path(normalized)}") + print( + f"{OKGREEN}Switching configuration to board:{ENDC} {OKBLUE}{normalized}{ENDC}" + ) + print(f"{OKGREEN}Using defaults from :{ENDC} {get_base_config_path()}") + print( + f"{OKGREEN}Using board config from :{ENDC} {get_board_config_path(normalized)}" + ) - with open(get_main_config_path(), "r+") as main_config: - parsed_main_config = parse_config(main_config) + with open(get_main_config_path(), "r+") as main_config: + parsed_main_config = parse_config(main_config) - with open(get_base_config_path(), "r") as base_config, open(get_board_config_path(normalized), "r") as board_config: - parsed_base_config = parse_config(base_config) - parsed_board_config = parse_config(board_config) + with ( + open(get_base_config_path(), "r") as base_config, + open(get_board_config_path(normalized), "r") as board_config, + ): + parsed_base_config = parse_config(base_config) + parsed_board_config = parse_config(board_config) - new_board_config = {**parsed_base_config, **parsed_board_config} - new_board_config = handle_wifi_config(new_board_config, parsed_main_config, args) + new_board_config = {**parsed_base_config, **parsed_board_config} + new_board_config = handle_wifi_config(new_board_config, parsed_main_config, args) - if args.diff: - print("---"*5, f"{WARNING}DIFF{ENDC}", "---"*5) - diff = compute_diff(parsed_main_config, new_board_config) - if not diff: - print(f"{HEADER_COLOR}[DIFF]{ENDC} No changes between existing main config and {OKBLUE}{normalized}{ENDC}") - else: - print(f"{HEADER_COLOR}[DIFF]{ENDC} Keys differing (main -> new {OKBLUE}{normalized}{ENDC}):") - for key in sorted(diff): - print(f"{HEADER_COLOR}[DIFF]{ENDC} {key} : {diff[key]}") - print("---"*14) - - if not args.dry_run: - print(f"{WARNING}Writing changes to main config file{ENDC}") - with open(get_main_config_path(), "w") as main_config: - for key, value in new_board_config.items(): - if value: - main_config.write(f"{key}={value}\n") + if args.diff: + print("---" * 5, f"{WARNING}DIFF{ENDC}", "---" * 5) + diff = compute_diff(parsed_main_config, new_board_config) + if not diff: + print( + f"{HEADER_COLOR}[DIFF]{ENDC} No changes between existing main config and {OKBLUE}{normalized}{ENDC}" + ) else: - main_config.write(f"{key}\n") - else: - print(f"{WARNING}[DRY-RUN]{ENDC} Skipping writing to files") - print(f"{OKGREEN}Done. ESP-IDF is setup to build for:{ENDC} {OKBLUE}{normalized}{ENDC}") + print( + f"{HEADER_COLOR}[DIFF]{ENDC} Keys differing (main -> new {OKBLUE}{normalized}{ENDC}):" + ) + for key in sorted(diff): + print(f"{HEADER_COLOR}[DIFF]{ENDC} {key} : {diff[key]}") + print("---" * 14) -if __name__ == "__main__": # pragma: no cover - main() \ No newline at end of file + if not args.dry_run: + print(f"{WARNING}Writing changes to main config file{ENDC}") + with open(get_main_config_path(), "w") as main_config: + for key, value in new_board_config.items(): + if value: + main_config.write(f"{key}={value}\n") + else: + main_config.write(f"{key}\n") + else: + print(f"{WARNING}[DRY-RUN]{ENDC} Skipping writing to files") + + handle_extra_components( + get_config_platform(parsed_main_config), + get_config_platform(new_board_config), + args.dry_run, + ) + + print( + f"{OKGREEN}Done. ESP-IDF is setup to build for:{ENDC} {OKBLUE}{normalized}{ENDC}" + ) + + +if __name__ == "__main__": + main() diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..8236c41 --- /dev/null +++ b/uv.lock @@ -0,0 +1,152 @@ +version = 1 +revision = 3 +requires-python = ">=3.12" + +[[package]] +name = "blink" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "pyserial" }, + { name = "pytest" }, + { name = "python-dotenv" }, +] + +[package.dev-dependencies] +dev = [ + { name = "bumpver" }, +] + +[package.metadata] +requires-dist = [ + { name = "pyserial", specifier = ">=3.5" }, + { name = "pytest", specifier = ">=9.0.1" }, + { name = "python-dotenv", specifier = ">=1.2.1" }, +] + +[package.metadata.requires-dev] +dev = [{ name = "bumpver", specifier = ">=2025.1131" }] + +[[package]] +name = "bumpver" +version = "2025.1131" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "colorama" }, + { name = "lexid" }, + { name = "toml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8f/8a/cc13e816e9f0849dce423b904b06fd91b5444cba6df3200d512a702f2e95/bumpver-2025.1131.tar.gz", hash = "sha256:a35fd2d43a5f65f014035c094866bd3bd6c739606f29fd41246d6ec6e839d3f9", size = 115372, upload-time = "2025-07-02T20:36:11.982Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/5b/2d5ea6802495ee4506721977be522804314aa66ad629d9356e3c7e5af4a6/bumpver-2025.1131-py2.py3-none-any.whl", hash = "sha256:c02527f6ed7887afbc06c07630047b24a9f9d02d544a65639e99bf8b92aaa674", size = 65361, upload-time = "2025-07-02T20:36:10.103Z" }, +] + +[[package]] +name = "click" +version = "8.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", size = 276943, upload-time = "2025-09-18T17:32:23.696Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295, upload-time = "2025-09-18T17:32:22.42Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "lexid" +version = "2021.1006" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/60/0b/28a3f9abc75abbf1fa996eb2dd77e1e33a5d1aac62566e3f60a8ec8b8a22/lexid-2021.1006.tar.gz", hash = "sha256:509a3a4cc926d3dbf22b203b18a4c66c25e6473fb7c0e0d30374533ac28bafe5", size = 11525, upload-time = "2021-04-02T20:18:34.668Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/e3/35764404a4b7e2021be1f88f42264c2e92e0c4720273559a62461ce64a47/lexid-2021.1006-py2.py3-none-any.whl", hash = "sha256:5526bb5606fd74c7add23320da5f02805bddd7c77916f2dc1943e6bada8605ed", size = 7587, upload-time = "2021-04-02T20:18:33.129Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pyserial" +version = "3.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/7d/ae3f0a63f41e4d2f6cb66a5b57197850f919f59e558159a4dd3a818f5082/pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", size = 159125, upload-time = "2020-11-23T03:59:15.045Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0", size = 90585, upload-time = "2020-11-23T03:59:13.41Z" }, +] + +[[package]] +name = "pytest" +version = "9.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/56/f013048ac4bc4c1d9be45afd4ab209ea62822fb1598f40687e6bf45dcea4/pytest-9.0.1.tar.gz", hash = "sha256:3e9c069ea73583e255c3b21cf46b8d3c56f6e3a1a8f6da94ccb0fcf57b9d73c8", size = 1564125, upload-time = "2025-11-12T13:05:09.333Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/8b/6300fb80f858cda1c51ffa17075df5d846757081d11ab4aa35cef9e6258b/pytest-9.0.1-py3-none-any.whl", hash = "sha256:67be0030d194df2dfa7b556f2e56fb3c3315bd5c8822c6951162b92b32ce7dad", size = 373668, upload-time = "2025-11-12T13:05:07.379Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, +] + +[[package]] +name = "toml" +version = "0.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/ba/1f744cdc819428fc6b5084ec34d9b30660f6f9daaf70eead706e3203ec3c/toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f", size = 22253, upload-time = "2020-11-01T01:40:22.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" }, +]