From f125ccbccdcdbf93dbfc378f71a23941cb341627 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 5 Sep 2023 13:05:51 -0400 Subject: [PATCH 01/58] remove adafruit_esp32spi_wsgiserver.py --- adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py deleted file mode 100644 index e69de29..0000000 From e7786335c3c6b1caa3852ceec6af3f05ed0e0252 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 18 Sep 2023 16:24:12 -0500 Subject: [PATCH 02/58] "fix rtd theme " --- docs/conf.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 9884e97..082d389 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -105,19 +105,10 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -on_rtd = os.environ.get("READTHEDOCS", None) == "True" - -if not on_rtd: # only import and set the theme if we're building docs locally - try: - import sphinx_rtd_theme - - html_theme = "sphinx_rtd_theme" - html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."] - except: - html_theme = "default" - html_theme_path = ["."] -else: - html_theme_path = ["."] +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 dbb035730fcc55201e4f74869da46322697bdad8 Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Thu, 2 Nov 2023 20:41:54 -0400 Subject: [PATCH 03/58] Modify examples using settings.toml --- .../adafruit_esp32spi_wifimanager.py | 18 +++---- examples/esp32spi_aio_post.py | 36 ++++++++++---- examples/esp32spi_cheerlights.py | 48 ++++++++++++++----- examples/esp32spi_ipconfig.py | 34 +++++++++---- examples/esp32spi_localtime.py | 44 +++++++++++++---- examples/esp32spi_secrets.py | 13 ----- examples/esp32spi_simpletest.py | 26 +++++++--- examples/esp32spi_simpletest_rp2040.py | 20 +++++--- examples/esp32spi_tcp_client.py | 25 +++++++++- examples/esp32spi_udp_client.py | 30 +++++++++--- examples/esp32spi_wpa2ent_aio_post.py | 42 ++++++++++++---- examples/esp32spi_wpa2ent_simpletest.py | 7 ++- examples/settings.toml | 5 ++ 13 files changed, 255 insertions(+), 93 deletions(-) delete mode 100644 examples/esp32spi_secrets.py create mode 100644 examples/settings.toml diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 0070b94..58e33de 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -42,6 +42,8 @@ def __init__( """ :param ESP_SPIcontrol esp: The ESP object we are using :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) + The use of secrets.py to populate the secrets dict is depreciated + in favor of using settings.toml. :param status_pixel: (Optional) The pixel device - A NeoPixel, DotStar, or RGB LED (default=None). The status LED, if given, turns red when attempting to connect to a Wi-Fi network or create an access point, @@ -65,18 +67,10 @@ def __init__( self._ap_index = 0 # Check for WPA2 Enterprise keys in the secrets dictionary and load them if they exist - if secrets.get("ent_ssid"): - self.ent_ssid = secrets["ent_ssid"] - else: - self.ent_ssid = secrets["ssid"] - if secrets.get("ent_ident"): - self.ent_ident = secrets["ent_ident"] - else: - self.ent_ident = "" - if secrets.get("ent_user"): - self.ent_user = secrets["ent_user"] - if secrets.get("ent_password"): - self.ent_password = secrets["ent_password"] + self.ent_ssid = secrets.get("ent_ssid",secrets["ssid"]) + self.ent_ident = secrets.get("ent_ident","") + self.ent_user = secrets.get("ent_user") + self.ent_password = secrets.get("ent_password") # pylint: enable=too-many-arguments diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index ef24db7..9770387 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -4,6 +4,7 @@ import time import board import busio +from os import getenv from digitalio import DigitalInOut import neopixel from adafruit_esp32spi import adafruit_esp32spi @@ -11,12 +12,24 @@ print("ESP32 SPI webclient test") -# Get wifi details and more from a secrets.py file -try: - from secrets import secrets -except ImportError: - print("WiFi secrets are kept in secrets.py, please add them there!") - raise +# Get wifi details and more from a settings.toml file +# tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD +# CIRCUITPY_AIO_USERNAME, CIRCUITPY_AIO_KEY +secrets = {} +for token in ["ssid","password"]: + if getenv("CIRCUITPY_WIFI_"+token.upper()): + secrets[token] = getenv("CIRCUITPY_WIFI_"+token.upper()) +for token in ["aio_username","aio_key"]: + if getenv("CIRCUITPY_"+token.upper()): + secrets[token] = getenv("CIRCUITPY_"+token.upper()) + +if secrets == {}: + try: + # Fallback on secrets.py until depreciation is over and option is removed + from secrets import secrets + except ImportError: + print("WiFi secrets are kept in settings.toml, please add them there!") + raise # If you are using a board with pre-defined ESP32 Pins: esp32_cs = DigitalInOut(board.ESP_CS) @@ -28,21 +41,26 @@ # esp32_ready = DigitalInOut(board.D10) # esp32_reset = DigitalInOut(board.D5) -spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +# Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 +if 'SCK1' in dir(board): + spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +else: + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" status_light = neopixel.NeoPixel( board.NEOPIXEL, 1, brightness=0.2 -) # Uncomment for Most Boards +) """Uncomment below for ItsyBitsy M4""" # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) -# Uncomment below for an externally defined RGB LED +"""Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" # import adafruit_rgbled # from adafruit_esp32spi import PWMOut # RED_LED = PWMOut.PWMOut(esp, 26) # GREEN_LED = PWMOut.PWMOut(esp, 27) # BLUE_LED = PWMOut.PWMOut(esp, 25) # status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) + wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) counter = 0 diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index 7ded593..5cf6f15 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -4,6 +4,7 @@ import time import board import busio +from os import getenv from digitalio import DigitalInOut import neopixel @@ -12,29 +13,54 @@ from adafruit_esp32spi import adafruit_esp32spi from adafruit_esp32spi import adafruit_esp32spi_wifimanager -# Get wifi details and more from a secrets.py file -try: - from secrets import secrets -except ImportError: - print("WiFi secrets are kept in secrets.py, please add them there!") - raise +# Get wifi details and more from a settings.toml file +# tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD +secrets = { + "ssid": getenv("CIRCUITPY_WIFI_SSID"), + "password": getenv("CIRCUITPY_WIFI_PASSWORD") +} +if secrets == {"ssid": None, "password": None}: + try: + # Fallback on secrets.py until depreciation is over and option is removed + from secrets import secrets + except ImportError: + print("WiFi secrets are kept in settings.toml, please add them there!") + raise print("ESP32 SPI webclient test") DATA_SOURCE = "https://api.thingspeak.com/channels/1417/feeds.json?results=1" DATA_LOCATION = ["feeds", 0, "field2"] -esp32_cs = DigitalInOut(board.D9) -esp32_ready = DigitalInOut(board.D10) -esp32_reset = DigitalInOut(board.D5) -spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +# If you are using a board with pre-defined ESP32 Pins: +esp32_cs = DigitalInOut(board.ESP_CS) +esp32_ready = DigitalInOut(board.ESP_BUSY) +esp32_reset = DigitalInOut(board.ESP_RESET) + +# If you have an externally connected ESP32: +# esp32_cs = DigitalInOut(board.D9) +# esp32_ready = DigitalInOut(board.D10) +# esp32_reset = DigitalInOut(board.D5) + +# Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 +if 'SCK1' in dir(board): + spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +else: + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" status_light = neopixel.NeoPixel( board.NEOPIXEL, 1, brightness=0.2 -) # Uncomment for Most Boards +) """Uncomment below for ItsyBitsy M4""" # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) +"""Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" +# import adafruit_rgbled +# from adafruit_esp32spi import PWMOut +# RED_LED = PWMOut.PWMOut(esp, 26) +# GREEN_LED = PWMOut.PWMOut(esp, 27) +# BLUE_LED = PWMOut.PWMOut(esp, 25) +# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) # neopixels diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index 5f67044..e82f7a3 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -4,16 +4,24 @@ import time import board import busio +from os import getenv from digitalio import DigitalInOut import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi -# Get wifi details and more from a secrets.py file -try: - from secrets import secrets -except ImportError: - print("WiFi secrets are kept in secrets.py, please add them there!") - raise +# Get wifi details and more from a settings.toml file +# tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD +secrets = { + "ssid": getenv("CIRCUITPY_WIFI_SSID"), + "password": getenv("CIRCUITPY_WIFI_PASSWORD") +} +if secrets == {"ssid": None, "password": None}: + try: + # Fallback on secrets.py until depreciation is over and option is removed + from secrets import secrets + except ImportError: + print("WiFi secrets are kept in settings.toml, please add them there!") + raise HOSTNAME = "esp32-spi-hostname-test" @@ -26,11 +34,21 @@ UDP_TIMEOUT = 20 -esp32_cs = DigitalInOut(board.CS1) +# If you are using a board with pre-defined ESP32 Pins: +esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) -spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +# If you have an externally connected ESP32: +# esp32_cs = DigitalInOut(board.D9) +# esp32_ready = DigitalInOut(board.D10) +# esp32_reset = DigitalInOut(board.D5) + +# Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 +if 'SCK1' in dir(board): + spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +else: + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) socket.set_interface(esp) diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index 01dd93b..64c20b2 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -4,34 +4,62 @@ import time import board import busio +from os import getenv from digitalio import DigitalInOut import neopixel import rtc from adafruit_esp32spi import adafruit_esp32spi from adafruit_esp32spi import adafruit_esp32spi_wifimanager -# Get wifi details and more from a secrets.py file -try: - from secrets import secrets -except ImportError: - print("WiFi secrets are kept in secrets.py, please add them there!") - raise +# Get wifi details and more from a settings.toml file +# tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD +secrets = { + "ssid": getenv("CIRCUITPY_WIFI_SSID"), + "password": getenv("CIRCUITPY_WIFI_PASSWORD") +} +if secrets == {"ssid": None, "password": None}: + try: + # Fallback on secrets.py until depreciation is over and option is removed + from secrets import secrets + except ImportError: + print("WiFi secrets are kept in settings.toml, please add them there!") + raise print("ESP32 local time") TIME_API = "http://worldtimeapi.org/api/ip" +# If you are using a board with pre-defined ESP32 Pins: esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) -spi = busio.SPI(board.SCK, board.MOSI, board.MISO) + +# If you have an externally connected ESP32: +# esp32_cs = DigitalInOut(board.D9) +# esp32_ready = DigitalInOut(board.D10) +# esp32_reset = DigitalInOut(board.D5) + +# Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 +if 'SCK1' in dir(board): + spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +else: + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) + """Use below for Most Boards""" status_light = neopixel.NeoPixel( board.NEOPIXEL, 1, brightness=0.2 -) # Uncomment for Most Boards +) """Uncomment below for ItsyBitsy M4""" # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) +"""Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" +# import adafruit_rgbled +# from adafruit_esp32spi import PWMOut +# RED_LED = PWMOut.PWMOut(esp, 26) +# GREEN_LED = PWMOut.PWMOut(esp, 27) +# BLUE_LED = PWMOut.PWMOut(esp, 25) +# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) + wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) the_rtc = rtc.RTC() diff --git a/examples/esp32spi_secrets.py b/examples/esp32spi_secrets.py deleted file mode 100644 index 02b75eb..0000000 --- a/examples/esp32spi_secrets.py +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries -# SPDX-License-Identifier: MIT - -# This file is where you keep secret settings, passwords, and tokens! -# If you put them in the code you risk committing that info or sharing it - -secrets = { - "ssid": "yourssid", - "password": "yourpassword", - "timezone": "America/New_York", # Check http://worldtimeapi.org/timezones - "aio_username": "youraiousername", - "aio_key": "youraiokey", -} diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index 7e01ad6..231773c 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -3,17 +3,25 @@ import board import busio +from os import getenv from digitalio import DigitalInOut import adafruit_requests as requests import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi -# Get wifi details and more from a secrets.py file -try: - from secrets import secrets -except ImportError: - print("WiFi secrets are kept in secrets.py, please add them there!") - raise +# Get wifi details and more from a settings.toml file +# tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD +secrets = { + "ssid": getenv("CIRCUITPY_WIFI_SSID"), + "password": getenv("CIRCUITPY_WIFI_PASSWORD") +} +if secrets == {"ssid": None, "password": None}: + try: + # Fallback on secrets.py until depreciation is over and option is removed + from secrets import secrets + except ImportError: + print("WiFi secrets are kept in settings.toml, please add them there!") + raise print("ESP32 SPI webclient test") @@ -42,7 +50,11 @@ # esp32_ready = DigitalInOut(board.D10) # esp32_reset = DigitalInOut(board.D5) -spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +# Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 +if 'SCK1' in dir(board): + spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +else: + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) requests.set_socket(socket, esp) diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index decd13e..04ee390 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -3,17 +3,25 @@ import board import busio +from os import getenv from digitalio import DigitalInOut import adafruit_requests as requests import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi -# Get wifi details and more from a secrets.py file -try: - from secrets import secrets -except ImportError: - print("WiFi secrets are kept in secrets.py, please add them there!") - raise +# Get wifi details and more from a settings.toml file +# tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD +secrets = { + "ssid": getenv("CIRCUITPY_WIFI_SSID"), + "password": getenv("CIRCUITPY_WIFI_PASSWORD") +} +if secrets == {"ssid": None, "password": None}: + try: + # Fallback on secrets.py until depreciation is over and option is removed + from secrets import secrets + except ImportError: + print("WiFi secrets are kept in settings.toml, please add them there!") + raise print("Raspberry Pi RP2040 - ESP32 SPI webclient test") diff --git a/examples/esp32spi_tcp_client.py b/examples/esp32spi_tcp_client.py index e635d0c..7f53af9 100644 --- a/examples/esp32spi_tcp_client.py +++ b/examples/esp32spi_tcp_client.py @@ -1,20 +1,41 @@ # SPDX-FileCopyrightText: 2021 Adafruit Industries # SPDX-License-Identifier: MIT -from secrets import secrets # pylint: disable=no-name-in-module +from os import getenv import board +import busio from digitalio import DigitalInOut from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_socket as socket +# Get wifi details and more from a settings.toml file +# tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD +secrets = { + "ssid": getenv("CIRCUITPY_WIFI_SSID"), + "password": getenv("CIRCUITPY_WIFI_PASSWORD") +} +if secrets == {"ssid": None, "password": None}: + try: + # Fallback on secrets.py until depreciation is over and option is removed + from secrets import secrets # pylint: disable=no-name-in-module + except ImportError: + print("WiFi secrets are kept in settings.toml, please add them there!") + raise TIMEOUT = 5 # edit host and port to match server HOST = "wifitest.adafruit.com" PORT = 80 +# Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 +if 'SCK1' in dir(board): + spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +else: + if "SPI" in dir(board): + spi = board.SPI() + else: + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) # PyPortal or similar; edit pins as needed -spi = board.SPI() esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) diff --git a/examples/esp32spi_udp_client.py b/examples/esp32spi_udp_client.py index 176e7a8..d87d975 100644 --- a/examples/esp32spi_udp_client.py +++ b/examples/esp32spi_udp_client.py @@ -4,16 +4,25 @@ import struct import time import board +import busio +from os import getenv from digitalio import DigitalInOut from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_socket as socket -# Get wifi details and more from a secrets.py file -try: - from secrets import secrets -except ImportError: - print("WiFi secrets are kept in secrets.py, please add them there!") - raise +# Get wifi details and more from a settings.toml file +# tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD +secrets = { + "ssid": getenv("CIRCUITPY_WIFI_SSID"), + "password": getenv("CIRCUITPY_WIFI_PASSWORD") +} +if secrets == {"ssid": None, "password": None}: + try: + # Fallback on secrets.py until depreciation is over and option is removed + from secrets import secrets # pylint: disable=no-name-in-module + except ImportError: + print("WiFi secrets are kept in settings.toml, please add them there!") + raise TIMEOUT = 5 # edit host and port to match server @@ -21,8 +30,15 @@ PORT = 123 NTP_TO_UNIX_EPOCH = 2208988800 # 1970-01-01 00:00:00 +# Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 +if 'SCK1' in dir(board): + spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +else: + if "SPI" in dir(board): + spi = board.SPI() + else: + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) # PyPortal or similar; edit pins as needed -spi = board.SPI() esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index 227bf91..76504e2 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -4,6 +4,7 @@ import time import board import busio +from os import getenv from digitalio import DigitalInOut import neopixel from adafruit_esp32spi import adafruit_esp32spi @@ -11,12 +12,24 @@ print("ESP32 SPI WPA2 Enterprise webclient test") -# Get wifi details and more from a secrets.py file -try: - from secrets import secrets -except ImportError: - print("WiFi secrets are kept in secrets.py, please add them there!") - raise +# Get wifi details and more from a settings.toml file +# tokens used by this Demo: CIRCUITPY_AIO_USERNAME, CIRCUITPY_AIO_KEY, +# CIRCUITPY_WIFI_ENT_SSID, CIRCUITPY_WIFI_ENT_PASSWORD, +# CIRCUITPY_WIFI_ENT_USER, CIRCUITPY_WIFI_ENT_IDENT +secrets = {} +for token in ["ssid","password","user","ident"]: + if getenv("CIRCUITPY_WIFI_ENT_"+token.upper()): + secrets[token] = getenv("CIRCUITPY_WIFI_"+token.upper()) +for token in ["aio_username","aio_key"]: + if getenv("CIRCUITPY_"+token.upper()): + secrets[token] = getenv("CIRCUITPY_"+token.upper()) +if secrets == {}: + try: + # Fallback on secrets.py until depreciation is over and option is removed + from secrets import secrets # pylint: disable=no-name-in-module + except ImportError: + print("WiFi secrets are kept in settings.toml, please add them there!") + raise # ESP32 setup # If your board does define the three pins listed below, @@ -30,14 +43,27 @@ esp32_ready = DigitalInOut(board.D10) esp32_reset = DigitalInOut(board.D5) -spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +# Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 +if 'SCK1' in dir(board): + spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +else: + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) + """Use below for Most Boards""" status_light = neopixel.NeoPixel( board.NEOPIXEL, 1, brightness=0.2 -) # Uncomment for Most Boards +) """Uncomment below for ItsyBitsy M4""" # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) +"""Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" +# import adafruit_rgbled +# from adafruit_esp32spi import PWMOut +# RED_LED = PWMOut.PWMOut(esp, 26) +# GREEN_LED = PWMOut.PWMOut(esp, 27) +# BLUE_LED = PWMOut.PWMOut(esp, 25) +# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) + wifi = ESPSPI_WiFiManager( esp, secrets, status_light, connection_type=ESPSPI_WiFiManager.ENTERPRISE ) diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index 879ac24..a8279ed 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -31,7 +31,6 @@ def normalize(v): normalize(version1) < normalize(version2) ) - print("ESP32 SPI WPA2 Enterprise test") # ESP32 setup @@ -46,7 +45,11 @@ def normalize(v): esp32_ready = DigitalInOut(board.D10) esp32_reset = DigitalInOut(board.D5) -spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +# Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 +if 'SCK1' in dir(board): + spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +else: + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) requests.set_socket(socket, esp) diff --git a/examples/settings.toml b/examples/settings.toml new file mode 100644 index 0000000..cab9eb6 --- /dev/null +++ b/examples/settings.toml @@ -0,0 +1,5 @@ +CIRCUITPY_WIFI_SSID="yourssid" +CIRCUITPY_WIFI_PASSWORD="yourpassword" +CIRCUITPY_TIMEZONE="America/New_York" +CIRCUITPY_AIO_USERNAME="youraiousername" +CIRCUITPY_AIO_KEY="youraiokey" From 07703c1cb79b9692feb244d4a0597fa03b2339a9 Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Thu, 2 Nov 2023 20:55:45 -0400 Subject: [PATCH 04/58] pre-commit fixes --- .../adafruit_esp32spi_wifimanager.py | 4 ++-- examples/esp32spi_aio_post.py | 22 +++++++++---------- examples/esp32spi_cheerlights.py | 10 ++++----- examples/esp32spi_ipconfig.py | 6 ++--- examples/esp32spi_localtime.py | 10 ++++----- examples/esp32spi_simpletest.py | 6 ++--- examples/esp32spi_simpletest_rp2040.py | 4 ++-- examples/esp32spi_tcp_client.py | 4 ++-- examples/esp32spi_udp_client.py | 6 ++--- examples/esp32spi_wpa2ent_aio_post.py | 22 +++++++++---------- examples/esp32spi_wpa2ent_simpletest.py | 3 ++- 11 files changed, 45 insertions(+), 52 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 58e33de..8cd9433 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -67,8 +67,8 @@ def __init__( self._ap_index = 0 # Check for WPA2 Enterprise keys in the secrets dictionary and load them if they exist - self.ent_ssid = secrets.get("ent_ssid",secrets["ssid"]) - self.ent_ident = secrets.get("ent_ident","") + self.ent_ssid = secrets.get("ent_ssid", secrets["ssid"]) + self.ent_ident = secrets.get("ent_ident", "") self.ent_user = secrets.get("ent_user") self.ent_password = secrets.get("ent_password") diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index 9770387..c4b5f7f 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -2,9 +2,9 @@ # SPDX-License-Identifier: MIT import time +from os import getenv import board import busio -from os import getenv from digitalio import DigitalInOut import neopixel from adafruit_esp32spi import adafruit_esp32spi @@ -16,14 +16,14 @@ # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD # CIRCUITPY_AIO_USERNAME, CIRCUITPY_AIO_KEY secrets = {} -for token in ["ssid","password"]: - if getenv("CIRCUITPY_WIFI_"+token.upper()): - secrets[token] = getenv("CIRCUITPY_WIFI_"+token.upper()) -for token in ["aio_username","aio_key"]: - if getenv("CIRCUITPY_"+token.upper()): - secrets[token] = getenv("CIRCUITPY_"+token.upper()) +for token in ["ssid", "password"]: + if getenv("CIRCUITPY_WIFI_" + token.upper()): + secrets[token] = getenv("CIRCUITPY_WIFI_" + token.upper()) +for token in ["aio_username", "aio_key"]: + if getenv("CIRCUITPY_" + token.upper()): + secrets[token] = getenv("CIRCUITPY_" + token.upper()) -if secrets == {}: +if not secrets: try: # Fallback on secrets.py until depreciation is over and option is removed from secrets import secrets @@ -42,15 +42,13 @@ # esp32_reset = DigitalInOut(board.D5) # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 -if 'SCK1' in dir(board): +if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" -status_light = neopixel.NeoPixel( - board.NEOPIXEL, 1, brightness=0.2 -) +status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) """Uncomment below for ItsyBitsy M4""" # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) """Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index 5cf6f15..9bac915 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -2,9 +2,9 @@ # SPDX-License-Identifier: MIT import time +from os import getenv import board import busio -from os import getenv from digitalio import DigitalInOut import neopixel @@ -17,7 +17,7 @@ # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD secrets = { "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD") + "password": getenv("CIRCUITPY_WIFI_PASSWORD"), } if secrets == {"ssid": None, "password": None}: try: @@ -43,15 +43,13 @@ # esp32_reset = DigitalInOut(board.D5) # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 -if 'SCK1' in dir(board): +if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" -status_light = neopixel.NeoPixel( - board.NEOPIXEL, 1, brightness=0.2 -) +status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) """Uncomment below for ItsyBitsy M4""" # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) """Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index e82f7a3..644de90 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -2,9 +2,9 @@ # SPDX-License-Identifier: MIT import time +from os import getenv import board import busio -from os import getenv from digitalio import DigitalInOut import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi @@ -13,7 +13,7 @@ # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD secrets = { "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD") + "password": getenv("CIRCUITPY_WIFI_PASSWORD"), } if secrets == {"ssid": None, "password": None}: try: @@ -45,7 +45,7 @@ # esp32_reset = DigitalInOut(board.D5) # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 -if 'SCK1' in dir(board): +if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: spi = busio.SPI(board.SCK, board.MOSI, board.MISO) diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index 64c20b2..b6ee671 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -2,9 +2,9 @@ # SPDX-License-Identifier: MIT import time +from os import getenv import board import busio -from os import getenv from digitalio import DigitalInOut import neopixel import rtc @@ -15,7 +15,7 @@ # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD secrets = { "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD") + "password": getenv("CIRCUITPY_WIFI_PASSWORD"), } if secrets == {"ssid": None, "password": None}: try: @@ -40,16 +40,14 @@ # esp32_reset = DigitalInOut(board.D5) # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 -if 'SCK1' in dir(board): +if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" -status_light = neopixel.NeoPixel( - board.NEOPIXEL, 1, brightness=0.2 -) +status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) """Uncomment below for ItsyBitsy M4""" # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) """Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index 231773c..1bcc4a9 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -1,9 +1,9 @@ # SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT +from os import getenv import board import busio -from os import getenv from digitalio import DigitalInOut import adafruit_requests as requests import adafruit_esp32spi.adafruit_esp32spi_socket as socket @@ -13,7 +13,7 @@ # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD secrets = { "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD") + "password": getenv("CIRCUITPY_WIFI_PASSWORD"), } if secrets == {"ssid": None, "password": None}: try: @@ -51,7 +51,7 @@ # esp32_reset = DigitalInOut(board.D5) # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 -if 'SCK1' in dir(board): +if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: spi = busio.SPI(board.SCK, board.MOSI, board.MISO) diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index 04ee390..8630a57 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -1,9 +1,9 @@ # SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT +from os import getenv import board import busio -from os import getenv from digitalio import DigitalInOut import adafruit_requests as requests import adafruit_esp32spi.adafruit_esp32spi_socket as socket @@ -13,7 +13,7 @@ # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD secrets = { "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD") + "password": getenv("CIRCUITPY_WIFI_PASSWORD"), } if secrets == {"ssid": None, "password": None}: try: diff --git a/examples/esp32spi_tcp_client.py b/examples/esp32spi_tcp_client.py index 7f53af9..3985278 100644 --- a/examples/esp32spi_tcp_client.py +++ b/examples/esp32spi_tcp_client.py @@ -12,7 +12,7 @@ # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD secrets = { "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD") + "password": getenv("CIRCUITPY_WIFI_PASSWORD"), } if secrets == {"ssid": None, "password": None}: try: @@ -28,7 +28,7 @@ PORT = 80 # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 -if 'SCK1' in dir(board): +if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: if "SPI" in dir(board): diff --git a/examples/esp32spi_udp_client.py b/examples/esp32spi_udp_client.py index d87d975..53ac2ba 100644 --- a/examples/esp32spi_udp_client.py +++ b/examples/esp32spi_udp_client.py @@ -3,9 +3,9 @@ import struct import time +from os import getenv import board import busio -from os import getenv from digitalio import DigitalInOut from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_socket as socket @@ -14,7 +14,7 @@ # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD secrets = { "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD") + "password": getenv("CIRCUITPY_WIFI_PASSWORD"), } if secrets == {"ssid": None, "password": None}: try: @@ -31,7 +31,7 @@ NTP_TO_UNIX_EPOCH = 2208988800 # 1970-01-01 00:00:00 # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 -if 'SCK1' in dir(board): +if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: if "SPI" in dir(board): diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index 76504e2..197f279 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -2,9 +2,9 @@ # SPDX-License-Identifier: MIT import time +from os import getenv import board import busio -from os import getenv from digitalio import DigitalInOut import neopixel from adafruit_esp32spi import adafruit_esp32spi @@ -17,13 +17,13 @@ # CIRCUITPY_WIFI_ENT_SSID, CIRCUITPY_WIFI_ENT_PASSWORD, # CIRCUITPY_WIFI_ENT_USER, CIRCUITPY_WIFI_ENT_IDENT secrets = {} -for token in ["ssid","password","user","ident"]: - if getenv("CIRCUITPY_WIFI_ENT_"+token.upper()): - secrets[token] = getenv("CIRCUITPY_WIFI_"+token.upper()) -for token in ["aio_username","aio_key"]: - if getenv("CIRCUITPY_"+token.upper()): - secrets[token] = getenv("CIRCUITPY_"+token.upper()) -if secrets == {}: +for token in ["ssid", "password", "user", "ident"]: + if getenv("CIRCUITPY_WIFI_ENT_" + token.upper()): + secrets[token] = getenv("CIRCUITPY_WIFI_" + token.upper()) +for token in ["aio_username", "aio_key"]: + if getenv("CIRCUITPY_" + token.upper()): + secrets[token] = getenv("CIRCUITPY_" + token.upper()) +if not secrets: try: # Fallback on secrets.py until depreciation is over and option is removed from secrets import secrets # pylint: disable=no-name-in-module @@ -44,16 +44,14 @@ esp32_reset = DigitalInOut(board.D5) # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 -if 'SCK1' in dir(board): +if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" -status_light = neopixel.NeoPixel( - board.NEOPIXEL, 1, brightness=0.2 -) +status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) """Uncomment below for ItsyBitsy M4""" # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) """Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index a8279ed..01d2bb0 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -31,6 +31,7 @@ def normalize(v): normalize(version1) < normalize(version2) ) + print("ESP32 SPI WPA2 Enterprise test") # ESP32 setup @@ -46,7 +47,7 @@ def normalize(v): esp32_reset = DigitalInOut(board.D5) # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 -if 'SCK1' in dir(board): +if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: spi = busio.SPI(board.SCK, board.MOSI, board.MISO) From 6092ea07bca234c58618c2f5fdf959f7898da215 Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Thu, 2 Nov 2023 21:01:21 -0400 Subject: [PATCH 05/58] settings.toml example rename + license --- examples/esp32spi_settings.toml | 14 ++++++++++++++ examples/settings.toml | 5 ----- 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 examples/esp32spi_settings.toml delete mode 100644 examples/settings.toml diff --git a/examples/esp32spi_settings.toml b/examples/esp32spi_settings.toml new file mode 100644 index 0000000..16208bd --- /dev/null +++ b/examples/esp32spi_settings.toml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +# This file is where you keep secret settings, passwords, and tokens! +# If you put them in the code you risk committing that info or sharing it + +# The file should be renamed to `settings.toml` and saved in the root of +# the CIRCUITPY drive. + +CIRCUITPY_WIFI_SSID="yourssid" +CIRCUITPY_WIFI_PASSWORD="yourpassword" +CIRCUITPY_TIMEZONE="America/New_York" +CIRCUITPY_AIO_USERNAME="youraiousername" +CIRCUITPY_AIO_KEY="youraiokey" diff --git a/examples/settings.toml b/examples/settings.toml deleted file mode 100644 index cab9eb6..0000000 --- a/examples/settings.toml +++ /dev/null @@ -1,5 +0,0 @@ -CIRCUITPY_WIFI_SSID="yourssid" -CIRCUITPY_WIFI_PASSWORD="yourpassword" -CIRCUITPY_TIMEZONE="America/New_York" -CIRCUITPY_AIO_USERNAME="youraiousername" -CIRCUITPY_AIO_KEY="youraiokey" From 1f35b4a552045bd1a216507b17833960364dce2c Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 16 Oct 2023 14:30:31 -0500 Subject: [PATCH 06/58] unpin sphinx and add sphinx-rtd-theme to docs reqs Signed-off-by: foamyguy --- docs/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 797aa04..979f568 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,5 +2,6 @@ # # SPDX-License-Identifier: Unlicense -sphinx>=4.0.0 +sphinx sphinxcontrib-jquery +sphinx-rtd-theme From a63118b37bd4256c7824599a66edfa513a0b969d Mon Sep 17 00:00:00 2001 From: Dorin Date: Mon, 15 Jan 2024 16:34:18 +0200 Subject: [PATCH 07/58] Fix double subtraction of bytes_read from num_to_read in recv_into --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index 1cf379f..fa3a082 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -121,7 +121,7 @@ def recv_into(self, buffer, nbytes: int = 0): ) buffer[num_read : num_read + len(bytes_read)] = bytes_read num_read += len(bytes_read) - num_to_read -= num_read + num_to_read -= len(bytes_read) elif num_read > 0: # We got a message, but there are no more bytes to read, so we can stop. break From e4583c6116879200df5403882189bbed3065b81b Mon Sep 17 00:00:00 2001 From: Dorin Date: Mon, 15 Jan 2024 18:25:42 +0200 Subject: [PATCH 08/58] Fix potential socket data read already into self._buffer --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index fa3a082..6ca0202 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -113,6 +113,17 @@ def recv_into(self, buffer, nbytes: int = 0): num_to_read = len(buffer) if nbytes == 0 else nbytes num_read = 0 while num_to_read > 0: + # we might have read socket data into the self._buffer with: + # esp32spi_wsgiserver: socket_readline + if len(self._buffer) > 0: + bytes_to_read = min(num_to_read, len(self._buffer)) + buffer[num_read : num_read + bytes_to_read] = self._buffer[:bytes_to_read] + num_read += bytes_to_read + num_to_read -= bytes_to_read + self._buffer = self._buffer[bytes_to_read:] + # explicitly recheck num_to_read to avoid extra checks + continue + num_avail = self._available() if num_avail > 0: last_read_time = time.monotonic() From e1197192651018e6aca8d843ea0c8d6415973b74 Mon Sep 17 00:00:00 2001 From: Dorin Date: Mon, 15 Jan 2024 18:59:34 +0200 Subject: [PATCH 09/58] Fix formatting --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index 6ca0202..70acbed 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -117,7 +117,9 @@ def recv_into(self, buffer, nbytes: int = 0): # esp32spi_wsgiserver: socket_readline if len(self._buffer) > 0: bytes_to_read = min(num_to_read, len(self._buffer)) - buffer[num_read : num_read + bytes_to_read] = self._buffer[:bytes_to_read] + buffer[num_read : num_read + bytes_to_read] = self._buffer[ + :bytes_to_read + ] num_read += bytes_to_read num_to_read -= bytes_to_read self._buffer = self._buffer[bytes_to_read:] From a9129c97d90f34d80bada055615e0fdf18c0d21b Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Fri, 23 Feb 2024 09:31:42 -0800 Subject: [PATCH 10/58] Remove legacy requests.set_socket --- .../adafruit_esp32spi_wifimanager.py | 20 +++++++++++-------- examples/esp32spi_simpletest.py | 8 +++++--- examples/esp32spi_simpletest_rp2040.py | 8 +++++--- examples/esp32spi_wpa2ent_simpletest.py | 9 +++++---- requirements.txt | 3 ++- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 8cd9433..01b97e8 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -15,9 +15,9 @@ from time import sleep from micropython import const -import adafruit_requests as requests +import adafruit_connection_manager +import adafruit_requests from adafruit_esp32spi import adafruit_esp32spi -import adafruit_esp32spi.adafruit_esp32spi_socket as socket # pylint: disable=too-many-instance-attributes @@ -61,11 +61,15 @@ def __init__( self.password = secrets.get("password", None) self.attempts = attempts self._connection_type = connection_type - requests.set_socket(socket, esp) self.statuspix = status_pixel self.pixel_status(0) self._ap_index = 0 + # create requests session + pool = adafruit_connection_manager.get_radio_socketpool(self.esp) + ssl_context = adafruit_connection_manager.get_radio_ssl_context(self.esp) + self._requests = adafruit_requests.Session(pool, ssl_context) + # Check for WPA2 Enterprise keys in the secrets dictionary and load them if they exist self.ent_ssid = secrets.get("ent_ssid", secrets["ssid"]) self.ent_ident = secrets.get("ent_ident", "") @@ -220,7 +224,7 @@ def get(self, url, **kw): if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) - return_val = requests.get(url, **kw) + return_val = self._requests.get(url, **kw) self.pixel_status(0) return return_val @@ -239,7 +243,7 @@ def post(self, url, **kw): if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) - return_val = requests.post(url, **kw) + return_val = self._requests.post(url, **kw) self.pixel_status(0) return return_val @@ -258,7 +262,7 @@ def put(self, url, **kw): if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) - return_val = requests.put(url, **kw) + return_val = self._requests.put(url, **kw) self.pixel_status(0) return return_val @@ -277,7 +281,7 @@ def patch(self, url, **kw): if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) - return_val = requests.patch(url, **kw) + return_val = self._requests.patch(url, **kw) self.pixel_status(0) return return_val @@ -296,7 +300,7 @@ def delete(self, url, **kw): if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) - return_val = requests.delete(url, **kw) + return_val = self._requests.delete(url, **kw) self.pixel_status(0) return return_val diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index 1bcc4a9..f436274 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -5,8 +5,8 @@ import board import busio from digitalio import DigitalInOut -import adafruit_requests as requests -import adafruit_esp32spi.adafruit_esp32spi_socket as socket +import adafruit_connection_manager +import adafruit_requests from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file @@ -57,7 +57,9 @@ spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) -requests.set_socket(socket, esp) +pool = adafruit_connection_manager.get_radio_socketpool(esp) +ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp) +requests = adafruit_requests.Session(pool, ssl_context) if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode") diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index 8630a57..4330b7d 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -5,8 +5,8 @@ import board import busio from digitalio import DigitalInOut -import adafruit_requests as requests -import adafruit_esp32spi.adafruit_esp32spi_socket as socket +import adafruit_connection_manager +import adafruit_requests from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file @@ -36,7 +36,9 @@ spi = busio.SPI(board.GP10, board.GP11, board.GP12) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) -requests.set_socket(socket, esp) +pool = adafruit_connection_manager.get_radio_socketpool(esp) +ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp) +requests = adafruit_requests.Session(pool, ssl_context) if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode") diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index 01d2bb0..0df4d28 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -14,9 +14,8 @@ import board import busio from digitalio import DigitalInOut - -import adafruit_requests as requests -import adafruit_esp32spi.adafruit_esp32spi_socket as socket +import adafruit_connection_manager +import adafruit_requests from adafruit_esp32spi import adafruit_esp32spi @@ -53,7 +52,9 @@ def normalize(v): spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) -requests.set_socket(socket, esp) +pool = adafruit_connection_manager.get_radio_socketpool(esp) +ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp) +requests = adafruit_requests.Session(pool, ssl_context) if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode") diff --git a/requirements.txt b/requirements.txt index 8bfb5f3..d689206 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,5 +3,6 @@ # SPDX-License-Identifier: Unlicense Adafruit-Blinka -adafruit-circuitpython-requests adafruit-circuitpython-busdevice +adafruit-circuitpython-connectionmanager +adafruit-circuitpython-requests From 5b06d235b3f36ba4b3c9afbf5e98d5f330decb5c Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 27 Feb 2024 12:46:41 -0800 Subject: [PATCH 11/58] Update README.rst --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index f05bc11..d0b6155 100644 --- a/README.rst +++ b/README.rst @@ -29,6 +29,7 @@ This driver depends on: * `Adafruit CircuitPython `_ * `Bus Device `_ +* `Adafruit CircuitPython ConnectionManager `_ Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading From d3101040e5d6a62b3962f71f09aaaa3ee6f36ada Mon Sep 17 00:00:00 2001 From: "H. Phil Duby" Date: Wed, 28 Feb 2024 19:07:03 -0700 Subject: [PATCH 12/58] tweak output formatting --- examples/esp32spi_simpletest.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index f436274..962c17e 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -63,11 +63,11 @@ if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode") -print("Firmware vers.", esp.firmware_version) -print("MAC addr:", [hex(i) for i in esp.MAC_address]) +print("Firmware vers.", esp.firmware_version.decode("utf-8")) +print("MAC addr:", ":".join("%02X" % byte for byte in esp.MAC_address)) for ap in esp.scan_networks(): - print("\t%s\t\tRSSI: %d" % (str(ap["ssid"], "utf-8"), ap["rssi"])) + print("\t%-23s RSSI: %d" % (str(ap["ssid"], "utf-8"), ap["rssi"])) print("Connecting to AP...") while not esp.is_connected: From 817d50e420cba3574cee91cec0c192420b1f5b10 Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Thu, 29 Feb 2024 06:34:49 -0800 Subject: [PATCH 13/58] Fix README requirements --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index d0b6155..9362475 100644 --- a/README.rst +++ b/README.rst @@ -30,6 +30,7 @@ This driver depends on: * `Adafruit CircuitPython `_ * `Bus Device `_ * `Adafruit CircuitPython ConnectionManager `_ +* `Adafruit CircuitPython Requests `_ Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading From f1f9251560d3de3bdc3868f15c780189f5d5707c Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 29 Feb 2024 10:57:31 -0500 Subject: [PATCH 14/58] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 9362475..f9cf497 100644 --- a/README.rst +++ b/README.rst @@ -28,7 +28,7 @@ Dependencies This driver depends on: * `Adafruit CircuitPython `_ -* `Bus Device `_ +* `Adafruit Bus Device `_ * `Adafruit CircuitPython ConnectionManager `_ * `Adafruit CircuitPython Requests `_ From 57ade90242b621057a01f68e3c68dc001b0ee767 Mon Sep 17 00:00:00 2001 From: anecdata <16617689+anecdata@users.noreply.github.com> Date: Fri, 15 Mar 2024 21:35:42 -0500 Subject: [PATCH 15/58] add __enter__ & __exit__ --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index 70acbed..347b330 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -66,6 +66,17 @@ def __init__( # pylint: enable=too-many-arguments + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb) -> None: + self.close() + while ( + _the_interface.socket_status(self._socknum) + != adafruit_esp32spi.SOCKET_CLOSED + ): + pass + def connect(self, address, conntype=None): """Connect the socket to the 'address' (which can be 32bit packed IP or a hostname string). 'conntype' is an extra that may indicate SSL or not, From 35fd193ecf8dd3a34f1b96a3c79fba35e54a53fb Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Wed, 24 Apr 2024 16:57:10 -0700 Subject: [PATCH 16/58] Convert to SocketPool --- ...ket.py => adafruit_esp32spi_socketpool.py} | 146 ++++++++++-------- docs/api.rst | 2 +- examples/esp32spi_ipconfig.py | 8 +- examples/esp32spi_tcp_client.py | 8 +- examples/esp32spi_udp_client.py | 8 +- 5 files changed, 98 insertions(+), 74 deletions(-) rename adafruit_esp32spi/{adafruit_esp32spi_socket.py => adafruit_esp32spi_socketpool.py} (55%) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py similarity index 55% rename from adafruit_esp32spi/adafruit_esp32spi_socket.py rename to adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 347b330..c67ef36 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -3,78 +3,103 @@ # SPDX-License-Identifier: MIT """ -`adafruit_esp32spi_socket` +`adafruit_esp32spi_socketpool` ================================================================================ A socket compatible interface thru the ESP SPI command set * Author(s): ladyada """ +from __future__ import annotations + +try: + from typing import TYPE_CHECKING, Optional + + if TYPE_CHECKING: + from esp32spi.adafruit_esp32spi import ESP_SPIcontrol +except ImportError: + pass -# pylint: disable=no-name-in-module import time import gc from micropython import const -from adafruit_esp32spi import adafruit_esp32spi +from adafruit_esp32spi import adafruit_esp32spi as esp32spi -_the_interface = None # pylint: disable=invalid-name +_global_socketpool = {} -def set_interface(iface): - """Helper to set the global internet interface""" - global _the_interface # pylint: disable=global-statement, invalid-name - _the_interface = iface +class SocketPoolContants: # pylint: disable=too-few-public-methods + """Helper class for the constants that are needed everywhere""" + SOCK_STREAM = const(0) + SOCK_DGRAM = const(1) + AF_INET = const(2) + NO_SOCKET_AVAIL = const(255) -SOCK_STREAM = const(0) -SOCK_DGRAM = const(1) -AF_INET = const(2) -NO_SOCKET_AVAIL = const(255) + MAX_PACKET = const(4000) -MAX_PACKET = const(4000) +class SocketPool(SocketPoolContants): + """ESP32SPI SocketPool library""" -# pylint: disable=too-many-arguments, unused-argument -def getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0): - """Given a hostname and a port name, return a 'socket.getaddrinfo' - compatible list of tuples. Honestly, we ignore anything but host & port""" - if not isinstance(port, int): - raise ValueError("Port must be an integer") - ipaddr = _the_interface.get_host_by_name(host) - return [(AF_INET, socktype, proto, "", (ipaddr, port))] + def __new__(cls, iface: ESP_SPIcontrol): + # We want to make sure to return the same pool for the same interface + if iface not in _global_socketpool: + _global_socketpool[iface] = object.__new__(cls) + return _global_socketpool[iface] + def __init__(self, iface: ESP_SPIcontrol): + self._interface = iface -# pylint: enable=too-many-arguments, unused-argument + def getaddrinfo( # pylint: disable=too-many-arguments,unused-argument + self, host, port, family=0, socktype=0, proto=0, flags=0 + ): + """Given a hostname and a port name, return a 'socket.getaddrinfo' + compatible list of tuples. Honestly, we ignore anything but host & port""" + if not isinstance(port, int): + raise ValueError("Port must be an integer") + ipaddr = self._interface.get_host_by_name(host) + return [(SocketPoolContants.AF_INET, socktype, proto, "", (ipaddr, port))] + + def socket( # pylint: disable=redefined-builtin + self, + family=SocketPoolContants.AF_INET, + type=SocketPoolContants.SOCK_STREAM, + proto=0, + fileno=None, + ): + """Create a new socket and return it""" + return Socket(self, family, type, proto, fileno) -# pylint: disable=unused-argument, redefined-builtin, invalid-name -class socket: +class Socket: """A simplified implementation of the Python 'socket' class, for connecting through an interface to a remote device""" - # pylint: disable=too-many-arguments - def __init__( - self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None, socknum=None + def __init__( # pylint: disable=redefined-builtin,too-many-arguments,unused-argument + self, + socket_pool: SocketPool, + family: int = SocketPool.AF_INET, + type: int = SocketPool.SOCK_STREAM, + proto: int = 0, + fileno: Optional[int] = None, ): - if family != AF_INET: + if family != SocketPool.AF_INET: raise ValueError("Only AF_INET family supported") + self._socket_pool = socket_pool + self._interface = self._socket_pool._interface self._type = type self._buffer = b"" - self._socknum = socknum if socknum else _the_interface.get_socket() + self._socknum = self._interface.get_socket() self.settimeout(0) - # pylint: enable=too-many-arguments - def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb) -> None: self.close() - while ( - _the_interface.socket_status(self._socknum) - != adafruit_esp32spi.SOCKET_CLOSED - ): + while self._interface.socket_status(self._socknum) != esp32spi.SOCKET_CLOSED: pass def connect(self, address, conntype=None): @@ -83,20 +108,20 @@ def connect(self, address, conntype=None): depending on the underlying interface""" host, port = address if conntype is None: - conntype = _the_interface.TCP_MODE - if not _the_interface.socket_connect( + conntype = self._interface.TCP_MODE + if not self._interface.socket_connect( self._socknum, host, port, conn_mode=conntype ): raise ConnectionError("Failed to connect to host", host) self._buffer = b"" - def send(self, data): # pylint: disable=no-self-use + def send(self, data): """Send some data to the socket.""" - if self._type is SOCK_DGRAM: - conntype = _the_interface.UDP_MODE + if self._type is SocketPool.SOCK_DGRAM: + conntype = self._interface.UDP_MODE else: - conntype = _the_interface.TCP_MODE - _the_interface.socket_write(self._socknum, data, conn_mode=conntype) + conntype = self._interface.TCP_MODE + self._interface.socket_write(self._socknum, data, conn_mode=conntype) gc.collect() def recv(self, bufsize: int) -> bytes: @@ -140,7 +165,7 @@ def recv_into(self, buffer, nbytes: int = 0): num_avail = self._available() if num_avail > 0: last_read_time = time.monotonic() - bytes_read = _the_interface.socket_read( + bytes_read = self._interface.socket_read( self._socknum, min(num_to_read, num_avail) ) buffer[num_read : num_read + len(bytes_read)] = bytes_read @@ -162,43 +187,42 @@ def settimeout(self, value): def _available(self): """Returns how many bytes of data are available to be read (up to the MAX_PACKET length)""" - if self._socknum != NO_SOCKET_AVAIL: - return min(_the_interface.socket_available(self._socknum), MAX_PACKET) + if self._socknum != SocketPool.NO_SOCKET_AVAIL: + return min( + self._interface.socket_available(self._socknum), SocketPool.MAX_PACKET + ) return 0 def _connected(self): """Whether or not we are connected to the socket""" - if self._socknum == NO_SOCKET_AVAIL: + if self._socknum == SocketPool.NO_SOCKET_AVAIL: return False if self._available(): return True - status = _the_interface.socket_status(self._socknum) + status = self._interface.socket_status(self._socknum) result = status not in ( - adafruit_esp32spi.SOCKET_LISTEN, - adafruit_esp32spi.SOCKET_CLOSED, - adafruit_esp32spi.SOCKET_FIN_WAIT_1, - adafruit_esp32spi.SOCKET_FIN_WAIT_2, - adafruit_esp32spi.SOCKET_TIME_WAIT, - adafruit_esp32spi.SOCKET_SYN_SENT, - adafruit_esp32spi.SOCKET_SYN_RCVD, - adafruit_esp32spi.SOCKET_CLOSE_WAIT, + esp32spi.SOCKET_LISTEN, + esp32spi.SOCKET_CLOSED, + esp32spi.SOCKET_FIN_WAIT_1, + esp32spi.SOCKET_FIN_WAIT_2, + esp32spi.SOCKET_TIME_WAIT, + esp32spi.SOCKET_SYN_SENT, + esp32spi.SOCKET_SYN_RCVD, + esp32spi.SOCKET_CLOSE_WAIT, ) if not result: self.close() - self._socknum = NO_SOCKET_AVAIL + self._socknum = SocketPool.NO_SOCKET_AVAIL return result def close(self): """Close the socket, after reading whatever remains""" - _the_interface.socket_close(self._socknum) + self._interface.socket_close(self._socknum) -class timeout(TimeoutError): +class timeout(TimeoutError): # pylint: disable=invalid-name """TimeoutError class. An instance of this error will be raised by recv_into() if the timeout has elapsed and we haven't received any data yet.""" def __init__(self, msg): super().__init__(msg) - - -# pylint: enable=unused-argument, redefined-builtin, invalid-name diff --git a/docs/api.rst b/docs/api.rst index 0cfe5a8..7726cc1 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -7,7 +7,7 @@ .. automodule:: adafruit_esp32spi.adafruit_esp32spi :members: -.. automodule:: adafruit_esp32spi.adafruit_esp32spi_socket +.. automodule:: adafruit_esp32spi.adafruit_esp32spi_socketpool :members: .. automodule:: adafruit_esp32spi.adafruit_esp32spi_wifimanager diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index 644de90..f29e9a1 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -6,7 +6,7 @@ import board import busio from digitalio import DigitalInOut -import adafruit_esp32spi.adafruit_esp32spi_socket as socket +import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file @@ -51,9 +51,9 @@ spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) -socket.set_interface(esp) +pool = socketpool.SocketPool(esp) -s_in = socket.socket(type=socket.SOCK_DGRAM) +s_in = pool.socket(type=pool.SOCK_DGRAM) s_in.settimeout(UDP_TIMEOUT) print("set hostname:", HOSTNAME) esp.set_hostname(HOSTNAME) @@ -96,7 +96,7 @@ print("My IP address is", esp.pretty_ip(esp.ip_address)) print("udp in addr: ", UDP_IN_ADDR, UDP_IN_PORT) -socketaddr_udp_in = socket.getaddrinfo(UDP_IN_ADDR, UDP_IN_PORT)[0][4] +socketaddr_udp_in = pool.getaddrinfo(UDP_IN_ADDR, UDP_IN_PORT)[0][4] s_in.connect(socketaddr_udp_in, conntype=esp.UDP_MODE) print("connected local UDP") diff --git a/examples/esp32spi_tcp_client.py b/examples/esp32spi_tcp_client.py index 3985278..2ec5d2a 100644 --- a/examples/esp32spi_tcp_client.py +++ b/examples/esp32spi_tcp_client.py @@ -6,7 +6,7 @@ import busio from digitalio import DigitalInOut from adafruit_esp32spi import adafruit_esp32spi -import adafruit_esp32spi.adafruit_esp32spi_socket as socket +import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD @@ -48,9 +48,9 @@ print("Server ping:", esp.ping(HOST), "ms") # create the socket -socket.set_interface(esp) -socketaddr = socket.getaddrinfo(HOST, PORT)[0][4] -s = socket.socket() +pool = socketpool.SocketPool(esp) +socketaddr = pool.getaddrinfo(HOST, PORT)[0][4] +s = pool.socket() s.settimeout(TIMEOUT) print("Connecting") diff --git a/examples/esp32spi_udp_client.py b/examples/esp32spi_udp_client.py index 53ac2ba..3dace7b 100644 --- a/examples/esp32spi_udp_client.py +++ b/examples/esp32spi_udp_client.py @@ -8,7 +8,7 @@ import busio from digitalio import DigitalInOut from adafruit_esp32spi import adafruit_esp32spi -import adafruit_esp32spi.adafruit_esp32spi_socket as socket +import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD @@ -51,9 +51,9 @@ print("Server ping:", esp.ping(HOST), "ms") # create the socket -socket.set_interface(esp) -socketaddr = socket.getaddrinfo(HOST, PORT)[0][4] -s = socket.socket(type=socket.SOCK_DGRAM) +pool = socketpool.SocketPool(esp) +socketaddr = pool.getaddrinfo(HOST, PORT)[0][4] +s = pool.socket(type=pool.SOCK_DGRAM) s.settimeout(TIMEOUT) From 06281a57ee77fdc6416587cf3656b0aff586a72d Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Fri, 26 Apr 2024 14:11:01 -0700 Subject: [PATCH 17/58] Use standard super() for __new__ --- adafruit_esp32spi/adafruit_esp32spi_socketpool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index c67ef36..2f7ca78 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -46,7 +46,7 @@ class SocketPool(SocketPoolContants): def __new__(cls, iface: ESP_SPIcontrol): # We want to make sure to return the same pool for the same interface if iface not in _global_socketpool: - _global_socketpool[iface] = object.__new__(cls) + _global_socketpool[iface] = super().__new__(cls) return _global_socketpool[iface] def __init__(self, iface: ESP_SPIcontrol): From 8349d77b4ecd9f313146cb61197579915b2b687b Mon Sep 17 00:00:00 2001 From: anecdata <16617689+anecdata@users.noreply.github.com> Date: Tue, 30 Apr 2024 14:07:23 -0500 Subject: [PATCH 18/58] Fully deprecate `secrets` and improve native wifi API compatibility. --- adafruit_esp32spi/adafruit_esp32spi.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 4c3fc5f..dde0784 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -545,7 +545,7 @@ def ip_address(self): return self.network_data["ip_addr"] @property - def is_connected(self): + def connected(self): """Whether the ESP32 is connected to an access point""" try: return self.status == WL_CONNECTED @@ -553,6 +553,11 @@ def is_connected(self): self.reset() return False + @property + def is_connected(self): + """Whether the ESP32 is connected to an access point""" + return self.connected + @property def ap_listening(self): """Returns if the ESP32 is in access point mode and is listening for connections""" @@ -568,10 +573,9 @@ def disconnect(self): if resp[0][0] != 1: raise OSError("Failed to disconnect") - def connect(self, secrets): - """Connect to an access point using a secrets dictionary - that contains a 'ssid' and 'password' entry""" - self.connect_AP(secrets["ssid"], secrets["password"]) + def connect(self, ssid, password, timeout=10): + """Connect to an access point with given name and password.""" + self.connect_AP(ssid, password, timeout_s=timeout) def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-name """Connect to an access point with given name and password. @@ -647,6 +651,11 @@ def create_AP( raise ConnectionError("Failed to create AP", ssid) raise OSError("Unknown error 0x%02x" % stat) + @property + def ipv4_address(self): + """IP address of the station when connected to an access point.""" + return self.pretty_ip(self.ip_address) + def pretty_ip(self, ip): # pylint: disable=no-self-use, invalid-name """Converts a bytearray IP address to a dotted-quad string for printing""" return "%d.%d.%d.%d" % (ip[0], ip[1], ip[2], ip[3]) From a589e81ea4c64d92ac7401b20b5ffc250f2f38b6 Mon Sep 17 00:00:00 2001 From: anecdata <16617689+anecdata@users.noreply.github.com> Date: Thu, 2 May 2024 12:42:33 -0500 Subject: [PATCH 19/58] ad `mac_address` and fix `connect` per discussion. `connect` with `secrets` dict, `ssid, password`, and `ssid`-only (open) all work as before. --- adafruit_esp32spi/adafruit_esp32spi.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index dde0784..895454f 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -372,12 +372,12 @@ def MAC_address(self): # pylint: disable=invalid-name @property def MAC_address_actual(self): # pylint: disable=invalid-name """A bytearray containing the actual MAC address of the ESP32""" - if self._debug: - print("MAC address") - resp = self._send_command_get_response(_GET_MACADDR_CMD, [b"\xFF"]) - new_resp = bytearray(resp[0]) - new_resp = reversed(new_resp) - return new_resp + return bytearray(reversed(self.MAC_address)) + + @property + def mac_address(self): + """A bytes containing the actual MAC address of the ESP32""" + return bytes(reversed(self.MAC_address)) def start_scan_networks(self): """Begin a scan of visible access points. Follow up with a call @@ -573,8 +573,10 @@ def disconnect(self): if resp[0][0] != 1: raise OSError("Failed to disconnect") - def connect(self, ssid, password, timeout=10): + def connect(self, ssid, password=None, timeout=10): """Connect to an access point with given name and password.""" + if isinstance(ssid, dict): # secrets + ssid, password = ssid["ssid"], ssid["password"] self.connect_AP(ssid, password, timeout_s=timeout) def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-name From cfb61f5fe7e6b4ce3e455f3dc6e5ec7933f0fa5d Mon Sep 17 00:00:00 2001 From: anecdata <16617689+anecdata@users.noreply.github.com> Date: Thu, 2 May 2024 12:47:41 -0500 Subject: [PATCH 20/58] Update adafruit_esp32spi/adafruit_esp32spi.py Co-authored-by: Justin Myers --- adafruit_esp32spi/adafruit_esp32spi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 895454f..552c1bd 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -377,7 +377,7 @@ def MAC_address_actual(self): # pylint: disable=invalid-name @property def mac_address(self): """A bytes containing the actual MAC address of the ESP32""" - return bytes(reversed(self.MAC_address)) + return bytes(self.MAC_address_actual) def start_scan_networks(self): """Begin a scan of visible access points. Follow up with a call From e69c95014e11c60760593d58931701352e489f57 Mon Sep 17 00:00:00 2001 From: anecdata <16617689+anecdata@users.noreply.github.com> Date: Thu, 2 May 2024 14:17:51 -0500 Subject: [PATCH 21/58] Update adafruit_esp32spi/adafruit_esp32spi.py Co-authored-by: Justin Myers --- adafruit_esp32spi/adafruit_esp32spi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 552c1bd..e1219d5 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -576,7 +576,7 @@ def disconnect(self): def connect(self, ssid, password=None, timeout=10): """Connect to an access point with given name and password.""" if isinstance(ssid, dict): # secrets - ssid, password = ssid["ssid"], ssid["password"] + ssid, password = ssid["ssid"], ssid.get("password") self.connect_AP(ssid, password, timeout_s=timeout) def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-name From 5a640445f4f0616382d45f62c4e5e7a368efec82 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 2 May 2024 22:03:06 -0400 Subject: [PATCH 22/58] add documentation for `.connect(secrets_dict)`. --- adafruit_esp32spi/adafruit_esp32spi.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index e1219d5..fd5b579 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -574,7 +574,13 @@ def disconnect(self): raise OSError("Failed to disconnect") def connect(self, ssid, password=None, timeout=10): - """Connect to an access point with given name and password.""" + """Connect to an access point with given name and password. + + **Deprecated functionality:** If the first argument (``ssid``) is a ``dict``, + assume it is a dictionary with entries for keys ``"ssid"`` and, optionally, ``"password"``. + This mimics the previous signature for ``connect()``. + This upward compatbility will be removed in a future release. + """ if isinstance(ssid, dict): # secrets ssid, password = ssid["ssid"], ssid.get("password") self.connect_AP(ssid, password, timeout_s=timeout) From 42dc7f5546ffeb0923fb025856c46b2f42d61cb7 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 2 May 2024 22:06:50 -0400 Subject: [PATCH 23/58] remove extraneous whitespace --- adafruit_esp32spi/adafruit_esp32spi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index fd5b579..a124323 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -575,7 +575,7 @@ def disconnect(self): def connect(self, ssid, password=None, timeout=10): """Connect to an access point with given name and password. - + **Deprecated functionality:** If the first argument (``ssid``) is a ``dict``, assume it is a dictionary with entries for keys ``"ssid"`` and, optionally, ``"password"``. This mimics the previous signature for ``connect()``. From 40b51dafcb982c72c2733c8f99132ea820be48d6 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 5 May 2024 20:36:20 -0500 Subject: [PATCH 24/58] socket.connect(): Auto-select UDP_MODE This improves compatibility with the standard socket module --- adafruit_esp32spi/adafruit_esp32spi_socketpool.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 2f7ca78..08015da 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -108,7 +108,11 @@ def connect(self, address, conntype=None): depending on the underlying interface""" host, port = address if conntype is None: - conntype = self._interface.TCP_MODE + conntype = ( + self._interface.UDP_MODE + if self._type == SocketPool.SOCK_DGRAM + else self._interface.TCP_MODE + ) if not self._interface.socket_connect( self._socknum, host, port, conn_mode=conntype ): From 86ffa6bfc338fa8c81677a8cd1ea3e1ec272df06 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 5 May 2024 20:39:55 -0500 Subject: [PATCH 25/58] socketpool: don't use "is" to compare numbers --- adafruit_esp32spi/adafruit_esp32spi_socketpool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 08015da..6f653f3 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -121,7 +121,7 @@ def connect(self, address, conntype=None): def send(self, data): """Send some data to the socket.""" - if self._type is SocketPool.SOCK_DGRAM: + if self._type == SocketPool.SOCK_DGRAM: conntype = self._interface.UDP_MODE else: conntype = self._interface.TCP_MODE From 380a242364c800993a373819bcc6babc198ec426 Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Wed, 15 May 2024 09:41:37 -0700 Subject: [PATCH 26/58] Add sendto --- adafruit_esp32spi/adafruit_esp32spi_socketpool.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 6f653f3..65226fe 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -128,6 +128,11 @@ def send(self, data): self._interface.socket_write(self._socknum, data, conn_mode=conntype) gc.collect() + def sendto(self, data, address): + """Connect and send some data to the socket.""" + self.connect(address) + self.send(data) + def recv(self, bufsize: int) -> bytes: """Reads some bytes from the connected remote address. Will only return an empty string after the configured timeout. From 3575a0e005f32bb40dcbbd42e749a84189617bb6 Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Mon, 20 May 2024 15:53:49 -0700 Subject: [PATCH 27/58] Remove SocketPoolContants --- adafruit_esp32spi/adafruit_esp32spi_socketpool.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 65226fe..1540c88 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -29,8 +29,8 @@ _global_socketpool = {} -class SocketPoolContants: # pylint: disable=too-few-public-methods - """Helper class for the constants that are needed everywhere""" +class SocketPool: + """ESP32SPI SocketPool library""" SOCK_STREAM = const(0) SOCK_DGRAM = const(1) @@ -39,10 +39,6 @@ class SocketPoolContants: # pylint: disable=too-few-public-methods MAX_PACKET = const(4000) - -class SocketPool(SocketPoolContants): - """ESP32SPI SocketPool library""" - def __new__(cls, iface: ESP_SPIcontrol): # We want to make sure to return the same pool for the same interface if iface not in _global_socketpool: @@ -60,12 +56,12 @@ def getaddrinfo( # pylint: disable=too-many-arguments,unused-argument if not isinstance(port, int): raise ValueError("Port must be an integer") ipaddr = self._interface.get_host_by_name(host) - return [(SocketPoolContants.AF_INET, socktype, proto, "", (ipaddr, port))] + return [(SocketPool.AF_INET, socktype, proto, "", (ipaddr, port))] def socket( # pylint: disable=redefined-builtin self, - family=SocketPoolContants.AF_INET, - type=SocketPoolContants.SOCK_STREAM, + family=AF_INET, + type=SOCK_STREAM, proto=0, fileno=None, ): From b16026756861facfb7fc2c362f8a0ea276590162 Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Mon, 20 May 2024 22:31:10 -0700 Subject: [PATCH 28/58] Remove timeout Exception --- adafruit_esp32spi/adafruit_esp32spi_socketpool.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 1540c88..6d8a32e 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -21,6 +21,7 @@ pass +import errno import time import gc from micropython import const @@ -181,7 +182,7 @@ def recv_into(self, buffer, nbytes: int = 0): break # No bytes yet, or more bytes requested. if self._timeout > 0 and time.monotonic() - last_read_time > self._timeout: - raise timeout("timed out") + raise OSError(errno.ETIMEDOUT) return num_read def settimeout(self, value): @@ -223,11 +224,3 @@ def _connected(self): def close(self): """Close the socket, after reading whatever remains""" self._interface.socket_close(self._socknum) - - -class timeout(TimeoutError): # pylint: disable=invalid-name - """TimeoutError class. An instance of this error will be raised by recv_into() if - the timeout has elapsed and we haven't received any data yet.""" - - def __init__(self, msg): - super().__init__(msg) From 30d73e0c76aafc866ceccaa80f6cdc79de0ae7e8 Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Thu, 23 May 2024 15:23:03 -0700 Subject: [PATCH 29/58] Clear error for only one SSL socket open at a time --- adafruit_esp32spi/adafruit_esp32spi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index a124323..cbb37e9 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -718,7 +718,7 @@ def socket_open(self, socket_num, dest, port, conn_mode=TCP_MODE): if self._debug: print("*** Open socket to", dest, port, conn_mode) if conn_mode == ESP_SPIcontrol.TLS_MODE and self._tls_socket is not None: - raise OSError(23) # ENFILE - File table overflow + raise OSError(23, "Only one open SSL connection allowed") port_param = struct.pack(">H", port) if isinstance(dest, str): # use the 5 arg version dest = bytes(dest, "utf-8") From 04b795086a2a594dbf27c270f7090bce0e2e24c2 Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Wed, 12 Jun 2024 14:27:13 -0700 Subject: [PATCH 30/58] Add ap_info --- adafruit_esp32spi/adafruit_esp32spi.py | 141 ++++++++++++++---- .../adafruit_esp32spi_wifimanager.py | 9 +- examples/esp32spi_ipconfig.py | 6 +- examples/esp32spi_simpletest.py | 8 +- examples/esp32spi_simpletest_rp2040.py | 6 +- examples/esp32spi_wpa2ent_simpletest.py | 12 +- examples/gpio/esp32spi_gpio.py | 6 +- 7 files changed, 130 insertions(+), 58 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index cbb37e9..5713c87 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -131,6 +131,97 @@ # pylint: disable=too-many-lines +class ESP_Network: + """A wifi network provided by a nearby access point.""" + + def __init__( # pylint: disable=too-many-arguments + self, + esp_spi_control=None, + raw_ssid=None, + raw_bssid=None, + raw_rssi=None, + raw_channel=None, + raw_country=None, + raw_authmode=None, + ): + self._esp_spi_control = esp_spi_control + self._raw_ssid = raw_ssid + self._raw_bssid = raw_bssid + self._raw_rssi = raw_rssi + self._raw_channel = raw_channel + self._raw_country = raw_country + self._raw_authmode = raw_authmode + + def _get_response(self, cmd): + respose = self._esp_spi_control._send_command_get_response( # pylint: disable=protected-access + cmd, [b"\xFF"] + ) + return respose[0] + + @property + def ssid(self): + """String id of the network""" + if self._raw_ssid: + response = self._raw_ssid + else: + response = self._get_response(_GET_CURR_SSID_CMD) + return response.decode("utf-8") + + @property + def bssid(self): + """BSSID of the network (usually the AP’s MAC address)""" + if self._raw_bssid: + response = self._raw_bssid + else: + response = self._get_response(_GET_CURR_BSSID_CMD) + return bytes(response) + + @property + def rssi(self): + """Signal strength of the network""" + if self._raw_bssid: + response = self._raw_rssi + else: + response = self._get_response(_GET_CURR_RSSI_CMD) + return struct.unpack(" 1.5.0 - fw_semver_maj = bytes(self.firmware_version).decode("utf-8")[2] + fw_semver_maj = self.firmware_version[2] assert int(fw_semver_maj) >= 5, "Please update nina-fw to 1.5.0 or above." resp = self._send_command_get_response(_SET_DIGITAL_READ_CMD, ((pin,),))[0] @@ -961,7 +1044,7 @@ def set_analog_read(self, pin, atten=ADC_ATTEN_DB_11): :param int atten: attenuation constant """ # Verify nina-fw => 1.5.0 - fw_semver_maj = bytes(self.firmware_version).decode("utf-8")[2] + fw_semver_maj = self.firmware_version[2] assert int(fw_semver_maj) >= 5, "Please update nina-fw to 1.5.0 or above." resp = self._send_command_get_response(_SET_ANALOG_READ_CMD, ((pin,), (atten,))) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 01b97e8..68cd058 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -96,10 +96,7 @@ def connect(self): print("Firmware vers.", self.esp.firmware_version) print("MAC addr:", [hex(i) for i in self.esp.MAC_address]) for access_pt in self.esp.scan_networks(): - print( - "\t%s\t\tRSSI: %d" - % (str(access_pt["ssid"], "utf-8"), access_pt["rssi"]) - ) + print("\t%s\t\tRSSI: %d" % (access_pt.ssid, access_pt.rssi)) if self._connection_type == ESPSPI_WiFiManager.NORMAL: self.connect_normal() elif self._connection_type == ESPSPI_WiFiManager.ENTERPRISE: @@ -328,7 +325,7 @@ def ip_address(self): self.connect() self.pixel_status((0, 0, 100)) self.pixel_status(0) - return self.esp.pretty_ip(self.esp.ip_address) + return self.esp.ipv4_address def pixel_status(self, value): """ @@ -349,4 +346,4 @@ def signal_strength(self): """ if not self.esp.is_connected: self.connect() - return self.esp.rssi + return self.esp.ap_info.rssi diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index f29e9a1..7e98df6 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -70,7 +70,7 @@ except OSError as e: print("could not connect to AP, retrying: ", e) continue -print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) +print("Connected to", esp.ap_info.ssid, "\tRSSI:", esp.ap_info.rssi) ip1 = esp.ip_address print("set ip dns") @@ -91,9 +91,7 @@ esp.pretty_ip(info["netmask"]), ) -IP_ADDR = esp.pretty_ip(esp.ip_address) -print("ip:", IP_ADDR) -print("My IP address is", esp.pretty_ip(esp.ip_address)) +print("My IP address is", esp.ipv4_address) print("udp in addr: ", UDP_IN_ADDR, UDP_IN_PORT) socketaddr_udp_in = pool.getaddrinfo(UDP_IN_ADDR, UDP_IN_PORT)[0][4] diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index 962c17e..c194648 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -63,11 +63,11 @@ if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode") -print("Firmware vers.", esp.firmware_version.decode("utf-8")) +print("Firmware vers.", esp.firmware_version) print("MAC addr:", ":".join("%02X" % byte for byte in esp.MAC_address)) for ap in esp.scan_networks(): - print("\t%-23s RSSI: %d" % (str(ap["ssid"], "utf-8"), ap["rssi"])) + print("\t%-23s RSSI: %d" % (ap.ssid, ap.rssi)) print("Connecting to AP...") while not esp.is_connected: @@ -76,8 +76,8 @@ except OSError as e: print("could not connect to AP, retrying: ", e) continue -print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) -print("My IP address is", esp.pretty_ip(esp.ip_address)) +print("Connected to", esp.ap_info.ssid, "\tRSSI:", esp.ap_info.rssi) +print("My IP address is", esp.ipv4_address) print( "IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com")) ) diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index 4330b7d..eb5b8dd 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -46,7 +46,7 @@ print("MAC addr:", [hex(i) for i in esp.MAC_address]) for ap in esp.scan_networks(): - print("\t%s\t\tRSSI: %d" % (str(ap["ssid"], "utf-8"), ap["rssi"])) + print("\t%s\t\tRSSI: %d" % (ap.ssid, ap.rssi)) print("Connecting to AP...") while not esp.is_connected: @@ -55,8 +55,8 @@ except OSError as e: print("could not connect to AP, retrying: ", e) continue -print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) -print("My IP address is", esp.pretty_ip(esp.ip_address)) +print("Connected to", esp.ap_info.ssid, "\tRSSI:", esp.ap_info.rssi) +print("My IP address is", esp.ipv4_address) print( "IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com")) ) diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index 0df4d28..db5019f 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -59,17 +59,15 @@ def normalize(v): if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode") -# Get the ESP32 fw version number, remove trailing byte off the returned bytearray -# and then convert it to a string for prettier printing and later comparison -firmware_version = "".join([chr(b) for b in esp.firmware_version[:-1]]) -print("Firmware vers.", firmware_version) +# Get the ESP32 fw version number +print("Firmware vers.", esp.firmware_version) print("MAC addr:", [hex(i) for i in esp.MAC_address]) # WPA2 Enterprise support was added in fw ver 1.3.0. Check that the ESP32 # is running at least that version, otherwise, bail out assert ( - version_compare(firmware_version, "1.3.0") >= 0 + version_compare(esp.firmware_version, "1.3.0") >= 0 ), "Incorrect ESP32 firmware version; >= 1.3.0 required." # Set up the SSID you would like to connect to @@ -98,8 +96,8 @@ def normalize(v): time.sleep(2) print("") -print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) -print("My IP address is", esp.pretty_ip(esp.ip_address)) +print("Connected to", esp.ap_info.ssid, "\tRSSI:", esp.ap_info.rssi) +print("My IP address is", esp.ipv4_address) print( "IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com")) ) diff --git a/examples/gpio/esp32spi_gpio.py b/examples/gpio/esp32spi_gpio.py index 6d7723b..b257eb8 100644 --- a/examples/gpio/esp32spi_gpio.py +++ b/examples/gpio/esp32spi_gpio.py @@ -67,11 +67,7 @@ def esp_init_pin_modes(din, dout): esp_reset_all() -espfirmware = "" -for _ in esp.firmware_version: - if _ != 0: - espfirmware += "{:c}".format(_) -print("ESP32 Firmware:", espfirmware) +print("ESP32 Firmware:", esp.firmware_version) print( "ESP32 MAC: {5:02X}:{4:02X}:{3:02X}:{2:02X}:{1:02X}:{0:02X}".format( From c4dfdf57c43af35f2622c84670b6d45167682512 Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Sun, 23 Jun 2024 11:36:39 -0800 Subject: [PATCH 31/58] Update adafruit_esp32spi/adafruit_esp32spi.py Co-authored-by: Dan Halbert --- adafruit_esp32spi/adafruit_esp32spi.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 5713c87..ed5ecad 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -195,9 +195,7 @@ def channel(self): @property def country(self): """String id of the country code""" - if self._raw_country: - return self._raw_country - return None + return self._raw_country @property def authmode(self): From 2da98438cf81145166f89cd7fa3969e32ca186af Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Sun, 23 Jun 2024 16:16:37 -0700 Subject: [PATCH 32/58] Rename from ESP_Network to Network --- adafruit_esp32spi/adafruit_esp32spi.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index ed5ecad..96b806d 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -131,7 +131,7 @@ # pylint: disable=too-many-lines -class ESP_Network: +class Network: """A wifi network provided by a nearby access point.""" def __init__( # pylint: disable=too-many-arguments @@ -491,7 +491,7 @@ def get_scan_networks(self): channel = self._send_command_get_response(_GET_IDX_CHAN_CMD, ((i,),))[0] authmode = self._send_command_get_response(_GET_IDX_ENCT_CMD, ((i,),))[0] APs.append( - ESP_Network( + Network( raw_ssid=name, raw_bssid=bssid, raw_rssi=rssi, @@ -608,7 +608,7 @@ def ap_info(self): """Network object containing BSSID, SSID, authmode, channel, country and RSSI when connected to an access point. None otherwise.""" if self.is_connected: - return ESP_Network(esp_spi_control=self) + return Network(esp_spi_control=self) return None @property From 5f388a66996cf2f22f2ae9ff0ed3ce92f4cf0606 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 29 Sep 2024 14:24:35 -0400 Subject: [PATCH 33/58] really remove examples/server/esp32spi_wsgiserver.py --- .pre-commit-config.yaml | 2 +- examples/server/esp32spi_wsgiserver.py | 0 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100755 examples/server/esp32spi_wsgiserver.py 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/examples/server/esp32spi_wsgiserver.py b/examples/server/esp32spi_wsgiserver.py deleted file mode 100755 index e69de29..0000000 From d82a300e5b3675d7c617bd6277015bd728397e47 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 29 Sep 2024 14:34:11 -0400 Subject: [PATCH 34/58] really, really remove wsgi server example; update pylint exceptions --- .pre-commit-config.yaml | 2 +- adafruit_esp32spi/adafruit_esp32spi.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 374676d..07a923e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: name: pylint (library code) types: [python] args: - - --disable=consider-using-f-string + - --disable=consider-using-f-string,too-many-arguments,too-many-positional-arguments exclude: "^(docs/|examples/|tests/|setup.py$)" - id: pylint name: pylint (example code) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 96b806d..346593a 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -416,7 +416,7 @@ def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False): print("Read %d: " % len(responses[0]), responses) return responses - def _send_command_get_response( + def _send_command_get_response( # pylint: disable=too-many-arguments self, cmd, params=None, From 152f3c0db56eed45599337dde38a3ed4efb03e42 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 29 Sep 2024 14:41:11 -0400 Subject: [PATCH 35/58] create non-empty esp32spi_wsgiserver.py so we can delete it! --- examples/server/esp32spi_wsgiserver.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/server/esp32spi_wsgiserver.py diff --git a/examples/server/esp32spi_wsgiserver.py b/examples/server/esp32spi_wsgiserver.py new file mode 100644 index 0000000..997bda4 --- /dev/null +++ b/examples/server/esp32spi_wsgiserver.py @@ -0,0 +1,3 @@ +# SPDX-FileCopyrightText: 2024 Dan Halbert for Adafruit Industries +# SPDX-License-Identifier: MIT +# will be empty From 91f0dfe729442168e8254338cdae72e01e6feef7 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 29 Sep 2024 14:48:24 -0400 Subject: [PATCH 36/58] try to delete zombie file --- examples/server/esp32spi_wsgiserver.py | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 examples/server/esp32spi_wsgiserver.py diff --git a/examples/server/esp32spi_wsgiserver.py b/examples/server/esp32spi_wsgiserver.py deleted file mode 100644 index 997bda4..0000000 --- a/examples/server/esp32spi_wsgiserver.py +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-FileCopyrightText: 2024 Dan Halbert for Adafruit Industries -# SPDX-License-Identifier: MIT -# will be empty From 99fd76db720550a9819c62e8dc95112cc3bdcb4f Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 7 Oct 2024 09:24:05 -0500 Subject: [PATCH 37/58] 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 082d389..fa88890 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -108,7 +108,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 71a07cc43a80d02d627dce595eeb246e089c2679 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 14 Jan 2025 11:32:34 -0600 Subject: [PATCH 38/58] 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 33c2a61..88bca9f 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 5dfafb69baf0b26189b110a6f4a7b6b3e7507931 Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Wed, 19 Feb 2025 14:18:39 -0800 Subject: [PATCH 39/58] WiFiManager updates --- adafruit_esp32spi/adafruit_esp32spi.py | 5 ++ .../adafruit_esp32spi_wifimanager.py | 88 ++++++++++++++++--- examples/esp32spi_aio_post.py | 28 ++---- examples/esp32spi_cheerlights.py | 17 +--- examples/esp32spi_ipconfig.py | 15 +--- examples/esp32spi_localtime.py | 17 +--- examples/esp32spi_settings.toml | 4 +- examples/esp32spi_simpletest.py | 15 +--- examples/esp32spi_simpletest_rp2040.py | 15 +--- examples/esp32spi_tcp_client.py | 15 +--- examples/esp32spi_udp_client.py | 15 +--- examples/esp32spi_wpa2ent_aio_post.py | 43 +++++---- 12 files changed, 134 insertions(+), 143 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 346593a..0e61109 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -28,6 +28,7 @@ import struct import time +import warnings from micropython import const from adafruit_bus_device.spi_device import SPIDevice from digitalio import Direction @@ -663,6 +664,10 @@ def connect(self, ssid, password=None, timeout=10): This upward compatbility will be removed in a future release. """ if isinstance(ssid, dict): # secrets + warnings.warn( + "The passing in of `secrets`, is deprecated. Use connect with a `ssid` and " + "`password` instead and fetch values from settings.toml with `os.getenv()`." + ) ssid, password = ssid["ssid"], ssid.get("password") self.connect_AP(ssid, password, timeout_s=timeout) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 68cd058..9f37ded 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -13,6 +13,7 @@ # pylint: disable=no-name-in-module +import warnings from time import sleep from micropython import const import adafruit_connection_manager @@ -21,7 +22,7 @@ # pylint: disable=too-many-instance-attributes -class ESPSPI_WiFiManager: +class WiFiManager: """ A class to help manage the Wifi connection """ @@ -33,7 +34,11 @@ class ESPSPI_WiFiManager: def __init__( self, esp, - secrets, + ssid, + password=None, + *, + enterprise_ident=None, + enterprise_user=None, status_pixel=None, attempts=2, connection_type=NORMAL, @@ -41,9 +46,10 @@ def __init__( ): """ :param ESP_SPIcontrol esp: The ESP object we are using - :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) - The use of secrets.py to populate the secrets dict is depreciated - in favor of using settings.toml. + :param str ssid: the SSID of the created Access Point. Must be less than 32 chars. + :param str password: the password of the created Access Point. Must be 8-63 chars. + :param str enterprise_ident: the ident when connecting to an enterprise Access Point. + :param str enterprise_user: the user when connecting to an enterprise Access Point. :param status_pixel: (Optional) The pixel device - A NeoPixel, DotStar, or RGB LED (default=None). The status LED, if given, turns red when attempting to connect to a Wi-Fi network or create an access point, @@ -57,8 +63,8 @@ def __init__( # Read the settings self.esp = esp self.debug = debug - self.ssid = secrets["ssid"] - self.password = secrets.get("password", None) + self.ssid = ssid + self.password = password self.attempts = attempts self._connection_type = connection_type self.statuspix = status_pixel @@ -70,11 +76,11 @@ def __init__( ssl_context = adafruit_connection_manager.get_radio_ssl_context(self.esp) self._requests = adafruit_requests.Session(pool, ssl_context) - # Check for WPA2 Enterprise keys in the secrets dictionary and load them if they exist - self.ent_ssid = secrets.get("ent_ssid", secrets["ssid"]) - self.ent_ident = secrets.get("ent_ident", "") - self.ent_user = secrets.get("ent_user") - self.ent_password = secrets.get("ent_password") + # Check for WPA2 Enterprise values + self.ent_ssid = ssid + self.ent_ident = enterprise_ident + self.ent_user = enterprise_user + self.ent_password = password # pylint: enable=too-many-arguments @@ -97,9 +103,9 @@ def connect(self): print("MAC addr:", [hex(i) for i in self.esp.MAC_address]) for access_pt in self.esp.scan_networks(): print("\t%s\t\tRSSI: %d" % (access_pt.ssid, access_pt.rssi)) - if self._connection_type == ESPSPI_WiFiManager.NORMAL: + if self._connection_type == WiFiManager.NORMAL: self.connect_normal() - elif self._connection_type == ESPSPI_WiFiManager.ENTERPRISE: + elif self._connection_type == WiFiManager.ENTERPRISE: self.connect_enterprise() else: raise TypeError("Invalid WiFi connection type specified") @@ -347,3 +353,57 @@ def signal_strength(self): if not self.esp.is_connected: self.connect() return self.esp.ap_info.rssi + + +# pylint: disable=too-many-instance-attributes +class ESPSPI_WiFiManager(WiFiManager): + """ + A legacy class to help manage the Wifi connection. Please update to using WiFiManager + """ + + # pylint: disable=too-many-arguments + def __init__( + self, + esp, + secrets, + status_pixel=None, + attempts=2, + connection_type=WiFiManager.NORMAL, + debug=False, + ): + """ + :param ESP_SPIcontrol esp: The ESP object we are using + :param dict secrets: The WiFi secrets dict + The use of secrets.py to populate the secrets dict is depreciated + in favor of using settings.toml. + :param status_pixel: (Optional) The pixel device - A NeoPixel, DotStar, + or RGB LED (default=None). The status LED, if given, turns red when + attempting to connect to a Wi-Fi network or create an access point, + turning green upon success. Additionally, if given, it will turn blue + when attempting an HTTP method or returning IP address, turning off + upon success. + :type status_pixel: NeoPixel, DotStar, or RGB LED + :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) + :param const connection_type: (Optional) Type of WiFi connection: NORMAL or ENTERPRISE + """ + + warnings.warn( + "ESP32WiFiManager, which uses `secrets`, is deprecated. Use WifiManager instead and " + "fetch values from settings.toml with `os.getenv()`." + ) + + ssid = secrets.get("ssid") + password = secrets.get("secrets", None) + enterprise_ident = secrets.get("ent_ident", "") + enterprise_user = secrets.get("ent_user") + super().__init__( + esp=esp, + ssid=ssid, + password=password, + enterprise_ident=enterprise_ident, + enterprise_user=enterprise_user, + status_pixel=status_pixel, + attempts=attempts, + connection_type=connection_type, + debug=debug, + ) diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index c4b5f7f..0ce2ab2 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -8,28 +8,18 @@ from digitalio import DigitalInOut import neopixel from adafruit_esp32spi import adafruit_esp32spi -from adafruit_esp32spi import adafruit_esp32spi_wifimanager +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager print("ESP32 SPI webclient test") # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD -# CIRCUITPY_AIO_USERNAME, CIRCUITPY_AIO_KEY -secrets = {} -for token in ["ssid", "password"]: - if getenv("CIRCUITPY_WIFI_" + token.upper()): - secrets[token] = getenv("CIRCUITPY_WIFI_" + token.upper()) -for token in ["aio_username", "aio_key"]: - if getenv("CIRCUITPY_" + token.upper()): - secrets[token] = getenv("CIRCUITPY_" + token.upper()) +# ADAFRUIT_AIO_USERNAME, ADAFRUIT_AIO_KEY +ssid = getenv("CIRCUITPY_WIFI_SSID") +password = getenv("CIRCUITPY_WIFI_PASSWORD") -if not secrets: - try: - # Fallback on secrets.py until depreciation is over and option is removed - from secrets import secrets - except ImportError: - print("WiFi secrets are kept in settings.toml, please add them there!") - raise +aio_username = getenv("ADAFRUIT_AIO_USERNAME") +aio_key = getenv("ADAFRUIT_AIO_KEY") # If you are using a board with pre-defined ESP32 Pins: esp32_cs = DigitalInOut(board.ESP_CS) @@ -59,7 +49,7 @@ # BLUE_LED = PWMOut.PWMOut(esp, 25) # status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) -wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) +wifi = WiFiManager(esp, ssid, password, status_light=status_light) counter = 0 @@ -71,12 +61,12 @@ payload = {"value": data} response = wifi.post( "https://io.adafruit.com/api/v2/" - + secrets["aio_username"] + + aio_username + "/feeds/" + feed + "/data", json=payload, - headers={"X-AIO-KEY": secrets["aio_key"]}, + headers={"X-AIO-KEY": aio_key}, ) print(response.json()) response.close() diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index 9bac915..d1e04fa 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -11,21 +11,12 @@ import adafruit_fancyled.adafruit_fancyled as fancy from adafruit_esp32spi import adafruit_esp32spi -from adafruit_esp32spi import adafruit_esp32spi_wifimanager +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD -secrets = { - "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD"), -} -if secrets == {"ssid": None, "password": None}: - try: - # Fallback on secrets.py until depreciation is over and option is removed - from secrets import secrets - except ImportError: - print("WiFi secrets are kept in settings.toml, please add them there!") - raise +ssid = getenv("CIRCUITPY_WIFI_SSID") +password = getenv("CIRCUITPY_WIFI_PASSWORD") print("ESP32 SPI webclient test") @@ -59,7 +50,7 @@ # GREEN_LED = PWMOut.PWMOut(esp, 27) # BLUE_LED = PWMOut.PWMOut(esp, 25) # status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) -wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) +wifi = WiFiManager(esp, ssid, password, status_light=status_light) # neopixels pixels = neopixel.NeoPixel(board.A1, 16, brightness=0.3) diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index 7e98df6..dec0f3a 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -11,17 +11,8 @@ # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD -secrets = { - "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD"), -} -if secrets == {"ssid": None, "password": None}: - try: - # Fallback on secrets.py until depreciation is over and option is removed - from secrets import secrets - except ImportError: - print("WiFi secrets are kept in settings.toml, please add them there!") - raise +ssid = getenv("CIRCUITPY_WIFI_SSID") +password = getenv("CIRCUITPY_WIFI_PASSWORD") HOSTNAME = "esp32-spi-hostname-test" @@ -66,7 +57,7 @@ print("Connecting to AP...") while not esp.is_connected: try: - esp.connect_AP(secrets["ssid"], secrets["password"]) + esp.connect_AP(ssid, password) except OSError as e: print("could not connect to AP, retrying: ", e) continue diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index b6ee671..0a19367 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -9,21 +9,12 @@ import neopixel import rtc from adafruit_esp32spi import adafruit_esp32spi -from adafruit_esp32spi import adafruit_esp32spi_wifimanager +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD -secrets = { - "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD"), -} -if secrets == {"ssid": None, "password": None}: - try: - # Fallback on secrets.py until depreciation is over and option is removed - from secrets import secrets - except ImportError: - print("WiFi secrets are kept in settings.toml, please add them there!") - raise +ssid = getenv("CIRCUITPY_WIFI_SSID") +password = getenv("CIRCUITPY_WIFI_PASSWORD") print("ESP32 local time") @@ -58,7 +49,7 @@ # BLUE_LED = PWMOut.PWMOut(esp, 25) # status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) -wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) +wifi = WiFiManager(esp, ssid, password, status_light=status_light) the_rtc = rtc.RTC() diff --git a/examples/esp32spi_settings.toml b/examples/esp32spi_settings.toml index 16208bd..4f5866e 100644 --- a/examples/esp32spi_settings.toml +++ b/examples/esp32spi_settings.toml @@ -10,5 +10,5 @@ CIRCUITPY_WIFI_SSID="yourssid" CIRCUITPY_WIFI_PASSWORD="yourpassword" CIRCUITPY_TIMEZONE="America/New_York" -CIRCUITPY_AIO_USERNAME="youraiousername" -CIRCUITPY_AIO_KEY="youraiokey" +ADAFRUIT_AIO_USERNAME="youraiousername" +ADAFRUIT_AIO_KEY="youraiokey" diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index c194648..d9a8edf 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -11,17 +11,8 @@ # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD -secrets = { - "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD"), -} -if secrets == {"ssid": None, "password": None}: - try: - # Fallback on secrets.py until depreciation is over and option is removed - from secrets import secrets - except ImportError: - print("WiFi secrets are kept in settings.toml, please add them there!") - raise +ssid = getenv("CIRCUITPY_WIFI_SSID") +password = getenv("CIRCUITPY_WIFI_PASSWORD") print("ESP32 SPI webclient test") @@ -72,7 +63,7 @@ print("Connecting to AP...") while not esp.is_connected: try: - esp.connect_AP(secrets["ssid"], secrets["password"]) + esp.connect_AP(ssid, password) except OSError as e: print("could not connect to AP, retrying: ", e) continue diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index eb5b8dd..1ee3fd6 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -11,17 +11,8 @@ # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD -secrets = { - "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD"), -} -if secrets == {"ssid": None, "password": None}: - try: - # Fallback on secrets.py until depreciation is over and option is removed - from secrets import secrets - except ImportError: - print("WiFi secrets are kept in settings.toml, please add them there!") - raise +ssid = getenv("CIRCUITPY_WIFI_SSID") +password = getenv("CIRCUITPY_WIFI_PASSWORD") print("Raspberry Pi RP2040 - ESP32 SPI webclient test") @@ -51,7 +42,7 @@ print("Connecting to AP...") while not esp.is_connected: try: - esp.connect_AP(secrets["ssid"], secrets["password"]) + esp.connect_AP(ssid, password) except OSError as e: print("could not connect to AP, retrying: ", e) continue diff --git a/examples/esp32spi_tcp_client.py b/examples/esp32spi_tcp_client.py index 2ec5d2a..275c1ce 100644 --- a/examples/esp32spi_tcp_client.py +++ b/examples/esp32spi_tcp_client.py @@ -10,17 +10,8 @@ # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD -secrets = { - "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD"), -} -if secrets == {"ssid": None, "password": None}: - try: - # Fallback on secrets.py until depreciation is over and option is removed - from secrets import secrets # pylint: disable=no-name-in-module - except ImportError: - print("WiFi secrets are kept in settings.toml, please add them there!") - raise +ssid = getenv("CIRCUITPY_WIFI_SSID") +password = getenv("CIRCUITPY_WIFI_PASSWORD") TIMEOUT = 5 # edit host and port to match server @@ -42,7 +33,7 @@ esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) # connect to wifi AP -esp.connect(secrets) +esp.connect(ssid, password) # test for connectivity to server print("Server ping:", esp.ping(HOST), "ms") diff --git a/examples/esp32spi_udp_client.py b/examples/esp32spi_udp_client.py index 3dace7b..2321c03 100644 --- a/examples/esp32spi_udp_client.py +++ b/examples/esp32spi_udp_client.py @@ -12,17 +12,8 @@ # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD -secrets = { - "ssid": getenv("CIRCUITPY_WIFI_SSID"), - "password": getenv("CIRCUITPY_WIFI_PASSWORD"), -} -if secrets == {"ssid": None, "password": None}: - try: - # Fallback on secrets.py until depreciation is over and option is removed - from secrets import secrets # pylint: disable=no-name-in-module - except ImportError: - print("WiFi secrets are kept in settings.toml, please add them there!") - raise +ssid = getenv("CIRCUITPY_WIFI_SSID") +password = getenv("CIRCUITPY_WIFI_PASSWORD") TIMEOUT = 5 # edit host and port to match server @@ -45,7 +36,7 @@ esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) # connect to wifi AP -esp.connect(secrets) +esp.connect(ssid, password) # test for connectivity to server print("Server ping:", esp.ping(HOST), "ms") diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index 197f279..ef02d76 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -8,28 +8,21 @@ from digitalio import DigitalInOut import neopixel from adafruit_esp32spi import adafruit_esp32spi -from adafruit_esp32spi.adafruit_esp32spi_wifimanager import ESPSPI_WiFiManager +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager print("ESP32 SPI WPA2 Enterprise webclient test") # Get wifi details and more from a settings.toml file -# tokens used by this Demo: CIRCUITPY_AIO_USERNAME, CIRCUITPY_AIO_KEY, -# CIRCUITPY_WIFI_ENT_SSID, CIRCUITPY_WIFI_ENT_PASSWORD, -# CIRCUITPY_WIFI_ENT_USER, CIRCUITPY_WIFI_ENT_IDENT -secrets = {} -for token in ["ssid", "password", "user", "ident"]: - if getenv("CIRCUITPY_WIFI_ENT_" + token.upper()): - secrets[token] = getenv("CIRCUITPY_WIFI_" + token.upper()) -for token in ["aio_username", "aio_key"]: - if getenv("CIRCUITPY_" + token.upper()): - secrets[token] = getenv("CIRCUITPY_" + token.upper()) -if not secrets: - try: - # Fallback on secrets.py until depreciation is over and option is removed - from secrets import secrets # pylint: disable=no-name-in-module - except ImportError: - print("WiFi secrets are kept in settings.toml, please add them there!") - raise +# tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD, +# CIRCUITPY_WIFI_ENT_USER, CIRCUITPY_WIFI_ENT_IDENT, +# ADAFRUIT_AIO_USERNAME, ADAFRUIT_AIO_KEY +ssid = getenv("CIRCUITPY_WIFI_SSID") +password = getenv("CIRCUITPY_WIFI_PASSWORD") +enterprise_ident = getenv("CIRCUITPY_WIFI_ENT_IDENT") +enterprise_user = getenv("CIRCUITPY_WIFI_ENT_USER") + +aio_username = getenv("ADAFRUIT_AIO_USERNAME") +aio_key = getenv("ADAFRUIT_AIO_KEY") # ESP32 setup # If your board does define the three pins listed below, @@ -62,8 +55,14 @@ # BLUE_LED = PWMOut.PWMOut(esp, 25) # status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) -wifi = ESPSPI_WiFiManager( - esp, secrets, status_light, connection_type=ESPSPI_WiFiManager.ENTERPRISE +wifi = WiFiManager( + esp, + ssid, + password, + enterprise_ident=enterprise_ident, + enterprise_user=enterprise_user, + status_light=status_light, + connection_type=WiFiManager.ENTERPRISE, ) counter = 0 @@ -76,12 +75,12 @@ payload = {"value": data} response = wifi.post( "https://io.adafruit.com/api/v2/" - + secrets["aio_username"] + + aio_username + "/feeds/" + feed + "/data", json=payload, - headers={"X-AIO-KEY": secrets["aio_key"]}, + headers={"X-AIO-KEY": aio_key}, ) print(response.json()) response.close() From 9c8baa8bcade5f158285f1380374340cd427e539 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 21 Feb 2025 12:27:12 -0500 Subject: [PATCH 40/58] Use adafruit-hosted sample JSON URL --- examples/esp32spi_simpletest.py | 2 +- examples/esp32spi_simpletest_rp2040.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index c194648..a0416e1 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -26,7 +26,7 @@ print("ESP32 SPI webclient test") TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html" -JSON_URL = "http://api.coindesk.com/v1/bpi/currentprice/USD.json" +JSON_URL = "http://wifitest.adafruit.com/testwifi/sample.json" # If you are using a board with pre-defined ESP32 Pins: diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index eb5b8dd..12a028d 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -26,7 +26,7 @@ print("Raspberry Pi RP2040 - ESP32 SPI webclient test") TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html" -JSON_URL = "http://api.coindesk.com/v1/bpi/currentprice/USD.json" +JSON_URL = "http://wifitest.adafruit.com/testwifi/sample.json" # Raspberry Pi RP2040 Pinout esp32_cs = DigitalInOut(board.GP13) From 35847378b13f02197d54d309d631d1cac7787f7c Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Fri, 21 Feb 2025 13:34:55 -0800 Subject: [PATCH 41/58] Apply suggestions from code review Co-authored-by: Dan Halbert --- adafruit_esp32spi/adafruit_esp32spi.py | 4 ++-- .../adafruit_esp32spi_wifimanager.py | 22 ++++++++----------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 0e61109..e2c16ea 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -661,11 +661,11 @@ def connect(self, ssid, password=None, timeout=10): **Deprecated functionality:** If the first argument (``ssid``) is a ``dict``, assume it is a dictionary with entries for keys ``"ssid"`` and, optionally, ``"password"``. This mimics the previous signature for ``connect()``. - This upward compatbility will be removed in a future release. + This upward compatibility will be removed in a future release. """ if isinstance(ssid, dict): # secrets warnings.warn( - "The passing in of `secrets`, is deprecated. Use connect with a `ssid` and " + "The passing in of `secrets`, is deprecated. Use connect() with `ssid` and " "`password` instead and fetch values from settings.toml with `os.getenv()`." ) ssid, password = ssid["ssid"], ssid.get("password") diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 9f37ded..ec5df81 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -46,10 +46,10 @@ def __init__( ): """ :param ESP_SPIcontrol esp: The ESP object we are using - :param str ssid: the SSID of the created Access Point. Must be less than 32 chars. - :param str password: the password of the created Access Point. Must be 8-63 chars. - :param str enterprise_ident: the ident when connecting to an enterprise Access Point. - :param str enterprise_user: the user when connecting to an enterprise Access Point. + :param str ssid: the SSID of the access point. Must be less than 32 chars. + :param str password: the password for the access point. Must be 8-63 chars. + :param str enterprise_ident: the ident to use when connecting to an enterprise access point. + :param str enterprise_user: the username to use when connecting to an enterprise access point. :param status_pixel: (Optional) The pixel device - A NeoPixel, DotStar, or RGB LED (default=None). The status LED, if given, turns red when attempting to connect to a Wi-Fi network or create an access point, @@ -374,7 +374,7 @@ def __init__( """ :param ESP_SPIcontrol esp: The ESP object we are using :param dict secrets: The WiFi secrets dict - The use of secrets.py to populate the secrets dict is depreciated + The use of secrets.py to populate the secrets dict is deprecated in favor of using settings.toml. :param status_pixel: (Optional) The pixel device - A NeoPixel, DotStar, or RGB LED (default=None). The status LED, if given, turns red when @@ -392,16 +392,12 @@ def __init__( "fetch values from settings.toml with `os.getenv()`." ) - ssid = secrets.get("ssid") - password = secrets.get("secrets", None) - enterprise_ident = secrets.get("ent_ident", "") - enterprise_user = secrets.get("ent_user") super().__init__( esp=esp, - ssid=ssid, - password=password, - enterprise_ident=enterprise_ident, - enterprise_user=enterprise_user, + ssid=secrets.get("ssid"), + password=secrets.get("secrets"), + enterprise_ident=secrets.get("ent_ident", ""), + enterprise_user=secrets.get("ent_user"), status_pixel=status_pixel, attempts=attempts, connection_type=connection_type, From 78c5cfab10f897fc5f5f11c819460e557071f07e Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Fri, 21 Feb 2025 13:41:31 -0800 Subject: [PATCH 42/58] Fix typo --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index ec5df81..05027e3 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -395,7 +395,7 @@ def __init__( super().__init__( esp=esp, ssid=secrets.get("ssid"), - password=secrets.get("secrets"), + password=secrets.get("password"), enterprise_ident=secrets.get("ent_ident", ""), enterprise_user=secrets.get("ent_user"), status_pixel=status_pixel, From 508935e1e39c7af7430015816f160d399528c666 Mon Sep 17 00:00:00 2001 From: Justin Myers Date: Fri, 21 Feb 2025 13:44:54 -0800 Subject: [PATCH 43/58] Fix lint error --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 05027e3..4db7463 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -49,7 +49,8 @@ def __init__( :param str ssid: the SSID of the access point. Must be less than 32 chars. :param str password: the password for the access point. Must be 8-63 chars. :param str enterprise_ident: the ident to use when connecting to an enterprise access point. - :param str enterprise_user: the username to use when connecting to an enterprise access point. + :param str enterprise_user: the username to use when connecting to an enterprise access + point. :param status_pixel: (Optional) The pixel device - A NeoPixel, DotStar, or RGB LED (default=None). The status LED, if given, turns red when attempting to connect to a Wi-Fi network or create an access point, From 45705df70b24be062051191ab3ab4210479cf0a8 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 21 Feb 2025 22:01:46 -0500 Subject: [PATCH 44/58] status_light -> status_pixel everywhere, to match now required keyword arg name --- examples/esp32spi_aio_post.py | 8 ++++---- examples/esp32spi_cheerlights.py | 8 ++++---- examples/esp32spi_localtime.py | 8 ++++---- examples/esp32spi_wpa2ent_aio_post.py | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index 0ce2ab2..9438856 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -38,18 +38,18 @@ spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" -status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) +status_pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) """Uncomment below for ItsyBitsy M4""" -# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) +# status_pixel = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) """Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" # import adafruit_rgbled # from adafruit_esp32spi import PWMOut # RED_LED = PWMOut.PWMOut(esp, 26) # GREEN_LED = PWMOut.PWMOut(esp, 27) # BLUE_LED = PWMOut.PWMOut(esp, 25) -# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) +# status_pixel = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) -wifi = WiFiManager(esp, ssid, password, status_light=status_light) +wifi = WiFiManager(esp, ssid, password, status_pixel=status_pixel) counter = 0 diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index d1e04fa..735dd4a 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -40,17 +40,17 @@ spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" -status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) +status_pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) """Uncomment below for ItsyBitsy M4""" -# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) +# status_pixel = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) """Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" # import adafruit_rgbled # from adafruit_esp32spi import PWMOut # RED_LED = PWMOut.PWMOut(esp, 26) # GREEN_LED = PWMOut.PWMOut(esp, 27) # BLUE_LED = PWMOut.PWMOut(esp, 25) -# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) -wifi = WiFiManager(esp, ssid, password, status_light=status_light) +# status_pixel = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) +wifi = WiFiManager(esp, ssid, password, status_pixel=status_pixel) # neopixels pixels = neopixel.NeoPixel(board.A1, 16, brightness=0.3) diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index 0a19367..53f8efa 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -38,18 +38,18 @@ esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" -status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) +status_pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) """Uncomment below for ItsyBitsy M4""" -# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) +# status_pixel = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) """Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" # import adafruit_rgbled # from adafruit_esp32spi import PWMOut # RED_LED = PWMOut.PWMOut(esp, 26) # GREEN_LED = PWMOut.PWMOut(esp, 27) # BLUE_LED = PWMOut.PWMOut(esp, 25) -# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) +# status_pixel = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) -wifi = WiFiManager(esp, ssid, password, status_light=status_light) +wifi = WiFiManager(esp, ssid, password, status_pixel=status_pixel) the_rtc = rtc.RTC() diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index ef02d76..d9f62d1 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -44,16 +44,16 @@ esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" -status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) +status_pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) """Uncomment below for ItsyBitsy M4""" -# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) +# status_pixel = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) """Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" # import adafruit_rgbled # from adafruit_esp32spi import PWMOut # RED_LED = PWMOut.PWMOut(esp, 26) # GREEN_LED = PWMOut.PWMOut(esp, 27) # BLUE_LED = PWMOut.PWMOut(esp, 25) -# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) +# status_pixel = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) wifi = WiFiManager( esp, @@ -61,7 +61,7 @@ password, enterprise_ident=enterprise_ident, enterprise_user=enterprise_user, - status_light=status_light, + status_pixel=status_pixel, connection_type=WiFiManager.ENTERPRISE, ) From 2be7aad5fb4f6db46533b0b8a3d9caae17142ac0 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Wed, 14 May 2025 15:20:38 +0000 Subject: [PATCH 45/58] change to ruff --- .gitattributes | 11 + .pre-commit-config.yaml | 43 +- .pylintrc | 399 ------------------ README.rst | 6 +- adafruit_esp32spi/PWMOut.py | 4 +- adafruit_esp32spi/adafruit_esp32spi.py | 113 ++--- .../adafruit_esp32spi_socketpool.py | 37 +- .../adafruit_esp32spi_wifimanager.py | 28 +- adafruit_esp32spi/digitalio.py | 16 +- docs/api.rst | 3 + docs/conf.py | 8 +- examples/esp32spi_aio_post.py | 10 +- examples/esp32spi_cheerlights.py | 6 +- examples/esp32spi_ipconfig.py | 2 + examples/esp32spi_localtime.py | 12 +- examples/esp32spi_simpletest.py | 10 +- examples/esp32spi_simpletest_rp2040.py | 10 +- examples/esp32spi_tcp_client.py | 11 +- examples/esp32spi_udp_client.py | 11 +- examples/esp32spi_wpa2ent_aio_post.py | 10 +- examples/esp32spi_wpa2ent_simpletest.py | 14 +- examples/gpio/esp32spi_gpio.py | 27 +- ruff.toml | 105 +++++ 23 files changed, 259 insertions(+), 637 deletions(-) create mode 100644 .gitattributes delete mode 100644 .pylintrc create mode 100644 ruff.toml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..21c125c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2024 Justin Myers for Adafruit Industries +# +# SPDX-License-Identifier: Unlicense + +.py text eol=lf +.rst text eol=lf +.txt text eol=lf +.yaml text eol=lf +.toml text eol=lf +.license text eol=lf +.md text eol=lf diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 07a923e..ff19dde 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,42 +1,21 @@ -# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò +# SPDX-FileCopyrightText: 2024 Justin Myers for Adafruit Industries # # SPDX-License-Identifier: Unlicense repos: - - repo: https://github.com/python/black - rev: 23.3.0 - hooks: - - id: black - - repo: https://github.com/fsfe/reuse-tool - rev: v1.1.2 - hooks: - - id: reuse - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - - repo: https://github.com/pycqa/pylint - rev: v3.3.1 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.4 hooks: - - id: pylint - name: pylint (library code) - types: [python] - args: - - --disable=consider-using-f-string,too-many-arguments,too-many-positional-arguments - exclude: "^(docs/|examples/|tests/|setup.py$)" - - id: pylint - name: pylint (example code) - description: Run pylint rules on "examples/*.py" files - types: [python] - files: "^examples/" - args: - - --disable=missing-docstring,invalid-name,consider-using-f-string,duplicate-code - - id: pylint - name: pylint (test code) - description: Run pylint rules on "tests/*.py" files - types: [python] - files: "^tests/" - args: - - --disable=missing-docstring,consider-using-f-string,duplicate-code + - id: ruff-format + - id: ruff + args: ["--fix"] + - repo: https://github.com/fsfe/reuse-tool + rev: v3.0.1 + hooks: + - id: reuse diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index f945e92..0000000 --- a/.pylintrc +++ /dev/null @@ -1,399 +0,0 @@ -# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries -# -# SPDX-License-Identifier: Unlicense - -[MASTER] - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code -extension-pkg-whitelist= - -# Add files or directories to the ignore-list. They should be base names, not -# paths. -ignore=CVS - -# Add files or directories matching the regex patterns to the ignore-list. The -# regex matches against base names, not paths. -ignore-patterns= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Use multiple processes to speed up Pylint. -jobs=1 - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins=pylint.extensions.no_self_use - -# Pickle collected data for later comparisons. -persistent=yes - -# Specify a configuration file. -#rcfile= - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED -confidence= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -# disable=import-error,raw-checker-failed,bad-inline-option,locally-disabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,deprecated-str-translate-call -disable=raw-checker-failed,bad-inline-option,locally-disabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,import-error,pointless-string-statement,unspecified-encoding - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable= - - -[REPORTS] - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details -#msg-template= - -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio).You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Tells whether to display a full report or only the messages -reports=no - -# Activate the evaluation score. -score=yes - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - - -[LOGGING] - -# Logging modules to check that the string format arguments are in logging -# function parameter format -logging-modules=logging - - -[SPELLING] - -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package. -spelling-dict= - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -# notes=FIXME,XXX,TODO -notes=FIXME,XXX - - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members= - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis. It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules=board - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - - -[VARIABLES] - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_,_cb - -# A regular expression matching the name of dummy variables (i.e. expectedly -# not used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.*|^ignored_|^unused_ - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,future.builtins - - -[FORMAT] - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -# expected-line-ending-format= -expected-line-ending-format=LF - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Maximum number of characters on a single line. -max-line-length=100 - -# Maximum number of lines in a module -max-module-lines=1000 - -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - - -[SIMILARITIES] - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=yes - -# Minimum lines number of a similarity. -min-similarity-lines=12 - - -[BASIC] - -# Regular expression matching correct argument names -argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct attribute names -attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression matching correct class attribute names -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Regular expression matching correct class names -# class-rgx=[A-Z_][a-zA-Z0-9]+$ -class-rgx=[A-Z_][a-zA-Z0-9_]+$ - -# Regular expression matching correct constant names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - -# Regular expression matching correct function names -function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Good variable names which should always be accepted, separated by a comma -# good-names=i,j,k,ex,Run,_ -good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_ - -# Include a hint for the correct naming format with invalid-name -include-naming-hint=no - -# Regular expression matching correct inline iteration names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Regular expression matching correct method names -method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ - -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -property-classes=abc.abstractproperty - -# Regular expression matching correct variable names -variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - - -[IMPORTS] - -# Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=optparse,tkinter.tix - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - - -[CLASSES] - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict,_fields,_replace,_source,_make - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Maximum number of attributes for a class (see R0902). -# max-attributes=7 -max-attributes=11 - -# Maximum number of boolean expressions in a if statement -max-bool-expr=5 - -# Maximum number of branch for function / method body -max-branches=12 - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of statements in function / method body -max-statements=50 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=1 - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=builtins.Exception diff --git a/README.rst b/README.rst index f9cf497..cb21217 100644 --- a/README.rst +++ b/README.rst @@ -13,9 +13,9 @@ Introduction :target: https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/actions/ :alt: Build Status -.. image:: https://img.shields.io/badge/code%20style-black-000000.svg - :target: https://github.com/psf/black - :alt: Code Style: Black +.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json + :target: https://github.com/astral-sh/ruff + :alt: Code Style: Ruff CircuitPython driver library for using ESP32 as WiFi co-processor using SPI. The companion firmware `is available on GitHub diff --git a/adafruit_esp32spi/PWMOut.py b/adafruit_esp32spi/PWMOut.py index f116103..94abfce 100755 --- a/adafruit_esp32spi/PWMOut.py +++ b/adafruit_esp32spi/PWMOut.py @@ -26,9 +26,7 @@ class PWMOut: [0, 1, 2, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33] ) - def __init__( - self, esp, pwm_pin, *, frequency=500, duty_cycle=0, variable_frequency=False - ): + def __init__(self, esp, pwm_pin, *, frequency=500, duty_cycle=0, variable_frequency=False): if pwm_pin in self.ESP32_PWM_PINS: self._pwm_pin = pwm_pin else: diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index e2c16ea..f0ff6b6 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -29,9 +29,10 @@ import struct import time import warnings -from micropython import const + from adafruit_bus_device.spi_device import SPIDevice from digitalio import Direction +from micropython import const __version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI.git" @@ -129,13 +130,11 @@ ADC_ATTEN_DB_6 = const(2) ADC_ATTEN_DB_11 = const(3) -# pylint: disable=too-many-lines - class Network: """A wifi network provided by a nearby access point.""" - def __init__( # pylint: disable=too-many-arguments + def __init__( self, esp_spi_control=None, raw_ssid=None, @@ -154,9 +153,7 @@ def __init__( # pylint: disable=too-many-arguments self._raw_authmode = raw_authmode def _get_response(self, cmd): - respose = self._esp_spi_control._send_command_get_response( # pylint: disable=protected-access - cmd, [b"\xFF"] - ) + respose = self._esp_spi_control._send_command_get_response(cmd, [b"\xff"]) return respose[0] @property @@ -221,7 +218,7 @@ def authmode(self): return "UNKNOWN" -class ESP_SPIcontrol: # pylint: disable=too-many-public-methods, too-many-instance-attributes +class ESP_SPIcontrol: """A class that will talk to an ESP32 module programmed with special firmware that lets it act as a fast an efficient WiFi co-processor""" @@ -229,7 +226,6 @@ class ESP_SPIcontrol: # pylint: disable=too-many-public-methods, too-many-insta UDP_MODE = const(1) TLS_MODE = const(2) - # pylint: disable=too-many-arguments def __init__( self, spi, @@ -297,7 +293,6 @@ def _wait_for_ready(self): if self._debug >= 3: print() - # pylint: disable=too-many-branches def _send_command(self, cmd, params=None, *, param_len_16=False): """Send over a command with a list of parameters""" if not params: @@ -342,14 +337,10 @@ def _send_command(self, cmd, params=None, *, param_len_16=False): break else: raise TimeoutError("ESP32 timed out on SPI select") - spi.write( - self._sendbuf, start=0, end=packet_len - ) # pylint: disable=no-member + spi.write(self._sendbuf, start=0, end=packet_len) if self._debug >= 3: print("Wrote: ", [hex(b) for b in self._sendbuf[0:packet_len]]) - # pylint: disable=too-many-branches - def _read_byte(self, spi): """Read one byte from SPI""" spi.readinto(self._pbuf) @@ -380,7 +371,7 @@ def _check_data(self, spi, desired): """Read a byte and verify its the value we want""" r = self._read_byte(spi) if r != desired: - raise BrokenPipeError("Expected %02X but got %02X" % (desired, r)) + raise BrokenPipeError(f"Expected {desired:02X} but got {r:02X}") def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False): """Wait for ready, then parse the response""" @@ -417,7 +408,7 @@ def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False): print("Read %d: " % len(responses[0]), responses) return responses - def _send_command_get_response( # pylint: disable=too-many-arguments + def _send_command_get_response( self, cmd, params=None, @@ -428,9 +419,7 @@ def _send_command_get_response( # pylint: disable=too-many-arguments ): """Send a high level SPI command, wait and return the response""" self._send_command(cmd, params, param_len_16=sent_param_len_16) - return self._wait_response_cmd( - cmd, reply_params, param_len_16=recv_param_len_16 - ) + return self._wait_response_cmd(cmd, reply_params, param_len_16=recv_param_len_16) @property def status(self): @@ -452,15 +441,15 @@ def firmware_version(self): return resp[0].decode("utf-8").replace("\x00", "") @property - def MAC_address(self): # pylint: disable=invalid-name + def MAC_address(self): """A bytearray containing the MAC address of the ESP32""" if self._debug: print("MAC address") - resp = self._send_command_get_response(_GET_MACADDR_CMD, [b"\xFF"]) + resp = self._send_command_get_response(_GET_MACADDR_CMD, [b"\xff"]) return resp[0] @property - def MAC_address_actual(self): # pylint: disable=invalid-name + def MAC_address_actual(self): """A bytearray containing the actual MAC address of the ESP32""" return bytearray(reversed(self.MAC_address)) @@ -485,7 +474,7 @@ def get_scan_networks(self): self._send_command(_SCAN_NETWORKS) names = self._wait_response_cmd(_SCAN_NETWORKS) # print("SSID names:", names) - APs = [] # pylint: disable=invalid-name + APs = [] for i, name in enumerate(names): bssid = self._send_command_get_response(_GET_IDX_BSSID_CMD, ((i,),))[0] rssi = self._send_command_get_response(_GET_IDX_RSSI_CMD, ((i,),))[0] @@ -509,13 +498,13 @@ def scan_networks(self): self.start_scan_networks() for _ in range(10): # attempts time.sleep(2) - APs = self.get_scan_networks() # pylint: disable=invalid-name + APs = self.get_scan_networks() if APs: return APs return None def set_ip_config(self, ip_address, gateway, mask="255.255.255.0"): - """Tells the ESP32 to set ip, gateway and network mask b"\xFF" + """Tells the ESP32 to set ip, gateway and network mask b"\xff" :param str ip_address: IP address (as a string). :param str gateway: Gateway (as a string). @@ -598,9 +587,7 @@ def _wifi_set_ap_network(self, ssid, channel): def _wifi_set_ap_passphrase(self, ssid, passphrase, channel): """Creates an Access point with SSID, passphrase, and Channel""" - resp = self._send_command_get_response( - _SET_AP_PASSPHRASE_CMD, [ssid, passphrase, channel] - ) + resp = self._send_command_get_response(_SET_AP_PASSPHRASE_CMD, [ssid, passphrase, channel]) if resp[0][0] != 1: raise OSError("Failed to setup AP password") @@ -616,9 +603,7 @@ def ap_info(self): def network_data(self): """A dictionary containing current connection details such as the 'ip_addr', 'netmask' and 'gateway'""" - resp = self._send_command_get_response( - _GET_IPADDR_CMD, [b"\xFF"], reply_params=3 - ) + resp = self._send_command_get_response(_GET_IPADDR_CMD, [b"\xff"], reply_params=3) return {"ip_addr": resp[0], "netmask": resp[1], "gateway": resp[2]} @property @@ -671,7 +656,7 @@ def connect(self, ssid, password=None, timeout=10): ssid, password = ssid["ssid"], ssid.get("password") self.connect_AP(ssid, password, timeout_s=timeout) - def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-name + def connect_AP(self, ssid, password, timeout_s=10): """Connect to an access point with given name and password. Will wait until specified timeout seconds and return on success or raise an exception on failure. @@ -699,15 +684,13 @@ def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-n if stat == WL_CONNECTED: return stat time.sleep(0.05) - if stat in (WL_CONNECT_FAILED, WL_CONNECTION_LOST, WL_DISCONNECTED): + if stat in {WL_CONNECT_FAILED, WL_CONNECTION_LOST, WL_DISCONNECTED}: raise ConnectionError("Failed to connect to ssid", ssid) if stat == WL_NO_SSID_AVAIL: raise ConnectionError("No such ssid", ssid) - raise OSError("Unknown error 0x%02X" % stat) + raise OSError(f"Unknown error 0x{stat:02X}") - def create_AP( - self, ssid, password, channel=1, timeout=10 - ): # pylint: disable=invalid-name + def create_AP(self, ssid, password, channel=1, timeout=10): """Create an access point with the given name, password, and channel. Will wait until specified timeout seconds and return on success or raise an exception on failure. @@ -743,18 +726,18 @@ def create_AP( time.sleep(0.05) if stat == WL_AP_FAILED: raise ConnectionError("Failed to create AP", ssid) - raise OSError("Unknown error 0x%02x" % stat) + raise OSError(f"Unknown error 0x{stat:02x}") @property def ipv4_address(self): """IP address of the station when connected to an access point.""" return self.pretty_ip(self.ip_address) - def pretty_ip(self, ip): # pylint: disable=no-self-use, invalid-name + def pretty_ip(self, ip): # noqa: PLR6301 """Converts a bytearray IP address to a dotted-quad string for printing""" - return "%d.%d.%d.%d" % (ip[0], ip[1], ip[2], ip[3]) + return f"{ip[0]}.{ip[1]}.{ip[2]}.{ip[3]}" - def unpretty_ip(self, ip): # pylint: disable=no-self-use, invalid-name + def unpretty_ip(self, ip): # noqa: PLR6301 """Converts a dotted-quad string to a bytearray IP address""" octets = [int(x) for x in ip.split(".")] return bytes(octets) @@ -834,9 +817,7 @@ def socket_status(self, socket_num): SOCKET_FIN_WAIT_2, SOCKET_CLOSE_WAIT, SOCKET_CLOSING, SOCKET_LAST_ACK, or SOCKET_TIME_WAIT""" self._socknum_ll[0][0] = socket_num - resp = self._send_command_get_response( - _GET_CLIENT_STATE_TCP_CMD, self._socknum_ll - ) + resp = self._send_command_get_response(_GET_CLIENT_STATE_TCP_CMD, self._socknum_ll) return resp[0][0] def socket_connected(self, socket_num): @@ -867,9 +848,7 @@ def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): if conn_mode == self.UDP_MODE: # UDP verifies chunks on write, not bytes if sent != total_chunks: - raise ConnectionError( - "Failed to write %d chunks (sent %d)" % (total_chunks, sent) - ) + raise ConnectionError("Failed to write %d chunks (sent %d)" % (total_chunks, sent)) # UDP needs to finalize with this command, does the actual sending resp = self._send_command_get_response(_SEND_UDP_DATA_CMD, self._socknum_ll) if resp[0][0] != 1: @@ -878,9 +857,7 @@ def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): if sent != len(buffer): self.socket_close(socket_num) - raise ConnectionError( - "Failed to send %d bytes (sent %d)" % (len(buffer), sent) - ) + raise ConnectionError("Failed to send %d bytes (sent %d)" % (len(buffer), sent)) resp = self._send_command_get_response(_DATA_SENT_TCP_CMD, self._socknum_ll) if resp[0][0] != 1: @@ -945,9 +922,7 @@ def socket_close(self, socket_num): if socket_num == self._tls_socket: self._tls_socket = None - def start_server( - self, port, socket_num, conn_mode=TCP_MODE, ip=None - ): # pylint: disable=invalid-name + def start_server(self, port, socket_num, conn_mode=TCP_MODE, ip=None): # pylint: disable=invalid-name """Opens a server on the specified port, using the ESP32's internal reference number""" if self._debug: print("*** starting server") @@ -1003,9 +978,7 @@ def set_digital_write(self, pin, value): :param int pin: ESP32 GPIO pin to write to. :param bool value: Value for the pin. """ - resp = self._send_command_get_response( - _SET_DIGITAL_WRITE_CMD, ((pin,), (value,)) - ) + resp = self._send_command_get_response(_SET_DIGITAL_WRITE_CMD, ((pin,), (value,))) if resp[0][0] != 1: raise OSError("Failed to write to pin") @@ -1016,9 +989,7 @@ def set_analog_write(self, pin, analog_value): :param float value: 0=off 1.0=full on """ value = int(255 * analog_value) - resp = self._send_command_get_response( - _SET_ANALOG_WRITE_CMD, ((pin,), (value,)) - ) + resp = self._send_command_get_response(_SET_ANALOG_WRITE_CMD, ((pin,), (value,))) if resp[0][0] != 1: raise OSError("Failed to write to pin") @@ -1036,9 +1007,7 @@ def set_digital_read(self, pin): return False if resp[0] == 1: return True - raise OSError( - "_SET_DIGITAL_READ response error: response is not boolean", resp[0] - ) + raise OSError("_SET_DIGITAL_READ response error: response is not boolean", resp[0]) def set_analog_read(self, pin, atten=ADC_ATTEN_DB_11): """Get the analog input value of pin. Returns an int between 0 and 65536. @@ -1053,9 +1022,7 @@ def set_analog_read(self, pin, atten=ADC_ATTEN_DB_11): resp = self._send_command_get_response(_SET_ANALOG_READ_CMD, ((pin,), (atten,))) resp_analog = struct.unpack(" 0: bytes_to_read = min(num_to_read, len(self._buffer)) - buffer[num_read : num_read + bytes_to_read] = self._buffer[ - :bytes_to_read - ] + buffer[num_read : num_read + bytes_to_read] = self._buffer[:bytes_to_read] num_read += bytes_to_read num_to_read -= bytes_to_read self._buffer = self._buffer[bytes_to_read:] @@ -171,9 +168,7 @@ def recv_into(self, buffer, nbytes: int = 0): num_avail = self._available() if num_avail > 0: last_read_time = time.monotonic() - bytes_read = self._interface.socket_read( - self._socknum, min(num_to_read, num_avail) - ) + bytes_read = self._interface.socket_read(self._socknum, min(num_to_read, num_avail)) buffer[num_read : num_read + len(bytes_read)] = bytes_read num_read += len(bytes_read) num_to_read -= len(bytes_read) @@ -194,9 +189,7 @@ def settimeout(self, value): def _available(self): """Returns how many bytes of data are available to be read (up to the MAX_PACKET length)""" if self._socknum != SocketPool.NO_SOCKET_AVAIL: - return min( - self._interface.socket_available(self._socknum), SocketPool.MAX_PACKET - ) + return min(self._interface.socket_available(self._socknum), SocketPool.MAX_PACKET) return 0 def _connected(self): @@ -206,7 +199,7 @@ def _connected(self): if self._available(): return True status = self._interface.socket_status(self._socknum) - result = status not in ( + result = status not in { esp32spi.SOCKET_LISTEN, esp32spi.SOCKET_CLOSED, esp32spi.SOCKET_FIN_WAIT_1, @@ -215,7 +208,7 @@ def _connected(self): esp32spi.SOCKET_SYN_SENT, esp32spi.SOCKET_SYN_RCVD, esp32spi.SOCKET_CLOSE_WAIT, - ) + } if not result: self.close() self._socknum = SocketPool.NO_SOCKET_AVAIL diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 4db7463..23c65b9 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -11,17 +11,16 @@ * Author(s): Melissa LeBlanc-Williams, ladyada """ -# pylint: disable=no-name-in-module - import warnings from time import sleep -from micropython import const + import adafruit_connection_manager import adafruit_requests +from micropython import const + from adafruit_esp32spi import adafruit_esp32spi -# pylint: disable=too-many-instance-attributes class WiFiManager: """ A class to help manage the Wifi connection @@ -30,7 +29,6 @@ class WiFiManager: NORMAL = const(1) ENTERPRISE = const(2) - # pylint: disable=too-many-arguments def __init__( self, esp, @@ -112,9 +110,7 @@ def connect(self): raise TypeError("Invalid WiFi connection type specified") def _get_next_ap(self): - if isinstance(self.ssid, (tuple, list)) and isinstance( - self.password, (tuple, list) - ): + if isinstance(self.ssid, (tuple, list)) and isinstance(self.password, (tuple, list)): if not self.ssid or not self.password: raise ValueError("SSID and Password should contain at least 1 value") if len(self.ssid) != len(self.password): @@ -124,9 +120,7 @@ def _get_next_ap(self): if self._ap_index >= len(self.ssid): self._ap_index = 0 return access_point - if isinstance(self.ssid, (tuple, list)) or isinstance( - self.password, (tuple, list) - ): + if isinstance(self.ssid, (tuple, list)) or isinstance(self.password, (tuple, list)): raise NotImplementedError( "If using multiple passwords, both SSID and Password should be lists or tuples" ) @@ -168,9 +162,7 @@ def create_ap(self): print("Waiting for AP to be initialized...") self.pixel_status((100, 0, 0)) if self.password: - self.esp.create_AP( - bytes(self.ssid, "utf-8"), bytes(self.password, "utf-8") - ) + self.esp.create_AP(bytes(self.ssid, "utf-8"), bytes(self.password, "utf-8")) else: self.esp.create_AP(bytes(self.ssid, "utf-8"), None) failure_count = 0 @@ -182,7 +174,7 @@ def create_ap(self): failure_count = 0 self.reset() continue - print("Access Point created! Connect to ssid:\n {}".format(self.ssid)) + print(f"Access Point created! Connect to ssid:\n {self.ssid}") def connect_enterprise(self): """ @@ -197,9 +189,7 @@ def connect_enterprise(self): while not self.esp.is_connected: try: if self.debug: - print( - "Waiting for the ESP32 to connect to the WPA2 Enterprise AP..." - ) + print("Waiting for the ESP32 to connect to the WPA2 Enterprise AP...") self.pixel_status((100, 0, 0)) sleep(1) failure_count = 0 @@ -356,13 +346,11 @@ def signal_strength(self): return self.esp.ap_info.rssi -# pylint: disable=too-many-instance-attributes class ESPSPI_WiFiManager(WiFiManager): """ A legacy class to help manage the Wifi connection. Please update to using WiFiManager """ - # pylint: disable=too-many-arguments def __init__( self, esp, diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index e934f2c..a9ee458 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -13,6 +13,7 @@ https://github.com/adafruit/Adafruit_Blinka/blob/master/src/adafruit_blinka/microcontroller/bcm283x/pin.py https://github.com/adafruit/Adafruit_Blinka/blob/master/src/digitalio.py """ + from micropython import const @@ -28,7 +29,6 @@ class Pin: or the use of internal pull-up resistors. """ - # pylint: disable=invalid-name IN = const(0x00) OUT = const(0x01) LOW = const(0x00) @@ -78,15 +78,12 @@ def value(self, val=None): else: raise ValueError("Invalid value for pin") else: - raise NotImplementedError( - "digitalRead not currently implemented in esp32spi" - ) + raise NotImplementedError("digitalRead not currently implemented in esp32spi") def __repr__(self): return str(self.pin_id) -# pylint: disable = too-few-public-methods class DriveMode: """DriveMode Enum.""" @@ -118,7 +115,6 @@ class DigitalInOut: _pin = None - # pylint: disable = attribute-defined-outside-init def __init__(self, esp, pin): self._esp = esp self._pin = Pin(pin, self._esp) @@ -149,9 +145,7 @@ def switch_to_input(self, pull=None): :param Pull pull: Pull configuration for the input. """ - raise NotImplementedError( - "Digital reads are not currently supported in ESP32SPI." - ) + raise NotImplementedError("Digital reads are not currently supported in ESP32SPI.") @property def direction(self): @@ -207,8 +201,6 @@ def drive_mode(self, mode): Either PUSH_PULL or OPEN_DRAIN """ if mode is DriveMode.OPEN_DRAIN: - raise NotImplementedError( - "Drive mode %s not implemented in ESP32SPI." % mode - ) + raise NotImplementedError("Drive mode %s not implemented in ESP32SPI." % mode) if mode is DriveMode.PUSH_PULL: self._pin.init(mode=Pin.OUT) diff --git a/docs/api.rst b/docs/api.rst index 7726cc1..4ac85a9 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -4,6 +4,9 @@ .. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py) .. use this format as the module name: "adafruit_foo.foo" +API Reference +############# + .. automodule:: adafruit_esp32spi.adafruit_esp32spi :members: diff --git a/docs/conf.py b/docs/conf.py index fa88890..4040956 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,12 +1,10 @@ -# -*- coding: utf-8 -*- - # SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries # # SPDX-License-Identifier: MIT +import datetime import os import sys -import datetime sys.path.insert(0, os.path.abspath("..")) @@ -52,9 +50,7 @@ creation_year = "2019" current_year = str(datetime.datetime.now().year) year_duration = ( - current_year - if current_year == creation_year - else creation_year + " - " + current_year + current_year if current_year == creation_year else creation_year + " - " + current_year ) copyright = year_duration + " ladyada" author = "ladyada" diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index 9438856..8be7e35 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -3,10 +3,12 @@ import time from os import getenv + import board import busio -from digitalio import DigitalInOut import neopixel +from digitalio import DigitalInOut + from adafruit_esp32spi import adafruit_esp32spi from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager @@ -60,11 +62,7 @@ feed = "test" payload = {"value": data} response = wifi.post( - "https://io.adafruit.com/api/v2/" - + aio_username - + "/feeds/" - + feed - + "/data", + "https://io.adafruit.com/api/v2/" + aio_username + "/feeds/" + feed + "/data", json=payload, headers={"X-AIO-KEY": aio_key}, ) diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index 735dd4a..ca74e90 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -3,12 +3,12 @@ import time from os import getenv + +import adafruit_fancyled.adafruit_fancyled as fancy import board import busio -from digitalio import DigitalInOut - import neopixel -import adafruit_fancyled.adafruit_fancyled as fancy +from digitalio import DigitalInOut from adafruit_esp32spi import adafruit_esp32spi from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index dec0f3a..36b8b8b 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -3,9 +3,11 @@ import time from os import getenv + import board import busio from digitalio import DigitalInOut + import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool from adafruit_esp32spi import adafruit_esp32spi diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index 53f8efa..0157864 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -3,11 +3,13 @@ import time from os import getenv + import board import busio -from digitalio import DigitalInOut import neopixel import rtc +from digitalio import DigitalInOut + from adafruit_esp32spi import adafruit_esp32spi from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager @@ -66,18 +68,16 @@ json = response.json() current_time = json["datetime"] the_date, the_time = current_time.split("T") -year, month, mday = [int(x) for x in the_date.split("-")] +year, month, mday = (int(x) for x in the_date.split("-")) the_time = the_time.split(".")[0] -hours, minutes, seconds = [int(x) for x in the_time.split(":")] +hours, minutes, seconds = (int(x) for x in the_time.split(":")) # We can also fill in these extra nice things year_day = json["day_of_year"] week_day = json["day_of_week"] is_dst = json["dst"] -now = time.struct_time( - (year, month, mday, hours, minutes, seconds, week_day, year_day, is_dst) -) +now = time.struct_time((year, month, mday, hours, minutes, seconds, week_day, year_day, is_dst)) print(now) the_rtc.datetime = now diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index 57a521e..2124991 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -2,11 +2,13 @@ # SPDX-License-Identifier: MIT from os import getenv + +import adafruit_connection_manager +import adafruit_requests import board import busio from digitalio import DigitalInOut -import adafruit_connection_manager -import adafruit_requests + from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file @@ -69,9 +71,7 @@ continue print("Connected to", esp.ap_info.ssid, "\tRSSI:", esp.ap_info.rssi) print("My IP address is", esp.ipv4_address) -print( - "IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com")) -) +print("IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com"))) print("Ping google.com: %d ms" % esp.ping("google.com")) # esp._debug = True diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index 5a17106..aab6776 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -2,11 +2,13 @@ # SPDX-License-Identifier: MIT from os import getenv + +import adafruit_connection_manager +import adafruit_requests import board import busio from digitalio import DigitalInOut -import adafruit_connection_manager -import adafruit_requests + from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file @@ -48,9 +50,7 @@ continue print("Connected to", esp.ap_info.ssid, "\tRSSI:", esp.ap_info.rssi) print("My IP address is", esp.ipv4_address) -print( - "IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com")) -) +print("IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com"))) print("Ping google.com: %d ms" % esp.ping("google.com")) # esp._debug = True diff --git a/examples/esp32spi_tcp_client.py b/examples/esp32spi_tcp_client.py index 275c1ce..f781cb9 100644 --- a/examples/esp32spi_tcp_client.py +++ b/examples/esp32spi_tcp_client.py @@ -2,11 +2,13 @@ # SPDX-License-Identifier: MIT from os import getenv + import board import busio from digitalio import DigitalInOut -from adafruit_esp32spi import adafruit_esp32spi + import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool +from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD @@ -21,11 +23,10 @@ # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +elif "SPI" in dir(board): + spi = board.SPI() else: - if "SPI" in dir(board): - spi = board.SPI() - else: - spi = busio.SPI(board.SCK, board.MOSI, board.MISO) + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) # PyPortal or similar; edit pins as needed esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) diff --git a/examples/esp32spi_udp_client.py b/examples/esp32spi_udp_client.py index 2321c03..b1226f9 100644 --- a/examples/esp32spi_udp_client.py +++ b/examples/esp32spi_udp_client.py @@ -4,11 +4,13 @@ import struct import time from os import getenv + import board import busio from digitalio import DigitalInOut -from adafruit_esp32spi import adafruit_esp32spi + import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool +from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD @@ -24,11 +26,10 @@ # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) +elif "SPI" in dir(board): + spi = board.SPI() else: - if "SPI" in dir(board): - spi = board.SPI() - else: - spi = busio.SPI(board.SCK, board.MOSI, board.MISO) + spi = busio.SPI(board.SCK, board.MOSI, board.MISO) # PyPortal or similar; edit pins as needed esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index d9f62d1..78e56a2 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -3,10 +3,12 @@ import time from os import getenv + import board import busio -from digitalio import DigitalInOut import neopixel +from digitalio import DigitalInOut + from adafruit_esp32spi import adafruit_esp32spi from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager @@ -74,11 +76,7 @@ feed = "test" payload = {"value": data} response = wifi.post( - "https://io.adafruit.com/api/v2/" - + aio_username - + "/feeds/" - + feed - + "/data", + "https://io.adafruit.com/api/v2/" + aio_username + "/feeds/" + feed + "/data", json=payload, headers={"X-AIO-KEY": aio_key}, ) diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index db5019f..f4b648e 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -11,11 +11,13 @@ import re import time + +import adafruit_connection_manager +import adafruit_requests import board import busio from digitalio import DigitalInOut -import adafruit_connection_manager -import adafruit_requests + from adafruit_esp32spi import adafruit_esp32spi @@ -26,9 +28,7 @@ def version_compare(version1, version2): def normalize(v): return [int(x) for x in re.sub(r"(\.0+)*$", "", v).split(".")] - return (normalize(version1) > normalize(version2)) - ( - normalize(version1) < normalize(version2) - ) + return (normalize(version1) > normalize(version2)) - (normalize(version1) < normalize(version2)) print("ESP32 SPI WPA2 Enterprise test") @@ -98,9 +98,7 @@ def normalize(v): print("") print("Connected to", esp.ap_info.ssid, "\tRSSI:", esp.ap_info.rssi) print("My IP address is", esp.ipv4_address) -print( - "IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com")) -) +print("IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com"))) print("Ping google.com: %d ms" % esp.ping("google.com")) print("Done!") diff --git a/examples/gpio/esp32spi_gpio.py b/examples/gpio/esp32spi_gpio.py index b257eb8..91a0fd0 100644 --- a/examples/gpio/esp32spi_gpio.py +++ b/examples/gpio/esp32spi_gpio.py @@ -2,13 +2,14 @@ # # SPDX-License-Identifier: MIT -import time import random +import time + import board -from digitalio import DigitalInOut, Direction import pulseio -from adafruit_esp32spi import adafruit_esp32spi +from digitalio import DigitalInOut, Direction +from adafruit_esp32spi import adafruit_esp32spi # ESP32SPI Digital and Analog Pin Reads & Writes @@ -69,11 +70,7 @@ def esp_init_pin_modes(din, dout): print("ESP32 Firmware:", esp.firmware_version) -print( - "ESP32 MAC: {5:02X}:{4:02X}:{3:02X}:{2:02X}:{1:02X}:{0:02X}".format( - *esp.MAC_address - ) -) +print("ESP32 MAC: {5:02X}:{4:02X}:{3:02X}:{2:02X}:{1:02X}:{0:02X}".format(*esp.MAC_address)) # initial digital write values m4_d_w_val = False @@ -113,7 +110,7 @@ def esp_init_pin_modes(din, dout): "Potentiometer --> ESP read: ", esp_a_r_val, " (", - "{:1.1f}".format(esp_a_r_val * 3.3 / 65536), + f"{esp_a_r_val * 3.3 / 65536:1.1f}", "v)", sep="", ) @@ -128,12 +125,12 @@ def esp_init_pin_modes(din, dout): esp.set_analog_write(ESP_A_W_PIN, esp_a_w_val) print( "ESP wrote: ", - "{:1.2f}".format(esp_a_w_val), + f"{esp_a_w_val:1.2f}", " (", - "{:d}".format(int(esp_a_w_val * 65536)), + f"{int(esp_a_w_val * 65536):d}", ")", " (", - "{:1.1f}".format(esp_a_w_val * 3.3), + f"{esp_a_w_val * 3.3:1.1f}", "v)", sep="", end=" ", @@ -149,12 +146,12 @@ def esp_init_pin_modes(din, dout): duty = M4_A_R_PIN[0] / (M4_A_R_PIN[0] + M4_A_R_PIN[1]) print( "--> M4 read: ", - "{:1.2f}".format(duty), + f"{duty:1.2f}", " (", - "{:d}".format(int(duty * 65536)), + f"{int(duty * 65536):d}", ")", " (", - "{:1.1f}".format(duty * 3.3), + f"{duty * 3.3:1.1f}", "v)", " [len=", len(M4_A_R_PIN), diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..36332ff --- /dev/null +++ b/ruff.toml @@ -0,0 +1,105 @@ +# SPDX-FileCopyrightText: 2024 Tim Cocks for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +target-version = "py38" +line-length = 100 + +[lint] +preview = true +select = ["I", "PL", "UP"] + +extend-select = [ + "D419", # empty-docstring + "E501", # line-too-long + "W291", # trailing-whitespace + "PLC0414", # useless-import-alias + "PLC2401", # non-ascii-name + "PLC2801", # unnecessary-dunder-call + "PLC3002", # unnecessary-direct-lambda-call + "E999", # syntax-error + "PLE0101", # return-in-init + "F706", # return-outside-function + "F704", # yield-outside-function + "PLE0116", # continue-in-finally + "PLE0117", # nonlocal-without-binding + "PLE0241", # duplicate-bases + "PLE0302", # unexpected-special-method-signature + "PLE0604", # invalid-all-object + "PLE0605", # invalid-all-format + "PLE0643", # potential-index-error + "PLE0704", # misplaced-bare-raise + "PLE1141", # dict-iter-missing-items + "PLE1142", # await-outside-async + "PLE1205", # logging-too-many-args + "PLE1206", # logging-too-few-args + "PLE1307", # bad-string-format-type + "PLE1310", # bad-str-strip-call + "PLE1507", # invalid-envvar-value + "PLE2502", # bidirectional-unicode + "PLE2510", # invalid-character-backspace + "PLE2512", # invalid-character-sub + "PLE2513", # invalid-character-esc + "PLE2514", # invalid-character-nul + "PLE2515", # invalid-character-zero-width-space + "PLR0124", # comparison-with-itself + "PLR0202", # no-classmethod-decorator + "PLR0203", # no-staticmethod-decorator + "UP004", # useless-object-inheritance + "PLR0206", # property-with-parameters + "PLR0904", # too-many-public-methods + "PLR0911", # too-many-return-statements + "PLR0912", # too-many-branches + "PLR0913", # too-many-arguments + "PLR0914", # too-many-locals + "PLR0915", # too-many-statements + "PLR0916", # too-many-boolean-expressions + "PLR1702", # too-many-nested-blocks + "PLR1704", # redefined-argument-from-local + "PLR1711", # useless-return + "C416", # unnecessary-comprehension + "PLR1733", # unnecessary-dict-index-lookup + "PLR1736", # unnecessary-list-index-lookup + + # ruff reports this rule is unstable + #"PLR6301", # no-self-use + + "PLW0108", # unnecessary-lambda + "PLW0120", # useless-else-on-loop + "PLW0127", # self-assigning-variable + "PLW0129", # assert-on-string-literal + "B033", # duplicate-value + "PLW0131", # named-expr-without-context + "PLW0245", # super-without-brackets + "PLW0406", # import-self + "PLW0602", # global-variable-not-assigned + "PLW0603", # global-statement + "PLW0604", # global-at-module-level + + # fails on the try: import typing used by libraries + #"F401", # unused-import + + "F841", # unused-variable + "E722", # bare-except + "PLW0711", # binary-op-exception + "PLW1501", # bad-open-mode + "PLW1508", # invalid-envvar-default + "PLW1509", # subprocess-popen-preexec-fn + "PLW2101", # useless-with-lock + "PLW3301", # nested-min-max +] + +ignore = [ + "PLR2004", # magic-value-comparison + "UP030", # format literals + "PLW1514", # unspecified-encoding + "PLR0913", # too-many-arguments + "PLR0915", # too-many-statements + "PLR0917", # too-many-positional-arguments + "PLR0904", # too-many-public-methods + "PLR0912", # too-many-branches + "PLR0916", # too-many-boolean-expressions +] + +[format] +line-ending = "lf" From 063b90c8706ddef97cc4abf9cb78e0cc09ff3c6c Mon Sep 17 00:00:00 2001 From: foamyguy Date: Wed, 4 Jun 2025 10:00:20 -0500 Subject: [PATCH 46/58] update rtd.yml file Signed-off-by: foamyguy --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 88bca9f..255dafd 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -12,7 +12,7 @@ sphinx: configuration: docs/conf.py build: - os: ubuntu-20.04 + os: ubuntu-lts-latest tools: python: "3" From d50d5d146f434bb49ff34d5a47216e982bfae4c0 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Wed, 22 Jan 2025 01:21:27 +0100 Subject: [PATCH 47/58] more compatible sockets: socket_write() and send() return the number of bytes sent add some of the constants used by httpserver (others missing) dummy entries for setsockopt(), listen() and setblocking() implement bind() by using ninafw start_server() implement accept() by getting a clien socket from that server add back socknum parameter to allow wrapping a Socket around a ninafw socket number, which is required to be able to receive a connection from the server --- adafruit_esp32spi/adafruit_esp32spi.py | 7 ++- .../adafruit_esp32spi_socketpool.py | 57 +++++++++++++++++-- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index f0ff6b6..03a4a66 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -825,7 +825,8 @@ def socket_connected(self, socket_num): return self.socket_status(socket_num) == SOCKET_ESTABLISHED def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): - """Write the bytearray buffer to a socket""" + """Write the bytearray buffer to a socket. + Returns the number of bytes written""" if self._debug: print("Writing:", buffer) self._socknum_ll[0][0] = socket_num @@ -853,7 +854,7 @@ def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): resp = self._send_command_get_response(_SEND_UDP_DATA_CMD, self._socknum_ll) if resp[0][0] != 1: raise ConnectionError("Failed to send UDP data") - return + return sent if sent != len(buffer): self.socket_close(socket_num) @@ -863,6 +864,8 @@ def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): if resp[0][0] != 1: raise ConnectionError("Failed to verify data sent") + return sent + def socket_available(self, socket_num): """Determine how many bytes are waiting to be read on the socket""" self._socknum_ll[0][0] = socket_num diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 91615dc..ff8821f 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -36,11 +36,15 @@ class SocketPool: """ESP32SPI SocketPool library""" - SOCK_STREAM = const(0) - SOCK_DGRAM = const(1) + # socketpool constants + SOCK_STREAM = const(1) + SOCK_DGRAM = const(2) AF_INET = const(2) - NO_SOCKET_AVAIL = const(255) + SOL_SOCKET = const(0xfff) + SO_REUSEADDR = const(0x0004) + # implementation specific constants + NO_SOCKET_AVAIL = const(255) MAX_PACKET = const(4000) def __new__(cls, iface: ESP_SPIcontrol): @@ -82,6 +86,7 @@ def __init__( type: int = SocketPool.SOCK_STREAM, proto: int = 0, fileno: Optional[int] = None, # noqa: UP007 + socknum: Optional[int] = None, # noqa: UP007 ): if family != SocketPool.AF_INET: raise ValueError("Only AF_INET family supported") @@ -89,7 +94,7 @@ def __init__( self._interface = self._socket_pool._interface self._type = type self._buffer = b"" - self._socknum = self._interface.get_socket() + self._socknum = socknum if socknum is not None else self._interface.get_socket() self.settimeout(0) def __enter__(self): @@ -121,13 +126,14 @@ def send(self, data): conntype = self._interface.UDP_MODE else: conntype = self._interface.TCP_MODE - self._interface.socket_write(self._socknum, data, conn_mode=conntype) + sent = self._interface.socket_write(self._socknum, data, conn_mode=conntype) gc.collect() + return sent def sendto(self, data, address): """Connect and send some data to the socket.""" self.connect(address) - self.send(data) + return self.send(data) def recv(self, bufsize: int) -> bytes: """Reads some bytes from the connected remote address. Will only return @@ -217,3 +223,42 @@ def _connected(self): def close(self): """Close the socket, after reading whatever remains""" self._interface.socket_close(self._socknum) + + #################################################################### + # WORK IN PROGRESS + #################################################################### + + def setsockopt(self, *opts, **kwopts): + """Dummy call for compatibility.""" + # FIXME + pass + + def listen(self, backlog): + """Dummy call for compatibility.""" + # FIXME + # probably nothing to do actually + # maybe check that we have called bind or something ? + pass + + def setblocking(self, blocking): + """Dummy call for compatibility.""" + # FIXME + # is this settimeout(0) ? (if True) or something else ? + pass + + def bind(self, host_port): + host, port = host_port + self._interface.start_server(port, self._socknum) + print(f"Binding to {self._socknum}") + + def accept(self): + client_sock_num = self._interface.socket_available(self._socknum) + if client_sock_num != SocketPool.NO_SOCKET_AVAIL: + sock = Socket(self._socket_pool, socknum=client_sock_num) + # get remote information (addr and port) + remote = self._interface.get_remote_data(client_sock_num) + IP_ADDRESS = "{}.{}.{}.{}".format(*remote['ip_addr']) + PORT = remote['port'] + client_address = (IP_ADDRESS, PORT) + return sock, client_address + raise OSError(errno.ECONNRESET) From d2d7ac3b9baff66d7e83f0feb3efd19a26fcf93f Mon Sep 17 00:00:00 2001 From: Neradoc Date: Wed, 22 Jan 2025 03:02:07 +0100 Subject: [PATCH 48/58] use time.monotonic_ns() to measure timeouts re-implement timeout similar to Circuitpython (None blocks, 0 doesn't) NOTE: this is a breaking change for any code that uses it bind() saves the bound address and port listen() uses the saved address and port or uses defaults some fixes for pylint/black --- .../adafruit_esp32spi_socketpool.py | 79 ++++++++++++------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index ff8821f..3bab399 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -14,7 +14,7 @@ from __future__ import annotations try: - from typing import TYPE_CHECKING, Optional + from typing import TYPE_CHECKING, Optional, Tuple if TYPE_CHECKING: from esp32spi.adafruit_esp32spi import ESP_SPIcontrol # noqa: UP007 @@ -40,7 +40,7 @@ class SocketPool: SOCK_STREAM = const(1) SOCK_DGRAM = const(2) AF_INET = const(2) - SOL_SOCKET = const(0xfff) + SOL_SOCKET = const(0xFFF) SO_REUSEADDR = const(0x0004) # implementation specific constants @@ -95,6 +95,7 @@ def __init__( self._type = type self._buffer = b"" self._socknum = socknum if socknum is not None else self._interface.get_socket() + self._bound = () self.settimeout(0) def __enter__(self): @@ -156,12 +157,12 @@ def recv_into(self, buffer, nbytes: int = 0): if not 0 <= nbytes <= len(buffer): raise ValueError("nbytes must be 0 to len(buffer)") - last_read_time = time.monotonic() + last_read_time = time.monotonic_ns() num_to_read = len(buffer) if nbytes == 0 else nbytes num_read = 0 while num_to_read > 0: # we might have read socket data into the self._buffer with: - # esp32spi_wsgiserver: socket_readline + # adafruit_wsgi.esp32spi_wsgiserver: socket_readline if len(self._buffer) > 0: bytes_to_read = min(num_to_read, len(self._buffer)) buffer[num_read : num_read + bytes_to_read] = self._buffer[:bytes_to_read] @@ -173,8 +174,10 @@ def recv_into(self, buffer, nbytes: int = 0): num_avail = self._available() if num_avail > 0: - last_read_time = time.monotonic() - bytes_read = self._interface.socket_read(self._socknum, min(num_to_read, num_avail)) + last_read_time = time.monotonic_ns() + bytes_read = self._interface.socket_read( + self._socknum, min(num_to_read, num_avail) + ) buffer[num_read : num_read + len(bytes_read)] = bytes_read num_read += len(bytes_read) num_to_read -= len(bytes_read) @@ -182,15 +185,27 @@ def recv_into(self, buffer, nbytes: int = 0): # We got a message, but there are no more bytes to read, so we can stop. break # No bytes yet, or more bytes requested. - if self._timeout > 0 and time.monotonic() - last_read_time > self._timeout: + + if self._timeout == 0: # if in non-blocking mode, stop now. + break + + # Time out if there's a positive timeout set. + delta = (time.monotonic_ns() - last_read_time) // 1_000_000 + if self._timeout > 0 and delta > self._timeout: raise OSError(errno.ETIMEDOUT) return num_read def settimeout(self, value): - """Set the read timeout for sockets. - If value is 0 socket reads will block until a message is available. + """Set the read timeout for sockets in seconds. + ``0`` means non-blocking. ``None`` means block indefinitely. """ - self._timeout = value + if value is None: + self._timeout = -1 + else: + if value < 0: + raise ValueError("Timeout cannot be a negative number") + # internally in milliseconds as an int + self._timeout = int(value * 1000) def _available(self): """Returns how many bytes of data are available to be read (up to the MAX_PACKET length)""" @@ -230,35 +245,41 @@ def close(self): def setsockopt(self, *opts, **kwopts): """Dummy call for compatibility.""" - # FIXME - pass - def listen(self, backlog): - """Dummy call for compatibility.""" - # FIXME - # probably nothing to do actually - # maybe check that we have called bind or something ? - pass + def setblocking(self, flag: bool): + """Set the blocking behaviour of this socket. + :param bool flag: False means non-blocking, True means block indefinitely. + """ + if flag: + self.settimeout(None) + else: + self.settimeout(0) - def setblocking(self, blocking): - """Dummy call for compatibility.""" - # FIXME - # is this settimeout(0) ? (if True) or something else ? - pass + def bind(self, address: Tuple[str, int]): + """Bind a socket to an address""" + self._bound = address - def bind(self, host_port): - host, port = host_port + def listen(self, backlog: int): # pylint: disable=unused-argument + """Set socket to listen for incoming connections. + :param int backlog: length of backlog queue for waiting connections (ignored) + """ + if not self._bound: + self._bound = (self._interface.ip_address, 80) + port = self._bound[1] self._interface.start_server(port, self._socknum) - print(f"Binding to {self._socknum}") def accept(self): + """Accept a connection on a listening socket of type SOCK_STREAM, + creating a new socket of type SOCK_STREAM. Returns a tuple of + (new_socket, remote_address) + """ client_sock_num = self._interface.socket_available(self._socknum) if client_sock_num != SocketPool.NO_SOCKET_AVAIL: sock = Socket(self._socket_pool, socknum=client_sock_num) # get remote information (addr and port) remote = self._interface.get_remote_data(client_sock_num) - IP_ADDRESS = "{}.{}.{}.{}".format(*remote['ip_addr']) - PORT = remote['port'] - client_address = (IP_ADDRESS, PORT) + ip_address = "{}.{}.{}.{}".format(*remote["ip_addr"]) + port = remote["port"] + client_address = (ip_address, port) return sock, client_address raise OSError(errno.ECONNRESET) From 07d74d492b02dac56c5731cfc250225e106b7763 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Wed, 22 Jan 2025 03:15:04 +0100 Subject: [PATCH 49/58] docstring --- adafruit_esp32spi/adafruit_esp32spi_socketpool.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 3bab399..7e72513 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -77,7 +77,13 @@ def socket( class Socket: """A simplified implementation of the Python 'socket' class, for connecting - through an interface to a remote device""" + through an interface to a remote device. Has properties specific to the + implementation. + + :param SocketPool socket_pool: The underlying socket pool. + :param Optional[int] socknum: Allows wrapping a Socket instance around a socket + number returned by the nina firmware. Used internally. + """ def __init__( self, From 2c0221bd954ce41f99850b4222b0a3ecf9e5fb73 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Wed, 26 Feb 2025 01:26:37 +0100 Subject: [PATCH 50/58] arrange socket methods in alphabetical order --- .../adafruit_esp32spi_socketpool.py | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 7e72513..1d31eb3 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -249,17 +249,21 @@ def close(self): # WORK IN PROGRESS #################################################################### - def setsockopt(self, *opts, **kwopts): - """Dummy call for compatibility.""" - - def setblocking(self, flag: bool): - """Set the blocking behaviour of this socket. - :param bool flag: False means non-blocking, True means block indefinitely. + def accept(self): + """Accept a connection on a listening socket of type SOCK_STREAM, + creating a new socket of type SOCK_STREAM. Returns a tuple of + (new_socket, remote_address) """ - if flag: - self.settimeout(None) - else: - self.settimeout(0) + client_sock_num = self._interface.socket_available(self._socknum) + if client_sock_num != SocketPool.NO_SOCKET_AVAIL: + sock = Socket(self._socket_pool, socknum=client_sock_num) + # get remote information (addr and port) + remote = self._interface.get_remote_data(client_sock_num) + ip_address = "{}.{}.{}.{}".format(*remote["ip_addr"]) + port = remote["port"] + client_address = (ip_address, port) + return sock, client_address + raise OSError(errno.ECONNRESET) def bind(self, address: Tuple[str, int]): """Bind a socket to an address""" @@ -274,18 +278,14 @@ def listen(self, backlog: int): # pylint: disable=unused-argument port = self._bound[1] self._interface.start_server(port, self._socknum) - def accept(self): - """Accept a connection on a listening socket of type SOCK_STREAM, - creating a new socket of type SOCK_STREAM. Returns a tuple of - (new_socket, remote_address) + def setblocking(self, flag: bool): + """Set the blocking behaviour of this socket. + :param bool flag: False means non-blocking, True means block indefinitely. """ - client_sock_num = self._interface.socket_available(self._socknum) - if client_sock_num != SocketPool.NO_SOCKET_AVAIL: - sock = Socket(self._socket_pool, socknum=client_sock_num) - # get remote information (addr and port) - remote = self._interface.get_remote_data(client_sock_num) - ip_address = "{}.{}.{}.{}".format(*remote["ip_addr"]) - port = remote["port"] - client_address = (ip_address, port) - return sock, client_address - raise OSError(errno.ECONNRESET) + if flag: + self.settimeout(None) + else: + self.settimeout(0) + + def setsockopt(self, *opts, **kwopts): + """Dummy call for compatibility.""" From 91b5d0e744ee6584801de2a0c2b59aeefdb79f13 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Tue, 24 Jun 2025 18:57:26 +0200 Subject: [PATCH 51/58] ruffing ruff --- adafruit_esp32spi/adafruit_esp32spi_socketpool.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 1d31eb3..442fd8b 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -181,9 +181,7 @@ def recv_into(self, buffer, nbytes: int = 0): num_avail = self._available() if num_avail > 0: last_read_time = time.monotonic_ns() - bytes_read = self._interface.socket_read( - self._socknum, min(num_to_read, num_avail) - ) + bytes_read = self._interface.socket_read(self._socknum, min(num_to_read, num_avail)) buffer[num_read : num_read + len(bytes_read)] = bytes_read num_read += len(bytes_read) num_to_read -= len(bytes_read) @@ -265,7 +263,7 @@ def accept(self): return sock, client_address raise OSError(errno.ECONNRESET) - def bind(self, address: Tuple[str, int]): + def bind(self, address: tuple[str, int]): """Bind a socket to an address""" self._bound = address From 3fcea236876b05d09ebf95f43cec6016667ccf84 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Fri, 10 Oct 2025 16:18:40 -0500 Subject: [PATCH 52/58] remove deprecated ruff rule, workaround RTD theme property inline issue. Signed-off-by: foamyguy --- docs/_static/custom.css | 8 ++++++++ docs/conf.py | 3 +++ ruff.toml | 1 - 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 docs/_static/custom.css diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 0000000..d60cf4b --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,8 @@ +/* SPDX-FileCopyrightText: 2025 Sam Blenny + * SPDX-License-Identifier: MIT + */ + +/* Monkey patch the rtd theme to prevent horizontal stacking of short items + * see https://github.com/readthedocs/sphinx_rtd_theme/issues/1301 + */ +.py.property{display: block !important;} diff --git a/docs/conf.py b/docs/conf.py index 4040956..b354489 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -110,6 +110,9 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] +# Include extra css to work around rtd theme glitches +html_css_files = ["custom.css"] + # The name of an image file (relative to this directory) to use as a favicon of # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. diff --git a/ruff.toml b/ruff.toml index 36332ff..9811947 100644 --- a/ruff.toml +++ b/ruff.toml @@ -17,7 +17,6 @@ extend-select = [ "PLC2401", # non-ascii-name "PLC2801", # unnecessary-dunder-call "PLC3002", # unnecessary-direct-lambda-call - "E999", # syntax-error "PLE0101", # return-in-init "F706", # return-outside-function "F704", # yield-outside-function From fd8a4c1f488b23c14a4224d6a04993f2a3f0ab4e Mon Sep 17 00:00:00 2001 From: Neradoc Date: Mon, 10 Nov 2025 17:20:07 +0100 Subject: [PATCH 53/58] sockets in blocking mode by default Co-authored-by: Dan Halbert --- adafruit_esp32spi/adafruit_esp32spi_socketpool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index 442fd8b..d9d9609 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -102,7 +102,7 @@ def __init__( self._buffer = b"" self._socknum = socknum if socknum is not None else self._interface.get_socket() self._bound = () - self.settimeout(0) + self.settimeout(None) def __enter__(self): return self From 426af8b1d81320ab8a0741794acf0ade660ec9b1 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 11 Nov 2025 16:05:00 -0500 Subject: [PATCH 54/58] Remove "work in progress comment" --- adafruit_esp32spi/adafruit_esp32spi_socketpool.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py index d9d9609..b86ae4a 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socketpool.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socketpool.py @@ -243,10 +243,6 @@ def close(self): """Close the socket, after reading whatever remains""" self._interface.socket_close(self._socknum) - #################################################################### - # WORK IN PROGRESS - #################################################################### - def accept(self): """Accept a connection on a listening socket of type SOCK_STREAM, creating a new socket of type SOCK_STREAM. Returns a tuple of From 0a6ba008c9de6f715e6133028c7b9a2eaffaf401 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 12 Nov 2025 13:09:52 -0500 Subject: [PATCH 55/58] allow shorter imports; update examples to match --- adafruit_esp32spi/__init__.py | 13 +++++++++++++ adafruit_esp32spi/socketpool.py | 10 ++++++++++ adafruit_esp32spi/wifimanager.py | 10 ++++++++++ examples/esp32spi_aio_post.py | 4 ++-- examples/esp32spi_cheerlights.py | 4 ++-- examples/esp32spi_ipconfig.py | 4 ++-- examples/esp32spi_localtime.py | 4 ++-- examples/esp32spi_simpletest.py | 2 +- examples/esp32spi_simpletest_rp2040.py | 2 +- examples/esp32spi_tcp_client.py | 4 ++-- examples/esp32spi_udp_client.py | 4 ++-- examples/esp32spi_wpa2ent_aio_post.py | 4 ++-- examples/esp32spi_wpa2ent_simpletest.py | 2 +- examples/gpio/esp32spi_gpio.py | 2 +- 14 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 adafruit_esp32spi/socketpool.py create mode 100644 adafruit_esp32spi/wifimanager.py diff --git a/adafruit_esp32spi/__init__.py b/adafruit_esp32spi/__init__.py index e69de29..d959cd5 100644 --- a/adafruit_esp32spi/__init__.py +++ b/adafruit_esp32spi/__init__.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +# Allow +# import adafruit_esp32spi +# from adafruit_esp32spi.ESP_SPIcontrol +# etc. +# instead of the more verbose +# import adafruit_esp32pi.adafruit_esp32spi +# etc. + +from .adafruit_esp32spi import * diff --git a/adafruit_esp32spi/socketpool.py b/adafruit_esp32spi/socketpool.py new file mode 100644 index 0000000..d32be0a --- /dev/null +++ b/adafruit_esp32spi/socketpool.py @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +# Allow +# from adafruit_esp32pi.socketpool import SocketPool +# instead of the more verbose +# from adafruit_esp32pi.adafruit_esp32spi_socketpool import SocketPool + +from .adafruit_esp32spi_socketpool import * diff --git a/adafruit_esp32spi/wifimanager.py b/adafruit_esp32spi/wifimanager.py new file mode 100644 index 0000000..4a57b7f --- /dev/null +++ b/adafruit_esp32spi/wifimanager.py @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +# Allow imports like +# from adafruit_esp32pi.wifimanager import WiFiManager +# instead of the more verbose +# from adafruit_esp32pi.adafruit_esp32spi_wifimanager import WiFiManager + +from .adafruit_esp32spi_wifimanager import * diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index 8be7e35..1a18670 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -9,8 +9,8 @@ import neopixel from digitalio import DigitalInOut -from adafruit_esp32spi import adafruit_esp32spi -from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager +import adafruit_esp32spi +from adafruit_esp32spi.wifimanager import WiFiManager print("ESP32 SPI webclient test") diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index ca74e90..43a76d1 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -10,8 +10,8 @@ import neopixel from digitalio import DigitalInOut -from adafruit_esp32spi import adafruit_esp32spi -from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager +import adafruit_esp32spi +from adafruit_esp32spi.wifimanager import WiFiManager # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index 36b8b8b..19cf494 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -8,8 +8,8 @@ import busio from digitalio import DigitalInOut -import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool -from adafruit_esp32spi import adafruit_esp32spi +import adafruit_esp32spi +from adafruit_esp32spi import socketpool # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index 0157864..45b4a17 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -10,8 +10,8 @@ import rtc from digitalio import DigitalInOut -from adafruit_esp32spi import adafruit_esp32spi -from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager +adafruit_esp32spi +from adafruit_esp32spi.wifimanager import WiFiManager # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index 2124991..6c8b203 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -9,7 +9,7 @@ import busio from digitalio import DigitalInOut -from adafruit_esp32spi import adafruit_esp32spi +import adafruit_esp32spi # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index aab6776..40b5e68 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -9,7 +9,7 @@ import busio from digitalio import DigitalInOut -from adafruit_esp32spi import adafruit_esp32spi +import adafruit_esp32spi # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_tcp_client.py b/examples/esp32spi_tcp_client.py index f781cb9..6d1883a 100644 --- a/examples/esp32spi_tcp_client.py +++ b/examples/esp32spi_tcp_client.py @@ -7,8 +7,8 @@ import busio from digitalio import DigitalInOut -import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool -from adafruit_esp32spi import adafruit_esp32spi +import adafruit_esp32spi +from adafruit_esp32spi import socketpool # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_udp_client.py b/examples/esp32spi_udp_client.py index b1226f9..ada7da1 100644 --- a/examples/esp32spi_udp_client.py +++ b/examples/esp32spi_udp_client.py @@ -9,8 +9,8 @@ import busio from digitalio import DigitalInOut -import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool -from adafruit_esp32spi import adafruit_esp32spi +import adafruit_esp32spi +from adafruit_esp32spi import socketpool # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index 78e56a2..7661001 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -9,8 +9,8 @@ import neopixel from digitalio import DigitalInOut -from adafruit_esp32spi import adafruit_esp32spi -from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager +import adafruit_esp32spi +from adafruit_esp32spi.wifimanager import WiFiManager print("ESP32 SPI WPA2 Enterprise webclient test") diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index f4b648e..69f4afa 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -18,7 +18,7 @@ import busio from digitalio import DigitalInOut -from adafruit_esp32spi import adafruit_esp32spi +import adafruit_esp32spi # Version number comparison code. Credit to gnud on stackoverflow diff --git a/examples/gpio/esp32spi_gpio.py b/examples/gpio/esp32spi_gpio.py index 91a0fd0..d6df6d1 100644 --- a/examples/gpio/esp32spi_gpio.py +++ b/examples/gpio/esp32spi_gpio.py @@ -9,7 +9,7 @@ import pulseio from digitalio import DigitalInOut, Direction -from adafruit_esp32spi import adafruit_esp32spi +import adafruit_esp32spi # ESP32SPI Digital and Analog Pin Reads & Writes From 0cfb4ae33ec68b053a232d4304c658e2e13ee69a Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 12 Nov 2025 19:48:23 -0500 Subject: [PATCH 56/58] fix imported-members doc; describe new import scheme --- docs/api.rst | 65 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index 4ac85a9..4a0705e 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,19 +1,68 @@ - -.. If you created a package, create one automodule per module in the package. - -.. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py) -.. use this format as the module name: "adafruit_foo.foo" - API Reference ############# .. automodule:: adafruit_esp32spi.adafruit_esp32spi + +.. note:: + As of version 11.0.0, it simpler to import this library and its submodules + The examples in this documentation use the new import names. + The old import names are still available, but are deprecated and may be removed in a future release. + +Before version 11.0.0, the library was structured like this (not all components are shown): + +* ``adafruit_esp32spi`` + + * ``adafruit_esp32spi`` + + * ``ESP32_SPIcontrol`` + + * ``adafruit_esp32spi_socketpool`` + + * ``SocketPool`` + + * ``adafruit_esp32spi_wifimanager`` + + * ``WiFiManager`` + +.. code:: python + + # Old import scheme + from adafruit_esp32spi import adafruit_esp32spi + from adafruit_esp32spi.adafruit_esp32spi_socketpool import SocketPool + from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager + +Now, the duplicated top-most name is not needed, and there are shorter names for the submodules. + +* ``adafruit_esp32spi`` + + * ``ESP32_SPIcontrol`` + + * ``socketpool`` + + * ``SocketPool`` + + * ``wifimanager`` + + * ``WiFiManager`` + +.. code:: python + + # New import scheme + import adafruit_esp32spi + from adafruit_esp32spi.socketpool import SocketPool + from adafruit_esp32spi.wifimanager import WiFiManager + + +.. automodule:: adafruit_esp32spi + :imported-members: :members: -.. automodule:: adafruit_esp32spi.adafruit_esp32spi_socketpool +.. automodule:: adafruit_esp32spi.socketpool + :imported-members: :members: -.. automodule:: adafruit_esp32spi.adafruit_esp32spi_wifimanager +.. automodule:: adafruit_esp32spi.wifimanager + :imported-members: :members: .. automodule:: adafruit_esp32spi.digitalio From ca84f8bdff1c187e3e1d5bb2bfc1b31fb9ff3806 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 3 Dec 2025 10:59:05 -0500 Subject: [PATCH 57/58] add WLSTOPPED --- adafruit_esp32spi/adafruit_esp32spi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 03a4a66..4aa8a46 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -114,6 +114,7 @@ WL_NO_SHIELD = const(0xFF) WL_NO_MODULE = const(0xFF) +WL_STOPPED = const(0xFE) WL_IDLE_STATUS = const(0) WL_NO_SSID_AVAIL = const(1) WL_SCAN_COMPLETED = const(2) @@ -424,7 +425,7 @@ def _send_command_get_response( @property def status(self): """The status of the ESP32 WiFi core. Can be WL_NO_SHIELD or WL_NO_MODULE - (not found), WL_IDLE_STATUS, WL_NO_SSID_AVAIL, WL_SCAN_COMPLETED, + (not found), WL_STOPPED, WL_IDLE_STATUS, WL_NO_SSID_AVAIL, WL_SCAN_COMPLETED, WL_CONNECTED, WL_CONNECT_FAILED, WL_CONNECTION_LOST, WL_DISCONNECTED, WL_AP_LISTENING, WL_AP_CONNECTED, WL_AP_FAILED""" resp = self._send_command_get_response(_GET_CONN_STATUS_CMD) From ab75b89041479b6f472f1cb7aa655946a28bb9fa Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 3 Dec 2025 11:17:48 -0500 Subject: [PATCH 58/58] revert examples to old API --- examples/esp32spi_aio_post.py | 8 ++++++-- examples/esp32spi_cheerlights.py | 8 ++++++-- examples/esp32spi_ipconfig.py | 8 ++++++-- examples/esp32spi_localtime.py | 8 ++++++-- examples/esp32spi_simpletest.py | 5 ++++- examples/esp32spi_simpletest_rp2040.py | 5 ++++- examples/esp32spi_tcp_client.py | 8 ++++++-- examples/esp32spi_udp_client.py | 8 ++++++-- examples/esp32spi_wpa2ent_aio_post.py | 8 ++++++-- examples/esp32spi_wpa2ent_simpletest.py | 5 ++++- 10 files changed, 54 insertions(+), 17 deletions(-) diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index 1a18670..c8f95c3 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -9,8 +9,12 @@ import neopixel from digitalio import DigitalInOut -import adafruit_esp32spi -from adafruit_esp32spi.wifimanager import WiFiManager +# Use these imports for adafruit_esp32spi version 11.0.0 and up. +# Note that frozen libraries may not be up to date. +# import adafruit_esp32spi +# from adafruit_esp32spi.wifimanager import WiFiManager +from adafruit_esp32spi import adafruit_esp32spi +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager print("ESP32 SPI webclient test") diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index 43a76d1..d11a018 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -10,8 +10,12 @@ import neopixel from digitalio import DigitalInOut -import adafruit_esp32spi -from adafruit_esp32spi.wifimanager import WiFiManager +# Use these imports for adafruit_esp32spi version 11.0.0 and up. +# Note that frozen libraries may not be up to date. +# import adafruit_esp32spi +# from adafruit_esp32spi.wifimanager import WiFiManager +from adafruit_esp32spi import adafruit_esp32spi +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index 19cf494..afdaaa2 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -8,8 +8,12 @@ import busio from digitalio import DigitalInOut -import adafruit_esp32spi -from adafruit_esp32spi import socketpool +# Use these imports for adafruit_esp32spi version 11.0.0 and up. +# Note that frozen libraries may not be up to date. +# import adafruit_esp32spi +# from adafruit_esp32spi import socketpool +import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool +from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index 45b4a17..ff6b298 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -10,8 +10,12 @@ import rtc from digitalio import DigitalInOut -adafruit_esp32spi -from adafruit_esp32spi.wifimanager import WiFiManager +# Use these imports for adafruit_esp32spi version 11.0.0 and up. +# Note that frozen libraries may not be up to date. +# import adafruit_esp32spi +# from adafruit_esp32spi.wifimanager import WiFiManager +from adafruit_esp32spi import adafruit_esp32spi +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index 6c8b203..015646d 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -9,7 +9,10 @@ import busio from digitalio import DigitalInOut -import adafruit_esp32spi +# Use this import for adafruit_esp32spi version 11.0.0 and up. +# Note that frozen libraries may not be up to date. +# import adafruit_esp32spi +from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index 40b5e68..9ace744 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -9,7 +9,10 @@ import busio from digitalio import DigitalInOut -import adafruit_esp32spi +# Use this import for adafruit_esp32spi version 11.0.0 and up. +# Note that frozen libraries may not be up to date. +# import adafruit_esp32spi +from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_tcp_client.py b/examples/esp32spi_tcp_client.py index 6d1883a..09d96aa 100644 --- a/examples/esp32spi_tcp_client.py +++ b/examples/esp32spi_tcp_client.py @@ -7,8 +7,12 @@ import busio from digitalio import DigitalInOut -import adafruit_esp32spi -from adafruit_esp32spi import socketpool +# Use these imports for adafruit_esp32spi version 11.0.0 and up. +# Note that frozen libraries may not be up to date. +# import adafruit_esp32spi +# from adafruit_esp32spi import socketpool +import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool +from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_udp_client.py b/examples/esp32spi_udp_client.py index ada7da1..5a36a5e 100644 --- a/examples/esp32spi_udp_client.py +++ b/examples/esp32spi_udp_client.py @@ -9,8 +9,12 @@ import busio from digitalio import DigitalInOut -import adafruit_esp32spi -from adafruit_esp32spi import socketpool +# Use these imports for adafruit_esp32spi version 11.0.0 and up. +# Note that frozen libraries may not be up to date. +# import adafruit_esp32spi +# from adafruit_esp32spi import socketpool +import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool +from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index 7661001..fde07e4 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -9,8 +9,12 @@ import neopixel from digitalio import DigitalInOut -import adafruit_esp32spi -from adafruit_esp32spi.wifimanager import WiFiManager +# Use this import for adafruit_esp32spi version 11.0.0 and up. +# Note that frozen libraries may not be up to date. +# import adafruit_esp32spi +# from adafruit_esp32spi.wifimanager import WiFiManager +from adafruit_esp32spi import adafruit_esp32spi +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager print("ESP32 SPI WPA2 Enterprise webclient test") diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index 69f4afa..2e9d86c 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -18,7 +18,10 @@ import busio from digitalio import DigitalInOut -import adafruit_esp32spi +# Use this import for adafruit_esp32spi version 11.0.0 and up. +# Note that frozen libraries may not be up to date. +# import adafruit_esp32spi +from adafruit_esp32spi import adafruit_esp32spi # Version number comparison code. Credit to gnud on stackoverflow