From f97db45bbe6072ae08c56773ba49eb9f5b779725 Mon Sep 17 00:00:00 2001 From: Antonin ENFRUN Date: Thu, 12 Nov 2020 18:03:58 +0100 Subject: [PATCH 001/155] wsgiserver: implement parse_headers, add 500 Internal Server Error when the wsgi application misbehaves, and make sure nobody think we can handle keep-alive requests. --- .../adafruit_esp32spi_wsgiserver.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index c869575..1510363 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py @@ -31,7 +31,6 @@ import io import gc from micropython import const -from adafruit_requests import parse_headers import adafruit_esp32spi.adafruit_esp32spi_socket as socket _the_interface = None # pylint: disable=invalid-name @@ -46,6 +45,18 @@ def set_interface(iface): NO_SOCK_AVAIL = const(255) + +def parse_headers(client): + headers = {} + while True: + line = str(client.readline(), "utf-8") + if not line: + break + title, content = line.split(':', 1) + headers[title.strip().lower()] = content.strip() + return headers + + # pylint: disable=invalid-name class WSGIServer: """ @@ -99,7 +110,7 @@ def finish_response(self, result): :param string result: the data string to send back in the response to the client. """ try: - response = "HTTP/1.1 {0}\r\n".format(self._response_status) + response = "HTTP/1.1 {0}\r\n".format(self._response_status or "500 ISE") for header in self._response_headers: response += "{0}: {1}\r\n".format(*header) response += "\r\n" @@ -159,7 +170,7 @@ def _start_response(self, status, response_headers): ex ("header-name", "header value") """ self._response_status = status - self._response_headers = [("Server", "esp32WSGIServer")] + response_headers + self._response_headers = [("Server", "esp32WSGIServer"), ("Connection", "close")] + response_headers def _get_environ(self, client): """ From c54ec1f9f79d93aa59cce610cd6c94e4d83bf1de Mon Sep 17 00:00:00 2001 From: Antonin ENFRUN Date: Thu, 12 Nov 2020 18:55:31 +0100 Subject: [PATCH 002/155] blackd --- adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index 1510363..698f220 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py @@ -52,7 +52,7 @@ def parse_headers(client): line = str(client.readline(), "utf-8") if not line: break - title, content = line.split(':', 1) + title, content = line.split(":", 1) headers[title.strip().lower()] = content.strip() return headers @@ -170,7 +170,10 @@ def _start_response(self, status, response_headers): ex ("header-name", "header value") """ self._response_status = status - self._response_headers = [("Server", "esp32WSGIServer"), ("Connection", "close")] + response_headers + self._response_headers = [ + ("Server", "esp32WSGIServer"), + ("Connection", "close"), + ] + response_headers def _get_environ(self, client): """ From 03954197d1b4e15e7fab5c8b8e5e141c7f755398 Mon Sep 17 00:00:00 2001 From: Antonin ENFRUN Date: Thu, 12 Nov 2020 19:58:32 +0100 Subject: [PATCH 003/155] documentation --- adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index 698f220..8d74965 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py @@ -47,6 +47,10 @@ def set_interface(iface): def parse_headers(client): + """ + Parses the header portion of an HTTP request from the socket. + Expects first line of HTTP request to have been read already. + """ headers = {} while True: line = str(client.readline(), "utf-8") From c87079bc13dba7183d662c354eac74ec92d7e8c5 Mon Sep 17 00:00:00 2001 From: Mike Corrigan Date: Tue, 6 Apr 2021 18:57:29 -0500 Subject: [PATCH 004/155] change timeout to retry count in _wait_spi_char --- adafruit_esp32spi/adafruit_esp32spi.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 76193a8..105a6d9 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -260,9 +260,8 @@ def _read_bytes(self, spi, buffer, start=0, end=None): print("\t\tRead:", [hex(i) for i in buffer]) def _wait_spi_char(self, spi, desired): - """Read a byte with a time-out, and if we get it, check that its what we expect""" - times = time.monotonic() - while (time.monotonic() - times) < 0.1: + """Read a byte with a retry loop, and if we get it, check that its what we expect""" + for _ in range(50): r = self._read_byte(spi) if r == _ERR_CMD: raise RuntimeError("Error response to command") From 907de10f9fe700316bac101b2dc888f0707edf2d Mon Sep 17 00:00:00 2001 From: Mike Corrigan Date: Wed, 7 Apr 2021 12:04:01 -0500 Subject: [PATCH 005/155] Updated retry loop to have a time.sleep(0.01) --- 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 105a6d9..c827408 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -261,12 +261,13 @@ def _read_bytes(self, spi, buffer, start=0, end=None): def _wait_spi_char(self, spi, desired): """Read a byte with a retry loop, and if we get it, check that its what we expect""" - for _ in range(50): + for _ in range(10): r = self._read_byte(spi) if r == _ERR_CMD: raise RuntimeError("Error response to command") if r == desired: return True + time.sleep(0.01) raise RuntimeError("Timed out waiting for SPI char") def _check_data(self, spi, desired): From 1b175f6c57d4b2b6412b09c717bcddfd11b61935 Mon Sep 17 00:00:00 2001 From: dherrada Date: Wed, 19 May 2021 13:32:42 -0400 Subject: [PATCH 006/155] Added pull request template Signed-off-by: dherrada --- .../adafruit_circuitpython_pr.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md diff --git a/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md b/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md new file mode 100644 index 0000000..71ef8f8 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2021 Adafruit Industries +# +# SPDX-License-Identifier: MIT + +Thank you for contributing! Before you submit a pull request, please read the following. + +Make sure any changes you're submitting are in line with the CircuitPython Design Guide, available here: https://circuitpython.readthedocs.io/en/latest/docs/design_guide.html + +If your changes are to documentation, please verify that the documentation builds locally by following the steps found here: https://adafru.it/build-docs + +Before submitting the pull request, make sure you've run Pylint and Black locally on your code. You can do this manually or using pre-commit. Instructions are available here: https://adafru.it/check-your-code + +Please remove all of this text before submitting. Include an explanation or list of changes included in your PR, as well as, if applicable, a link to any related issues. From 155bec4ae6a7776d7982c4532d5f2d4fcfaece3e Mon Sep 17 00:00:00 2001 From: dherrada Date: Wed, 19 May 2021 13:35:18 -0400 Subject: [PATCH 007/155] Added help text and problem matcher Signed-off-by: dherrada --- .github/workflows/build.yml | 2 ++ .github/workflows/failure-help-text.yml | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 .github/workflows/failure-help-text.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9f539d8..cd56bdd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,3 +55,5 @@ jobs: - name: Build docs working-directory: docs run: sphinx-build -E -W -b html . _build/html + - name: Setup problem matchers + uses: adafruit/circuitpython-action-library-ci-problem-matchers@v1 diff --git a/.github/workflows/failure-help-text.yml b/.github/workflows/failure-help-text.yml new file mode 100644 index 0000000..0b1194f --- /dev/null +++ b/.github/workflows/failure-help-text.yml @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2021 Scott Shawcroft for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +name: Failure help text + +on: + workflow_run: + workflows: ["Build CI"] + types: + - completed + +jobs: + post-help: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event == 'pull_request' }} + steps: + - name: Post comment to help + uses: adafruit/circuitpython-action-library-ci-failed@v1 From 877156455da17e58b67dc98a18fd56c1de25ec11 Mon Sep 17 00:00:00 2001 From: dherrada Date: Mon, 24 May 2021 09:54:31 -0400 Subject: [PATCH 008/155] Moved CI to Python 3.7 Signed-off-by: dherrada --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cd56bdd..19fae5a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,10 +22,10 @@ jobs: awk -F '\/' '{ print tolower($2) }' | tr '_' '-' ) - - name: Set up Python 3.6 + - name: Set up Python 3.7 uses: actions/setup-python@v1 with: - python-version: 3.6 + python-version: 3.7 - name: Versions run: | python3 --version From b96b0debef16c41c35a8579ccbbb1779ca1eaf0c Mon Sep 17 00:00:00 2001 From: dherrada Date: Mon, 7 Jun 2021 14:50:12 -0400 Subject: [PATCH 009/155] Moved default branch to main --- README.rst | 2 +- examples/gpio/gpio.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index bc48ff4..51918a0 100644 --- a/README.rst +++ b/README.rst @@ -63,7 +63,7 @@ Contributing ============ Contributions are welcome! Please read our `Code of Conduct -`_ +`_ before contributing to help this project stay welcoming. Documentation diff --git a/examples/gpio/gpio.md b/examples/gpio/gpio.md index 57b8336..42d40a8 100644 --- a/examples/gpio/gpio.md +++ b/examples/gpio/gpio.md @@ -16,7 +16,7 @@ As of NINA firmware version 1.5.0, the ESP32SPI library can be used to read digi ``` # ESP32_GPIO_PINS: - # https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/blob/master/adafruit_esp32spi/digitalio.py + # https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/blob/main/adafruit_esp32spi/digitalio.py # 0, 1, 2, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33, 34, 35, 36, 39 # # Pins Used for ESP32SPI From 7b048134c49c6fb45b33fab4534114b8a89e4d29 Mon Sep 17 00:00:00 2001 From: dherrada Date: Thu, 23 Sep 2021 17:52:55 -0400 Subject: [PATCH 010/155] Globally disabled consider-using-f-string pylint check Signed-off-by: dherrada --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 354c761..8810708 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,5 +30,5 @@ repos: name: pylint (examples code) description: Run pylint rules on "examples/*.py" files entry: /usr/bin/env bash -c - args: ['([[ ! -d "examples" ]] || for example in $(find . -path "./examples/*.py"); do pylint --disable=missing-docstring,invalid-name $example; done)'] + args: ['([[ ! -d "examples" ]] || for example in $(find . -path "./examples/*.py"); do pylint --disable=missing-docstring,invalid-name,consider-using-f-string $example; done)'] language: system From bb3ac8614ecdcf05ef4d512a74930f9fa620ed03 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 25 Oct 2021 11:15:52 -0500 Subject: [PATCH 011/155] add docs link to readme --- README.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.rst b/README.rst index 51918a0..f36e33a 100644 --- a/README.rst +++ b/README.rst @@ -59,6 +59,11 @@ Usage Example Check the examples folder for various demos for connecting and fetching data! +Documentation +============= + +API documentation for this library can be found on `Read the Docs `_. + Contributing ============ From 0c3262847964e0e011a6de7f328e5e7bb78a10f5 Mon Sep 17 00:00:00 2001 From: dherrada Date: Wed, 3 Nov 2021 14:40:16 -0400 Subject: [PATCH 012/155] PATCH Pylint and readthedocs patch test Signed-off-by: dherrada --- .github/workflows/build.yml | 4 ++-- .pre-commit-config.yaml | 26 +++++++++++++++++--------- .pylintrc | 2 +- .readthedocs.yml | 2 +- docs/requirements.txt | 5 +++++ 5 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 docs/requirements.txt diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 19fae5a..3947ad3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,9 +42,9 @@ jobs: # (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.) run: | source actions-ci/install.sh - - name: Pip install pylint, Sphinx, pre-commit + - name: Pip install Sphinx, pre-commit run: | - pip install --force-reinstall pylint Sphinx sphinx-rtd-theme pre-commit + pip install --force-reinstall Sphinx sphinx-rtd-theme pre-commit - name: Library version run: git describe --dirty --always --tags - name: Pre-commit hooks diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8810708..1b9fadc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,17 +18,25 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/pycqa/pylint - rev: pylint-2.7.1 + rev: v2.11.1 hooks: - id: pylint name: pylint (library code) types: [python] - exclude: "^(docs/|examples/|setup.py$)" -- repo: local - hooks: - - id: pylint_examples - name: pylint (examples code) + args: + - --disable=consider-using-f-string + exclude: "^(docs/|examples/|tests/|setup.py$)" + - id: pylint + name: pylint (example code) description: Run pylint rules on "examples/*.py" files - entry: /usr/bin/env bash -c - args: ['([[ ! -d "examples" ]] || for example in $(find . -path "./examples/*.py"); do pylint --disable=missing-docstring,invalid-name,consider-using-f-string $example; done)'] - language: system + 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 diff --git a/.pylintrc b/.pylintrc index ab4d457..e0171d5 100644 --- a/.pylintrc +++ b/.pylintrc @@ -252,7 +252,7 @@ ignore-docstrings=yes ignore-imports=yes # Minimum lines number of a similarity. -min-similarity-lines=12 +min-similarity-lines=4 [BASIC] diff --git a/.readthedocs.yml b/.readthedocs.yml index 011c3a9..9513b39 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -4,4 +4,4 @@ python: version: 3 -requirements_file: requirements.txt +requirements_file: docs/requirements.txt diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..88e6733 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries +# +# SPDX-License-Identifier: Unlicense + +sphinx>=4.0.0 From 58aca27dad4097ceeb983c840b8e5423e22d3b09 Mon Sep 17 00:00:00 2001 From: dherrada Date: Fri, 5 Nov 2021 14:49:30 -0400 Subject: [PATCH 013/155] Disabled unspecified-encoding pylint check Signed-off-by: dherrada --- .pylintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index e0171d5..d6fefec 100644 --- a/.pylintrc +++ b/.pylintrc @@ -55,7 +55,7 @@ confidence= # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" # disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call -disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation +disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation,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 From c86f7cf1f5ca68abff0b6d455c6b0a72e9f47fba Mon Sep 17 00:00:00 2001 From: dherrada Date: Mon, 8 Nov 2021 12:14:39 -0500 Subject: [PATCH 014/155] Linted --- adafruit_esp32spi/digitalio.py | 1 - examples/esp32spi_tcp_client.py | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index f46fc9b..c3d05ee 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -197,7 +197,6 @@ def drive_mode(self, mode): :param DriveMode mode: Defines the drive mode when outputting digital values. Either PUSH_PULL or OPEN_DRAIN """ - self.__drive_mode = mode if mode is DriveMode.OPEN_DRAIN: raise NotImplementedError( "Drive mode %s not implemented in ESP32SPI." % mode diff --git a/examples/esp32spi_tcp_client.py b/examples/esp32spi_tcp_client.py index d178c20..e635d0c 100644 --- a/examples/esp32spi_tcp_client.py +++ b/examples/esp32spi_tcp_client.py @@ -1,12 +1,11 @@ # SPDX-FileCopyrightText: 2021 Adafruit Industries # SPDX-License-Identifier: MIT +from secrets import secrets # pylint: disable=no-name-in-module import board from digitalio import DigitalInOut from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_socket as socket -import adafruit_requests as requests -from secrets import secrets TIMEOUT = 5 From e25c1801c5428598f543873bb846851b78efb329 Mon Sep 17 00:00:00 2001 From: dherrada Date: Tue, 9 Nov 2021 15:32:35 -0500 Subject: [PATCH 015/155] Updated readthedocs file --- .readthedocs.yaml | 15 +++++++++++++++ .readthedocs.yml | 7 ------- 2 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 .readthedocs.yaml delete mode 100644 .readthedocs.yml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..95ec218 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +# +# SPDX-License-Identifier: Unlicense + +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +python: + version: "3.6" + install: + - requirements: docs/requirements.txt + - requirements: requirements.txt diff --git a/.readthedocs.yml b/.readthedocs.yml deleted file mode 100644 index 9513b39..0000000 --- a/.readthedocs.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries -# -# SPDX-License-Identifier: Unlicense - -python: - version: 3 -requirements_file: docs/requirements.txt From 365560b3f4cb6796f047bc270574079cf680775c Mon Sep 17 00:00:00 2001 From: foamyguy Date: Tue, 23 Nov 2021 13:01:37 -0600 Subject: [PATCH 016/155] update rtd py version --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 95ec218..1335112 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -9,7 +9,7 @@ version: 2 python: - version: "3.6" + version: "3.7" install: - requirements: docs/requirements.txt - requirements: requirements.txt From daeb34cd3ae1fe6bf3f082de00182c43b6a6f9e6 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 1 Dec 2021 12:17:28 -0500 Subject: [PATCH 017/155] add empty __init__.py to make proper package --- adafruit_esp32spi/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 adafruit_esp32spi/__init__.py diff --git a/adafruit_esp32spi/__init__.py b/adafruit_esp32spi/__init__.py new file mode 100644 index 0000000..e69de29 From 04b7c95b655e75274a2f13e7be8fbcdf2c7bea76 Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Wed, 29 Dec 2021 12:37:51 -0500 Subject: [PATCH 018/155] Change _pin arguments to _dio --- adafruit_esp32spi/adafruit_esp32spi.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index c827408..23adb3b 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -134,7 +134,7 @@ class ESP_SPIcontrol: # pylint: disable=too-many-public-methods, too-many-insta # pylint: disable=too-many-arguments def __init__( - self, spi, cs_pin, ready_pin, reset_pin, gpio0_pin=None, *, debug=False + self, spi, cs_dio, ready_dio, reset_dio, gpio0_dio=None, *, debug=False ): self._debug = debug self.set_psk = False @@ -145,10 +145,10 @@ def __init__( self._socknum_ll = [[0]] # pre-made list of list of socket # self._spi_device = SPIDevice(spi, cs_pin, baudrate=8000000) - self._cs = cs_pin - self._ready = ready_pin - self._reset = reset_pin - self._gpio0 = gpio0_pin + self._cs = cs_dio + self._ready = ready_dio + self._reset = reset_dio + self._gpio0 = gpio0_dio self._cs.direction = Direction.OUTPUT self._ready.direction = Direction.INPUT self._reset.direction = Direction.OUTPUT From b037a5374b8239f0f296464b5926a2073d45fcba Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Wed, 29 Dec 2021 12:47:11 -0500 Subject: [PATCH 019/155] Change cs_pin reference to cs_dio --- 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 23adb3b..c14e901 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -144,7 +144,7 @@ def __init__( self._sendbuf = bytearray(256) # buffer for command sending self._socknum_ll = [[0]] # pre-made list of list of socket # - self._spi_device = SPIDevice(spi, cs_pin, baudrate=8000000) + self._spi_device = SPIDevice(spi, cs_dio, baudrate=8000000) self._cs = cs_dio self._ready = ready_dio self._reset = reset_dio From 86111196d6155b6bf4eb9d032d6488a0d5211ea6 Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Thu, 30 Dec 2021 12:18:04 -0500 Subject: [PATCH 020/155] Revert status LED to off after POST --- 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 930b33c..a02cada 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -128,7 +128,7 @@ def _get_next_ap(self): def connect_normal(self): """ - Attempt a regular style WiFi connection + Attempt a regular style WiFi connection. """ failure_count = 0 (ssid, password) = self._get_next_ap() @@ -242,6 +242,7 @@ def post(self, url, **kw): self.connect() self.pixel_status((0, 0, 100)) return_val = requests.post(url, **kw) + self.pixel_status(0) return return_val def put(self, url, **kw): From fd7c932af3f8662b3b9135683430fed99df3a122 Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Thu, 30 Dec 2021 12:33:46 -0500 Subject: [PATCH 021/155] Update __init__() LED argument to describe LED behavior --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index a02cada..5e3262e 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -43,7 +43,11 @@ def __init__( :param ESP_SPIcontrol esp: The ESP object we are using :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) :param status_pixel: (Optional) The pixel device - A NeoPixel, DotStar, - or RGB LED (default=None) + 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 From 436700ae46a67c7ed62f86dfab735cb129df5d5c Mon Sep 17 00:00:00 2001 From: Tekktrik Date: Thu, 30 Dec 2021 09:44:31 -0800 Subject: [PATCH 022/155] Reformatted per pre-commit --- 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 5e3262e..739f7a9 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -132,7 +132,7 @@ def _get_next_ap(self): def connect_normal(self): """ - Attempt a regular style WiFi connection. + Attempt a regular style WiFi connection. """ failure_count = 0 (ssid, password) = self._get_next_ap() From 78189d779fb20aa5940f6cf51522022bed07a857 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 13 Jan 2022 12:17:57 -0500 Subject: [PATCH 023/155] Add missing files to api.rst --- docs/api.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/api.rst b/docs/api.rst index bee5de4..9da4926 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -9,3 +9,15 @@ .. automodule:: adafruit_esp32spi.adafruit_esp32spi_socket :members: + +.. automodule:: adafruit_esp32spi.adafruit_esp32spi_wifimanager + :members: + +.. automodule:: adafruit_esp32spi.adafruit_esp32spi_wsgiserver + :members: + +.. automodule:: adafruit_esp32spi.digitalio + :members: + +.. automodule:: adafruit_esp32spi.PWMOut + :members: From 09ce803efacb4ee2fc075ee11324b7c97f8541a8 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 13 Jan 2022 12:41:58 -0500 Subject: [PATCH 024/155] Add adafruit_requests to mock imports --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 879c0aa..0d0f507 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -25,7 +25,7 @@ # Uncomment the below if you use native CircuitPython modules such as # digitalio, micropython and busio. List the modules you use. Without it, the # autodoc module docs will fail to generate with a warning. -# autodoc_mock_imports = ["digitalio", "busio"] +autodoc_mock_imports = ["adafruit_requests"] intersphinx_mapping = { From afccfab5e6cecf9453836818f96f3eb8520ff63b Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 13 Jan 2022 12:46:24 -0500 Subject: [PATCH 025/155] Add indent to Sphinx param line in docstring --- adafruit_esp32spi/digitalio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index c3d05ee..8c2313a 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -195,7 +195,7 @@ def drive_mode(self): def drive_mode(self, mode): """Sets the pin drive mode. :param DriveMode mode: Defines the drive mode when outputting digital values. - Either PUSH_PULL or OPEN_DRAIN + Either PUSH_PULL or OPEN_DRAIN """ if mode is DriveMode.OPEN_DRAIN: raise NotImplementedError( From 42dfe33b9f715d98a80432e98ceab9d9afa8be35 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 13 Jan 2022 12:46:43 -0500 Subject: [PATCH 026/155] Add line after bullet list in module docstring --- adafruit_esp32spi/digitalio.py | 1 + 1 file changed, 1 insertion(+) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index 8c2313a..4a0a9fb 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -9,6 +9,7 @@ * Author(s): Brent Rubell, based on Adafruit_Blinka digitalio implementation and bcm283x Pin implementation. + 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 50e239747615688db6d1f4af5d2d0ce7a1a82df1 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 13 Jan 2022 12:50:21 -0500 Subject: [PATCH 027/155] Add indent to line after bullet point --- adafruit_esp32spi/digitalio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index 4a0a9fb..eec0527 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -8,7 +8,7 @@ DigitalIO for ESP32 over SPI. * Author(s): Brent Rubell, based on Adafruit_Blinka digitalio implementation -and bcm283x Pin implementation. + and bcm283x Pin implementation. 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 77abe4805e4f88dfba6341bd6d0e3a8f2ddd6375 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 13 Jan 2022 13:09:47 -0500 Subject: [PATCH 028/155] Make EOL character configurable in readline() --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index d3941fe..267f173 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -92,11 +92,13 @@ def write(self, data): """ self.send(data) - def readline(self): - """Attempt to return as many bytes as we can up to but not including '\r\n'""" + def readline(self, eol=b"\r\n"): + """Attempt to return as many bytes as we can up to but not including + end-of-line character (default is '\\r\\n')""" + # print("Socket readline") stamp = time.monotonic() - while b"\r\n" not in self._buffer: + while eol not in self._buffer: # there's no line already in there, read some more avail = self.available() if avail: @@ -104,7 +106,7 @@ def readline(self): elif self._timeout > 0 and time.monotonic() - stamp > self._timeout: self.close() # Make sure to close socket so that we don't exhaust sockets. raise RuntimeError("Didn't receive full response, failing out") - firstline, self._buffer = self._buffer.split(b"\r\n", 1) + firstline, self._buffer = self._buffer.split(eol, 1) gc.collect() return firstline From 4a21b4c53cd95253dfdb5889fd7ea2dc24ec01eb Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 13 Jan 2022 13:10:17 -0500 Subject: [PATCH 029/155] Reformatted pre pre-commit --- 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 267f173..9d3650e 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -95,7 +95,7 @@ def write(self, data): def readline(self, eol=b"\r\n"): """Attempt to return as many bytes as we can up to but not including end-of-line character (default is '\\r\\n')""" - + # print("Socket readline") stamp = time.monotonic() while eol not in self._buffer: From bee74145cdebdf7769f12c79e0d41d63c3b09d70 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 13 Jan 2022 16:57:32 -0500 Subject: [PATCH 030/155] Add recv_into method --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index d3941fe..05e6602 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -159,6 +159,36 @@ def recv(self, bufsize=0): gc.collect() return ret + def recv_into(self, buffer): + """Read some bytes from the connected remote address into a given buffer + + :param bytearray buffer: The buffer to read into + """ + + stamp = time.monotonic() + to_read = len(buffer) + received = [] + while to_read > 0: + # print("Bytes to read:", to_read) + avail = self.available() + if avail: + stamp = time.monotonic() + recv = _the_interface.socket_read(self._socknum, min(to_read, avail)) + # received.append(recv) + start = len(buffer) - to_read + to_read -= len(recv) + end = len(buffer) - to_read + buffer[start:end] = bytearray(recv) + gc.collect() + elif received: + # We've received some bytes but no more are available. So return + # what we have. + break + if self._timeout > 0 and time.monotonic() - stamp > self._timeout: + break + gc.collect() + return buffer + def read(self, size=0): """Read up to 'size' bytes from the socket, this may be buffered internally! If 'size' isnt specified, return everything in the buffer. From 71456a40624dd8f2d41c7a87feddd4f95e220400 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 13 Jan 2022 18:59:35 -0500 Subject: [PATCH 031/155] Change return of recv_into() to number of bytes read --- 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 05e6602..d47ad94 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -187,7 +187,7 @@ def recv_into(self, buffer): if self._timeout > 0 and time.monotonic() - stamp > self._timeout: break gc.collect() - return buffer + return len(buffer) - to_read def read(self, size=0): """Read up to 'size' bytes from the socket, this may be buffered internally! From 2bc4d13aaa65695ff431d1158d1dc74401854f4f Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Fri, 14 Jan 2022 11:48:29 -0500 Subject: [PATCH 032/155] Minor formatting fixes --- adafruit_esp32spi/adafruit_esp32spi.py | 3 ++- adafruit_esp32spi/digitalio.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index c827408..2492d49 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -21,7 +21,8 @@ * Adafruit CircuitPython firmware for the supported boards: https://github.com/adafruit/circuitpython/releases -* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice +* Adafruit's Bus Device library: + https://github.com/adafruit/Adafruit_CircuitPython_BusDevice """ diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index eec0527..4a0a9fb 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -8,7 +8,7 @@ DigitalIO for ESP32 over SPI. * Author(s): Brent Rubell, based on Adafruit_Blinka digitalio implementation - and bcm283x Pin implementation. +and bcm283x Pin implementation. 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 b989067a316935bbcde5805a6b988da3bd86242f Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Fri, 14 Jan 2022 11:55:09 -0500 Subject: [PATCH 033/155] Fix indentation This should be the culprit --- adafruit_esp32spi/digitalio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index 4a0a9fb..d825f70 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -8,7 +8,7 @@ DigitalIO for ESP32 over SPI. * Author(s): Brent Rubell, based on Adafruit_Blinka digitalio implementation -and bcm283x Pin implementation. + and bcm283x Pin implementation. 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 52208e4752bee510b24ac775763776231b5912cc Mon Sep 17 00:00:00 2001 From: dherrada Date: Thu, 13 Jan 2022 16:27:30 -0500 Subject: [PATCH 034/155] First part of patch Signed-off-by: dherrada --- .../PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md | 2 +- .github/workflows/build.yml | 6 +++--- .github/workflows/release.yml | 8 ++++---- .readthedocs.yaml | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md b/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md index 71ef8f8..8de294e 100644 --- a/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md +++ b/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md @@ -4,7 +4,7 @@ Thank you for contributing! Before you submit a pull request, please read the following. -Make sure any changes you're submitting are in line with the CircuitPython Design Guide, available here: https://circuitpython.readthedocs.io/en/latest/docs/design_guide.html +Make sure any changes you're submitting are in line with the CircuitPython Design Guide, available here: https://docs.circuitpython.org/en/latest/docs/design_guide.html If your changes are to documentation, please verify that the documentation builds locally by following the steps found here: https://adafru.it/build-docs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3947ad3..8a99647 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,10 +22,10 @@ jobs: awk -F '\/' '{ print tolower($2) }' | tr '_' '-' ) - - name: Set up Python 3.7 - uses: actions/setup-python@v1 + - name: Set up Python 3.x + uses: actions/setup-python@v2 with: - python-version: 3.7 + python-version: "3.x" - name: Versions run: | python3 --version diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c872723..be5f7be 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,10 +24,10 @@ jobs: awk -F '\/' '{ print tolower($2) }' | tr '_' '-' ) - - name: Set up Python 3.6 - uses: actions/setup-python@v1 + - name: Set up Python 3.x + uses: actions/setup-python@v2 with: - python-version: 3.6 + python-version: "3.x" - name: Versions run: | python3 --version @@ -67,7 +67,7 @@ jobs: echo ::set-output name=setup-py::$( find . -wholename './setup.py' ) - name: Set up Python if: contains(steps.need-pypi.outputs.setup-py, 'setup.py') - uses: actions/setup-python@v1 + uses: actions/setup-python@v2 with: python-version: '3.x' - name: Install dependencies diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 1335112..f8b2891 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -9,7 +9,7 @@ version: 2 python: - version: "3.7" + version: "3.x" install: - requirements: docs/requirements.txt - requirements: requirements.txt From e480277dc902f74f8474deb5e594f530e630e9ed Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Sat, 22 Jan 2022 00:18:50 -0500 Subject: [PATCH 035/155] Allow optional nbytes parameter for recv_into --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index f340807..3ccf070 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -161,14 +161,14 @@ def recv(self, bufsize=0): gc.collect() return ret - def recv_into(self, buffer): + def recv_into(self, buffer, nbytes=None): """Read some bytes from the connected remote address into a given buffer :param bytearray buffer: The buffer to read into """ stamp = time.monotonic() - to_read = len(buffer) + to_read = len(buffer) if nbytes is None else nbytes received = [] while to_read > 0: # print("Bytes to read:", to_read) From 2cf98c0cfd3ad8f21fe7c778c86c24db89d53fc1 Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Sat, 22 Jan 2022 00:52:51 -0500 Subject: [PATCH 036/155] Correct number of bytes to read math, add param to docstring --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index 3ccf070..338bf32 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -165,12 +165,16 @@ def recv_into(self, buffer, nbytes=None): """Read some bytes from the connected remote address into a given buffer :param bytearray buffer: The buffer to read into + :param int nbytes: (Optional) Number of bytes to receive + default is as many as possible before filling the + buffer or timing out """ stamp = time.monotonic() - to_read = len(buffer) if nbytes is None else nbytes + to_read = len(buffer) + nbytes = to_read if nbytes is None else to_read - nbytes received = [] - while to_read > 0: + while to_read > len(buffer) - nbytes: # print("Bytes to read:", to_read) avail = self.available() if avail: From adacbb1f61f924a88c31afe52222cc401f8d3460 Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Sat, 22 Jan 2022 00:59:26 -0500 Subject: [PATCH 037/155] Fix limit of reads based on nbytes --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index 338bf32..3dd7cf7 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -172,9 +172,9 @@ def recv_into(self, buffer, nbytes=None): stamp = time.monotonic() to_read = len(buffer) - nbytes = to_read if nbytes is None else to_read - nbytes + limit = to_read if nbytes is None else to_read - nbytes received = [] - while to_read > len(buffer) - nbytes: + while to_read > limit: # print("Bytes to read:", to_read) avail = self.available() if avail: From 6f3d99f7a24e478affd5e04077ef76883dc2e391 Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Sat, 22 Jan 2022 01:07:39 -0500 Subject: [PATCH 038/155] Change limit to 0 if nbytes is None --- 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 3dd7cf7..6a68cf3 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -172,7 +172,7 @@ def recv_into(self, buffer, nbytes=None): stamp = time.monotonic() to_read = len(buffer) - limit = to_read if nbytes is None else to_read - nbytes + limit = 0 if nbytes is None else to_read - nbytes received = [] while to_read > limit: # print("Bytes to read:", to_read) From 201e925fff5f3f056273fec27d843bdab64371be Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Sat, 22 Jan 2022 18:15:37 -0500 Subject: [PATCH 039/155] Fix default nbytes and behavior of recv_into --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index 6a68cf3..b5f3d8a 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -161,20 +161,24 @@ def recv(self, bufsize=0): gc.collect() return ret - def recv_into(self, buffer, nbytes=None): + def recv_into(self, buffer, nbytes=0): """Read some bytes from the connected remote address into a given buffer :param bytearray buffer: The buffer to read into - :param int nbytes: (Optional) Number of bytes to receive - default is as many as possible before filling the + :param int nbytes: (Optional) Number of bytes to receive default is 0, + which will receive as many bytes as possible before filling the buffer or timing out """ + if not (0 <= nbytes <= len(buffer)): + raise ValueError( + "Can only read number of bytes between 0 and length of supplied buffer" + ) + stamp = time.monotonic() to_read = len(buffer) - limit = 0 if nbytes is None else to_read - nbytes received = [] - while to_read > limit: + while to_read > nbytes: # print("Bytes to read:", to_read) avail = self.available() if avail: From eec2c72130c6c5ce2a9e4cd595f3a6f447332e99 Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Sat, 22 Jan 2022 20:21:34 -0500 Subject: [PATCH 040/155] Remove superfluous not --- 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 b5f3d8a..f6f1865 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -170,7 +170,7 @@ def recv_into(self, buffer, nbytes=0): buffer or timing out """ - if not (0 <= nbytes <= len(buffer)): + if not 0 <= nbytes <= len(buffer): raise ValueError( "Can only read number of bytes between 0 and length of supplied buffer" ) From 43cb366e26ea711ddfd49792d3c0c397a4a85712 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Sun, 23 Jan 2022 22:08:24 -0500 Subject: [PATCH 041/155] Readd appending data to list --- 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 f6f1865..b664da9 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -184,7 +184,7 @@ def recv_into(self, buffer, nbytes=0): if avail: stamp = time.monotonic() recv = _the_interface.socket_read(self._socknum, min(to_read, avail)) - # received.append(recv) + received.append(recv) start = len(buffer) - to_read to_read -= len(recv) end = len(buffer) - to_read From 2542b261b7b5063a2d05b4066a1ed2816005a8b1 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Sun, 23 Jan 2022 22:08:42 -0500 Subject: [PATCH 042/155] Implement correct usage of limit based on nbytes argument --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index b664da9..c35a94b 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -177,8 +177,9 @@ def recv_into(self, buffer, nbytes=0): stamp = time.monotonic() to_read = len(buffer) + limit = 0 if nbytes == 0 else to_read - nbytes received = [] - while to_read > nbytes: + while to_read > limit: # print("Bytes to read:", to_read) avail = self.available() if avail: From 13775b058422085762874fde8e587f2e9f066855 Mon Sep 17 00:00:00 2001 From: dherrada Date: Mon, 24 Jan 2022 16:46:16 -0500 Subject: [PATCH 043/155] Updated docs link, updated python docs link, updated setup.py --- README.rst | 4 ++-- docs/conf.py | 6 +++--- docs/index.rst | 2 +- setup.py | 2 -- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index f36e33a..fc1e655 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ Introduction ============ .. image:: https://readthedocs.org/projects/adafruit-circuitpython-esp32spi/badge/?version=latest - :target: https://circuitpython.readthedocs.io/projects/esp32spi/en/latest/ + :target: https://docs.circuitpython.org/projects/esp32spi/en/latest/ :alt: Documentation Status .. image:: https://img.shields.io/discord/327254708534116352.svg @@ -62,7 +62,7 @@ Check the examples folder for various demos for connecting and fetching data! Documentation ============= -API documentation for this library can be found on `Read the Docs `_. +API documentation for this library can be found on `Read the Docs `_. Contributing ============ diff --git a/docs/conf.py b/docs/conf.py index 0d0f507..53953b2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,12 +29,12 @@ intersphinx_mapping = { - "python": ("https://docs.python.org/3.4", None), + "python": ("https://docs.python.org/3", None), "BusDevice": ( - "https://circuitpython.readthedocs.io/projects/busdevice/en/latest/", + "https://docs.circuitpython.org/projects/busdevice/en/latest/", None, ), - "CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None), + "CircuitPython": ("https://docs.circuitpython.org/en/latest/", None), } # Add any paths that contain templates here, relative to this directory. diff --git a/docs/index.rst b/docs/index.rst index 77f1cdc..3d33eb3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -30,7 +30,7 @@ Table of Contents :caption: Other Links Download - CircuitPython Reference Documentation + CircuitPython Reference Documentation CircuitPython Support Forum Discord Chat Adafruit Learning System diff --git a/setup.py b/setup.py index e9829b4..03dac02 100644 --- a/setup.py +++ b/setup.py @@ -44,8 +44,6 @@ "Topic :: System :: Hardware", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", ], # What does your project relate to? keywords="adafruit blinka circuitpython micropython esp32spi wifi esp32", From 532b973185eec710042a628a5d7a56eb37aeb3d4 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Wed, 9 Feb 2022 12:57:40 -0500 Subject: [PATCH 044/155] Consolidate Documentation sections of README --- README.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index fc1e655..7137911 100644 --- a/README.rst +++ b/README.rst @@ -64,14 +64,11 @@ Documentation API documentation for this library can be found on `Read the Docs `_. +For information on building library documentation, please check out `this guide `_. + Contributing ============ Contributions are welcome! Please read our `Code of Conduct `_ before contributing to help this project stay welcoming. - -Documentation -============= - -For information on building library documentation, please check out `this guide `_. From 971d361d9c8c114bfc61ce925d5a149b6e83495a Mon Sep 17 00:00:00 2001 From: dherrada Date: Mon, 14 Feb 2022 15:35:02 -0500 Subject: [PATCH 045/155] Fixed readthedocs build Signed-off-by: dherrada --- .readthedocs.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index f8b2891..33c2a61 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -8,8 +8,12 @@ # Required version: 2 +build: + os: ubuntu-20.04 + tools: + python: "3" + python: - version: "3.x" install: - requirements: docs/requirements.txt - requirements: requirements.txt From d07f70bcfdbcff6b7b91991248e42b5404f361f5 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Fri, 18 Feb 2022 14:27:35 +0100 Subject: [PATCH 046/155] Add adafruit_requests to requirements `adafruit_esp32spi_wifimanager.py` uses `adafruit_requests`. --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index e50bb10..d066152 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ Adafruit-Blinka adafruit-circuitpython-busdevice +adafruit-circuitpython-requests From 09036f204fdac4979b52718c3246234924552631 Mon Sep 17 00:00:00 2001 From: sdfsdf Date: Sat, 23 Oct 2021 17:52:35 +0200 Subject: [PATCH 047/155] Added the ability to set static ip, set hostname, and set DNS with the esp32spi interface as the esp32SPI interface supports this --- adafruit_esp32spi/adafruit_esp32spi.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index f93a0f7..cac8b93 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -37,6 +37,9 @@ _SET_NET_CMD = const(0x10) _SET_PASSPHRASE_CMD = const(0x11) +_SET_IP_CONFIG = const(0x14) +_SET_DNS_CONFIG = const(0x15) +_SET_HOSTNAME = const(0x16) _SET_AP_NET_CMD = const(0x18) _SET_AP_PASSPHRASE_CMD = const(0x19) _SET_DEBUG_CMD = const(0x1A) @@ -405,6 +408,26 @@ def scan_networks(self): return APs return None + def set_ip_config(self, ip, gw, mask="255.255.255.0"): + """Tells the ESP32 to set ip, gateway and network mask b"\xFF" """ + resp = self._send_command_get_response(_SET_IP_CONFIG, + params= [b"\x00",self.unpretty_ip(ip),self.unpretty_ip(gw), self.unpretty_ip(mask)], + sent_param_len_16=False) + return resp + + def set_dns_config(self, dns1, dns2="8.8.8.8"): + """Tells the ESP32 to set DNS, with dns2 default to google dns=8.8.8.8""" + resp = self._send_command_get_response(_SET_DNS_CONFIG, [b"\x00", self.unpretty_ip(dns1), self.unpretty_ip(dns2)]) + if resp[0][0] != 1: + raise RuntimeError("Failed to set dns with esp32") + + def set_hostname(self, hostname): + """Tells the ESP32 to set hostname""" + resp = self._send_command_get_response(_SET_HOSTNAME, [hostname]) + return resp + if resp[0][0] != 1: + raise RuntimeError("Failed to set hostname with esp32") + def wifi_set_network(self, ssid): """Tells the ESP32 to set the access point to the given ssid""" resp = self._send_command_get_response(_SET_NET_CMD, [ssid]) From 9a40af7e56d9d88587f873b7ba91dcf3cef98c48 Mon Sep 17 00:00:00 2001 From: manpowre Date: Sat, 23 Oct 2021 19:57:12 +0200 Subject: [PATCH 048/155] Update adafruit_esp32spi.py --- adafruit_esp32spi/adafruit_esp32spi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index cac8b93..aa1a854 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -408,10 +408,10 @@ def scan_networks(self): return APs return None - def set_ip_config(self, ip, gw, mask="255.255.255.0"): + def set_ip_config(self, new_ip, new_gw, new_mask="255.255.255.0"): """Tells the ESP32 to set ip, gateway and network mask b"\xFF" """ resp = self._send_command_get_response(_SET_IP_CONFIG, - params= [b"\x00",self.unpretty_ip(ip),self.unpretty_ip(gw), self.unpretty_ip(mask)], + params= [b"\x00",self.unpretty_ip(new_ip),self.unpretty_ip(new_gw), self.unpretty_ip(new_mask)], sent_param_len_16=False) return resp From 6b6b14627d5748d1f0ae29bfe7b85ece2c00bc24 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Fri, 18 Feb 2022 15:57:39 +0100 Subject: [PATCH 049/155] oops forgot setup.py --- setup.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 03dac02..6872298 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,11 @@ # Author details author="Adafruit Industries", author_email="circuitpython@adafruit.com", - install_requires=["Adafruit-Blinka", "adafruit-circuitpython-busdevice"], + install_requires=[ + "Adafruit-Blinka", + "adafruit-circuitpython-busdevice", + "adafruit-circuitpython-requests", + ], # Choose your license license="MIT", # See https://pypi.python.org/pypi?%3Aaction=list_classifiers From 88d03e947d90d8543f8506755fc886e5b5cf6129 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Sun, 6 Mar 2022 17:08:44 +0000 Subject: [PATCH 050/155] Remove this debug My experiments with the WSGI server are being flooded out by this message. --- adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py | 1 - 1 file changed, 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index 866c553..e24cbd5 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py @@ -126,7 +126,6 @@ def finish_response(self, result): self._client_sock.send(data.encode("utf-8")) gc.collect() finally: - print("closing") self._client_sock.close() def client_available(self): From e433ef675a119bf5f3cefcbde825718c2b6839b2 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Thu, 17 Mar 2022 20:28:09 +0100 Subject: [PATCH 051/155] apply black and add example --- adafruit_esp32spi/adafruit_esp32spi.py | 30 +++++++--- examples/esp32spi_ipconfig.py | 82 ++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 examples/esp32spi_ipconfig.py diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index aa1a854..c9d5ace 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -410,21 +410,35 @@ def scan_networks(self): def set_ip_config(self, new_ip, new_gw, new_mask="255.255.255.0"): """Tells the ESP32 to set ip, gateway and network mask b"\xFF" """ - resp = self._send_command_get_response(_SET_IP_CONFIG, - params= [b"\x00",self.unpretty_ip(new_ip),self.unpretty_ip(new_gw), self.unpretty_ip(new_mask)], - sent_param_len_16=False) + resp = self._send_command_get_response( + _SET_IP_CONFIG, + params=[ + b"\x00", + self.unpretty_ip(new_ip), + self.unpretty_ip(new_gw), + self.unpretty_ip(new_mask), + ], + sent_param_len_16=False, + ) return resp def set_dns_config(self, dns1, dns2="8.8.8.8"): """Tells the ESP32 to set DNS, with dns2 default to google dns=8.8.8.8""" - resp = self._send_command_get_response(_SET_DNS_CONFIG, [b"\x00", self.unpretty_ip(dns1), self.unpretty_ip(dns2)]) + resp = self._send_command_get_response( + _SET_DNS_CONFIG, [b"\x00", self.unpretty_ip(dns1), self.unpretty_ip(dns2)] + ) if resp[0][0] != 1: raise RuntimeError("Failed to set dns with esp32") - + def set_hostname(self, hostname): - """Tells the ESP32 to set hostname""" - resp = self._send_command_get_response(_SET_HOSTNAME, [hostname]) - return resp + """ + Tells the ESP32 to set hostname + + :params str hostname: Set the host name, used by DHCP to associate a local + domain name like hostname.home for example, depending + on the DHCP server setup. + """ + resp = self._send_command_get_response(_SET_HOSTNAME, [hostname.encode()]) if resp[0][0] != 1: raise RuntimeError("Failed to set hostname with esp32") diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py new file mode 100644 index 0000000..fceb512 --- /dev/null +++ b/examples/esp32spi_ipconfig.py @@ -0,0 +1,82 @@ +import time +import board +import busio +from digitalio import DigitalInOut +import adafruit_requests as requests +import adafruit_esp32spi.adafruit_esp32spi_socket as socket +from adafruit_esp32spi import adafruit_esp32spi +import neopixel +from rainbowio import colorwheel +import gc +from secrets import secrets + +IP_ADDRESS = "192.168.2.2" +GATEWAY_ADDRESS = "192.168.2.1" +SUBNET_MASK = "255.255.255.0" + +UDP_IN_ADDR = "192.168.2.2" +UDP_IN_PORT = 5500 + +UDP_TIMEOUT = 20 + +esp32_cs = DigitalInOut(board.CS1) +esp32_ready = DigitalInOut(board.ESP_BUSY) +esp32_reset = DigitalInOut(board.ESP_RESET) + +spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) + +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +socket.set_interface(esp) + +s_in = socket.socket(type=socket.SOCK_DGRAM) +s_in.settimeout(UDP_TIMEOUT) +print("set hostname:") +esp.set_hostname("new_hostname".encode("utf-8")) + +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("Connecting to AP...") +while not esp.is_connected: + try: + esp.connect_AP(secrets["ssid"], secrets["password"]) + except RuntimeError as e: + print("could not connect to AP, retrying: ", e) + continue +print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) +ip1 = esp.ip_address + +print("set ip dns") +esp.set_dns_config("192.168.2.1", "8.8.8.8") + +print("set ip config") +esp.set_ip_config(IP_ADDRESS, GATEWAY_ADDRESS, SUBNET_MASK) + +time.sleep(1) +ip2 = esp.ip_address + +time.sleep(1) +info = esp.network_data +print( + "get network_data: ", + esp.pretty_ip(info["ip_addr"]), + esp.pretty_ip(info["gateway"]), + 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("udp in addr: ", UDP_IN_ADDR, UDP_IN_PORT) + +socketaddr_udp_in = socket.getaddrinfo(UDP_IN_ADDR, UDP_IN_PORT)[0][4] +s_in.connect(socketaddr_udp_in, conntype=esp.UDP_MODE) +print("connected local UDP") + +while True: + data = s_in.recv(1205) + if len(data) >= 1: + data = data.decode("utf-8") + print(len(data), data) From f4481be6608aa6546500f5dd55be11b3e994aea8 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Thu, 17 Mar 2022 22:59:17 +0100 Subject: [PATCH 052/155] cleanup and fix comments, cleanup examples --- adafruit_esp32spi/adafruit_esp32spi.py | 53 +++++++++++++------------- adafruit_esp32spi/digitalio.py | 9 ++++- examples/esp32spi_ipconfig.py | 23 ++++++----- 3 files changed, 49 insertions(+), 36 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index c9d5ace..2b113d8 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -408,22 +408,31 @@ def scan_networks(self): return APs return None - def set_ip_config(self, new_ip, new_gw, new_mask="255.255.255.0"): - """Tells the ESP32 to set ip, gateway and network mask b"\xFF" """ + 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" + + :param str ip_address: IP address (as a string). + :param str gateway: Gateway (as a string). + :param str mask: Mask, defaults to 255.255.255.0 (as a string). + """ resp = self._send_command_get_response( _SET_IP_CONFIG, params=[ b"\x00", - self.unpretty_ip(new_ip), - self.unpretty_ip(new_gw), - self.unpretty_ip(new_mask), + self.unpretty_ip(ip_address), + self.unpretty_ip(gateway), + self.unpretty_ip(mask), ], sent_param_len_16=False, ) return resp - def set_dns_config(self, dns1, dns2="8.8.8.8"): - """Tells the ESP32 to set DNS, with dns2 default to google dns=8.8.8.8""" + def set_dns_config(self, dns1, dns2): + """Tells the ESP32 to set DNS + + :param str dns1: DNS server 1 IP as a string. + :param str dns2: DNS server 2 IP as a string. + """ resp = self._send_command_get_response( _SET_DNS_CONFIG, [b"\x00", self.unpretty_ip(dns1), self.unpretty_ip(dns2)] ) @@ -431,12 +440,9 @@ def set_dns_config(self, dns1, dns2="8.8.8.8"): raise RuntimeError("Failed to set dns with esp32") def set_hostname(self, hostname): - """ - Tells the ESP32 to set hostname + """Tells the ESP32 to set hostname for DHCP. - :params str hostname: Set the host name, used by DHCP to associate a local - domain name like hostname.home for example, depending - on the DHCP server setup. + :param str hostname: The new host name. """ resp = self._send_command_get_response(_SET_HOSTNAME, [hostname.encode()]) if resp[0][0] != 1: @@ -555,8 +561,7 @@ def connect(self, secrets): self.connect_AP(secrets["ssid"], secrets["password"]) def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-name - """ - Connect to an access point with given name and password. + """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. @@ -589,8 +594,7 @@ def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-n def create_AP( self, ssid, password, channel=1, timeout=10 ): # pylint: disable=invalid-name - """ - Create an access point with the given name, password, and channel. + """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. @@ -851,8 +855,7 @@ def set_esp_debug(self, enabled): raise RuntimeError("Failed to set debug mode") def set_pin_mode(self, pin, mode): - """ - Set the io mode for a GPIO pin. + """Set the io mode for a GPIO pin. :param int pin: ESP32 GPIO pin to set. :param value: direction for pin, digitalio.Direction or integer (0=input, 1=output). @@ -868,8 +871,7 @@ def set_pin_mode(self, pin, mode): raise RuntimeError("Failed to set pin mode") def set_digital_write(self, pin, value): - """ - Set the digital output value of pin. + """Set the digital output value of pin. :param int pin: ESP32 GPIO pin to write to. :param bool value: Value for the pin. @@ -881,8 +883,7 @@ def set_digital_write(self, pin, value): raise RuntimeError("Failed to write to pin") def set_analog_write(self, pin, analog_value): - """ - Set the analog output value of pin, using PWM. + """Set the analog output value of pin, using PWM. :param int pin: ESP32 GPIO pin to write to. :param float value: 0=off 1.0=full on @@ -895,8 +896,7 @@ def set_analog_write(self, pin, analog_value): raise RuntimeError("Failed to write to pin") def set_digital_read(self, pin): - """ - Get the digital input value of pin. Returns the boolean value of the pin. + """Get the digital input value of pin. Returns the boolean value of the pin. :param int pin: ESP32 GPIO pin to read from. """ @@ -914,8 +914,7 @@ def set_digital_read(self, pin): ) 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. + """Get the analog input value of pin. Returns an int between 0 and 65536. :param int pin: ESP32 GPIO pin to read from. :param int atten: attenuation constant @@ -951,6 +950,7 @@ def get_time(self): def set_certificate(self, client_certificate): """Sets client certificate. Must be called BEFORE a network connection is established. + :param str client_certificate: User-provided .PEM certificate up to 1300 bytes. """ if self._debug: @@ -973,6 +973,7 @@ def set_certificate(self, client_certificate): def set_private_key(self, private_key): """Sets private key. Must be called BEFORE a network connection is established. + :param str private_key: User-provided .PEM file up to 1700 bytes. """ if self._debug: diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index d825f70..c935794 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -50,6 +50,7 @@ def __init__(self, esp_pin, esp): def init(self, mode=IN): """Initalizes a pre-defined pin. + :param mode: Pin mode (IN, OUT, LOW, HIGH). Defaults to IN. """ if mode is not None: @@ -64,6 +65,7 @@ def init(self, mode=IN): def value(self, val=None): """Sets ESP32 Pin GPIO output mode. + :param val: Pin output level (LOW, HIGH) """ if val is not None: @@ -133,6 +135,7 @@ def deinit(self): def switch_to_output(self, value=False, drive_mode=DriveMode.PUSH_PULL): """Set the drive mode and value and then switch to writing out digital values. + :param bool value: Default mode to set upon switching. :param DriveMode drive_mode: Drive mode for the output. """ @@ -142,6 +145,7 @@ def switch_to_output(self, value=False, drive_mode=DriveMode.PUSH_PULL): def switch_to_input(self, pull=None): """Sets the pull and then switch to read in digital values. + :param Pull pull: Pull configuration for the input. """ raise NotImplementedError( @@ -156,6 +160,7 @@ def direction(self): @direction.setter def direction(self, pin_dir): """Sets the direction of the pin. + :param Direction dir: Pin direction (Direction.OUTPUT or Direction.INPUT) """ self.__direction = pin_dir @@ -176,6 +181,7 @@ def value(self): @value.setter def value(self, val): """Sets the digital logic level of the pin. + :param type value: Pin logic level. :param int value: Pin logic level. 1 is logic high, 0 is logic low. :param bool value: Pin logic level. True is logic high, False is logic low. @@ -195,8 +201,9 @@ def drive_mode(self): @drive_mode.setter def drive_mode(self, mode): """Sets the pin drive mode. + :param DriveMode mode: Defines the drive mode when outputting digital values. - Either PUSH_PULL or OPEN_DRAIN + Either PUSH_PULL or OPEN_DRAIN """ if mode is DriveMode.OPEN_DRAIN: raise NotImplementedError( diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index fceb512..c72e34a 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -1,20 +1,25 @@ +# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + import time import board import busio from digitalio import DigitalInOut -import adafruit_requests as requests import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi -import neopixel -from rainbowio import colorwheel -import gc -from secrets import secrets -IP_ADDRESS = "192.168.2.2" -GATEWAY_ADDRESS = "192.168.2.1" +# 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 + +IP_ADDRESS = "192.168.1.111" +GATEWAY_ADDRESS = "192.168.1.1" SUBNET_MASK = "255.255.255.0" -UDP_IN_ADDR = "192.168.2.2" +UDP_IN_ADDR = "192.168.1.1" UDP_IN_PORT = 5500 UDP_TIMEOUT = 20 @@ -49,7 +54,7 @@ ip1 = esp.ip_address print("set ip dns") -esp.set_dns_config("192.168.2.1", "8.8.8.8") +esp.set_dns_config("192.168.1.1", "8.8.8.8") print("set ip config") esp.set_ip_config(IP_ADDRESS, GATEWAY_ADDRESS, SUBNET_MASK) From ab41a20f701850693f8401c557448e4f60a9751d Mon Sep 17 00:00:00 2001 From: Neradoc Date: Fri, 18 Mar 2022 09:30:50 +0100 Subject: [PATCH 053/155] fix ipconfig example use of encode --- examples/esp32spi_ipconfig.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index c72e34a..01f01c8 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -15,6 +15,8 @@ print("WiFi secrets are kept in secrets.py, please add them there!") raise +HOSTNAME = "esp32-spi-hostname-test" + IP_ADDRESS = "192.168.1.111" GATEWAY_ADDRESS = "192.168.1.1" SUBNET_MASK = "255.255.255.0" @@ -35,8 +37,8 @@ s_in = socket.socket(type=socket.SOCK_DGRAM) s_in.settimeout(UDP_TIMEOUT) -print("set hostname:") -esp.set_hostname("new_hostname".encode("utf-8")) +print("set hostname:", HOSTNAME) +esp.set_hostname(HOSTNAME) if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode") From da7bfb2cc46a2de39fa007312a3c8f4d78644a28 Mon Sep 17 00:00:00 2001 From: anecdata <16617689+anecdata@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:36:58 -0500 Subject: [PATCH 054/155] get_remote_data() exposes NINA getRemoteData() --- adafruit_esp32spi/adafruit_esp32spi.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 2b113d8..1a3f384 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -70,6 +70,7 @@ _START_SCAN_NETWORKS = const(0x36) _GET_FW_VERSION_CMD = const(0x37) _SEND_UDP_DATA_CMD = const(0x39) +_GET_REMOTE_DATA_CMD = const(0x3A) _GET_TIME = const(0x3B) _GET_IDX_BSSID_CMD = const(0x3C) _GET_IDX_CHAN_CMD = const(0x3D) @@ -847,6 +848,12 @@ def server_state(self, socket_num): resp = self._send_command_get_response(_GET_STATE_TCP_CMD, self._socknum_ll) return resp[0][0] + def get_remote_data(self, socket_num): + """Get the IP address and port of the remote host""" + self._socknum_ll[0][0] = socket_num + resp = self._send_command_get_response(_GET_REMOTE_DATA_CMD, self._socknum_ll, reply_params=2) + return {"ip_addr": resp[0], "port": struct.unpack(" Date: Mon, 21 Mar 2022 20:04:30 -0500 Subject: [PATCH 055/155] black --- adafruit_esp32spi/adafruit_esp32spi.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 1a3f384..566cb9e 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -851,7 +851,9 @@ def server_state(self, socket_num): def get_remote_data(self, socket_num): """Get the IP address and port of the remote host""" self._socknum_ll[0][0] = socket_num - resp = self._send_command_get_response(_GET_REMOTE_DATA_CMD, self._socknum_ll, reply_params=2) + resp = self._send_command_get_response( + _GET_REMOTE_DATA_CMD, self._socknum_ll, reply_params=2 + ) return {"ip_addr": resp[0], "port": struct.unpack(" Date: Mon, 21 Mar 2022 20:11:20 -0500 Subject: [PATCH 056/155] pylint --- 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 566cb9e..b2a9d8d 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -29,8 +29,8 @@ import struct import time from micropython import const -from digitalio import Direction from adafruit_bus_device.spi_device import SPIDevice +from digitalio import Direction __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI.git" @@ -128,6 +128,7 @@ ADC_ATTEN_DB_6 = const(2) ADC_ATTEN_DB_11 = const(3) +# pylint: disable=too-many-lines class ESP_SPIcontrol: # pylint: disable=too-many-public-methods, too-many-instance-attributes """A class that will talk to an ESP32 module programmed with special firmware From 5c58a8da07dc4e69752d33c6d42416c30cfbddbf Mon Sep 17 00:00:00 2001 From: anecdata <16617689+anecdata@users.noreply.github.com> Date: Mon, 21 Mar 2022 20:15:05 -0500 Subject: [PATCH 057/155] blacker --- adafruit_esp32spi/adafruit_esp32spi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index b2a9d8d..fae4cc6 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -130,6 +130,7 @@ # pylint: disable=too-many-lines + class ESP_SPIcontrol: # pylint: disable=too-many-public-methods, too-many-instance-attributes """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""" From 65087725add5ae9d6be250231831f23bd994793f Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Mon, 28 Mar 2022 15:52:04 -0400 Subject: [PATCH 058/155] Update Black to latest. Signed-off-by: Kattni Rembor --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1b9fadc..7467c1d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: - repo: https://github.com/python/black - rev: 20.8b1 + rev: 22.3.0 hooks: - id: black - repo: https://github.com/fsfe/reuse-tool From 5127b44a1a992f579dc23b2200ee9aed3ab972e6 Mon Sep 17 00:00:00 2001 From: Eva Herrada <33632497+evaherrada@users.noreply.github.com> Date: Thu, 21 Apr 2022 18:46:34 -0400 Subject: [PATCH 059/155] Update .gitignore --- .gitignore | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 7455881..544ec4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,47 @@ -# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-FileCopyrightText: 2022 Kattni Rembor, written for Adafruit Industries # -# SPDX-License-Identifier: Unlicense +# SPDX-License-Identifier: MIT +# Do not include files and directories created by your personal work environment, such as the IDE +# you use, except for those already listed here. Pull requests including changes to this file will +# not be accepted. + +# This .gitignore file contains rules for files generated by working with CircuitPython libraries, +# including building Sphinx, testing with pip, and creating a virual environment, as well as the +# MacOS and IDE-specific files generated by using MacOS in general, or the PyCharm or VSCode IDEs. + +# If you find that there are files being generated on your machine that should not be included in +# your git commit, you should create a .gitignore_global file on your computer to include the +# files created by your personal setup. To do so, follow the two steps below. + +# First, create a file called .gitignore_global somewhere convenient for you, and add rules for +# the files you want to exclude from git commits. + +# Second, configure Git to use the exclude file for all Git repositories by running the +# following via commandline, replacing "path/to/your/" with the actual path to your newly created +# .gitignore_global file: +# git config --global core.excludesfile path/to/your/.gitignore_global + +# CircuitPython-specific files *.mpy -.idea + +# Python-specific files __pycache__ -_build *.pyc + +# Sphinx build-specific files +_build + +# This file results from running `pip -e install .` in a local repository +*.egg-info + +# Virtual environment-specific files .env -bundles + +# MacOS-specific files *.DS_Store -.eggs -dist -**/*.egg-info + +# IDE-specific files +.idea +.vscode +*~ From c2219f8802f2406c60a36b675c3f09dd30c6126e Mon Sep 17 00:00:00 2001 From: evaherrada Date: Fri, 22 Apr 2022 15:58:39 -0400 Subject: [PATCH 060/155] Patch: Replaced discord badge image --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 7137911..ea28d09 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ Introduction :target: https://docs.circuitpython.org/projects/esp32spi/en/latest/ :alt: Documentation Status -.. image:: https://img.shields.io/discord/327254708534116352.svg +.. image:: https://github.com/adafruit/Adafruit_CircuitPython_Bundle/blob/main/badges/adafruit_discord.svg :target: https://adafru.it/discord :alt: Discord From 35cebc923e5481b84a3a49795efa4623085a47ad Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 24 Apr 2022 13:51:28 -0500 Subject: [PATCH 061/155] change discord badge --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index ea28d09..856e4ee 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ Introduction :target: https://docs.circuitpython.org/projects/esp32spi/en/latest/ :alt: Documentation Status -.. image:: https://github.com/adafruit/Adafruit_CircuitPython_Bundle/blob/main/badges/adafruit_discord.svg +.. image:: https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_Bundle/main/badges/adafruit_discord.svg :target: https://adafru.it/discord :alt: Discord From b3cc17bc1457f674c26f968e60545b3304ad61fe Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 14:42:11 +0100 Subject: [PATCH 062/155] Lets make this available with debug levels making it consistent with other debug in the module --- adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index e24cbd5..956a36c 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py @@ -126,6 +126,8 @@ def finish_response(self, result): self._client_sock.send(data.encode("utf-8")) gc.collect() finally: + if self._debug > 2: + print("closing") self._client_sock.close() def client_available(self): From 911445dd658f8e5b0f994bb2806f1e82ec6ff4da Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 14:50:50 +0100 Subject: [PATCH 063/155] Make these connection errors distinct from other error types. --- adafruit_esp32spi/adafruit_esp32spi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index fae4cc6..1abad64 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -751,24 +751,24 @@ 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 RuntimeError( + 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: - raise RuntimeError("Failed to send UDP data") + raise ConnectionError("Failed to send UDP data") return if sent != len(buffer): self.socket_close(socket_num) - raise RuntimeError( + 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: - raise RuntimeError("Failed to verify data sent") + raise ConnectionError("Failed to verify data sent") def socket_available(self, socket_num): """Determine how many bytes are waiting to be read on the socket""" From 4455889b16af3b2b4a01e9e5fad187a160d57a64 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:02:20 +0100 Subject: [PATCH 064/155] Another OSError derived error here. --- 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 1abad64..7a2907a 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -815,7 +815,7 @@ def socket_connect(self, socket_num, dest, port, conn_mode=TCP_MODE): if self.socket_connected(socket_num): return True time.sleep(0.01) - raise RuntimeError("Failed to establish connection") + raise TimeoutError("Failed to establish connection") def socket_close(self, socket_num): """Close a socket using the ESP32's internal reference number""" From de04df15243d537045684c366aacfa5c07abcd30 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:11:45 +0100 Subject: [PATCH 065/155] These now derive also from OSError types - without timeouts being specific. --- adafruit_esp32spi/adafruit_esp32spi.py | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 7a2907a..014d69e 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -194,7 +194,7 @@ def _wait_for_ready(self): print(".", end="") time.sleep(0.05) else: - raise RuntimeError("ESP32 not responding") + raise TimeoutError("ESP32 not responding") if self._debug >= 3: print() @@ -242,7 +242,7 @@ def _send_command(self, cmd, params=None, *, param_len_16=False): if self._ready.value: # ok ready to send! break else: - raise RuntimeError("ESP32 timed out on SPI select") + raise TimeoutError("ESP32 timed out on SPI select") spi.write( self._sendbuf, start=0, end=packet_len ) # pylint: disable=no-member @@ -271,17 +271,17 @@ def _wait_spi_char(self, spi, desired): for _ in range(10): r = self._read_byte(spi) if r == _ERR_CMD: - raise RuntimeError("Error response to command") + raise BrokenPipeError("Error response to command") if r == desired: return True time.sleep(0.01) - raise RuntimeError("Timed out waiting for SPI char") + raise TimeoutError("Timed out waiting for SPI char") 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 RuntimeError("Expected %02X but got %02X" % (desired, r)) + raise BrokenPipeError("Expected %02X but got %02X" % (desired, r)) def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False): """Wait for ready, then parse the response""" @@ -294,7 +294,7 @@ def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False): if self._ready.value: # ok ready to send! break else: - raise RuntimeError("ESP32 timed out on SPI select") + raise TimeoutError("ESP32 timed out on SPI select") self._wait_spi_char(spi, _START_CMD) self._check_data(spi, cmd | _REPLY_FLAG) @@ -440,7 +440,7 @@ def set_dns_config(self, dns1, dns2): _SET_DNS_CONFIG, [b"\x00", self.unpretty_ip(dns1), self.unpretty_ip(dns2)] ) if resp[0][0] != 1: - raise RuntimeError("Failed to set dns with esp32") + raise OSError("Failed to set dns with esp32") def set_hostname(self, hostname): """Tells the ESP32 to set hostname for DHCP. @@ -449,49 +449,49 @@ def set_hostname(self, hostname): """ resp = self._send_command_get_response(_SET_HOSTNAME, [hostname.encode()]) if resp[0][0] != 1: - raise RuntimeError("Failed to set hostname with esp32") + raise OSError("Failed to set hostname with esp32") def wifi_set_network(self, ssid): """Tells the ESP32 to set the access point to the given ssid""" resp = self._send_command_get_response(_SET_NET_CMD, [ssid]) if resp[0][0] != 1: - raise RuntimeError("Failed to set network") + raise OSError("Failed to set network") def wifi_set_passphrase(self, ssid, passphrase): """Sets the desired access point ssid and passphrase""" resp = self._send_command_get_response(_SET_PASSPHRASE_CMD, [ssid, passphrase]) if resp[0][0] != 1: - raise RuntimeError("Failed to set passphrase") + raise OSError("Failed to set passphrase") def wifi_set_entidentity(self, ident): """Sets the WPA2 Enterprise anonymous identity""" resp = self._send_command_get_response(_SET_ENT_IDENT_CMD, [ident]) if resp[0][0] != 1: - raise RuntimeError("Failed to set enterprise anonymous identity") + raise OSError("Failed to set enterprise anonymous identity") def wifi_set_entusername(self, username): """Sets the desired WPA2 Enterprise username""" resp = self._send_command_get_response(_SET_ENT_UNAME_CMD, [username]) if resp[0][0] != 1: - raise RuntimeError("Failed to set enterprise username") + raise OSError("Failed to set enterprise username") def wifi_set_entpassword(self, password): """Sets the desired WPA2 Enterprise password""" resp = self._send_command_get_response(_SET_ENT_PASSWD_CMD, [password]) if resp[0][0] != 1: - raise RuntimeError("Failed to set enterprise password") + raise OSError("Failed to set enterprise password") def wifi_set_entenable(self): """Enables WPA2 Enterprise mode""" resp = self._send_command_get_response(_SET_ENT_ENABLE_CMD) if resp[0][0] != 1: - raise RuntimeError("Failed to enable enterprise mode") + raise OSError("Failed to enable enterprise mode") def _wifi_set_ap_network(self, ssid, channel): """Creates an Access point with SSID and Channel""" resp = self._send_command_get_response(_SET_AP_NET_CMD, [ssid, channel]) if resp[0][0] != 1: - raise RuntimeError("Failed to setup AP network") + raise OSError("Failed to setup AP network") def _wifi_set_ap_passphrase(self, ssid, passphrase, channel): """Creates an Access point with SSID, passphrase, and Channel""" @@ -499,7 +499,7 @@ def _wifi_set_ap_passphrase(self, ssid, passphrase, channel): _SET_AP_PASSPHRASE_CMD, [ssid, passphrase, channel] ) if resp[0][0] != 1: - raise RuntimeError("Failed to setup AP password") + raise OSError("Failed to setup AP password") @property def ssid(self): From 5abca8de61bdd02392764f43411518e6bca862bb Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:14:18 +0100 Subject: [PATCH 066/155] More error specificity --- adafruit_esp32spi/adafruit_esp32spi.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 014d69e..efd6e38 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -539,7 +539,7 @@ def is_connected(self): """Whether the ESP32 is connected to an access point""" try: return self.status == WL_CONNECTED - except RuntimeError: + except OSError: self.reset() return False @@ -548,7 +548,7 @@ def ap_listening(self): """Returns if the ESP32 is in access point mode and is listening for connections""" try: return self.status == WL_AP_LISTENING - except RuntimeError: + except OSError: self.reset() return False @@ -556,7 +556,7 @@ def disconnect(self): """Disconnect from the access point""" resp = self._send_command_get_response(_DISCONNECT_CMD) if resp[0][0] != 1: - raise RuntimeError("Failed to disconnect") + raise OSError("Failed to disconnect") def connect(self, secrets): """Connect to an access point using a secrets dictionary @@ -589,10 +589,10 @@ def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-n return stat time.sleep(0.05) if stat in (WL_CONNECT_FAILED, WL_CONNECTION_LOST, WL_DISCONNECTED): - raise RuntimeError("Failed to connect to ssid", ssid) + raise ConnectionError("Failed to connect to ssid", ssid) if stat == WL_NO_SSID_AVAIL: - raise RuntimeError("No such ssid", ssid) - raise RuntimeError("Unknown error 0x%02X" % stat) + raise ConnectionError("No such ssid", ssid) + raise OSError("Unknown error 0x%02X" % stat) def create_AP( self, ssid, password, channel=1, timeout=10 @@ -607,11 +607,11 @@ def create_AP( :param int timeout: number of seconds until we time out and fail to create AP """ if len(ssid) > 32: - raise RuntimeError("ssid must be no more than 32 characters") + raise ValueError("ssid must be no more than 32 characters") if password and (len(password) < 8 or len(password) > 64): - raise RuntimeError("password must be 8 - 63 characters") + raise ValueError("password must be 8 - 63 characters") if channel < 1 or channel > 14: - raise RuntimeError("channel must be between 1 and 14") + raise ValueError("channel must be between 1 and 14") if isinstance(channel, int): channel = bytes(channel) From 6605027da19be2345c74fb70609455fd57fc6a56 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:17:08 +0100 Subject: [PATCH 067/155] These are now in the OSError heirarchy --- adafruit_esp32spi/adafruit_esp32spi.py | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index efd6e38..2cb9369 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -377,7 +377,7 @@ def start_scan_networks(self): print("Start scan") resp = self._send_command_get_response(_START_SCAN_NETWORKS) if resp[0][0] != 1: - raise RuntimeError("Failed to start AP scan") + raise OSError("Failed to start AP scan") def get_scan_networks(self): """The results of the latest SSID scan. Returns a list of dictionaries with @@ -631,8 +631,8 @@ def create_AP( return stat time.sleep(0.05) if stat == WL_AP_FAILED: - raise RuntimeError("Failed to create AP", ssid) - raise RuntimeError("Unknown error 0x%02x" % stat) + raise ConnectionError("Failed to create AP", ssid) + raise OSError("Unknown error 0x%02x" % stat) def pretty_ip(self, ip): # pylint: disable=no-self-use, invalid-name """Converts a bytearray IP address to a dotted-quad string for printing""" @@ -652,7 +652,7 @@ def get_host_by_name(self, hostname): hostname = bytes(hostname, "utf-8") resp = self._send_command_get_response(_REQ_HOST_BY_NAME_CMD, (hostname,)) if resp[0][0] != 1: - raise RuntimeError("Failed to request hostname") + raise ConnectionError("Failed to request hostname") resp = self._send_command_get_response(_GET_HOST_BY_NAME_CMD) return resp[0] @@ -708,7 +708,7 @@ def socket_open(self, socket_num, dest, port, conn_mode=TCP_MODE): (dest, port_param, self._socknum_ll[0], (conn_mode,)), ) if resp[0][0] != 1: - raise RuntimeError("Could not connect to remote server") + raise ConnectionError("Could not connect to remote server") if conn_mode == ESP_SPIcontrol.TLS_MODE: self._tls_socket = socket_num @@ -824,7 +824,7 @@ def socket_close(self, socket_num): self._socknum_ll[0][0] = socket_num try: self._send_command_get_response(_STOP_CLIENT_TCP_CMD, self._socknum_ll) - except RuntimeError: + except OSError: pass if socket_num == self._tls_socket: self._tls_socket = None @@ -842,7 +842,7 @@ def start_server( resp = self._send_command_get_response(_START_SERVER_TCP_CMD, params) if resp[0][0] != 1: - raise RuntimeError("Could not start server") + raise OSError("Could not start server") def server_state(self, socket_num): """Get the state of the ESP32's internal reference server socket number""" @@ -863,7 +863,7 @@ def set_esp_debug(self, enabled): written to the ESP32's UART.""" resp = self._send_command_get_response(_SET_DEBUG_CMD, ((bool(enabled),),)) if resp[0][0] != 1: - raise RuntimeError("Failed to set debug mode") + raise OSError("Failed to set debug mode") def set_pin_mode(self, pin, mode): """Set the io mode for a GPIO pin. @@ -879,7 +879,7 @@ def set_pin_mode(self, pin, mode): pin_mode = mode resp = self._send_command_get_response(_SET_PIN_MODE_CMD, ((pin,), (pin_mode,))) if resp[0][0] != 1: - raise RuntimeError("Failed to set pin mode") + raise OSError("Failed to set pin mode") def set_digital_write(self, pin, value): """Set the digital output value of pin. @@ -891,7 +891,7 @@ def set_digital_write(self, pin, value): _SET_DIGITAL_WRITE_CMD, ((pin,), (value,)) ) if resp[0][0] != 1: - raise RuntimeError("Failed to write to pin") + raise OSError("Failed to write to pin") def set_analog_write(self, pin, analog_value): """Set the analog output value of pin, using PWM. @@ -904,7 +904,7 @@ def set_analog_write(self, pin, analog_value): _SET_ANALOG_WRITE_CMD, ((pin,), (value,)) ) if resp[0][0] != 1: - raise RuntimeError("Failed to write to pin") + raise OSError("Failed to write to pin") def set_digital_read(self, pin): """Get the digital input value of pin. Returns the boolean value of the pin. @@ -953,10 +953,10 @@ def get_time(self): raise ValueError("_GET_TIME returned 0") return resp_time if self.status in (WL_AP_LISTENING, WL_AP_CONNECTED): - raise RuntimeError( + raise OSError( "Cannot obtain NTP while in AP mode, must be connected to internet" ) - raise RuntimeError("Must be connected to WiFi before obtaining NTP.") + raise OSError("Must be connected to WiFi before obtaining NTP.") def set_certificate(self, client_certificate): """Sets client certificate. Must be called @@ -967,7 +967,7 @@ def set_certificate(self, client_certificate): if self._debug: print("** Setting client certificate") if self.status == WL_CONNECTED: - raise RuntimeError( + raise ValueError( "set_certificate must be called BEFORE a connection is established." ) if isinstance(client_certificate, str): @@ -977,7 +977,7 @@ def set_certificate(self, client_certificate): assert len(client_certificate) < 1300, ".PEM must be less than 1300 bytes." resp = self._send_command_get_response(_SET_CLI_CERT, (client_certificate,)) if resp[0][0] != 1: - raise RuntimeError("Failed to set client certificate") + raise OSError("Failed to set client certificate") self.set_crt = True return resp[0] @@ -990,7 +990,7 @@ def set_private_key(self, private_key): if self._debug: print("** Setting client's private key.") if self.status == WL_CONNECTED: - raise RuntimeError( + raise ValueError( "set_private_key must be called BEFORE a connection is established." ) if isinstance(private_key, str): @@ -1000,6 +1000,6 @@ def set_private_key(self, private_key): assert len(private_key) < 1700, ".PEM must be less than 1700 bytes." resp = self._send_command_get_response(_SET_PK, (private_key,)) if resp[0][0] != 1: - raise RuntimeError("Failed to set private key.") + raise OSError("Failed to set private key.") self.set_psk = True return resp[0] From d17790c85591bd0debb579e53b8bb95cce57a4b1 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:18:01 +0100 Subject: [PATCH 068/155] Make these more specific too --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index c35a94b..4a8cb2b 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -39,7 +39,7 @@ 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 RuntimeError("Port must be an integer") + raise ValueError("Port must be an integer") ipaddr = _the_interface.get_host_by_name(host) return [(AF_INET, socktype, proto, "", (ipaddr, port))] @@ -56,7 +56,7 @@ def __init__( self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None, socknum=None ): if family != AF_INET: - raise RuntimeError("Only AF_INET family supported") + raise ValueError("Only AF_INET family supported") self._type = type self._buffer = b"" self._socknum = socknum if socknum else _the_interface.get_socket() @@ -74,7 +74,7 @@ def connect(self, address, conntype=None): if not _the_interface.socket_connect( self._socknum, host, port, conn_mode=conntype ): - raise RuntimeError("Failed to connect to host", host) + raise ConnectionError("Failed to connect to host", host) self._buffer = b"" def send(self, data): # pylint: disable=no-self-use @@ -105,7 +105,7 @@ def readline(self, eol=b"\r\n"): self._buffer += _the_interface.socket_read(self._socknum, avail) elif self._timeout > 0 and time.monotonic() - stamp > self._timeout: self.close() # Make sure to close socket so that we don't exhaust sockets. - raise RuntimeError("Didn't receive full response, failing out") + raise OSError("Didn't receive full response, failing out") firstline, self._buffer = self._buffer.split(eol, 1) gc.collect() return firstline From c961c09417cc6e8b3757c92b0869114dbe8f4836 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:20:25 +0100 Subject: [PATCH 069/155] This now accepts the same set of errors - atlhough it could be more discerning --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 739f7a9..e1cccb5 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -144,7 +144,7 @@ def connect_normal(self): self.esp.connect_AP(bytes(ssid, "utf-8"), bytes(password, "utf-8")) failure_count = 0 self.pixel_status((0, 100, 0)) - except (ValueError, RuntimeError) as error: + except (ValueError, OSError) as error: print("Failed to connect, retrying\n", error) failure_count += 1 if failure_count >= self.attempts: @@ -173,7 +173,7 @@ def create_ap(self): self.esp.create_AP(bytes(self.ssid, "utf-8"), None) failure_count = 0 self.pixel_status((0, 100, 0)) - except (ValueError, RuntimeError) as error: + except (ValueError, OSError) as error: print("Failed to create access point\n", error) failure_count += 1 if failure_count >= self.attempts: @@ -203,7 +203,7 @@ def connect_enterprise(self): failure_count = 0 self.pixel_status((0, 100, 0)) sleep(1) - except (ValueError, RuntimeError) as error: + except (ValueError, OSError) as error: print("Failed to connect, retrying\n", error) failure_count += 1 if failure_count >= self.attempts: From f7d899c4ee87fa5a4c13fe56a51cbc769559042f Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Sun, 15 May 2022 12:21:51 -0400 Subject: [PATCH 070/155] Patch .pre-commit-config.yaml --- .pre-commit-config.yaml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7467c1d..3343606 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,40 +3,40 @@ # SPDX-License-Identifier: Unlicense repos: -- repo: https://github.com/python/black + - repo: https://github.com/python/black rev: 22.3.0 hooks: - - id: black -- repo: https://github.com/fsfe/reuse-tool - rev: v0.12.1 + - id: black + - repo: https://github.com/fsfe/reuse-tool + rev: v0.14.0 hooks: - - id: reuse -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.3.0 + - id: reuse + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.2.0 hooks: - - id: check-yaml - - id: end-of-file-fixer - - id: trailing-whitespace -- repo: https://github.com/pycqa/pylint + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/pycqa/pylint rev: v2.11.1 hooks: - - id: pylint + - id: pylint name: pylint (library code) types: [python] args: - --disable=consider-using-f-string exclude: "^(docs/|examples/|tests/|setup.py$)" - - id: pylint + - 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 + - --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 + - --disable=missing-docstring,consider-using-f-string,duplicate-code From 19e47fd5bb6fcc47da67d5f300d17d4d79649950 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:29:30 +0100 Subject: [PATCH 071/155] Make the suggested change for handling valueerrors. --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index e1cccb5..0070b94 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -144,7 +144,7 @@ def connect_normal(self): self.esp.connect_AP(bytes(ssid, "utf-8"), bytes(password, "utf-8")) failure_count = 0 self.pixel_status((0, 100, 0)) - except (ValueError, OSError) as error: + except OSError as error: print("Failed to connect, retrying\n", error) failure_count += 1 if failure_count >= self.attempts: @@ -173,7 +173,7 @@ def create_ap(self): self.esp.create_AP(bytes(self.ssid, "utf-8"), None) failure_count = 0 self.pixel_status((0, 100, 0)) - except (ValueError, OSError) as error: + except OSError as error: print("Failed to create access point\n", error) failure_count += 1 if failure_count >= self.attempts: @@ -203,7 +203,7 @@ def connect_enterprise(self): failure_count = 0 self.pixel_status((0, 100, 0)) sleep(1) - except (ValueError, OSError) as error: + except OSError as error: print("Failed to connect, retrying\n", error) failure_count += 1 if failure_count >= self.attempts: From fa311a1a4f7b1e0b38136a13e22b358355bbc420 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:30:37 +0100 Subject: [PATCH 072/155] These are definitely valueerrors. --- adafruit_esp32spi/digitalio.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index c935794..3e4cc15 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -61,7 +61,7 @@ def init(self, mode=IN): self._mode = self.OUT self._esp.set_pin_mode(self.pin_id, 1) else: - raise RuntimeError("Invalid mode defined") + raise ValueError("Invalid mode defined") def value(self, val=None): """Sets ESP32 Pin GPIO output mode. @@ -76,7 +76,7 @@ def value(self, val=None): self._value = val self._esp.set_digital_write(self.pin_id, 1) else: - raise RuntimeError("Invalid value for pin") + raise ValueError("Invalid value for pin") else: raise NotImplementedError( "digitalRead not currently implemented in esp32spi" From 1756c8166b47fc293d96b6963cc75293f420419f Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:32:29 +0100 Subject: [PATCH 073/155] Swap those runtime errors for OSerrors - most will be. Also removed some extraneous brackets on OSerrors. --- examples/esp32spi_simpletest.py | 2 +- examples/esp32spi_simpletest_rp2040.py | 2 +- examples/gpio/esp32spi_gpio.py | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index af8c2f1..7e01ad6 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -59,7 +59,7 @@ while not esp.is_connected: try: esp.connect_AP(secrets["ssid"], secrets["password"]) - except RuntimeError as e: + except OSError as e: print("could not connect to AP, retrying: ", e) continue print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index eb52592..decd13e 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -42,7 +42,7 @@ while not esp.is_connected: try: esp.connect_AP(secrets["ssid"], secrets["password"]) - except RuntimeError as e: + except OSError as e: print("could not connect to AP, retrying: ", e) continue print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) diff --git a/examples/gpio/esp32spi_gpio.py b/examples/gpio/esp32spi_gpio.py index a9c857d..866fd63 100644 --- a/examples/gpio/esp32spi_gpio.py +++ b/examples/gpio/esp32spi_gpio.py @@ -94,7 +94,7 @@ def esp_init_pin_modes(din, dout): esp_init_pin_modes(ESP_D_R_PIN, ESP_D_W_PIN) esp_d_r_val = esp.set_digital_read(ESP_D_R_PIN) print("--> ESP read:", esp_d_r_val) - except (RuntimeError, AssertionError) as e: + except (OSError, AssertionError) as e: print("ESP32 Error", e) esp_reset_all() @@ -104,7 +104,7 @@ def esp_init_pin_modes(din, dout): esp_init_pin_modes(ESP_D_R_PIN, ESP_D_W_PIN) esp.set_digital_write(ESP_D_W_PIN, esp_d_w_val) print("ESP wrote:", esp_d_w_val, "--> Red LED") - except (RuntimeError) as e: + except OSError as e: print("ESP32 Error", e) esp_reset_all() @@ -121,7 +121,7 @@ def esp_init_pin_modes(din, dout): "v)", sep="", ) - except (RuntimeError, AssertionError) as e: + except (OSError, AssertionError) as e: print("ESP32 Error", e) esp_reset_all() @@ -166,7 +166,7 @@ def esp_init_pin_modes(din, dout): sep="", ) - except (RuntimeError) as e: + except OSError as e: print("ESP32 Error", e) esp_reset_all() From 39c672d42fba4fa2e496fe43f3a4e76c4e506313 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:32:44 +0100 Subject: [PATCH 074/155] More runtime error catches --- examples/esp32spi_aio_post.py | 2 +- examples/esp32spi_cheerlights.py | 2 +- examples/esp32spi_ipconfig.py | 2 +- examples/esp32spi_localtime.py | 2 +- examples/esp32spi_wpa2ent_aio_post.py | 2 +- examples/server/esp32spi_wsgiserver.py | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index b74e4e3..75cae78 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -66,7 +66,7 @@ response.close() counter = counter + 1 print("OK") - except (ValueError, RuntimeError) as e: + except (ValueError, OSError) as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index 46d75af..03ed3f3 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -54,7 +54,7 @@ value = value[key] print(value) response.close() - except (ValueError, RuntimeError) as e: + except (ValueError, OSError) as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index 01f01c8..5f67044 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -49,7 +49,7 @@ while not esp.is_connected: try: esp.connect_AP(secrets["ssid"], secrets["password"]) - except RuntimeError as e: + except OSError as e: print("could not connect to AP, retrying: ", e) continue print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index 1c27304..d610c69 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -42,7 +42,7 @@ print("Fetching json from", TIME_API) response = wifi.get(TIME_API) break - except (ValueError, RuntimeError) as e: + except (ValueError, OSError) as e: print("Failed to get data, retrying\n", e) continue diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index b6bdd99..42701c7 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -63,7 +63,7 @@ response.close() counter = counter + 1 print("OK") - except (ValueError, RuntimeError) as e: + except (ValueError, OSError) as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/server/esp32spi_wsgiserver.py b/examples/server/esp32spi_wsgiserver.py index d9f0979..af7daa2 100755 --- a/examples/server/esp32spi_wsgiserver.py +++ b/examples/server/esp32spi_wsgiserver.py @@ -213,7 +213,7 @@ def led_color(environ): # pylint: disable=unused-argument static ) ) -except (OSError) as e: +except OSError as e: raise RuntimeError( """ This example depends on a static asset directory. @@ -240,7 +240,7 @@ def led_color(environ): # pylint: disable=unused-argument try: wsgiServer.update_poll() # Could do any other background tasks here, like reading sensors - except (ValueError, RuntimeError) as e: + except (ValueError, OSError) as e: print("Failed to update server, restarting ESP32\n", e) wifi.reset() continue From 71f38569aa0c192fb08c1287bea141c34260916a Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:35:29 +0100 Subject: [PATCH 075/155] The parts that can raise assertion errors are not recoverable. --- examples/gpio/esp32spi_gpio.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gpio/esp32spi_gpio.py b/examples/gpio/esp32spi_gpio.py index 866fd63..6d7723b 100644 --- a/examples/gpio/esp32spi_gpio.py +++ b/examples/gpio/esp32spi_gpio.py @@ -94,7 +94,7 @@ def esp_init_pin_modes(din, dout): esp_init_pin_modes(ESP_D_R_PIN, ESP_D_W_PIN) esp_d_r_val = esp.set_digital_read(ESP_D_R_PIN) print("--> ESP read:", esp_d_r_val) - except (OSError, AssertionError) as e: + except OSError as e: print("ESP32 Error", e) esp_reset_all() @@ -121,7 +121,7 @@ def esp_init_pin_modes(din, dout): "v)", sep="", ) - except (OSError, AssertionError) as e: + except OSError as e: print("ESP32 Error", e) esp_reset_all() From df4112ac2209bd696449ef31d275eacfa7f1a962 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:44:46 +0100 Subject: [PATCH 076/155] These are OSErrors - or connection errors, we got an unexpected response from the spi device. --- adafruit_esp32spi/adafruit_esp32spi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 2cb9369..2cd2d4e 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -920,7 +920,7 @@ def set_digital_read(self, pin): return False if resp[0] == 1: return True - raise ValueError( + raise OSError( "_SET_DIGITAL_READ response error: response is not boolean", resp[0] ) @@ -950,7 +950,7 @@ def get_time(self): resp = self._send_command_get_response(_GET_TIME) resp_time = struct.unpack(" Date: Tue, 17 May 2022 15:46:22 +0100 Subject: [PATCH 077/155] The value errors caught in these wouldn't be recoverable, but the OS errors may be. --- examples/esp32spi_aio_post.py | 2 +- examples/esp32spi_cheerlights.py | 2 +- examples/esp32spi_localtime.py | 2 +- examples/esp32spi_wpa2ent_aio_post.py | 2 +- examples/server/esp32spi_wsgiserver.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index 75cae78..ef24db7 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -66,7 +66,7 @@ response.close() counter = counter + 1 print("OK") - except (ValueError, OSError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index 03ed3f3..7ded593 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -54,7 +54,7 @@ value = value[key] print(value) response.close() - except (ValueError, OSError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index d610c69..01dd93b 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -42,7 +42,7 @@ print("Fetching json from", TIME_API) response = wifi.get(TIME_API) break - except (ValueError, OSError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) continue diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index 42701c7..227bf91 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -63,7 +63,7 @@ response.close() counter = counter + 1 print("OK") - except (ValueError, OSError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/server/esp32spi_wsgiserver.py b/examples/server/esp32spi_wsgiserver.py index af7daa2..0220d2f 100755 --- a/examples/server/esp32spi_wsgiserver.py +++ b/examples/server/esp32spi_wsgiserver.py @@ -240,7 +240,7 @@ def led_color(environ): # pylint: disable=unused-argument try: wsgiServer.update_poll() # Could do any other background tasks here, like reading sensors - except (ValueError, OSError) as e: + except OSError as e: print("Failed to update server, restarting ESP32\n", e) wifi.reset() continue From 753d766a934716716fafa1eff0d8aae7f57a530d Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Sun, 22 May 2022 00:18:55 -0400 Subject: [PATCH 078/155] Increase min lines similarity Signed-off-by: Alec Delaney --- .pylintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index d6fefec..1056d5b 100644 --- a/.pylintrc +++ b/.pylintrc @@ -252,7 +252,7 @@ ignore-docstrings=yes ignore-imports=yes # Minimum lines number of a similarity. -min-similarity-lines=4 +min-similarity-lines=12 [BASIC] From 7e0796c9ec3909515df9b35e67b8ed9d9785dfed Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Sun, 22 May 2022 00:18:23 -0400 Subject: [PATCH 079/155] Switch to inclusive terminology Signed-off-by: Alec Delaney --- .pylintrc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pylintrc b/.pylintrc index 1056d5b..27c6c07 100644 --- a/.pylintrc +++ b/.pylintrc @@ -9,11 +9,11 @@ # run arbitrary code extension-pkg-whitelist= -# Add files or directories to the blacklist. They should be base names, not +# 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 blacklist. The +# Add files or directories matching the regex patterns to the ignore-list. The # regex matches against base names, not paths. ignore-patterns= From db2cc2518cac226e85bb81c4accbfb4501ac9d27 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 28 May 2022 08:56:40 -0400 Subject: [PATCH 080/155] fix recv_into for larger fetches --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 56 ++++++++----------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index c35a94b..1e92c47 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -161,44 +161,36 @@ def recv(self, bufsize=0): gc.collect() return ret - def recv_into(self, buffer, nbytes=0): - """Read some bytes from the connected remote address into a given buffer + def recv_into(self, buffer, nbytes: int = 0): + """Read bytes from the connected remote address into a given buffer. - :param bytearray buffer: The buffer to read into - :param int nbytes: (Optional) Number of bytes to receive default is 0, - which will receive as many bytes as possible before filling the + :param bytearray buffer: the buffer to read into + :param int nbytes: maximum number of bytes to receive; if 0, + receive as many bytes as possible before filling the buffer or timing out """ - if not 0 <= nbytes <= len(buffer): - raise ValueError( - "Can only read number of bytes between 0 and length of supplied buffer" - ) - - stamp = time.monotonic() - to_read = len(buffer) - limit = 0 if nbytes == 0 else to_read - nbytes - received = [] - while to_read > limit: - # print("Bytes to read:", to_read) - avail = self.available() - if avail: - stamp = time.monotonic() - recv = _the_interface.socket_read(self._socknum, min(to_read, avail)) - received.append(recv) - start = len(buffer) - to_read - to_read -= len(recv) - end = len(buffer) - to_read - buffer[start:end] = bytearray(recv) - gc.collect() - elif received: - # We've received some bytes but no more are available. So return - # what we have. + raise ValueError("nbytes must be 0 to len(buffer)") + + last_read_time = time.monotonic() + num_to_read = len(buffer) if nbytes == 0 else nbytes + num_read = 0 + while num_read < num_to_read: + num_avail = self.available() + if num_avail > 0: + last_read_time = time.monotonic() + bytes_read = _the_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) + elif num_read > 0: + # We got a message, but there are no more bytes to read, so we can stop. break - if self._timeout > 0 and time.monotonic() - stamp > self._timeout: + # No bytes yet, or more byte requested. + if self._timeout > 0 and time.monotonic() - last_read_time > self._timeout: break - gc.collect() - return len(buffer) - to_read + return num_read def read(self, size=0): """Read up to 'size' bytes from the socket, this may be buffered internally! From 5b5c5c616ef3a15fd7c30c9161f6ca24b8a5296c Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 28 May 2022 09:14:43 -0400 Subject: [PATCH 081/155] Remove non-CPython socket methods; remove wsgi server --- adafruit_esp32spi/adafruit_esp32spi.py | 2 +- adafruit_esp32spi/adafruit_esp32spi_socket.py | 156 +++-------- .../adafruit_esp32spi_wsgiserver.py | 227 ---------------- examples/server/esp32spi_wsgiserver.py | 246 ------------------ examples/server/static/index.html | 16 -- .../server/static/led_color_picker_example.js | 129 --------- 6 files changed, 37 insertions(+), 739 deletions(-) delete mode 100644 adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py delete mode 100755 examples/server/esp32spi_wsgiserver.py delete mode 100755 examples/server/static/index.html delete mode 100755 examples/server/static/led_color_picker_example.js diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index fae4cc6..7d82c6b 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -780,7 +780,7 @@ def socket_available(self, socket_num): return reply def socket_read(self, socket_num, size): - """Read up to 'size' bytes from the socket number. Returns a bytearray""" + """Read up to 'size' bytes from the socket number. Returns a bytes""" if self._debug: print( "Reading %d bytes from ESP socket with status %d" diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index c35a94b..d08f090 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -86,144 +86,65 @@ def send(self, data): # pylint: disable=no-self-use _the_interface.socket_write(self._socknum, data, conn_mode=conntype) gc.collect() - def write(self, data): - """Sends data to the socket. - NOTE: This method is deprecated and will be removed. - """ - self.send(data) - - def readline(self, eol=b"\r\n"): - """Attempt to return as many bytes as we can up to but not including - end-of-line character (default is '\\r\\n')""" - - # print("Socket readline") - stamp = time.monotonic() - while eol not in self._buffer: - # there's no line already in there, read some more - avail = self.available() - if avail: - self._buffer += _the_interface.socket_read(self._socknum, avail) - elif self._timeout > 0 and time.monotonic() - stamp > self._timeout: - self.close() # Make sure to close socket so that we don't exhaust sockets. - raise RuntimeError("Didn't receive full response, failing out") - firstline, self._buffer = self._buffer.split(eol, 1) - gc.collect() - return firstline - - def recv(self, bufsize=0): + def recv(self, bufsize: int): """Reads some bytes from the connected remote address. Will only return an empty string after the configured timeout. :param int bufsize: maximum number of bytes to receive """ - # print("Socket read", bufsize) - if bufsize == 0: # read as much as we can at the moment - while True: - avail = self.available() - if avail: - self._buffer += _the_interface.socket_read(self._socknum, avail) - else: - break - gc.collect() - ret = self._buffer - self._buffer = b"" - gc.collect() - return ret - stamp = time.monotonic() - - to_read = bufsize - len(self._buffer) - received = [] - while to_read > 0: - # print("Bytes to read:", to_read) - avail = self.available() - if avail: - stamp = time.monotonic() - recv = _the_interface.socket_read(self._socknum, min(to_read, avail)) - received.append(recv) - to_read -= len(recv) - gc.collect() - elif received: - # We've received some bytes but no more are available. So return - # what we have. - break - if self._timeout > 0 and time.monotonic() - stamp > self._timeout: - break - # print(received) - self._buffer += b"".join(received) - - ret = None - if len(self._buffer) == bufsize: - ret = self._buffer - self._buffer = b"" - else: - ret = self._buffer[:bufsize] - self._buffer = self._buffer[bufsize:] - gc.collect() - return ret + buf = bytearray(bufsize) + self.recv_into(buf, bufsize) - def recv_into(self, buffer, nbytes=0): - """Read some bytes from the connected remote address into a given buffer + def recv_into(self, buffer, nbytes: int = 0): + """Read bytes from the connected remote address into a given buffer. - :param bytearray buffer: The buffer to read into - :param int nbytes: (Optional) Number of bytes to receive default is 0, - which will receive as many bytes as possible before filling the + :param bytearray buffer: the buffer to read into + :param int nbytes: maximum number of bytes to receive; if 0, + receive as many bytes as possible before filling the buffer or timing out """ - if not 0 <= nbytes <= len(buffer): - raise ValueError( - "Can only read number of bytes between 0 and length of supplied buffer" - ) - - stamp = time.monotonic() - to_read = len(buffer) - limit = 0 if nbytes == 0 else to_read - nbytes - received = [] - while to_read > limit: - # print("Bytes to read:", to_read) - avail = self.available() - if avail: - stamp = time.monotonic() - recv = _the_interface.socket_read(self._socknum, min(to_read, avail)) - received.append(recv) - start = len(buffer) - to_read - to_read -= len(recv) - end = len(buffer) - to_read - buffer[start:end] = bytearray(recv) - gc.collect() - elif received: - # We've received some bytes but no more are available. So return - # what we have. + raise ValueError("nbytes must be 0 to len(buffer)") + + last_read_time = time.monotonic() + num_to_read = len(buffer) if nbytes == 0 else nbytes + num_read = 0 + while num_read < num_to_read: + num_avail = self._available() + if num_avail > 0: + last_read_time = time.monotonic() + bytes_read = _the_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) + elif num_read > 0: + # We got a message, but there are no more bytes to read, so we can stop. break - if self._timeout > 0 and time.monotonic() - stamp > self._timeout: + # No bytes yet, or more byte requested. + if self._timeout > 0 and time.monotonic() - last_read_time > self._timeout: break - gc.collect() - return len(buffer) - to_read - - def read(self, size=0): - """Read up to 'size' bytes from the socket, this may be buffered internally! - If 'size' isnt specified, return everything in the buffer. - NOTE: This method is deprecated and will be removed. - """ - return self.recv(size) + return num_read def settimeout(self, value): - """Set the read timeout for sockets, if value is 0 it will block""" + """Set the read timeout for sockets. + If value is 0 socket reads will block until a message is available. + """ self._timeout = value - def available(self): + 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: + if self._socknum != NO_SOCKET_AVAIL: return min(_the_interface.socket_available(self._socknum), MAX_PACKET) return 0 - def connected(self): + def _connected(self): """Whether or not we are connected to the socket""" - if self.socknum == NO_SOCKET_AVAIL: + if self._socknum == NO_SOCKET_AVAIL: return False - if self.available(): + if self._available(): return True - status = _the_interface.socket_status(self.socknum) + status = _the_interface.socket_status(self._socknum) result = status not in ( adafruit_esp32spi.SOCKET_LISTEN, adafruit_esp32spi.SOCKET_CLOSED, @@ -239,11 +160,6 @@ def connected(self): self._socknum = NO_SOCKET_AVAIL return result - @property - def socknum(self): - """The socket number""" - return self._socknum - def close(self): """Close the socket, after reading whatever remains""" _the_interface.socket_close(self._socknum) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py deleted file mode 100644 index 956a36c..0000000 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ /dev/null @@ -1,227 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2019 Matt Costi for Adafruit Industries -# -# SPDX-License-Identifier: MIT - -""" -`adafruit_esp32spi_wsgiserver` -================================================================================ - -A simple WSGI (Web Server Gateway Interface) server that interfaces with the ESP32 over SPI. -Opens a specified port on the ESP32 to listen for incoming HTTP Requests and -Accepts an Application object that must be callable, which gets called -whenever a new HTTP Request has been received. - -The Application MUST accept 2 ordered parameters: - 1. environ object (incoming request data) - 2. start_response function. Must be called before the Application - callable returns, in order to set the response status and headers. - -The Application MUST return a single string in a list, -which is the response data - -Requires update_poll being called in the applications main event loop. - -For more details about Python WSGI see: -https://www.python.org/dev/peps/pep-0333/ - -* Author(s): Matt Costi -""" -# pylint: disable=no-name-in-module - -import io -import gc -from micropython import const -import adafruit_esp32spi.adafruit_esp32spi_socket as socket - -_the_interface = None # pylint: disable=invalid-name - - -def set_interface(iface): - """Helper to set the global internet interface""" - global _the_interface # pylint: disable=global-statement, invalid-name - _the_interface = iface - socket.set_interface(iface) - - -NO_SOCK_AVAIL = const(255) - - -def parse_headers(client): - """ - Parses the header portion of an HTTP request from the socket. - Expects first line of HTTP request to have been read already. - """ - headers = {} - while True: - line = str(client.readline(), "utf-8") - if not line: - break - title, content = line.split(":", 1) - headers[title.strip().lower()] = content.strip() - return headers - - -# pylint: disable=invalid-name -class WSGIServer: - """ - A simple server that implements the WSGI interface - """ - - def __init__(self, port=80, debug=False, application=None): - self.application = application - self.port = port - self._server_sock = socket.socket(socknum=NO_SOCK_AVAIL) - self._client_sock = socket.socket(socknum=NO_SOCK_AVAIL) - self._debug = debug - - self._response_status = None - self._response_headers = [] - - def start(self): - """ - starts the server and begins listening for incoming connections. - Call update_poll in the main loop for the application callable to be - invoked on receiving an incoming request. - """ - self._server_sock = socket.socket() - _the_interface.start_server(self.port, self._server_sock.socknum) - if self._debug: - ip = _the_interface.pretty_ip(_the_interface.ip_address) - print("Server available at {0}:{1}".format(ip, self.port)) - print( - "Server status: ", - _the_interface.server_state(self._server_sock.socknum), - ) - - def update_poll(self): - """ - Call this method inside your main event loop to get the server - check for new incoming client requests. When a request comes in, - the application callable will be invoked. - """ - self.client_available() - if self._client_sock and self._client_sock.available(): - environ = self._get_environ(self._client_sock) - result = self.application(environ, self._start_response) - self.finish_response(result) - - def finish_response(self, result): - """ - Called after the application callbile returns result data to respond with. - Creates the HTTP Response payload from the response_headers and results data, - and sends it back to client. - - :param string result: the data string to send back in the response to the client. - """ - try: - response = "HTTP/1.1 {0}\r\n".format(self._response_status or "500 ISE") - for header in self._response_headers: - response += "{0}: {1}\r\n".format(*header) - response += "\r\n" - self._client_sock.send(response.encode("utf-8")) - for data in result: - if isinstance(data, bytes): - self._client_sock.send(data) - else: - self._client_sock.send(data.encode("utf-8")) - gc.collect() - finally: - if self._debug > 2: - print("closing") - self._client_sock.close() - - def client_available(self): - """ - returns a client socket connection if available. - Otherwise, returns None - :return: the client - :rtype: Socket - """ - sock = None - if self._server_sock.socknum != NO_SOCK_AVAIL: - if self._client_sock.socknum != NO_SOCK_AVAIL: - # check previous received client socket - if self._debug > 2: - print("checking if last client sock still valid") - if self._client_sock.connected() and self._client_sock.available(): - sock = self._client_sock - if not sock: - # check for new client sock - if self._debug > 2: - print("checking for new client sock") - client_sock_num = _the_interface.socket_available( - self._server_sock.socknum - ) - sock = socket.socket(socknum=client_sock_num) - else: - print("Server has not been started, cannot check for clients!") - - if sock and sock.socknum != NO_SOCK_AVAIL: - if self._debug > 2: - print("client sock num is: ", sock.socknum) - self._client_sock = sock - return self._client_sock - - return None - - def _start_response(self, status, response_headers): - """ - The application callable will be given this method as the second param - This is to be called before the application callable returns, to signify - the response can be started with the given status and headers. - - :param string status: a status string including the code and reason. ex: "200 OK" - :param list response_headers: a list of tuples to represent the headers. - ex ("header-name", "header value") - """ - self._response_status = status - self._response_headers = [ - ("Server", "esp32WSGIServer"), - ("Connection", "close"), - ] + response_headers - - def _get_environ(self, client): - """ - The application callable will be given the resulting environ dictionary. - It contains metadata about the incoming request and the request body ("wsgi.input") - - :param Socket client: socket to read the request from - """ - env = {} - line = str(client.readline(), "utf-8") - (method, path, ver) = line.rstrip("\r\n").split(None, 2) - - env["wsgi.version"] = (1, 0) - env["wsgi.url_scheme"] = "http" - env["wsgi.multithread"] = False - env["wsgi.multiprocess"] = False - env["wsgi.run_once"] = False - - env["REQUEST_METHOD"] = method - env["SCRIPT_NAME"] = "" - env["SERVER_NAME"] = _the_interface.pretty_ip(_the_interface.ip_address) - env["SERVER_PROTOCOL"] = ver - env["SERVER_PORT"] = self.port - if path.find("?") >= 0: - env["PATH_INFO"] = path.split("?")[0] - env["QUERY_STRING"] = path.split("?")[1] - else: - env["PATH_INFO"] = path - - headers = parse_headers(client) - if "content-type" in headers: - env["CONTENT_TYPE"] = headers.get("content-type") - if "content-length" in headers: - env["CONTENT_LENGTH"] = headers.get("content-length") - body = client.read(int(env["CONTENT_LENGTH"])) - env["wsgi.input"] = io.StringIO(body) - else: - body = client.read() - env["wsgi.input"] = io.StringIO(body) - for name, value in headers.items(): - key = "HTTP_" + name.replace("-", "_").upper() - if key in env: - value = "{0},{1}".format(env[key], value) - env[key] = value - - return env diff --git a/examples/server/esp32spi_wsgiserver.py b/examples/server/esp32spi_wsgiserver.py deleted file mode 100755 index d9f0979..0000000 --- a/examples/server/esp32spi_wsgiserver.py +++ /dev/null @@ -1,246 +0,0 @@ -# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries -# -# SPDX-License-Identifier: MIT - -import os -import board -import busio -from digitalio import DigitalInOut -import neopixel - -from adafruit_esp32spi import adafruit_esp32spi -import adafruit_esp32spi.adafruit_esp32spi_wifimanager as wifimanager -import adafruit_esp32spi.adafruit_esp32spi_wsgiserver as server - -# This example depends on the 'static' folder in the examples folder -# being copied to the root of the circuitpython filesystem. -# This is where our static assets like html, js, and css live. - -# 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 - -try: - import json as json_module -except ImportError: - import ujson as json_module - -print("ESP32 SPI simple web server test!") - -# 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) - -spi = busio.SPI(board.SCK, board.MOSI, board.MISO) -esp = adafruit_esp32spi.ESP_SPIcontrol( - spi, esp32_cs, esp32_ready, esp32_reset -) # pylint: disable=line-too-long - -print("MAC addr:", [hex(i) for i in esp.MAC_address]) -print("MAC addr actual:", [hex(i) for i in esp.MAC_address_actual]) - -# Use below for Most Boards -status_light = neopixel.NeoPixel( - board.NEOPIXEL, 1, brightness=0.2 -) # Uncomment for Most Boards -# Uncomment below for ItsyBitsy M4 -# import adafruit_dotstar as dotstar -# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=1) - -## If you want to connect to wifi with secrets: -wifi = wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) -wifi.connect() - -## If you want to create a WIFI hotspot to connect to with secrets: -# secrets = {"ssid": "My ESP32 AP!", "password": "supersecret"} -# wifi = wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) -# wifi.create_ap() - -## To you want to create an un-protected WIFI hotspot to connect to with secrets:" -# secrets = {"ssid": "My ESP32 AP!"} -# wifi = wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light) -# wifi.create_ap() - - -class SimpleWSGIApplication: - """ - An example of a simple WSGI Application that supports - basic route handling and static asset file serving for common file types - """ - - INDEX = "/index.html" - CHUNK_SIZE = 8912 # max number of bytes to read at once when reading files - - def __init__(self, static_dir=None, debug=False): - self._debug = debug - self._listeners = {} - self._start_response = None - self._static = static_dir - if self._static: - self._static_files = ["/" + file for file in os.listdir(self._static)] - - def __call__(self, environ, start_response): - """ - Called whenever the server gets a request. - The environ dict has details about the request per wsgi specification. - Call start_response with the response status string and headers as a list of tuples. - Return a single item list with the item being your response data string. - """ - if self._debug: - self._log_environ(environ) - - self._start_response = start_response - status = "" - headers = [] - resp_data = [] - - key = self._get_listener_key( - environ["REQUEST_METHOD"].lower(), environ["PATH_INFO"] - ) - if key in self._listeners: - status, headers, resp_data = self._listeners[key](environ) - if environ["REQUEST_METHOD"].lower() == "get" and self._static: - path = environ["PATH_INFO"] - if path in self._static_files: - status, headers, resp_data = self.serve_file( - path, directory=self._static - ) - elif path == "/" and self.INDEX in self._static_files: - status, headers, resp_data = self.serve_file( - self.INDEX, directory=self._static - ) - - self._start_response(status, headers) - return resp_data - - def on(self, method, path, request_handler): - """ - Register a Request Handler for a particular HTTP method and path. - request_handler will be called whenever a matching HTTP request is received. - - request_handler should accept the following args: - (Dict environ) - request_handler should return a tuple in the shape of: - (status, header_list, data_iterable) - - :param str method: the method of the HTTP request - :param str path: the path of the HTTP request - :param func request_handler: the function to call - """ - self._listeners[self._get_listener_key(method, path)] = request_handler - - def serve_file(self, file_path, directory=None): - status = "200 OK" - headers = [("Content-Type", self._get_content_type(file_path))] - - full_path = file_path if not directory else directory + file_path - - def resp_iter(): - with open(full_path, "rb") as file: - while True: - chunk = file.read(self.CHUNK_SIZE) - if chunk: - yield chunk - else: - break - - return (status, headers, resp_iter()) - - def _log_environ(self, environ): # pylint: disable=no-self-use - print("environ map:") - for name, value in environ.items(): - print(name, value) - - def _get_listener_key(self, method, path): # pylint: disable=no-self-use - return "{0}|{1}".format(method.lower(), path) - - def _get_content_type(self, file): # pylint: disable=no-self-use - ext = file.split(".")[-1] - if ext in ("html", "htm"): - return "text/html" - if ext == "js": - return "application/javascript" - if ext == "css": - return "text/css" - if ext in ("jpg", "jpeg"): - return "image/jpeg" - if ext == "png": - return "image/png" - return "text/plain" - - -# Our HTTP Request handlers -def led_on(environ): # pylint: disable=unused-argument - print("led on!") - status_light.fill((0, 0, 100)) - return web_app.serve_file("static/index.html") - - -def led_off(environ): # pylint: disable=unused-argument - print("led off!") - status_light.fill(0) - return web_app.serve_file("static/index.html") - - -def led_color(environ): # pylint: disable=unused-argument - json = json_module.loads(environ["wsgi.input"].getvalue()) - print(json) - rgb_tuple = (json.get("r"), json.get("g"), json.get("b")) - status_light.fill(rgb_tuple) - return ("200 OK", [], []) - - -# Here we create our application, setting the static directory location -# and registering the above request_handlers for specific HTTP requests -# we want to listen and respond to. -static = "/static" -try: - static_files = os.listdir(static) - if "index.html" not in static_files: - raise RuntimeError( - """ - This example depends on an index.html, but it isn't present. - Please add it to the {0} directory""".format( - static - ) - ) -except (OSError) as e: - raise RuntimeError( - """ - This example depends on a static asset directory. - Please create one named {0} in the root of the device filesystem.""".format( - static - ) - ) from e - -web_app = SimpleWSGIApplication(static_dir=static) -web_app.on("GET", "/led_on", led_on) -web_app.on("GET", "/led_off", led_off) -web_app.on("POST", "/ajax/ledcolor", led_color) - -# Here we setup our server, passing in our web_app as the application -server.set_interface(esp) -wsgiServer = server.WSGIServer(80, application=web_app) - -print("open this IP in your browser: ", esp.pretty_ip(esp.ip_address)) - -# Start the server -wsgiServer.start() -while True: - # Our main loop where we have the server poll for incoming requests - try: - wsgiServer.update_poll() - # Could do any other background tasks here, like reading sensors - except (ValueError, RuntimeError) as e: - print("Failed to update server, restarting ESP32\n", e) - wifi.reset() - continue diff --git a/examples/server/static/index.html b/examples/server/static/index.html deleted file mode 100755 index df08ec7..0000000 --- a/examples/server/static/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - -

