From 2e85b52ee9332abd6aecd966c73bea5618a0e3a6 Mon Sep 17 00:00:00 2001 From: Vilem Zavodny Date: Wed, 2 Apr 2025 15:39:53 +0200 Subject: [PATCH 1/7] ci(runner): Save image from camera --- .github/ci/runner_camera.py | 21 +++ .github/workflows/build-run-applications.yml | 162 ++++++++++--------- conftest.py | 46 +++++- examples/display/pytest_display.py | 2 +- examples/pytest_helpers.py | 28 ++++ 5 files changed, 177 insertions(+), 82 deletions(-) create mode 100644 .github/ci/runner_camera.py create mode 100644 examples/pytest_helpers.py diff --git a/.github/ci/runner_camera.py b/.github/ci/runner_camera.py new file mode 100644 index 000000000..992c0cef7 --- /dev/null +++ b/.github/ci/runner_camera.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import cv2 + +# This will return video from the first webcam on your computer. +cap = cv2.VideoCapture(0) + +# reads frames from a camera +# ret checks return at each frame +ret, frame = cap.read() +if ret: + # Save image + image_path = "snapshot.jpg" + cv2.imwrite(image_path, frame) + print(f"Image saved {image_path}") +else: + print("Cannot save image.") + +# Close the window / Release webcam +cap.release() diff --git a/.github/workflows/build-run-applications.yml b/.github/workflows/build-run-applications.yml index a1c6a643b..dc9361a6f 100644 --- a/.github/workflows/build-run-applications.yml +++ b/.github/workflows/build-run-applications.yml @@ -1,4 +1,4 @@ -name: Build ESP-BSP apps +name: Build and Run ESP-BSP apps # This job builds all examples and test_applications in this repo # Applications are selected for build based on changes files and dependencies defined in .build-test-rules.yml @@ -47,30 +47,30 @@ jobs: - idf_ver: "latest" parallel_count: 5 parallel_index: 5 - - idf_ver: "release-v5.1" - parallel_count: 2 - parallel_index: 1 - - idf_ver: "release-v5.1" - parallel_count: 2 - parallel_index: 2 - - idf_ver: "release-v5.2" - parallel_count: 2 - parallel_index: 1 - - idf_ver: "release-v5.2" - parallel_count: 2 - parallel_index: 2 - - idf_ver: "release-v5.3" - parallel_count: 2 - parallel_index: 1 - - idf_ver: "release-v5.3" - parallel_count: 2 - parallel_index: 2 - - idf_ver: "release-v5.4" - parallel_count: 2 - parallel_index: 1 - - idf_ver: "release-v5.4" - parallel_count: 2 - parallel_index: 2 + #- idf_ver: "release-v5.1" + # parallel_count: 2 + # parallel_index: 1 + #- idf_ver: "release-v5.1" + # parallel_count: 2 + # parallel_index: 2 + #- idf_ver: "release-v5.2" + # parallel_count: 2 + # parallel_index: 1 + #- idf_ver: "release-v5.2" + # parallel_count: 2 + # parallel_index: 2 + #- idf_ver: "release-v5.3" + # parallel_count: 2 + # parallel_index: 1 + #- idf_ver: "release-v5.3" + # parallel_count: 2 + # parallel_index: 2 + #- idf_ver: "release-v5.4" + # parallel_count: 2 + # parallel_index: 1 + #- idf_ver: "release-v5.4" + # parallel_count: 2 + # parallel_index: 2 runs-on: ubuntu-latest container: espressif/idf:${{ matrix.idf_ver }} steps: @@ -124,60 +124,60 @@ jobs: - runs-on: "esp-box-3" marker: "esp_box_3" target: "esp32s3" - - runs-on: "esp32_c3_lcdkit" - marker: "esp32_c3_lcdkit" - target: "esp32c3" - - runs-on: "esp32_p4_box" - marker: "esp32_p4_box" - target: "esp32p4" - - runs-on: "esp32_p4_function_ev_board" - marker: "esp32_p4_function_ev_board" - target: "esp32p4" - - runs-on: "esp32_s3_eye" - marker: "esp32_s3_eye" - target: "esp32s3" - - runs-on: "esp32_s3_lcd_ev_board" - marker: "esp32_s3_lcd_ev_board" - target: "esp32s3" - - runs-on: "esp32_s3_lcd_ev_board" - marker: "esp32_s3_lcd_ev_board_2" - target: "esp32s3" - - runs-on: "esp32_s3_usb_otg" - marker: "esp32_s3_usb_otg" - target: "esp32s3" - - runs-on: "esp_wrover_kit" - marker: "esp_wrover_kit" - target: "esp32" - - runs-on: "m5dial" - marker: "m5dial" - target: "esp32s3" - - runs-on: "m5stack_core" - marker: "m5stack_core" - target: "esp32" - - runs-on: "m5stack_core_2" - marker: "m5stack_core_2" - target: "esp32" - - runs-on: "m5stack_core_s3" - marker: "m5stack_core_s3" - target: "esp32s3" - - runs-on: "m5stack_core_s3" - marker: "m5stack_core_s3_se" - target: "esp32s3" - - runs-on: "esp32_azure_iot_kit" - marker: "esp32_azure_iot_kit" - target: "esp32" - - runs-on: "esp_bsp_devkit" - marker: "esp_bsp_devkit" - target: "esp32s3" - - runs-on: "esp_bsp_generic" - marker: "esp_bsp_generic" - target: "esp32s3" - - runs-on: "esp32_s3_korvo_2" - marker: "esp32_s3_korvo_2" - target: "esp32s3" - - runs-on: "m5_atom_s3" - marker: "m5_atom_s3" - target: "esp32s3" + #- runs-on: "esp32_c3_lcdkit" + # marker: "esp32_c3_lcdkit" + # target: "esp32c3" + #- runs-on: "esp32_p4_box" + # marker: "esp32_p4_box" + # target: "esp32p4" + #- runs-on: "esp32_p4_function_ev_board" + # marker: "esp32_p4_function_ev_board" + # target: "esp32p4" + #- runs-on: "esp32_s3_eye" + # marker: "esp32_s3_eye" + # target: "esp32s3" + #- runs-on: "esp32_s3_lcd_ev_board" + # marker: "esp32_s3_lcd_ev_board" + # target: "esp32s3" + #- runs-on: "esp32_s3_lcd_ev_board" + # marker: "esp32_s3_lcd_ev_board_2" + # target: "esp32s3" + #- runs-on: "esp32_s3_usb_otg" + # marker: "esp32_s3_usb_otg" + # target: "esp32s3" + #- runs-on: "esp_wrover_kit" + # marker: "esp_wrover_kit" + # target: "esp32" + #- runs-on: "m5dial" + # marker: "m5dial" + # target: "esp32s3" + #- runs-on: "m5stack_core" + # marker: "m5stack_core" + # target: "esp32" + #- runs-on: "m5stack_core_2" + # marker: "m5stack_core_2" + # target: "esp32" + #- runs-on: "m5stack_core_s3" + # marker: "m5stack_core_s3" + # target: "esp32s3" + #- runs-on: "m5stack_core_s3" + # marker: "m5stack_core_s3_se" + # target: "esp32s3" + #- runs-on: "esp32_azure_iot_kit" + # marker: "esp32_azure_iot_kit" + # target: "esp32" + #- runs-on: "esp_bsp_devkit" + # marker: "esp_bsp_devkit" + # target: "esp32s3" + #- runs-on: "esp_bsp_generic" + # marker: "esp_bsp_generic" + # target: "esp32s3" + #- runs-on: "esp32_s3_korvo_2" + # marker: "esp32_s3_korvo_2" + # target: "esp32s3" + #- runs-on: "m5_atom_s3" + # marker: "m5_atom_s3" + # target: "esp32s3" env: TEST_RESULT_NAME: test_results_${{ matrix.runner.target }}_${{ matrix.runner.marker }}_${{ matrix.idf_ver }} BENCHMARK_RESULT_NAME: benchmark_${{ matrix.runner.target }}_${{ matrix.runner.marker }}_${{ matrix.idf_ver }} @@ -197,7 +197,8 @@ jobs: env: PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi/" run: | - pip install --prefer-binary cryptography pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf pytest-custom_exit_code + pip install --prefer-binary cryptography pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf pytest-custom_exit_code opencv-python numpy + apt-get update && apt-get install -y libgl1 - name: Download latest results uses: actions/download-artifact@v4 with: @@ -216,6 +217,7 @@ jobs: benchmark_*.md benchmark_*.json benchmark.json + *.jpg - name: Check if benchmark files exist id: check_files run: | diff --git a/conftest.py b/conftest.py index 138488777..6e0407c35 100644 --- a/conftest.py +++ b/conftest.py @@ -1,6 +1,8 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest +import cv2 +from pathlib import Path def pytest_generate_tests(metafunc): @@ -38,3 +40,45 @@ def pytest_collection_modifyitems(config, items): marker_option = "[" + config.getoption("-m") + "]" if marker_option not in item.nodeid: item.add_marker(pytest.mark.skip(reason="Not for selected params")) + + +def bsp_capture_image(image_path, board): + # Return video from the first webcam on your computer. + cap = cv2.VideoCapture(0) + # Set FullHD resolution (1920x1080) + cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) + cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) + + # TODO: Camera calibration + + # reads frames from a camera + # ret checks return at each frame + ret, frame = cap.read() + if ret: + # TODO: Camera calibration / Perspective transform + # TODO: Change size image + # TODO: Crop image for {board} + + # Save image + cv2.imwrite(image_path, frame) + print(f"Image saved {image_path}") + else: + print("Cannot save image.") + + # Close the window / Release webcam + cap.release() + + +def bsp_test_image(board, example, expectation): + image_file = f"snapshot_{board}_{example}.jpg" + bsp_capture_image(image_file, board) + + +@pytest.fixture(autouse=True) +def bsp_test(request): + board = request.node.callspec.id + path = Path(str(request.node.fspath)) + test_name = path.parent.name + yield + print(f"Capturing image for: {board}") + bsp_test_image(board, test_name, "") diff --git a/examples/display/pytest_display.py b/examples/display/pytest_display.py index cc5ea168b..f5b097da6 100644 --- a/examples/display/pytest_display.py +++ b/examples/display/pytest_display.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest diff --git a/examples/pytest_helpers.py b/examples/pytest_helpers.py new file mode 100644 index 000000000..9a74cf403 --- /dev/null +++ b/examples/pytest_helpers.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +import cv2 + + +def bsp_capture_image(image_path): + # Return video from the first webcam on your computer. + cap = cv2.VideoCapture(0) + # reads frames from a camera + # ret checks return at each frame + ret, frame = cap.read() + if ret: + # TODO: Change size image + # TODO: Crop image + + # Save image + cv2.imwrite(image_path, frame) + print(f"Image saved {image_path}") + else: + print("Cannot save image.") + + # Close the window / Release webcam + cap.release() + + +def bsp_test_image(board, example, expectation): + image_file = f"snapshot_{example}_{board}.jpg" + bsp_capture_image(image_file) From 2a2b77e956583025fcb655c7f0861d8f9ad4adfd Mon Sep 17 00:00:00 2001 From: Vilem Zavodny Date: Tue, 10 Jun 2025 14:39:09 +0200 Subject: [PATCH 2/7] Cam rotation and focus --- .github/ci/runner_camera.py | 21 --------------------- examples/pytest_helpers.py | 6 +++++- 2 files changed, 5 insertions(+), 22 deletions(-) delete mode 100644 .github/ci/runner_camera.py diff --git a/.github/ci/runner_camera.py b/.github/ci/runner_camera.py deleted file mode 100644 index 992c0cef7..000000000 --- a/.github/ci/runner_camera.py +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Apache-2.0 - -import cv2 - -# This will return video from the first webcam on your computer. -cap = cv2.VideoCapture(0) - -# reads frames from a camera -# ret checks return at each frame -ret, frame = cap.read() -if ret: - # Save image - image_path = "snapshot.jpg" - cv2.imwrite(image_path, frame) - print(f"Image saved {image_path}") -else: - print("Cannot save image.") - -# Close the window / Release webcam -cap.release() diff --git a/examples/pytest_helpers.py b/examples/pytest_helpers.py index 9a74cf403..e9dd56ee2 100644 --- a/examples/pytest_helpers.py +++ b/examples/pytest_helpers.py @@ -6,15 +6,19 @@ def bsp_capture_image(image_path): # Return video from the first webcam on your computer. cap = cv2.VideoCapture(0) + cap.set(cv2.CAP_PROP_AUTOFOCUS, 1) + cap.set(cv2.CAP_PROP_EXPOSURE, 7.0) # reads frames from a camera # ret checks return at each frame ret, frame = cap.read() if ret: + # Image rotation + frame_rotated = cv2.rotate(frame, cv2.ROTATE_180) # TODO: Change size image # TODO: Crop image # Save image - cv2.imwrite(image_path, frame) + cv2.imwrite(image_path, frame_rotated) print(f"Image saved {image_path}") else: print("Cannot save image.") From 829ccd2591b22d216ba13f6451ce469036c3c5e0 Mon Sep 17 00:00:00 2001 From: Vilem Zavodny Date: Tue, 10 Jun 2025 15:43:31 +0200 Subject: [PATCH 3/7] test rotation --- .github/workflows/build-run-applications.yml | 1 + conftest.py | 9 ++++++ examples/pytest_helpers.py | 32 -------------------- 3 files changed, 10 insertions(+), 32 deletions(-) delete mode 100644 examples/pytest_helpers.py diff --git a/.github/workflows/build-run-applications.yml b/.github/workflows/build-run-applications.yml index dc9361a6f..f75288f4d 100644 --- a/.github/workflows/build-run-applications.yml +++ b/.github/workflows/build-run-applications.yml @@ -199,6 +199,7 @@ jobs: run: | pip install --prefer-binary cryptography pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf pytest-custom_exit_code opencv-python numpy apt-get update && apt-get install -y libgl1 + apt-get update && apt-get install -y v4l-utils - name: Download latest results uses: actions/download-artifact@v4 with: diff --git a/conftest.py b/conftest.py index 6e0407c35..91d5c91ba 100644 --- a/conftest.py +++ b/conftest.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest import cv2 +import subprocess from pathlib import Path @@ -43,6 +44,12 @@ def pytest_collection_modifyitems(config, items): def bsp_capture_image(image_path, board): + # Enable auto-focus + subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=focus_auto=1"]) + # Manual exposition + subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=exposure_auto=1"]) + subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=exposure_absolute=100"]) + # Return video from the first webcam on your computer. cap = cv2.VideoCapture(0) # Set FullHD resolution (1920x1080) @@ -55,6 +62,8 @@ def bsp_capture_image(image_path, board): # ret checks return at each frame ret, frame = cap.read() if ret: + # Image rotation + frame = cv2.rotate(frame, cv2.ROTATE_180) # TODO: Camera calibration / Perspective transform # TODO: Change size image # TODO: Crop image for {board} diff --git a/examples/pytest_helpers.py b/examples/pytest_helpers.py deleted file mode 100644 index e9dd56ee2..000000000 --- a/examples/pytest_helpers.py +++ /dev/null @@ -1,32 +0,0 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Apache-2.0 -import cv2 - - -def bsp_capture_image(image_path): - # Return video from the first webcam on your computer. - cap = cv2.VideoCapture(0) - cap.set(cv2.CAP_PROP_AUTOFOCUS, 1) - cap.set(cv2.CAP_PROP_EXPOSURE, 7.0) - # reads frames from a camera - # ret checks return at each frame - ret, frame = cap.read() - if ret: - # Image rotation - frame_rotated = cv2.rotate(frame, cv2.ROTATE_180) - # TODO: Change size image - # TODO: Crop image - - # Save image - cv2.imwrite(image_path, frame_rotated) - print(f"Image saved {image_path}") - else: - print("Cannot save image.") - - # Close the window / Release webcam - cap.release() - - -def bsp_test_image(board, example, expectation): - image_file = f"snapshot_{example}_{board}.jpg" - bsp_capture_image(image_file) From 546fb031227090e2aa48878ab28d04f8eaa684bf Mon Sep 17 00:00:00 2001 From: Vilem Zavodny Date: Wed, 11 Jun 2025 14:08:41 +0200 Subject: [PATCH 4/7] exposure --- conftest.py | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/conftest.py b/conftest.py index 91d5c91ba..ccd9b51f5 100644 --- a/conftest.py +++ b/conftest.py @@ -3,6 +3,7 @@ import pytest import cv2 import subprocess +import numpy as np from pathlib import Path @@ -43,18 +44,42 @@ def pytest_collection_modifyitems(config, items): item.add_marker(pytest.mark.skip(reason="Not for selected params")) +def bsp_image_correction(image): + pts_src = np.float32([ + [160, 80], # top-left + [1044, 87], # top-right + [279, 720], # bottom-left + [913, 718] # bottom-right + ]) + + width, height = 1000, 884 + pts_dst = np.float32([ + [0, 0], + [width, 0], + [0, height], + [width, height] + ]) + + matrix = cv2.getPerspectiveTransform(pts_src, pts_dst) + warped = cv2.warpPerspective(image, matrix, (width, height)) + return warped + + def bsp_capture_image(image_path, board): # Enable auto-focus - subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=focus_auto=1"]) + # subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=focus_auto=1"]) + # Manual focus + subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=focus_auto=0"]) + subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=focus_absolute=20"]) # Manual exposition subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=exposure_auto=1"]) - subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=exposure_absolute=100"]) + subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=exposure_absolute=1"]) # Return video from the first webcam on your computer. cap = cv2.VideoCapture(0) # Set FullHD resolution (1920x1080) - cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) - cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) + cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) + cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) # TODO: Camera calibration @@ -68,6 +93,9 @@ def bsp_capture_image(image_path, board): # TODO: Change size image # TODO: Crop image for {board} + # correction image perspective and crop + frame = bsp_image_correction(frame) + # Save image cv2.imwrite(image_path, frame) print(f"Image saved {image_path}") From 5bdc72264cb27d4e8600390e87859c46e7929e8a Mon Sep 17 00:00:00 2001 From: Vilem Zavodny Date: Fri, 13 Jun 2025 14:05:33 +0200 Subject: [PATCH 5/7] correction of fisheye + crop --- conftest.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/conftest.py b/conftest.py index ccd9b51f5..960707be7 100644 --- a/conftest.py +++ b/conftest.py @@ -44,7 +44,7 @@ def pytest_collection_modifyitems(config, items): item.add_marker(pytest.mark.skip(reason="Not for selected params")) -def bsp_image_correction(image): +def bsp_image_correction(image, width, height): pts_src = np.float32([ [160, 80], # top-left [1044, 87], # top-right @@ -52,7 +52,6 @@ def bsp_image_correction(image): [913, 718] # bottom-right ]) - width, height = 1000, 884 pts_dst = np.float32([ [0, 0], [width, 0], @@ -65,6 +64,21 @@ def bsp_image_correction(image): return warped +def bsp_fisheye_correction(image, width, height): + K = np.array([ + [width, 0, width / 2], # Focal length x + [0, width, height / 2], # Focal length y + [0, 0, 1]]) # Principal point + # [k1, k2, p1, p2, k3] - main is k1 a k2 + dist_coeffs = np.array([-0.3, 0.1, 0, 0, 0]) + + new_K, _ = cv2.getOptimalNewCameraMatrix(K, dist_coeffs, (width, height), 1, (width, height)) + map1, map2 = cv2.initUndistortRectifyMap(K, dist_coeffs, None, new_K, (width, height), 5) + undistorted = cv2.remap(image, map1, map2, interpolation=cv2.INTER_LINEAR) + + return undistorted + + def bsp_capture_image(image_path, board): # Enable auto-focus # subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=focus_auto=1"]) @@ -94,7 +108,11 @@ def bsp_capture_image(image_path, board): # TODO: Crop image for {board} # correction image perspective and crop - frame = bsp_image_correction(frame) + frame = bsp_image_correction(frame, 1000, 884) + # correction of fisheye + frame = bsp_fisheye_correction(frame, 1000, 884) + # crop + frame = frame[30:848, 38:980] # Save image cv2.imwrite(image_path, frame) From 49ed592b94609e3bea98f6b56b643f543e61f603 Mon Sep 17 00:00:00 2001 From: Vilem Zavodny Date: Fri, 13 Jun 2025 15:59:32 +0200 Subject: [PATCH 6/7] Camera update --- conftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conftest.py b/conftest.py index 960707be7..76aad490f 100644 --- a/conftest.py +++ b/conftest.py @@ -84,7 +84,7 @@ def bsp_capture_image(image_path, board): # subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=focus_auto=1"]) # Manual focus subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=focus_auto=0"]) - subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=focus_absolute=20"]) + subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=focus_absolute=50"]) # Manual exposition subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=exposure_auto=1"]) subprocess.run(["v4l2-ctl", "-d", "/dev/video0", "--set-ctrl=exposure_absolute=1"]) @@ -129,7 +129,7 @@ def bsp_test_image(board, example, expectation): bsp_capture_image(image_file, board) -@pytest.fixture(autouse=True) +@pytest.fixture() def bsp_test(request): board = request.node.callspec.id path = Path(str(request.node.fspath)) From 356ad78d93502d05016e490a07506a17464be777 Mon Sep 17 00:00:00 2001 From: Vilem Zavodny Date: Mon, 16 Jun 2025 14:16:39 +0200 Subject: [PATCH 7/7] Run only selected tests + wait --- conftest.py | 4 +++- examples/display/pytest_display.py | 2 +- examples/display_lvgl_demos/pytest_display_lvgl_demos.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/conftest.py b/conftest.py index 76aad490f..4ff2844a9 100644 --- a/conftest.py +++ b/conftest.py @@ -4,6 +4,7 @@ import cv2 import subprocess import numpy as np +import time from pathlib import Path @@ -130,10 +131,11 @@ def bsp_test_image(board, example, expectation): @pytest.fixture() -def bsp_test(request): +def bsp_test_capture_image(request): board = request.node.callspec.id path = Path(str(request.node.fspath)) test_name = path.parent.name yield + time.sleep(5) # wait 5 seconds print(f"Capturing image for: {board}") bsp_test_image(board, test_name, "") diff --git a/examples/display/pytest_display.py b/examples/display/pytest_display.py index f5b097da6..4d15aa6d0 100644 --- a/examples/display/pytest_display.py +++ b/examples/display/pytest_display.py @@ -20,6 +20,6 @@ @pytest.mark.m5stack_core_s3 @pytest.mark.m5stack_core_s3_se @pytest.mark.m5_atom_s3 -def test_display_example(dut: Dut) -> None: +def test_display_example(dut: Dut, bsp_test_capture_image) -> None: dut.expect_exact('example: Display LVGL animation') dut.expect_exact('main_task: Returned from app_main()') diff --git a/examples/display_lvgl_demos/pytest_display_lvgl_demos.py b/examples/display_lvgl_demos/pytest_display_lvgl_demos.py index daf7a05a4..cadec3ebc 100644 --- a/examples/display_lvgl_demos/pytest_display_lvgl_demos.py +++ b/examples/display_lvgl_demos/pytest_display_lvgl_demos.py @@ -13,6 +13,6 @@ @pytest.mark.m5dial @pytest.mark.m5stack_core_s3 @pytest.mark.m5stack_core_s3_se -def test_display_example(dut: Dut) -> None: +def test_display_example(dut: Dut, bsp_test_capture_image) -> None: dut.expect_exact('app_main: Display LVGL demo') dut.expect_exact('main_task: Returned from app_main()')