From aca887be8dc120698ae40f9a785cecf32c225de6 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 25 Feb 2024 09:27:53 -0600 Subject: [PATCH 01/24] allow custom filenaming --- adafruit_pycamera/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/adafruit_pycamera/__init__.py b/adafruit_pycamera/__init__.py index d019cf5..8c68479 100644 --- a/adafruit_pycamera/__init__.py +++ b/adafruit_pycamera/__init__.py @@ -820,14 +820,17 @@ def live_preview_mode(self): # self.effect = self._effect self.continuous_capture_start() - def open_next_image(self, extension="jpg"): + def open_next_image(self, extension="jpg", filename_prefix="img"): """Return an opened numbered file on the sdcard, such as "img01234.jpg".""" try: os.stat("/sd") except OSError as exc: # no SD card! raise RuntimeError("No SD card mounted") from exc while True: - filename = "/sd/img%04d.%s" % (self._image_counter, extension) + filename = f"/sd/{filename_prefix}%04d.%s" % ( + self._image_counter, + extension, + ) self._image_counter += 1 try: os.stat(filename) @@ -837,7 +840,7 @@ def open_next_image(self, extension="jpg"): print("Writing to", filename) return open(filename, "wb") - def capture_jpeg(self): + def capture_jpeg(self, filename_prefix="img"): """Capture a jpeg file and save it to the SD card""" try: os.stat("/sd") @@ -855,7 +858,7 @@ def capture_jpeg(self): print(f"Captured {len(jpeg)} bytes of jpeg data") print("Resolution %d x %d" % (self.camera.width, self.camera.height)) - with self.open_next_image() as dest: + with self.open_next_image(filename_prefix=filename_prefix) as dest: chunksize = 16384 for offset in range(0, len(jpeg), chunksize): dest.write(jpeg[offset : offset + chunksize]) From 23c7fa5c288f283603835c3172dbd814851411be Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 25 Feb 2024 10:25:33 -0600 Subject: [PATCH 02/24] timestamp filename example --- examples/timestamp_filename/code.py | 78 +++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 examples/timestamp_filename/code.py diff --git a/examples/timestamp_filename/code.py b/examples/timestamp_filename/code.py new file mode 100644 index 0000000..1022cef --- /dev/null +++ b/examples/timestamp_filename/code.py @@ -0,0 +1,78 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 Tim Cocks for Adafruit Industries +# +# SPDX-License-Identifier: MIT +""" simple point-and-shoot camera example. With NTP and internal RTC to + add timestamp to photo filenames. Must install adafruit_ntp library!""" + +import time +import adafruit_pycamera # pylint: disable=import-error +import wifi +import socketpool +import adafruit_ntp +import rtc +import time + +pool = socketpool.SocketPool(wifi.radio) +ntp = adafruit_ntp.NTP(pool, tz_offset=0) +rtc.RTC().datetime = ntp.datetime + +pycam = adafruit_pycamera.PyCamera() +pycam.mode = 0 # only mode 0 (JPEG) will work in this example + +# User settings - try changing these: +pycam.resolution = 2 # 0-12 preset resolutions: +# 0: 240x240, 1: 320x240, 2: 640x480, 3: 800x600, 4: 1024x768, +# 5: 1280x720, 6: 1280x1024, 7: 1600x1200, 8: 1920x1080, 9: 2048x1536, +# 10: 2560x1440, 11: 2560x1600, 12: 2560x1920 +pycam.led_level = 1 # 0-4 preset brightness levels +pycam.led_color = 0 # 0-7 preset colors: 0: white, 1: green, 2: yellow, 3: red, +# 4: pink, 5: blue, 6: teal, 7: rainbow +pycam.effect = 0 # 0-7 preset FX: 0: normal, 1: invert, 2: b&w, 3: red, +# 4: green, 5: blue, 6: sepia, 7: solarize + +print("Simple camera ready.") +pycam.tone(800, 0.1) +pycam.tone(1200, 0.05) + +while True: + pycam.blit(pycam.continuous_capture()) + pycam.keys_debounce() + + if pycam.shutter.short_count: + print("Shutter released") + pycam.tone(1200, 0.05) + pycam.tone(1600, 0.05) + try: + pycam.display_message("snap", color=0x00DD00) + timestamp = f"img_{time.localtime().tm_year}-{time.localtime().tm_mon}-{time.localtime().tm_mday}_{time.localtime().tm_hour:02}-{time.localtime().tm_min:02}-{time.localtime().tm_sec:02}_" + pycam.capture_jpeg(filename_prefix=timestamp) + pycam.live_preview_mode() + except TypeError as exception: + pycam.display_message("Failed", color=0xFF0000) + time.sleep(0.5) + pycam.live_preview_mode() + except RuntimeError as exception: + pycam.display_message("Error\nNo SD Card", color=0xFF0000) + time.sleep(0.5) + + if pycam.card_detect.fell: + print("SD card removed") + pycam.unmount_sd_card() + pycam.display.refresh() + + if pycam.card_detect.rose: + print("SD card inserted") + pycam.display_message("Mounting\nSD Card", color=0xFFFFFF) + for _ in range(3): + try: + print("Mounting card") + pycam.mount_sd_card() + print("Success!") + break + except OSError as exception: + print("Retrying!", exception) + time.sleep(0.5) + else: + pycam.display_message("SD Card\nFailed!", color=0xFF0000) + time.sleep(0.5) + pycam.display.refresh() From 994dd1ccef8877b208778171169e076fa889b6a4 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 25 Feb 2024 10:27:32 -0600 Subject: [PATCH 03/24] pylint fixes --- examples/timestamp_filename/code.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/timestamp_filename/code.py b/examples/timestamp_filename/code.py index 1022cef..03308af 100644 --- a/examples/timestamp_filename/code.py +++ b/examples/timestamp_filename/code.py @@ -5,12 +5,11 @@ add timestamp to photo filenames. Must install adafruit_ntp library!""" import time -import adafruit_pycamera # pylint: disable=import-error import wifi import socketpool -import adafruit_ntp import rtc -import time +import adafruit_ntp +import adafruit_pycamera # pylint: disable=import-error pool = socketpool.SocketPool(wifi.radio) ntp = adafruit_ntp.NTP(pool, tz_offset=0) @@ -44,7 +43,11 @@ pycam.tone(1600, 0.05) try: pycam.display_message("snap", color=0x00DD00) - timestamp = f"img_{time.localtime().tm_year}-{time.localtime().tm_mon}-{time.localtime().tm_mday}_{time.localtime().tm_hour:02}-{time.localtime().tm_min:02}-{time.localtime().tm_sec:02}_" + # pylint: disable=line-too-long + timestamp = ( + f"img_{time.localtime().tm_year}-{time.localtime().tm_mon}-{time.localtime().tm_mday}" + f"_{time.localtime().tm_hour:02}-{time.localtime().tm_min:02}-{time.localtime().tm_sec:02}_" + ) pycam.capture_jpeg(filename_prefix=timestamp) pycam.live_preview_mode() except TypeError as exception: From 91969b403c6edfc4fac63ffaf238bfaf7a3399cf Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 25 Feb 2024 10:30:55 -0600 Subject: [PATCH 04/24] more details in comment --- examples/timestamp_filename/code.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/timestamp_filename/code.py b/examples/timestamp_filename/code.py index 03308af..3ac59d3 100644 --- a/examples/timestamp_filename/code.py +++ b/examples/timestamp_filename/code.py @@ -2,7 +2,10 @@ # # SPDX-License-Identifier: MIT """ simple point-and-shoot camera example. With NTP and internal RTC to - add timestamp to photo filenames. Must install adafruit_ntp library!""" + add timestamp to photo filenames. Must install adafruit_ntp library! + Example code assumes WIFI credentials are properly setup and web workflow + enabled in settings.toml. If not, you'll need to add code to manually connect + to your network.""" import time import wifi From c8d4a046b25520cd9c9d5b6dd7d1c91a0bb1cb15 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 4 Mar 2024 14:52:23 -0600 Subject: [PATCH 05/24] reduce to single string format. Fix long line in example for CircuitPython --- adafruit_pycamera/__init__.py | 5 +---- examples/timestamp_filename/code.py | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/adafruit_pycamera/__init__.py b/adafruit_pycamera/__init__.py index 8c68479..9b056bc 100644 --- a/adafruit_pycamera/__init__.py +++ b/adafruit_pycamera/__init__.py @@ -827,10 +827,7 @@ def open_next_image(self, extension="jpg", filename_prefix="img"): except OSError as exc: # no SD card! raise RuntimeError("No SD card mounted") from exc while True: - filename = f"/sd/{filename_prefix}%04d.%s" % ( - self._image_counter, - extension, - ) + filename = f"/sd/{filename_prefix}{self._image_counter}.{extension}" self._image_counter += 1 try: os.stat(filename) diff --git a/examples/timestamp_filename/code.py b/examples/timestamp_filename/code.py index 3ac59d3..93f4a8b 100644 --- a/examples/timestamp_filename/code.py +++ b/examples/timestamp_filename/code.py @@ -47,10 +47,7 @@ try: pycam.display_message("snap", color=0x00DD00) # pylint: disable=line-too-long - timestamp = ( - f"img_{time.localtime().tm_year}-{time.localtime().tm_mon}-{time.localtime().tm_mday}" - f"_{time.localtime().tm_hour:02}-{time.localtime().tm_min:02}-{time.localtime().tm_sec:02}_" - ) + timestamp = f"img_{time.localtime().tm_year}-{time.localtime().tm_mon}-{time.localtime().tm_mday}_{time.localtime().tm_hour:02}-{time.localtime().tm_min:02}-{time.localtime().tm_sec:02}_" pycam.capture_jpeg(filename_prefix=timestamp) pycam.live_preview_mode() except TypeError as exception: From 9410a211ae72c14449fe5662c16cfe141a114079 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 4 Mar 2024 14:59:36 -0600 Subject: [PATCH 06/24] refactor longline to use format() --- examples/timestamp_filename/code.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/timestamp_filename/code.py b/examples/timestamp_filename/code.py index 93f4a8b..3edd7fa 100644 --- a/examples/timestamp_filename/code.py +++ b/examples/timestamp_filename/code.py @@ -47,7 +47,14 @@ try: pycam.display_message("snap", color=0x00DD00) # pylint: disable=line-too-long - timestamp = f"img_{time.localtime().tm_year}-{time.localtime().tm_mon}-{time.localtime().tm_mday}_{time.localtime().tm_hour:02}-{time.localtime().tm_min:02}-{time.localtime().tm_sec:02}_" + timestamp = "img_{}-{}-{}_{:02}-{:02}-{:02}_".format( + time.localtime().tm_year, + time.localtime().tm_mon, + time.localtime().tm_mday, + time.localtime().tm_hour, + time.localtime().tm_min, + time.localtime().tm_sec, + ) pycam.capture_jpeg(filename_prefix=timestamp) pycam.live_preview_mode() except TypeError as exception: From b57c955df4183ac226e3cfec6acd29228cf99b1a Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 4 Mar 2024 15:00:04 -0600 Subject: [PATCH 07/24] remove pylint disable --- examples/timestamp_filename/code.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/timestamp_filename/code.py b/examples/timestamp_filename/code.py index 3edd7fa..05c2a2e 100644 --- a/examples/timestamp_filename/code.py +++ b/examples/timestamp_filename/code.py @@ -46,7 +46,6 @@ pycam.tone(1600, 0.05) try: pycam.display_message("snap", color=0x00DD00) - # pylint: disable=line-too-long timestamp = "img_{}-{}-{}_{:02}-{:02}-{:02}_".format( time.localtime().tm_year, time.localtime().tm_mon, From 85d76995c65a0cb37a356fc58263fd4afd5a5e2a Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 5 Mar 2024 11:24:49 -0600 Subject: [PATCH 08/24] leading 0s format --- adafruit_pycamera/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_pycamera/__init__.py b/adafruit_pycamera/__init__.py index 9b056bc..a7cbe35 100644 --- a/adafruit_pycamera/__init__.py +++ b/adafruit_pycamera/__init__.py @@ -827,7 +827,7 @@ def open_next_image(self, extension="jpg", filename_prefix="img"): except OSError as exc: # no SD card! raise RuntimeError("No SD card mounted") from exc while True: - filename = f"/sd/{filename_prefix}{self._image_counter}.{extension}" + filename = f"/sd/{filename_prefix}{self._image_counter:04d}.{extension}" self._image_counter += 1 try: os.stat(filename) From e0dc69aaf9d5d64b6c5ce1e9a51564d7bce560d6 Mon Sep 17 00:00:00 2001 From: Fred Meyer <56278928+VPTechOps@users.noreply.github.com> Date: Sun, 17 Mar 2024 10:21:26 -0700 Subject: [PATCH 09/24] Update code.py to handle RTC and NTP --- examples/camera/code.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/examples/camera/code.py b/examples/camera/code.py index 553c035..5a3ae9a 100644 --- a/examples/camera/code.py +++ b/examples/camera/code.py @@ -3,11 +3,49 @@ # # SPDX-License-Identifier: Unlicense +import ipaddress +import ssl +import wifi +import socketpool +import adafruit_requests +import os +import rtc +import adafruit_ntp +from adafruit_datetime import datetime + import time import bitmaptools import displayio import gifio import ulab.numpy as np +UTC_OFFSET = os.getenv('UTC_OFFSET') +TZ = os.getenv('TZ') + +# Wifi details are in settings.toml file, also, +# timezone info should be included to allow local time and DST adjustments +# # UTC_OFFSET, if present, will override TZ and DST and no API query will be done +# UTC_OFFSET=-25200 +# # TZ="America/Phoenix" + +try: + print("Connecting to %s"%os.getenv("CIRCUITPY_WIFI_SSID")) + wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")) + print("Connected to %s!"%os.getenv("CIRCUITPY_WIFI_SSID")) + print("My IP address is", wifi.radio.ipv4_address) + pool = socketpool.SocketPool(wifi.radio) + + if UTC_OFFSET is None: + requests = adafruit_requests.Session(pool, ssl.create_default_context()) + response = requests.get("http://worldtimeapi.org/api/timezone/" + TZ) + response_as_json = response.json() + UTC_OFFSET = response_as_json["raw_offset"] + response_as_json["dst_offset"] + + ntp = adafruit_ntp.NTP(pool, server="pool.ntp.org", tz_offset=UTC_OFFSET // 3600) + + rtc.RTC().datetime = ntp.datetime +except Exception as e: + print("Wifi error:", e) + print("Time not set") import adafruit_pycamera From 076ea3c6452eb50a4f52415433f5656ee8be8c56 Mon Sep 17 00:00:00 2001 From: Fred Meyer <56278928+VPTechOps@users.noreply.github.com> Date: Sun, 17 Mar 2024 10:36:59 -0700 Subject: [PATCH 10/24] Update code.py to correct errors in pull request checks --- examples/camera/code.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/camera/code.py b/examples/camera/code.py index 5a3ae9a..4f2e17a 100644 --- a/examples/camera/code.py +++ b/examples/camera/code.py @@ -3,21 +3,21 @@ # # SPDX-License-Identifier: Unlicense -import ipaddress +import adafruit_pycamera + import ssl -import wifi import socketpool import adafruit_requests import os import rtc import adafruit_ntp -from adafruit_datetime import datetime - import time +import wifi import bitmaptools import displayio import gifio import ulab.numpy as np + UTC_OFFSET = os.getenv('UTC_OFFSET') TZ = os.getenv('TZ') From 481409725594815284201c905da0c810905d7497 Mon Sep 17 00:00:00 2001 From: Fred Meyer <56278928+VPTechOps@users.noreply.github.com> Date: Sun, 17 Mar 2024 10:40:00 -0700 Subject: [PATCH 11/24] Update code.py correct errora in pull request checks --- examples/camera/code.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/camera/code.py b/examples/camera/code.py index 4f2e17a..71c4d7f 100644 --- a/examples/camera/code.py +++ b/examples/camera/code.py @@ -47,8 +47,6 @@ print("Wifi error:", e) print("Time not set") -import adafruit_pycamera - pycam = adafruit_pycamera.PyCamera() # pycam.live_preview_mode() From 272f80e2c07b8769885d8d0260c9e1be80a14dfa Mon Sep 17 00:00:00 2001 From: Fred Meyer <56278928+VPTechOps@users.noreply.github.com> Date: Sun, 17 Mar 2024 10:51:20 -0700 Subject: [PATCH 12/24] Update code.py Correct errors in pull request checks --- examples/camera/code.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/camera/code.py b/examples/camera/code.py index 71c4d7f..61c0a56 100644 --- a/examples/camera/code.py +++ b/examples/camera/code.py @@ -3,21 +3,21 @@ # # SPDX-License-Identifier: Unlicense -import adafruit_pycamera - import ssl +import os +import time import socketpool import adafruit_requests -import os import rtc import adafruit_ntp -import time import wifi import bitmaptools import displayio import gifio import ulab.numpy as np +import adafruit_pycamera + UTC_OFFSET = os.getenv('UTC_OFFSET') TZ = os.getenv('TZ') From ffa8575fc389bad95b9292af1c518ed12ebba3a9 Mon Sep 17 00:00:00 2001 From: Fred Meyer Date: Sun, 17 Mar 2024 16:57:17 -0700 Subject: [PATCH 13/24] Change to run pre-commit --- examples/camera/code.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/examples/camera/code.py b/examples/camera/code.py index 61c0a56..a4e6868 100644 --- a/examples/camera/code.py +++ b/examples/camera/code.py @@ -2,7 +2,6 @@ # SPDX-FileCopyrightText: 2023 Limor Fried for Adafruit Industries # # SPDX-License-Identifier: Unlicense - import ssl import os import time @@ -18,19 +17,21 @@ import adafruit_pycamera -UTC_OFFSET = os.getenv('UTC_OFFSET') -TZ = os.getenv('TZ') - # Wifi details are in settings.toml file, also, -# timezone info should be included to allow local time and DST adjustments +# timezone info should be included in settings.toml to allow local time and DST adjustments # # UTC_OFFSET, if present, will override TZ and DST and no API query will be done # UTC_OFFSET=-25200 # # TZ="America/Phoenix" +UTC_OFFSET = os.getenv("UTC_OFFSET") +TZ = os.getenv("TZ") + try: - print("Connecting to %s"%os.getenv("CIRCUITPY_WIFI_SSID")) - wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")) - print("Connected to %s!"%os.getenv("CIRCUITPY_WIFI_SSID")) + print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}") + wifi.radio.connect( + os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD") + ) + print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}!") print("My IP address is", wifi.radio.ipv4_address) pool = socketpool.SocketPool(wifi.radio) From bf348c19d46424d4dc3cac940a759ba94f06809f Mon Sep 17 00:00:00 2001 From: Fred Meyer Date: Sun, 17 Mar 2024 17:26:13 -0700 Subject: [PATCH 14/24] Correct 1 more pre-commit error --- examples/camera/code.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/camera/code.py b/examples/camera/code.py index a4e6868..a8dfc48 100644 --- a/examples/camera/code.py +++ b/examples/camera/code.py @@ -26,11 +26,11 @@ UTC_OFFSET = os.getenv("UTC_OFFSET") TZ = os.getenv("TZ") -try: - print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}") - wifi.radio.connect( - os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD") +print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}") +wifi.radio.connect( + os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD") ) +if wifi.radio.connected: print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}!") print("My IP address is", wifi.radio.ipv4_address) pool = socketpool.SocketPool(wifi.radio) @@ -44,9 +44,8 @@ ntp = adafruit_ntp.NTP(pool, server="pool.ntp.org", tz_offset=UTC_OFFSET // 3600) rtc.RTC().datetime = ntp.datetime -except Exception as e: - print("Wifi error:", e) - print("Time not set") +else: + print("Wifi failed to connect. Time not set.") pycam = adafruit_pycamera.PyCamera() # pycam.live_preview_mode() From 3fb24e986a43998a9beaa0105fe7e27fb24ba526 Mon Sep 17 00:00:00 2001 From: Fred Meyer Date: Sun, 17 Mar 2024 17:59:58 -0700 Subject: [PATCH 15/24] Correct DOS file endings --- examples/camera/code.py | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/examples/camera/code.py b/examples/camera/code.py index 5a3ae9a..6c957c0 100644 --- a/examples/camera/code.py +++ b/examples/camera/code.py @@ -2,35 +2,37 @@ # SPDX-FileCopyrightText: 2023 Limor Fried for Adafruit Industries # # SPDX-License-Identifier: Unlicense - -import ipaddress import ssl -import wifi +import os +import time import socketpool import adafruit_requests -import os import rtc import adafruit_ntp -from adafruit_datetime import datetime - -import time +import wifi import bitmaptools import displayio import gifio import ulab.numpy as np -UTC_OFFSET = os.getenv('UTC_OFFSET') -TZ = os.getenv('TZ') + +import adafruit_pycamera # Wifi details are in settings.toml file, also, -# timezone info should be included to allow local time and DST adjustments +# timezone info should be included in settings.toml to allow local time and DST adjustments + # # UTC_OFFSET, if present, will override TZ and DST and no API query will be done # UTC_OFFSET=-25200 # # TZ="America/Phoenix" -try: - print("Connecting to %s"%os.getenv("CIRCUITPY_WIFI_SSID")) - wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")) - print("Connected to %s!"%os.getenv("CIRCUITPY_WIFI_SSID")) +UTC_OFFSET = os.getenv("UTC_OFFSET") +TZ = os.getenv("TZ") + +print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}") +wifi.radio.connect( + os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD") + ) +if wifi.radio.connected: + print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}!") print("My IP address is", wifi.radio.ipv4_address) pool = socketpool.SocketPool(wifi.radio) @@ -43,11 +45,8 @@ ntp = adafruit_ntp.NTP(pool, server="pool.ntp.org", tz_offset=UTC_OFFSET // 3600) rtc.RTC().datetime = ntp.datetime -except Exception as e: - print("Wifi error:", e) - print("Time not set") - -import adafruit_pycamera +else: + print("Wifi failed to connect. Time not set.") pycam = adafruit_pycamera.PyCamera() # pycam.live_preview_mode() From bf5559c3d3dc13c00187328cf4195af3c21b1e5d Mon Sep 17 00:00:00 2001 From: Fred Meyer Date: Sun, 17 Mar 2024 18:13:18 -0700 Subject: [PATCH 16/24] Correct Another DOS line ending --- examples/camera/code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/camera/code.py b/examples/camera/code.py index 37b7b0b..1825f23 100644 --- a/examples/camera/code.py +++ b/examples/camera/code.py @@ -29,7 +29,7 @@ print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}") wifi.radio.connect( os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD") - ) +) if wifi.radio.connected: print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}!") print("My IP address is", wifi.radio.ipv4_address) From 1e219f2d85a90cacab3819a224b15da727ed2997 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Fri, 10 May 2024 17:39:41 -0500 Subject: [PATCH 17/24] continue if no WIFI --- examples/camera/code.py | 42 +++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/examples/camera/code.py b/examples/camera/code.py index 1825f23..a03ea64 100644 --- a/examples/camera/code.py +++ b/examples/camera/code.py @@ -27,25 +27,35 @@ TZ = os.getenv("TZ") print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}") -wifi.radio.connect( - os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD") -) -if wifi.radio.connected: - print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}!") - print("My IP address is", wifi.radio.ipv4_address) - pool = socketpool.SocketPool(wifi.radio) +SSID = os.getenv("CIRCUITPY_WIFI_SSID") +PASSWORD = os.getenv("CIRCUITPY_WIFI_PASSWORD") + +if SSID and PASSWORD: + wifi.radio.connect( + os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD") + ) + if wifi.radio.connected: + print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}!") + print("My IP address is", wifi.radio.ipv4_address) + pool = socketpool.SocketPool(wifi.radio) - if UTC_OFFSET is None: - requests = adafruit_requests.Session(pool, ssl.create_default_context()) - response = requests.get("http://worldtimeapi.org/api/timezone/" + TZ) - response_as_json = response.json() - UTC_OFFSET = response_as_json["raw_offset"] + response_as_json["dst_offset"] + if UTC_OFFSET is None: + requests = adafruit_requests.Session(pool, ssl.create_default_context()) + response = requests.get("http://worldtimeapi.org/api/timezone/" + TZ) + response_as_json = response.json() + UTC_OFFSET = response_as_json["raw_offset"] + response_as_json["dst_offset"] + print(f"UTC_OFFSET: {UTC_OFFSET}") - ntp = adafruit_ntp.NTP(pool, server="pool.ntp.org", tz_offset=UTC_OFFSET // 3600) + ntp = adafruit_ntp.NTP( + pool, server="pool.ntp.org", tz_offset=UTC_OFFSET // 3600 + ) - rtc.RTC().datetime = ntp.datetime + print(f"ntp time: {ntp.datetime}") + rtc.RTC().datetime = ntp.datetime + else: + print("Wifi failed to connect. Time not set.") else: - print("Wifi failed to connect. Time not set.") + print("Wifi config not found in settintgs.toml. Time not set.") pycam = adafruit_pycamera.PyCamera() # pycam.live_preview_mode() @@ -199,7 +209,7 @@ t0 = t1 pycam._mode_label.text = "GIF" # pylint: disable=protected-access print(f"\nfinal size {f.tell()} for {i} frames") - print(f"average framerate {i/(t1-t00)}fps") + print(f"average framerate {i / (t1 - t00)}fps") print(f"best {max(ft)} worst {min(ft)} std. deviation {np.std(ft)}") f.close() pycam.display.refresh() From ae3dd31989e3ff0a8c6ba2863b126496c5947279 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 28 Sep 2024 11:08:15 -0400 Subject: [PATCH 18/24] use espcamera reset functionality; other minor changes - espcamera knows how to toggle the power and reset pins to do a reset. Let it do it. - Make docstring be one string - use I2C write_then_readinto --- .pre-commit-config.yaml | 2 +- adafruit_pycamera/__init__.py | 30 +++++++++++------------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 70ade69..374676d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/pycqa/pylint - rev: v2.17.4 + rev: v3.3.1 hooks: - id: pylint name: pylint (library code) diff --git a/adafruit_pycamera/__init__.py b/adafruit_pycamera/__init__.py index 45dcb3c..6a4807c 100644 --- a/adafruit_pycamera/__init__.py +++ b/adafruit_pycamera/__init__.py @@ -81,9 +81,10 @@ class PyCameraBase: # pylint: disable=too-many-instance-attributes,too-many-public-methods - """Base class for PyCamera hardware""" + """Base class for PyCamera hardware - """Wrapper class for the PyCamera hardware with lots of smarts""" + Wrapper class for the PyCamera hardware with lots of smarts + """ _finalize_firmware_load = ( 0x3022, @@ -253,9 +254,6 @@ def __init__(self) -> None: # pylint: disable=too-many-statements self.shutter_button.switch_to_input(Pull.UP) self.shutter = Button(self.shutter_button) - self._cam_reset = DigitalInOut(board.CAMERA_RESET) - self._cam_pwdn = DigitalInOut(board.CAMERA_PWDN) - # AW9523 GPIO expander self._aw = adafruit_aw9523.AW9523(self._i2c, address=0x58) print("Found AW9523") @@ -374,14 +372,6 @@ def init_neopixel(self): def init_camera(self, init_autofocus=True) -> None: """Initialize the camera, by default including autofocus""" - print("reset camera") - self._cam_reset.switch_to_output(False) - self._cam_pwdn.switch_to_output(True) - time.sleep(0.01) - self._cam_pwdn.switch_to_output(False) - time.sleep(0.01) - self._cam_reset.switch_to_output(True) - time.sleep(0.01) print("Initializing camera") self.camera = espcamera.Camera( @@ -390,6 +380,8 @@ def init_camera(self, init_autofocus=True) -> None: pixel_clock_pin=board.CAMERA_PCLK, vsync_pin=board.CAMERA_VSYNC, href_pin=board.CAMERA_HREF, + powerdown_pin=board.CAMERA_PWDN, + reset_pin=board.CAMERA_RESET, pixel_format=espcamera.PixelFormat.RGB565, frame_size=espcamera.FrameSize.HQVGA, i2c=board.I2C(), @@ -455,13 +447,13 @@ def write_camera_list(self, reg_list: Sequence[int]) -> None: def read_camera_register(self, reg: int) -> int: """Read a 1-byte camera register""" - b = bytearray(2) - b[0] = reg >> 8 - b[1] = reg & 0xFF + b_out = bytearray(2) + b_out[0] = reg >> 8 + b_out[1] = reg & 0xFF + b_in = bytearray(1) with self._camera_device as i2c: - i2c.write(b) - i2c.readinto(b, end=1) - return b[0] + i2c.write_then_readinto(b_out, b_in) + return b_in[0] def autofocus_init_from_bitstream(self, firmware: bytes): """Initialize the autofocus engine from a bytestring""" From 5ca0969597e48fe8e1ec00a2e9324c702b71945c Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 28 Sep 2024 11:19:16 -0400 Subject: [PATCH 19/24] pylint wants yield from --- examples/filter/code.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/filter/code.py b/examples/filter/code.py index 8d4598c..207b55f 100644 --- a/examples/filter/code.py +++ b/examples/filter/code.py @@ -139,8 +139,7 @@ def sketch(b): def cycle(seq): while True: - for s in seq: - yield s + yield from seq effects_cycle = iter(cycle(effects)) From dcdeb5fcfcef4a4c2c8e49745915432b96c5a47b Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 7 Oct 2024 09:24:05 -0500 Subject: [PATCH 20/24] remove deprecated get_html_theme_path() call Signed-off-by: foamyguy --- docs/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index cbf1452..9993665 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -137,7 +137,6 @@ import sphinx_rtd_theme html_theme = "sphinx_rtd_theme" -html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."] # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, From 3e5695361bd05dbf20be03ccb7239bb7b451f64a Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 14 Jan 2025 11:32:34 -0600 Subject: [PATCH 21/24] add sphinx configuration to rtd.yaml Signed-off-by: foamyguy --- .readthedocs.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index b79ec5b..fe4faae 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -8,6 +8,9 @@ # Required version: 2 +sphinx: + configuration: docs/conf.py + build: os: ubuntu-20.04 tools: From 2aa48460f89a1347991cb05915e7beac9370447d Mon Sep 17 00:00:00 2001 From: foamyguy Date: Thu, 16 Jan 2025 15:33:42 -0600 Subject: [PATCH 22/24] update rtd badge url --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index af6a199..ff8c96e 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ Introduction ============ -.. image:: https://readthedocs.org/projects/adafruit-circuitpython-pycamera/badge/?version=latest +.. image:: https://readthedocs.org/projects/pycamera/badge/?version=latest :target: https://docs.circuitpython.org/projects/pycamera/en/latest/ :alt: Documentation Status From 9bccbf87204ce4fc81bdffdb90ba1a059cd72a71 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Thu, 16 Jan 2025 15:35:00 -0600 Subject: [PATCH 23/24] update rtd badge url --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index ff8c96e..48e9ca9 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ Introduction ============ -.. image:: https://readthedocs.org/projects/pycamera/badge/?version=latest +.. image:: https://readthedocs.org/projects/circuitpython-pycamera/badge/?version=latest :target: https://docs.circuitpython.org/projects/pycamera/en/latest/ :alt: Documentation Status From 85ede001e8d62edd250c33d2b68138c7e36f2173 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Fri, 17 Jan 2025 15:37:25 -0600 Subject: [PATCH 24/24] last_saved_filename property --- adafruit_pycamera/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/adafruit_pycamera/__init__.py b/adafruit_pycamera/__init__.py index 32d8e14..1ef4c94 100644 --- a/adafruit_pycamera/__init__.py +++ b/adafruit_pycamera/__init__.py @@ -946,6 +946,13 @@ def blit_overlay_into_last_capture(self): del cc565_swapped gc.collect() + @property + def last_saved_filename(self) -> str: + """ + The filename of the last image saved. + """ + return self._last_saved_image_filename + def continuous_capture_start(self): """Switch the camera to continuous-capture mode""" pass # pylint: disable=unnecessary-pass