LED color picker demo!

- - - diff --git a/examples/server/static/led_color_picker_example.js b/examples/server/static/led_color_picker_example.js deleted file mode 100755 index 810ca44..0000000 --- a/examples/server/static/led_color_picker_example.js +++ /dev/null @@ -1,129 +0,0 @@ -// SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -let canvas = document.getElementById('colorPicker'); -let ctx = canvas.getContext("2d"); -ctx.width = 300; -ctx.height = 300; - -function drawColorPicker() { - /** - * Color picker inspired by: - * https://medium.com/@bantic/hand-coding-a-color-wheel-with-canvas-78256c9d7d43 - */ - let radius = 150; - let image = ctx.createImageData(2*radius, 2*radius); - let data = image.data; - - for (let x = -radius; x < radius; x++) { - for (let y = -radius; y < radius; y++) { - - let [r, phi] = xy2polar(x, y); - - if (r > radius) { - // skip all (x,y) coordinates that are outside of the circle - continue; - } - - let deg = rad2deg(phi); - - // Figure out the starting index of this pixel in the image data array. - let rowLength = 2*radius; - let adjustedX = x + radius; // convert x from [-50, 50] to [0, 100] (the coordinates of the image data array) - let adjustedY = y + radius; // convert y from [-50, 50] to [0, 100] (the coordinates of the image data array) - let pixelWidth = 4; // each pixel requires 4 slots in the data array - let index = (adjustedX + (adjustedY * rowLength)) * pixelWidth; - - let hue = deg; - let saturation = r / radius; - let value = 1.0; - - let [red, green, blue] = hsv2rgb(hue, saturation, value); - let alpha = 255; - - data[index] = red; - data[index+1] = green; - data[index+2] = blue; - data[index+3] = alpha; - } - } - - ctx.putImageData(image, 0, 0); -} - -function xy2polar(x, y) { - let r = Math.sqrt(x*x + y*y); - let phi = Math.atan2(y, x); - return [r, phi]; -} - -// rad in [-π, π] range -// return degree in [0, 360] range -function rad2deg(rad) { - return ((rad + Math.PI) / (2 * Math.PI)) * 360; -} - - // hue in range [0, 360] - // saturation, value in range [0,1] - // return [r,g,b] each in range [0,255] - // See: https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV -function hsv2rgb(hue, saturation, value) { - let chroma = value * saturation; - let hue1 = hue / 60; - let x = chroma * (1- Math.abs((hue1 % 2) - 1)); - let r1, g1, b1; - if (hue1 >= 0 && hue1 <= 1) { - ([r1, g1, b1] = [chroma, x, 0]); - } else if (hue1 >= 1 && hue1 <= 2) { - ([r1, g1, b1] = [x, chroma, 0]); - } else if (hue1 >= 2 && hue1 <= 3) { - ([r1, g1, b1] = [0, chroma, x]); - } else if (hue1 >= 3 && hue1 <= 4) { - ([r1, g1, b1] = [0, x, chroma]); - } else if (hue1 >= 4 && hue1 <= 5) { - ([r1, g1, b1] = [x, 0, chroma]); - } else if (hue1 >= 5 && hue1 <= 6) { - ([r1, g1, b1] = [chroma, 0, x]); - } - - let m = value - chroma; - let [r,g,b] = [r1+m, g1+m, b1+m]; - - // Change r,g,b values from [0,1] to [0,255] - return [255*r,255*g,255*b]; -} - -function onColorPick(event) { - coords = getCursorPosition(canvas, event) - imageData = ctx.getImageData(coords[0],coords[1],1,1) - rgbObject = { - r: imageData.data[0], - g: imageData.data[1], - b: imageData.data[2] - } - console.log(`r: ${rgbObject.r} g: ${rgbObject.g} b: ${rgbObject.b}`); - data = JSON.stringify(rgbObject); - window.fetch("/ajax/ledcolor", { - method: "POST", - body: data, - headers: { - 'Content-Type': 'application/json; charset=utf-8', - }, - }).then(response => { - console.log("sucess!: " + response) - }, error => { - console.log("error!: " + error) - }) -} - -function getCursorPosition(canvas, event) { - const rect = canvas.getBoundingClientRect() - const x = event.clientX - rect.left - const y = event.clientY - rect.top - console.log("x: " + x + " y: " + y) - return [x,y] -} - -drawColorPicker(); -canvas.addEventListener('mousedown', onColorPick); From 43d6243ab6ba18ab5e134cff8ec18fe40acc538a Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 28 May 2022 09:27:39 -0400 Subject: [PATCH 082/155] Remove non-CPython socket methods; remove wsgi server --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 3 ++- docs/api.rst | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index d08f090..c5c3573 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -86,7 +86,7 @@ def send(self, data): # pylint: disable=no-self-use _the_interface.socket_write(self._socknum, data, conn_mode=conntype) gc.collect() - def recv(self, bufsize: int): + def recv(self, bufsize: int) -> bytes: """Reads some bytes from the connected remote address. Will only return an empty string after the configured timeout. @@ -94,6 +94,7 @@ def recv(self, bufsize: int): """ buf = bytearray(bufsize) self.recv_into(buf, bufsize) + return bytes(buf) def recv_into(self, buffer, nbytes: int = 0): """Read bytes from the connected remote address into a given buffer. diff --git a/docs/api.rst b/docs/api.rst index 9da4926..0cfe5a8 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -13,9 +13,6 @@ .. automodule:: adafruit_esp32spi.adafruit_esp32spi_wifimanager :members: -.. automodule:: adafruit_esp32spi.adafruit_esp32spi_wsgiserver - :members: - .. automodule:: adafruit_esp32spi.digitalio :members: From 7b5985d096a5375f7a70228c8c3b6d6d22a5a57a Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Mon, 30 May 2022 14:25:04 -0400 Subject: [PATCH 083/155] Set language to "en" for documentation Signed-off-by: Alec Delaney --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 53953b2..bc466b6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -64,7 +64,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. From 91c4396b20b2d857b8ff5403fe5ac72a23fbd79d Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 6 Jun 2022 23:49:17 -0400 Subject: [PATCH 084/155] fix recv_into again --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index 1e92c47..fa41855 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -175,7 +175,7 @@ def recv_into(self, buffer, nbytes: int = 0): last_read_time = time.monotonic() num_to_read = len(buffer) if nbytes == 0 else nbytes num_read = 0 - while num_read < num_to_read: + while num_to_read > 0: num_avail = self.available() if num_avail > 0: last_read_time = time.monotonic() @@ -184,10 +184,11 @@ 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 elif num_read > 0: # We got a message, but there are no more bytes to read, so we can stop. break - # No bytes yet, or more byte requested. + # No bytes yet, or more bytes requested. if self._timeout > 0 and time.monotonic() - last_read_time > self._timeout: break return num_read From a8c8f717271562fbfab295bdfd506c39f50de0fb Mon Sep 17 00:00:00 2001 From: evaherrada Date: Tue, 7 Jun 2022 15:34:20 -0400 Subject: [PATCH 085/155] Added cp.org link to index.rst --- docs/index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 3d33eb3..7fcb348 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,7 +29,8 @@ Table of Contents .. toctree:: :caption: Other Links - Download + Download from GitHub + Download Library Bundle CircuitPython Reference Documentation CircuitPython Support Forum Discord Chat From c6ad4f4b9887de5041327196dc253618a36ef3b7 Mon Sep 17 00:00:00 2001 From: evaherrada Date: Fri, 22 Jul 2022 13:58:45 -0400 Subject: [PATCH 086/155] Changed .env to .venv in README.rst --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 856e4ee..55b5f3b 100644 --- a/README.rst +++ b/README.rst @@ -50,8 +50,8 @@ To install in a virtual environment in your current project: .. code-block:: shell mkdir project-name && cd project-name - python3 -m venv .env - source .env/bin/activate + python3 -m venv .venv + source .venv/bin/activate pip3 install adafruit-circuitpython-esp32spi Usage Example From 661de7d60e2d544c2e3ef196f1335c93b6c5755d Mon Sep 17 00:00:00 2001 From: evaherrada Date: Tue, 2 Aug 2022 17:00:33 -0400 Subject: [PATCH 087/155] Added Black formatting badge --- README.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.rst b/README.rst index 55b5f3b..f05bc11 100644 --- a/README.rst +++ b/README.rst @@ -13,6 +13,10 @@ 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 + CircuitPython driver library for using ESP32 as WiFi co-processor using SPI. The companion firmware `is available on GitHub `_. Please be sure to check the example code for From a15b06f71a996ecfe2b274e9f0c888ac60aaedc4 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Mon, 8 Aug 2022 22:05:52 -0400 Subject: [PATCH 088/155] Switched to pyproject.toml --- .github/workflows/build.yml | 26 ++++++++++++--- .github/workflows/release.yml | 21 +++++++------ optional_requirements.txt | 3 ++ pyproject.toml | 47 +++++++++++++++++++++++++--- requirements.txt | 4 +-- setup.py | 59 ----------------------------------- 6 files changed, 82 insertions(+), 78 deletions(-) create mode 100644 optional_requirements.txt delete mode 100644 setup.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8a99647..22f6582 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,6 @@ -# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries # -# SPDX-License-Identifier: Unlicense +# SPDX-License-Identifier: MIT name: Build CI @@ -47,13 +47,31 @@ jobs: pip install --force-reinstall Sphinx sphinx-rtd-theme pre-commit - name: Library version run: git describe --dirty --always --tags + - name: Setup problem matchers + uses: adafruit/circuitpython-action-library-ci-problem-matchers@v1 - name: Pre-commit hooks run: | pre-commit run --all-files - name: Build assets run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location . + - name: Archive bundles + uses: actions/upload-artifact@v2 + with: + name: bundles + path: ${{ github.workspace }}/bundles/ - name: Build docs working-directory: docs run: sphinx-build -E -W -b html . _build/html - - name: Setup problem matchers - uses: adafruit/circuitpython-action-library-ci-problem-matchers@v1 + - name: Check For pyproject.toml + id: need-pypi + run: | + echo ::set-output name=pyproject-toml::$( find . -wholename './pyproject.toml' ) + - name: Build Python package + if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') + run: | + pip install --upgrade build twine + for file in $(find -not -path "./.*" -not -path "./docs*" \( -name "*.py" -o -name "*.toml" \) ); do + sed -i -e "s/0.0.0-auto.0/1.2.3/" $file; + done; + python -m build + twine check dist/* diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index be5f7be..d1b4f8d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ -# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries # -# SPDX-License-Identifier: Unlicense +# SPDX-License-Identifier: MIT name: Release Actions @@ -61,25 +61,28 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - name: Check For setup.py + - name: Check For pyproject.toml id: need-pypi run: | - echo ::set-output name=setup-py::$( find . -wholename './setup.py' ) + echo ::set-output name=pyproject-toml::$( find . -wholename './pyproject.toml' ) - name: Set up Python - if: contains(steps.need-pypi.outputs.setup-py, 'setup.py') + if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') uses: actions/setup-python@v2 with: python-version: '3.x' - name: Install dependencies - if: contains(steps.need-pypi.outputs.setup-py, 'setup.py') + if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') run: | python -m pip install --upgrade pip - pip install setuptools wheel twine + pip install --upgrade build twine - name: Build and publish - if: contains(steps.need-pypi.outputs.setup-py, 'setup.py') + if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') env: TWINE_USERNAME: ${{ secrets.pypi_username }} TWINE_PASSWORD: ${{ secrets.pypi_password }} run: | - python setup.py sdist + for file in $(find -not -path "./.*" -not -path "./docs*" \( -name "*.py" -o -name "*.toml" \) ); do + sed -i -e "s/0.0.0-auto.0/${{github.event.release.tag_name}}/" $file; + done; + python -m build twine upload dist/* diff --git a/optional_requirements.txt b/optional_requirements.txt new file mode 100644 index 0000000..d4e27c4 --- /dev/null +++ b/optional_requirements.txt @@ -0,0 +1,3 @@ +# SPDX-FileCopyrightText: 2022 Alec Delaney, for Adafruit Industries +# +# SPDX-License-Identifier: Unlicense diff --git a/pyproject.toml b/pyproject.toml index f3c35ae..b26962a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,45 @@ -# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò +# SPDX-FileCopyrightText: 2022 Alec Delaney for Adafruit Industries # -# SPDX-License-Identifier: Unlicense +# SPDX-License-Identifier: MIT -[tool.black] -target-version = ['py35'] +[build-system] +requires = [ + "setuptools", + "wheel", +] + +[project] +name = "adafruit-circuitpython-esp32spi" +description = "CircuitPython driver library for using ESP32 as WiFi co-processor using SPI" +version = "0.0.0-auto.0" +readme = "README.rst" +authors = [ + {name = "Adafruit Industries", email = "circuitpython@adafruit.com"} +] +urls = {Homepage = "https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI"} +keywords = [ + "adafruit", + "blinka", + "circuitpython", + "micropython", + "esp32spi", + "wifi", + "esp32", +] +license = {text = "MIT"} +classifiers = [ + "Intended Audience :: Developers", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development :: Embedded Systems", + "Topic :: System :: Hardware", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", +] +dynamic = ["dependencies", "optional-dependencies"] + +[tool.setuptools] +packages = ["adafruit_esp32spi"] + +[tool.setuptools.dynamic] +dependencies = {file = ["requirements.txt"]} +optional-dependencies = {optional = {file = ["optional_requirements.txt"]}} diff --git a/requirements.txt b/requirements.txt index d066152..8bfb5f3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ -# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-FileCopyrightText: 2022 Alec Delaney, for Adafruit Industries # # SPDX-License-Identifier: Unlicense Adafruit-Blinka -adafruit-circuitpython-busdevice adafruit-circuitpython-requests +adafruit-circuitpython-busdevice diff --git a/setup.py b/setup.py deleted file mode 100644 index 6872298..0000000 --- a/setup.py +++ /dev/null @@ -1,59 +0,0 @@ -# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries -# -# SPDX-License-Identifier: MIT - -"""A setuptools based setup module. - -See: -https://packaging.python.org/en/latest/distributing.html -https://github.com/pypa/sampleproject -""" - -from setuptools import setup, find_packages - -# To use a consistent encoding -from codecs import open -from os import path - -here = path.abspath(path.dirname(__file__)) - -# Get the long description from the README file -with open(path.join(here, "README.rst"), encoding="utf-8") as f: - long_description = f.read() - -setup( - name="adafruit-circuitpython-esp32spi", - use_scm_version=True, - setup_requires=["setuptools_scm"], - description="CircuitPython driver library for using ESP32 as WiFi co-processor using SPI", - long_description=long_description, - long_description_content_type="text/x-rst", - # The project's main homepage. - url="https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI", - # Author details - author="Adafruit Industries", - author_email="circuitpython@adafruit.com", - install_requires=[ - "Adafruit-Blinka", - "adafruit-circuitpython-busdevice", - "adafruit-circuitpython-requests", - ], - # Choose your license - license="MIT", - # See https://pypi.python.org/pypi?%3Aaction=list_classifiers - classifiers=[ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "Topic :: Software Development :: Libraries", - "Topic :: System :: Hardware", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - ], - # What does your project relate to? - keywords="adafruit blinka circuitpython micropython esp32spi wifi esp32", - # You can just specify the packages manually here if your project is - # simple. Or you can use find_packages(). - # TODO: IF LIBRARY FILES ARE A PACKAGE FOLDER, - # CHANGE `py_modules=['...']` TO `packages=['...']` - packages=["adafruit_esp32spi"], -) From 9cca65bd52f1b0be672fa8c1ea74b278366851a9 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Tue, 9 Aug 2022 12:03:54 -0400 Subject: [PATCH 089/155] Add setuptools-scm to build system requirements Signed-off-by: Alec Delaney --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index b26962a..8f26a71 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,7 @@ requires = [ "setuptools", "wheel", + "setuptools-scm", ] [project] From 37deb2de619d95beda8f33e3c08d440ec75a78db Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Tue, 16 Aug 2022 18:09:13 -0400 Subject: [PATCH 090/155] Update version string --- adafruit_esp32spi/adafruit_esp32spi.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 2cd2d4e..e1ef2d0 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -32,7 +32,7 @@ from adafruit_bus_device.spi_device import SPIDevice from digitalio import Direction -__version__ = "0.0.0-auto.0" +__version__ = "0.0.0+auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI.git" _SET_NET_CMD = const(0x10) diff --git a/pyproject.toml b/pyproject.toml index 8f26a71..3c42c46 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ requires = [ [project] name = "adafruit-circuitpython-esp32spi" description = "CircuitPython driver library for using ESP32 as WiFi co-processor using SPI" -version = "0.0.0-auto.0" +version = "0.0.0+auto.0" readme = "README.rst" authors = [ {name = "Adafruit Industries", email = "circuitpython@adafruit.com"} From f4ffa72db17fd7c62f8a8dc6439b7c433285438b Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Tue, 16 Aug 2022 21:09:13 -0400 Subject: [PATCH 091/155] Fix version strings in workflow files --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 22f6582..cb2f60e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,7 +71,7 @@ jobs: run: | pip install --upgrade build twine for file in $(find -not -path "./.*" -not -path "./docs*" \( -name "*.py" -o -name "*.toml" \) ); do - sed -i -e "s/0.0.0-auto.0/1.2.3/" $file; + sed -i -e "s/0.0.0+auto.0/1.2.3/" $file; done; python -m build twine check dist/* diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d1b4f8d..f3a0325 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -82,7 +82,7 @@ jobs: TWINE_PASSWORD: ${{ secrets.pypi_password }} run: | for file in $(find -not -path "./.*" -not -path "./docs*" \( -name "*.py" -o -name "*.toml" \) ); do - sed -i -e "s/0.0.0-auto.0/${{github.event.release.tag_name}}/" $file; + sed -i -e "s/0.0.0+auto.0/${{github.event.release.tag_name}}/" $file; done; python -m build twine upload dist/* From a74f25206858d6c5c11da7e4ba1b9e9dcafab38f Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Mon, 22 Aug 2022 21:36:30 -0400 Subject: [PATCH 092/155] Keep copyright up to date in documentation --- docs/conf.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index bc466b6..04fd6fa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,6 +6,7 @@ import os import sys +import datetime sys.path.insert(0, os.path.abspath("..")) @@ -47,7 +48,8 @@ # General information about the project. project = "Adafruit ESP32SPI Library" -copyright = "2019 ladyada" +current_year = str(datetime.datetime.now().year) +copyright = current_year + " ladyada" author = "ladyada" # The version info for the project you're documenting, acts as replacement for From 5e6d367273c2193fda8177fbdb5fca433133a0a7 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Tue, 23 Aug 2022 17:26:20 -0400 Subject: [PATCH 093/155] Use year duration range for copyright attribution --- docs/conf.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 04fd6fa..37499d2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,8 +48,14 @@ # General information about the project. project = "Adafruit ESP32SPI Library" +creation_year = "2019" current_year = str(datetime.datetime.now().year) -copyright = current_year + " ladyada" +year_duration = ( + current_year + if current_year == creation_year + else creation_year + " - " + current_year +) +copyright = year_duration + " ladyada" author = "ladyada" # The version info for the project you're documenting, acts as replacement for From 4f7a1895b162c129451a71ba59831ea9acbcfeed Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Wed, 31 Aug 2022 00:41:40 -0400 Subject: [PATCH 094/155] Add optional requirements to file --- optional_requirements.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/optional_requirements.txt b/optional_requirements.txt index d4e27c4..f2e3a6c 100644 --- a/optional_requirements.txt +++ b/optional_requirements.txt @@ -1,3 +1,7 @@ # SPDX-FileCopyrightText: 2022 Alec Delaney, for Adafruit Industries # # SPDX-License-Identifier: Unlicense + +adafruit-circuitpython-neopixel +adafruit-circuitpython-fancyled +adafruit-circuitpython-requests From 6f2b40e16817a16c16308b72ca9faee825d5d2c1 Mon Sep 17 00:00:00 2001 From: rivques <38469076+rivques@users.noreply.github.com> Date: Sat, 10 Sep 2022 13:01:21 -0400 Subject: [PATCH 095/155] close #174 by sending entire webserver response to esp32 in one go if possible --- adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index 956a36c..c4a4059 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py @@ -119,11 +119,16 @@ def finish_response(self, result): response += "{0}: {1}\r\n".format(*header) response += "\r\n" self._client_sock.send(response.encode("utf-8")) - for data in result: - if isinstance(data, bytes): - self._client_sock.send(data) - else: - self._client_sock.send(data.encode("utf-8")) + if isinstance(result, bytes): # send whole response if possible (see #174) + self._client_sock.send(result) + elif isinstance(result, str): + self._client_sock.send(result.encode("utf-8")) + else: # fall back to sending byte-by-byte + for data in result: + if isinstance(data, bytes): + self._client_sock.send(data) + else: + self._client_sock.send(data.encode("utf-8")) gc.collect() finally: if self._debug > 2: From c50a1037fa4492efd4755b61bd5abfd50746f4a7 Mon Sep 17 00:00:00 2001 From: rivques <38469076+rivques@users.noreply.github.com> Date: Sat, 10 Sep 2022 14:23:25 -0400 Subject: [PATCH 096/155] make black happy --- adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index c4a4059..2d7a098 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py @@ -119,11 +119,11 @@ def finish_response(self, result): response += "{0}: {1}\r\n".format(*header) response += "\r\n" self._client_sock.send(response.encode("utf-8")) - if isinstance(result, bytes): # send whole response if possible (see #174) + if isinstance(result, bytes): # send whole response if possible (see #174) self._client_sock.send(result) elif isinstance(result, str): self._client_sock.send(result.encode("utf-8")) - else: # fall back to sending byte-by-byte + else: # fall back to sending byte-by-byte for data in result: if isinstance(data, bytes): self._client_sock.send(data) From c5fe8a8d9427f915e0869b9c2438c362dc9a7af0 Mon Sep 17 00:00:00 2001 From: Alec Delaney <89490472+tekktrik@users.noreply.github.com> Date: Fri, 4 Nov 2022 00:02:49 -0400 Subject: [PATCH 097/155] Switching to composite actions --- .github/workflows/build.yml | 67 +---------------------- .github/workflows/release.yml | 88 ------------------------------ .github/workflows/release_gh.yml | 14 +++++ .github/workflows/release_pypi.yml | 14 +++++ 4 files changed, 30 insertions(+), 153 deletions(-) delete mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/release_gh.yml create mode 100644 .github/workflows/release_pypi.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cb2f60e..041a337 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,68 +10,5 @@ jobs: test: runs-on: ubuntu-latest steps: - - name: Dump GitHub context - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: echo "$GITHUB_CONTEXT" - - name: Translate Repo Name For Build Tools filename_prefix - id: repo-name - run: | - echo ::set-output name=repo-name::$( - echo ${{ github.repository }} | - awk -F '\/' '{ print tolower($2) }' | - tr '_' '-' - ) - - name: Set up Python 3.x - uses: actions/setup-python@v2 - with: - python-version: "3.x" - - name: Versions - run: | - python3 --version - - name: Checkout Current Repo - uses: actions/checkout@v1 - with: - submodules: true - - name: Checkout tools repo - uses: actions/checkout@v2 - with: - repository: adafruit/actions-ci-circuitpython-libs - path: actions-ci - - name: Install dependencies - # (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.) - run: | - source actions-ci/install.sh - - name: Pip install Sphinx, pre-commit - run: | - pip install --force-reinstall Sphinx sphinx-rtd-theme pre-commit - - name: Library version - run: git describe --dirty --always --tags - - name: Setup problem matchers - uses: adafruit/circuitpython-action-library-ci-problem-matchers@v1 - - name: Pre-commit hooks - run: | - pre-commit run --all-files - - name: Build assets - run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location . - - name: Archive bundles - uses: actions/upload-artifact@v2 - with: - name: bundles - path: ${{ github.workspace }}/bundles/ - - name: Build docs - working-directory: docs - run: sphinx-build -E -W -b html . _build/html - - name: Check For pyproject.toml - id: need-pypi - run: | - echo ::set-output name=pyproject-toml::$( find . -wholename './pyproject.toml' ) - - name: Build Python package - if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') - run: | - pip install --upgrade build twine - for file in $(find -not -path "./.*" -not -path "./docs*" \( -name "*.py" -o -name "*.toml" \) ); do - sed -i -e "s/0.0.0+auto.0/1.2.3/" $file; - done; - python -m build - twine check dist/* + - name: Run Build CI workflow + uses: adafruit/workflows-circuitpython-libs/build@main diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index f3a0325..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,88 +0,0 @@ -# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries -# -# SPDX-License-Identifier: MIT - -name: Release Actions - -on: - release: - types: [published] - -jobs: - upload-release-assets: - runs-on: ubuntu-latest - steps: - - name: Dump GitHub context - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: echo "$GITHUB_CONTEXT" - - name: Translate Repo Name For Build Tools filename_prefix - id: repo-name - run: | - echo ::set-output name=repo-name::$( - echo ${{ github.repository }} | - awk -F '\/' '{ print tolower($2) }' | - tr '_' '-' - ) - - name: Set up Python 3.x - uses: actions/setup-python@v2 - with: - python-version: "3.x" - - name: Versions - run: | - python3 --version - - name: Checkout Current Repo - uses: actions/checkout@v1 - with: - submodules: true - - name: Checkout tools repo - uses: actions/checkout@v2 - with: - repository: adafruit/actions-ci-circuitpython-libs - path: actions-ci - - name: Install deps - run: | - source actions-ci/install.sh - - name: Build assets - run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location . - - name: Upload Release Assets - # the 'official' actions version does not yet support dynamically - # supplying asset names to upload. @csexton's version chosen based on - # discussion in the issue below, as its the simplest to implement and - # allows for selecting files with a pattern. - # https://github.com/actions/upload-release-asset/issues/4 - #uses: actions/upload-release-asset@v1.0.1 - uses: csexton/release-asset-action@master - with: - pattern: "bundles/*" - github-token: ${{ secrets.GITHUB_TOKEN }} - - upload-pypi: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Check For pyproject.toml - id: need-pypi - run: | - echo ::set-output name=pyproject-toml::$( find . -wholename './pyproject.toml' ) - - name: Set up Python - if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - name: Install dependencies - if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') - run: | - python -m pip install --upgrade pip - pip install --upgrade build twine - - name: Build and publish - if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') - env: - TWINE_USERNAME: ${{ secrets.pypi_username }} - TWINE_PASSWORD: ${{ secrets.pypi_password }} - run: | - for file in $(find -not -path "./.*" -not -path "./docs*" \( -name "*.py" -o -name "*.toml" \) ); do - sed -i -e "s/0.0.0+auto.0/${{github.event.release.tag_name}}/" $file; - done; - python -m build - twine upload dist/* diff --git a/.github/workflows/release_gh.yml b/.github/workflows/release_gh.yml new file mode 100644 index 0000000..041a337 --- /dev/null +++ b/.github/workflows/release_gh.yml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +name: Build CI + +on: [pull_request, push] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Run Build CI workflow + uses: adafruit/workflows-circuitpython-libs/build@main diff --git a/.github/workflows/release_pypi.yml b/.github/workflows/release_pypi.yml new file mode 100644 index 0000000..041a337 --- /dev/null +++ b/.github/workflows/release_pypi.yml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +name: Build CI + +on: [pull_request, push] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Run Build CI workflow + uses: adafruit/workflows-circuitpython-libs/build@main From 168955e08bb5873b26c0033653f7218ec64c6ebc Mon Sep 17 00:00:00 2001 From: Alec Delaney <89490472+tekktrik@users.noreply.github.com> Date: Fri, 4 Nov 2022 00:46:59 -0400 Subject: [PATCH 098/155] Updated pylint version to 2.13.0 --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3343606..4c43710 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.11.1 + rev: v2.13.0 hooks: - id: pylint name: pylint (library code) From 3abefa5629f7e7cff20b3fae0315fad1869a552e Mon Sep 17 00:00:00 2001 From: Alec Delaney <89490472+tekktrik@users.noreply.github.com> Date: Fri, 4 Nov 2022 08:15:19 -0400 Subject: [PATCH 099/155] Update pylint to 2.15.5 --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4c43710..0e5fccc 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.13.0 + rev: v2.15.5 hooks: - id: pylint name: pylint (library code) From df9ff109d9e77bd5462995062ccb49c625baa379 Mon Sep 17 00:00:00 2001 From: Alec Delaney <89490472+tekktrik@users.noreply.github.com> Date: Fri, 4 Nov 2022 09:12:43 -0400 Subject: [PATCH 100/155] Fix release CI files --- .github/workflows/release_gh.yml | 14 +++++++++----- .github/workflows/release_pypi.yml | 15 ++++++++++----- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release_gh.yml b/.github/workflows/release_gh.yml index 041a337..b8aa8d6 100644 --- a/.github/workflows/release_gh.yml +++ b/.github/workflows/release_gh.yml @@ -2,13 +2,17 @@ # # SPDX-License-Identifier: MIT -name: Build CI +name: GitHub Release Actions -on: [pull_request, push] +on: + release: + types: [published] jobs: - test: + upload-release-assets: runs-on: ubuntu-latest steps: - - name: Run Build CI workflow - uses: adafruit/workflows-circuitpython-libs/build@main + - name: Run GitHub Release CI workflow + uses: adafruit/workflows-circuitpython-libs/release-gh@main + with: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release_pypi.yml b/.github/workflows/release_pypi.yml index 041a337..65775b7 100644 --- a/.github/workflows/release_pypi.yml +++ b/.github/workflows/release_pypi.yml @@ -2,13 +2,18 @@ # # SPDX-License-Identifier: MIT -name: Build CI +name: PyPI Release Actions -on: [pull_request, push] +on: + release: + types: [published] jobs: - test: + upload-release-assets: runs-on: ubuntu-latest steps: - - name: Run Build CI workflow - uses: adafruit/workflows-circuitpython-libs/build@main + - name: Run PyPI Release CI workflow + uses: adafruit/workflows-circuitpython-libs/release-pypi@main + with: + pypi-username: ${{ secrets.pypi_username }} + pypi-password: ${{ secrets.pypi_password }} From e135c9c848fb0abda9af1aeadf4e00f9e2820c60 Mon Sep 17 00:00:00 2001 From: Alec Delaney <89490472+tekktrik@users.noreply.github.com> Date: Fri, 4 Nov 2022 18:34:32 -0400 Subject: [PATCH 101/155] Update .pylintrc for v2.15.5 --- .pylintrc | 45 ++++----------------------------------------- 1 file changed, 4 insertions(+), 41 deletions(-) diff --git a/.pylintrc b/.pylintrc index 27c6c07..40208c3 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries # # SPDX-License-Identifier: Unlicense @@ -26,7 +26,7 @@ jobs=1 # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. -load-plugins= +load-plugins=pylint.extensions.no_self_use # Pickle collected data for later comparisons. persistent=yes @@ -54,8 +54,8 @@ confidence= # --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,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call -disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation,unspecified-encoding +# 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 @@ -225,12 +225,6 @@ max-line-length=100 # Maximum number of lines in a module max-module-lines=1000 -# List of optional constructs for which whitespace checking is disabled. `dict- -# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. -# `trailing-comma` allows a space between comma and closing bracket: (a, ). -# `empty-line` allows space-only lines. -no-space-check=trailing-comma,dict-separator - # 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 @@ -257,38 +251,22 @@ min-similarity-lines=12 [BASIC] -# Naming hint for argument names -argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct argument names argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ -# Naming hint for attribute names -attr-name-hint=(([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 -# Naming hint for class attribute names -class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - # Regular expression matching correct class attribute names class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ -# Naming hint for class names -# class-name-hint=[A-Z_][a-zA-Z0-9]+$ -class-name-hint=[A-Z_][a-zA-Z0-9_]+$ - # Regular expression matching correct class names # class-rgx=[A-Z_][a-zA-Z0-9]+$ class-rgx=[A-Z_][a-zA-Z0-9_]+$ -# Naming hint for constant names -const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - # Regular expression matching correct constant names const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ @@ -296,9 +274,6 @@ const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ # ones are exempt. docstring-min-length=-1 -# Naming hint for function names -function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct function names function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ @@ -309,21 +284,12 @@ 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 -# Naming hint for inline iteration names -inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ - # Regular expression matching correct inline iteration names inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ -# Naming hint for method names -method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct method names method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ -# Naming hint for module names -module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - # Regular expression matching correct module names module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ @@ -339,9 +305,6 @@ no-docstring-rgx=^_ # to this list to register other decorators that produce valid properties. property-classes=abc.abstractproperty -# Naming hint for variable names -variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - # Regular expression matching correct variable names variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ From f6cf6eb6a6ba8ed109eaf87ca08a8c29e60d00bb Mon Sep 17 00:00:00 2001 From: Alec Delaney <89490472+tekktrik@users.noreply.github.com> Date: Thu, 1 Sep 2022 20:16:31 -0400 Subject: [PATCH 102/155] Add .venv to .gitignore Signed-off-by: Alec Delaney <89490472+tekktrik@users.noreply.github.com> --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 544ec4a..db3d538 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ _build # Virtual environment-specific files .env +.venv # MacOS-specific files *.DS_Store From 410e5a8b11e7ead6dd5c4293070b6b6d7e64a5a3 Mon Sep 17 00:00:00 2001 From: Alec Delaney <89490472+tekktrik@users.noreply.github.com> Date: Thu, 19 Jan 2023 23:39:55 -0500 Subject: [PATCH 103/155] Add upload url to release action Signed-off-by: Alec Delaney <89490472+tekktrik@users.noreply.github.com> --- .github/workflows/release_gh.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release_gh.yml b/.github/workflows/release_gh.yml index b8aa8d6..9acec60 100644 --- a/.github/workflows/release_gh.yml +++ b/.github/workflows/release_gh.yml @@ -16,3 +16,4 @@ jobs: uses: adafruit/workflows-circuitpython-libs/release-gh@main with: github-token: ${{ secrets.GITHUB_TOKEN }} + upload-url: ${{ github.event.release.upload_url }} From 1614277f1d7555d95ccf268d159185d0df47c27c Mon Sep 17 00:00:00 2001 From: zachariah pifer Date: Tue, 25 Apr 2023 17:30:54 -0600 Subject: [PATCH 104/155] toggle password --- adafruit_esp32spi/adafruit_esp32spi.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index e1ef2d0..3a9cce3 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -325,7 +325,7 @@ def _send_command_get_response( *, reply_params=1, sent_param_len_16=False, - recv_param_len_16=False + recv_param_len_16=False, ): """Send a high level SPI command, wait and return the response""" self._send_command(cmd, params, param_len_16=sent_param_len_16) @@ -563,7 +563,9 @@ def connect(self, secrets): that contains a 'ssid' and 'password' entry""" self.connect_AP(secrets["ssid"], secrets["password"]) - def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-name + def connect_AP( + self, ssid, password, timeout_s=10, show_password=False + ): # pylint: disable=invalid-name """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. @@ -571,9 +573,13 @@ def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-n :param ssid: the SSID to connect to :param passphrase: the password of the access point :param timeout_s: number of seconds until we time out and fail to create AP + :param show_password: print password if debug == True (default False) """ if self._debug: - print("Connect to AP", ssid, password) + print( + f"Connect to AP: {ssid=}, password=\ + {repr(password if show_password else '*' * len(password))}" + ) if isinstance(ssid, str): ssid = bytes(ssid, "utf-8") if password: From b7385a073ddd74b2b706f666ba74cc661386ed2c Mon Sep 17 00:00:00 2001 From: zachariah pifer Date: Wed, 26 Apr 2023 12:28:37 -0600 Subject: [PATCH 105/155] move debug_show_secrets flag to ctor --- adafruit_esp32spi/adafruit_esp32spi.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 3a9cce3..718057b 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -141,9 +141,18 @@ class ESP_SPIcontrol: # pylint: disable=too-many-public-methods, too-many-insta # pylint: disable=too-many-arguments def __init__( - self, spi, cs_dio, ready_dio, reset_dio, gpio0_dio=None, *, debug=False + self, + spi, + cs_dio, + ready_dio, + reset_dio, + gpio0_dio=None, + *, + debug=False, + debug_show_secrets=False, ): self._debug = debug + self._debug_show_secrets = debug_show_secrets self.set_psk = False self.set_crt = False self._buffer = bytearray(10) @@ -563,9 +572,7 @@ def connect(self, secrets): that contains a 'ssid' and 'password' entry""" self.connect_AP(secrets["ssid"], secrets["password"]) - def connect_AP( - self, ssid, password, timeout_s=10, show_password=False - ): # pylint: disable=invalid-name + def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-name """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. @@ -573,12 +580,11 @@ def connect_AP( :param ssid: the SSID to connect to :param passphrase: the password of the access point :param timeout_s: number of seconds until we time out and fail to create AP - :param show_password: print password if debug == True (default False) """ if self._debug: print( f"Connect to AP: {ssid=}, password=\ - {repr(password if show_password else '*' * len(password))}" + {repr(password if self._debug_show_secrets else '*' * len(password))}" ) if isinstance(ssid, str): ssid = bytes(ssid, "utf-8") From 83301114b5fd32125056d5fcfe05cd547c5079c5 Mon Sep 17 00:00:00 2001 From: Tekktrik Date: Tue, 9 May 2023 20:26:25 -0400 Subject: [PATCH 106/155] Update pre-commit hooks Signed-off-by: Tekktrik --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0e5fccc..70ade69 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,21 +4,21 @@ repos: - repo: https://github.com/python/black - rev: 22.3.0 + rev: 23.3.0 hooks: - id: black - repo: https://github.com/fsfe/reuse-tool - rev: v0.14.0 + rev: v1.1.2 hooks: - id: reuse - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.2.0 + rev: v4.4.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/pycqa/pylint - rev: v2.15.5 + rev: v2.17.4 hooks: - id: pylint name: pylint (library code) From b12434d1fb4fa5566edefe0b11f2357c8661c64c Mon Sep 17 00:00:00 2001 From: Tekktrik Date: Wed, 10 May 2023 22:32:17 -0400 Subject: [PATCH 107/155] Run pre-commit --- adafruit_esp32spi/adafruit_esp32spi.py | 3 ++- adafruit_esp32spi/adafruit_esp32spi_socket.py | 2 ++ adafruit_esp32spi/digitalio.py | 1 + examples/esp32spi_wpa2ent_simpletest.py | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 718057b..ab62592 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -390,7 +390,8 @@ def start_scan_networks(self): def get_scan_networks(self): """The results of the latest SSID scan. Returns a list of dictionaries with - 'ssid', 'rssi', 'encryption', bssid, and channel entries, one for each AP found""" + 'ssid', 'rssi', 'encryption', bssid, and channel entries, one for each AP found + """ self._send_command(_SCAN_NETWORKS) names = self._wait_response_cmd(_SCAN_NETWORKS) # print("SSID names:", names) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index 1d254a3..1a4e1a1 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -34,6 +34,7 @@ def set_interface(iface): MAX_PACKET = const(4000) + # 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' @@ -46,6 +47,7 @@ def getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0): # pylint: enable=too-many-arguments, unused-argument + # pylint: disable=unused-argument, redefined-builtin, invalid-name class socket: """A simplified implementation of the Python 'socket' class, for connecting diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index 3e4cc15..e934f2c 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -117,6 +117,7 @@ class DigitalInOut: """ _pin = None + # pylint: disable = attribute-defined-outside-init def __init__(self, esp, pin): self._esp = esp diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index 692177f..879ac24 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -19,6 +19,7 @@ import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi + # Version number comparison code. Credit to gnud on stackoverflow # (https://stackoverflow.com/a/1714190), swapping out cmp() to # support Python 3.x and thus, CircuitPython From 2e74c68eddff715ea790583425cd61577404e2e1 Mon Sep 17 00:00:00 2001 From: Tekktrik Date: Sun, 14 May 2023 13:00:32 -0400 Subject: [PATCH 108/155] Update .pylintrc, fix jQuery for docs Signed-off-by: Tekktrik --- .pylintrc | 2 +- docs/conf.py | 1 + docs/requirements.txt | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index 40208c3..f945e92 100644 --- a/.pylintrc +++ b/.pylintrc @@ -396,4 +396,4 @@ min-public-methods=1 # Exceptions that will emit a warning when being caught. Defaults to # "Exception" -overgeneral-exceptions=Exception +overgeneral-exceptions=builtins.Exception diff --git a/docs/conf.py b/docs/conf.py index 37499d2..9884e97 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,6 +17,7 @@ # ones. extensions = [ "sphinx.ext.autodoc", + "sphinxcontrib.jquery", "sphinx.ext.intersphinx", "sphinx.ext.napoleon", "sphinx.ext.todo", diff --git a/docs/requirements.txt b/docs/requirements.txt index 88e6733..797aa04 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -3,3 +3,4 @@ # SPDX-License-Identifier: Unlicense sphinx>=4.0.0 +sphinxcontrib-jquery From c5b62033beb82395823735ed89d38e7ac915bbc8 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Mon, 19 Jun 2023 13:21:36 -0500 Subject: [PATCH 109/155] timeout error property. Raise from recv_into if timeout time has elapsed --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index 23fcc56..1cf379f 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -127,7 +127,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: - break + raise timeout("timed out") return num_read def settimeout(self, value): @@ -169,4 +169,12 @@ def close(self): _the_interface.socket_close(self._socknum) +class timeout(TimeoutError): + """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 From f125ccbccdcdbf93dbfc378f71a23941cb341627 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 5 Sep 2023 13:05:51 -0400 Subject: [PATCH 110/155] 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 111/155] "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 112/155] 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 113/155] 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 114/155] 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 115/155] 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 116/155] 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 117/155] 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 118/155] 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 119/155] 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 120/155] 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 121/155] 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 122/155] 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 123/155] 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 124/155] 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 125/155] 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 126/155] 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 127/155] 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 128/155] 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 129/155] 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 130/155] 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 131/155] 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 132/155] 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 133/155] 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 134/155] 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 135/155] 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 136/155] 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 137/155] 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 138/155] 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 139/155] 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 140/155] 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 141/155] 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 142/155] 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 143/155] 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 144/155] 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 145/155] 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 146/155] 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 147/155] 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 148/155] 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 149/155] 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 150/155] 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 151/155] 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 152/155] 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 153/155] 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 154/155] 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 155/155] 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" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy