From 8e654594854d61494d3ff6895fc4c47bfc83de05 Mon Sep 17 00:00:00 2001 From: Marty McGuire Date: Wed, 13 Mar 2019 15:41:38 -0400 Subject: [PATCH 01/37] Chunk buffer sends into 64 byte chunks Prevents errors with unsent data on large header values, long URL paths --- adafruit_esp32spi/adafruit_esp32spi.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 76e6cc8..5b14643 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -527,11 +527,15 @@ def socket_write(self, socket_num, buffer): if self._debug: print("Writing:", buffer) self._socknum_ll[0][0] = socket_num - resp = self._send_command_get_response(_SEND_DATA_TCP_CMD, - (self._socknum_ll[0], buffer), - sent_param_len_16=True) + chunk_size = 64 + sent = 0 + for chunk in range((len(buffer) // chunk_size)+1): + chunk_buffer = buffer[(chunk*chunk_size):((chunk+1)*chunk_size)] + resp = self._send_command_get_response(_SEND_DATA_TCP_CMD, + (self._socknum_ll[0], chunk_buffer), + sent_param_len_16=True) + sent += resp[0][0] - sent = resp[0][0] if sent != len(buffer): raise RuntimeError("Failed to send %d bytes (sent %d)" % (len(buffer), sent)) From 9cade637762be22db3025cc82077ebc05f688509 Mon Sep 17 00:00:00 2001 From: Marty McGuire Date: Wed, 13 Mar 2019 17:59:05 -0400 Subject: [PATCH 02/37] rm temp vars. replace buffer slice w/ memoryview. --- adafruit_esp32spi/adafruit_esp32spi.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 5b14643..421cdd1 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -527,12 +527,11 @@ def socket_write(self, socket_num, buffer): if self._debug: print("Writing:", buffer) self._socknum_ll[0][0] = socket_num - chunk_size = 64 sent = 0 - for chunk in range((len(buffer) // chunk_size)+1): - chunk_buffer = buffer[(chunk*chunk_size):((chunk+1)*chunk_size)] + for chunk in range((len(buffer) // 64)+1): resp = self._send_command_get_response(_SEND_DATA_TCP_CMD, - (self._socknum_ll[0], chunk_buffer), + (self._socknum_ll[0], + memoryview(buffer)[(chunk*64):((chunk+1)*64)]), sent_param_len_16=True) sent += resp[0][0] From 79425a687901793d241744ff23765b514c6a2047 Mon Sep 17 00:00:00 2001 From: Zach Nofz Date: Sun, 5 May 2019 15:06:30 -0700 Subject: [PATCH 03/37] Fixed infinite loop when socket readline fails In certain cases, the socket may not receive a full response (or any response), causing the while loop in readline to go on forever. After failing to receive any data, this fix will raise an exception and fail out. --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index aec0f6d..4b5dcec 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -85,11 +85,15 @@ def write(self, data): # pylint: disable=no-self-use def readline(self): """Attempt to return as many bytes as we can up to but not including '\r\n'""" #print("Socket readline") + stamp = time.monotonic() while b'\r\n' not in self._buffer: # there's no line already in there, read some more avail = min(_the_interface.socket_available(self._socknum), MAX_PACKET) if avail: self._buffer += _the_interface.socket_read(self._socknum, avail) + elif 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) gc.collect() return firstline From bf54a08358cbea90cb78975f21b601aee9398123 Mon Sep 17 00:00:00 2001 From: Zachary N Date: Sat, 18 May 2019 22:43:18 -0700 Subject: [PATCH 04/37] Update adafruit_esp32spi/adafruit_esp32spi_socket.py Co-Authored-By: Craig --- 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 4b5dcec..6c09d6a 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -91,7 +91,7 @@ def readline(self): avail = min(_the_interface.socket_available(self._socknum), MAX_PACKET) if avail: self._buffer += _the_interface.socket_read(self._socknum, avail) - elif time.monotonic() - stamp > self._timeout: + 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) From 73865347813ecf561ffdd405cb5a6a9d852a1602 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sun, 19 May 2019 11:30:35 -0700 Subject: [PATCH 05/37] Adding WPA2 Enterprise support to the WiFi manager library --- .../adafruit_esp32spi_wifimanager.py | 60 ++++++++++++++----- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 9906847..40ad354 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -38,20 +38,26 @@ class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection """ - def __init__(self, esp, secrets, status_pixel=None, attempts=2): + def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): """ :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 or DotStar (default=None) :type status_pixel: NeoPixel or DotStar :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) + :param int con_type: (Optional) Type of WiFi connection to make: normal=1, WPA2 Enterprise=2 """ # Read the settings self._esp = esp self.debug = False self.ssid = secrets['ssid'] self.password = secrets['password'] + self.ent_ssid = secrets['ent_ssid'] + self.ent_ident = secrets['ent_ident'] + self.ent_user = secrets['ent_user'] + self.ent_passwd = secrets['ent_passwd'] self.attempts = attempts + self.con_type = con_type requests.set_interface(self._esp) self.statuspix = status_pixel self.pixel_status(0) @@ -76,21 +82,45 @@ def connect(self): for access_pt in self._esp.scan_networks(): print("\t%s\t\tRSSI: %d" % (str(access_pt['ssid'], 'utf-8'), access_pt['rssi'])) failure_count = 0 - while not self._esp.is_connected: - try: - if self.debug: - print("Connecting to AP...") - self.pixel_status((100, 0, 0)) - self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) - failure_count = 0 - self.pixel_status((0, 100, 0)) - except (ValueError, RuntimeError) as error: - print("Failed to connect, retrying\n", error) - failure_count += 1 - if failure_count >= self.attempts: + if self.con_type == 1: + while not self._esp.is_connected: + try: + if self.debug: + print("Connecting to AP...") + self.pixel_status((100, 0, 0)) + self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) failure_count = 0 - self.reset() - continue + self.pixel_status((0, 100, 0)) + except (ValueError, RuntimeError) as error: + print("Failed to connect, retrying\n", error) + failure_count += 1 + if failure_count >= self.attempts: + failure_count = 0 + self.reset() + continue + elif self.con_type == 2: + self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) + self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) + self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) + self._esp.wifi_set_entpassword(bytes(self.ent_passwd, 'utf-8')) + self._esp.wifi_set_entenable() + while not self._esp.is_connected: + try: + if self.debug: + print("Connecting to WPA2 Enterprise AP...") + self.pixel_status((100, 0, 0)) + failure_count = 0 + self.pixel_status((0, 100, 0)) + except (ValueError, RuntimeError) as error: + print("Failed to connect, retrying\n", error) + failure_count += 1 + if failure_count >= self.attempts: + failure_count = 0 + self.reset() + continue + else: + print("Invalid connection type! Exiting...") + exit(1) def get(self, url, **kw): """ From d8f4ad2eca0d9b88f2ef0e2fbf29dbbf40b695f5 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sun, 19 May 2019 15:18:06 -0700 Subject: [PATCH 06/37] Added an enum-like class for the WiFi connection type and refactored the code --- .../adafruit_esp32spi_wifimanager.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 40ad354..64cbffe 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -34,18 +34,31 @@ from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_requests as requests +class WiFiConnType: # pylint: disable=too-few-public-methods + """An enum-like class representing the different types of WiFi connections + that can be made. The values can be referenced like ``WiFiConnType.normal``. + Possible values are + - ``ThermocoupleType.normal`` + - ``ThermocoupleType.enterprise`` + """ + # pylint: disable=invalid-name + normal = 1 + enterprise = 2 + class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection """ - def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): + def __init__(self, esp, secrets, status_pixel=None, attempts=2, wificonntype=WiFiConnType.normal): """ :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 or DotStar (default=None) :type status_pixel: NeoPixel or DotStar :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) - :param int con_type: (Optional) Type of WiFi connection to make: normal=1, WPA2 Enterprise=2 + :param const con_type: (Optional) Type of WiFi connection: normal=1, WPA2 Enterprise=2 + :param ~adafruit_esp32spi_wifimanager.WiFiConnType wificonntype: The type of WiFi \ + connection to make. The default is "normal". """ # Read the settings self._esp = esp @@ -57,7 +70,7 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): self.ent_user = secrets['ent_user'] self.ent_passwd = secrets['ent_passwd'] self.attempts = attempts - self.con_type = con_type + self.wificonntype = wificonntype requests.set_interface(self._esp) self.statuspix = status_pixel self.pixel_status(0) @@ -82,7 +95,7 @@ def connect(self): for access_pt in self._esp.scan_networks(): print("\t%s\t\tRSSI: %d" % (str(access_pt['ssid'], 'utf-8'), access_pt['rssi'])) failure_count = 0 - if self.con_type == 1: + if self.wificonntype == WiFiConnType.normal: while not self._esp.is_connected: try: if self.debug: @@ -98,7 +111,7 @@ def connect(self): failure_count = 0 self.reset() continue - elif self.con_type == 2: + elif self.wificonntype == WiFiConnType.enterprise: self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) From 8e2b7876cf4480f7ad62ed93d33bbf95549f248c Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Tue, 21 May 2019 20:09:02 -0700 Subject: [PATCH 07/37] Replaced enum-like class with 2 constants; various fix-ups based on PR reviews; added WPA2 Enterprise version of aio example script --- .../adafruit_esp32spi_wifimanager.py | 30 ++++------ examples/esp32spi_wpa2ent_aio_post.py | 57 +++++++++++++++++++ 2 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 examples/esp32spi_wpa2ent_aio_post.py diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 64cbffe..1618db6 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -31,25 +31,18 @@ # pylint: disable=no-name-in-module +from micropython import const from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_requests as requests -class WiFiConnType: # pylint: disable=too-few-public-methods - """An enum-like class representing the different types of WiFi connections - that can be made. The values can be referenced like ``WiFiConnType.normal``. - Possible values are - - ``ThermocoupleType.normal`` - - ``ThermocoupleType.enterprise`` - """ - # pylint: disable=invalid-name - normal = 1 - enterprise = 2 - class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection """ - def __init__(self, esp, secrets, status_pixel=None, attempts=2, wificonntype=WiFiConnType.normal): + NORMAL = const(1) + ENTERPRISE = const(2) + + def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type=NORMAL): """ :param ESP_SPIcontrol esp: The ESP object we are using :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) @@ -68,9 +61,9 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, wificonntype=WiF self.ent_ssid = secrets['ent_ssid'] self.ent_ident = secrets['ent_ident'] self.ent_user = secrets['ent_user'] - self.ent_passwd = secrets['ent_passwd'] + self.ent_password = secrets['ent_password'] self.attempts = attempts - self.wificonntype = wificonntype + self._connection_type = connection_type requests.set_interface(self._esp) self.statuspix = status_pixel self.pixel_status(0) @@ -95,7 +88,7 @@ def connect(self): for access_pt in self._esp.scan_networks(): print("\t%s\t\tRSSI: %d" % (str(access_pt['ssid'], 'utf-8'), access_pt['rssi'])) failure_count = 0 - if self.wificonntype == WiFiConnType.normal: + if self._connection_type == ESPSPI_WiFiManager.NORMAL: while not self._esp.is_connected: try: if self.debug: @@ -111,11 +104,11 @@ def connect(self): failure_count = 0 self.reset() continue - elif self.wificonntype == WiFiConnType.enterprise: + elif self._connection_type == ESPSPI_WiFiManager.ENTERPRISE: self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) - self._esp.wifi_set_entpassword(bytes(self.ent_passwd, 'utf-8')) + self._esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) self._esp.wifi_set_entenable() while not self._esp.is_connected: try: @@ -132,8 +125,7 @@ def connect(self): self.reset() continue else: - print("Invalid connection type! Exiting...") - exit(1) + raise TypeError("Invalid WiFi connection type specified") def get(self, url, **kw): """ diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py new file mode 100644 index 0000000..bd23a3b --- /dev/null +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -0,0 +1,57 @@ +import time +import board +import busio +from digitalio import DigitalInOut +import neopixel +from adafruit_esp32spi import adafruit_esp32spi +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import ESPSPI_WiFiManager + +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 + +# 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) +"""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) +wifi = ESPSPI_WiFiManager(esp, secrets, status_light, connection_type=ESPSPI_WiFiManager.ENTERPRISE) + +counter = 0 + +while True: + try: + print("Posting data...", end='') + data = counter + feed = 'test' + payload = {'value':data} + response = wifi.post( + "https://io.adafruit.com/api/v2/"+secrets['aio_username']+"/feeds/"+feed+"/data", + json=payload, + headers={"X-AIO-KEY":secrets['aio_key']}) + print(response.json()) + response.close() + counter = counter + 1 + print("OK") + except (ValueError, RuntimeError) as e: + print("Failed to get data, retrying\n", e) + wifi.reset() + continue + response = None + time.sleep(15) From c25157e6b1af7f9414ac7ae854ebd120e88fcfba Mon Sep 17 00:00:00 2001 From: anecdata <16617689+anecdata@users.noreply.github.com> Date: Tue, 4 Jun 2019 09:47:09 -0500 Subject: [PATCH 08/37] Make timeout a keyword argument --- adafruit_esp32spi/adafruit_esp32spi_requests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_requests.py b/adafruit_esp32spi/adafruit_esp32spi_requests.py index ec17481..3857061 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_requests.py +++ b/adafruit_esp32spi/adafruit_esp32spi_requests.py @@ -129,7 +129,7 @@ def iter_content(self, chunk_size=1, decode_unicode=False): return # pylint: disable=too-many-branches, too-many-statements, unused-argument, too-many-arguments, too-many-locals -def request(method, url, data=None, json=None, headers=None, stream=False): +def request(method, url, data=None, json=None, headers=None, stream=False, timeout=1): """Perform an HTTP request to the given url which we will parse to determine whether to use SSL ('https://') or not. We can also send some provided 'data' or a json dictionary which we will stringify. 'headers' is optional HTTP headers @@ -163,7 +163,7 @@ def request(method, url, data=None, json=None, headers=None, stream=False): sock = socket.socket(addr_info[0], addr_info[1], addr_info[2]) resp = Response(sock) # our response - sock.settimeout(1) # 1 second timeout + sock.settimeout(timeout) # socket read timeout try: if proto == "https:": From 4df8144a91b98082db25bfb7b18b9379d7add6fc Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 6 Jun 2019 11:53:59 -0400 Subject: [PATCH 09/37] add first mock api, blinks! --- adafruit_esp32spi/digitalio.py | 146 +++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100755 adafruit_esp32spi/digitalio.py diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py new file mode 100755 index 0000000..b03da8c --- /dev/null +++ b/adafruit_esp32spi/digitalio.py @@ -0,0 +1,146 @@ +# The MIT License (MIT) +# +# Copyright (c) 2019 Brent Rubell for Adafruit +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +`digitalio` +============================== +DigitalIO for ESP32 over SPI. + +* Author(s): Brent Rubell +""" +from micropython import const + +class DriveMode(): + PUSH_PULL = None + OPEN_DRAIN = None + +DriveMode.PUSH_PULL = DriveMode() +DriveMode.OPEN_DRAIN = DriveMode() + +class Direction: + INPUT = None + OUTPUT = None + +Direction.INPUT = Direction() +Direction.OUTPUT = Direction() + +class Pull: + UP = None + DOWN = None + +Pull.UP = Pull() +Pull.DOWN = Pull() + +class Pin: + IN = const(0x00) + OUT = const(0x01) + LOW = const(0x00) + HIGH = const(0x01) + id = None + _value = LOW + _mode = IN + + def __init__(self, esp_pin_number, esp): + self.id = esp_pin_number + self._esp = esp + + def init(self, mode=IN, pull=None): + """Initalizes a pre-defined pin. + :param mode: Pin mode (IN, OUT, LOW, HIGH) + :param pull: Pull value (PULL_NONE, PULL_UP, PULL_DOWN) + """ + print('pin init') + if mode != None: + if mode == self.IN: + self._mode = self.IN + self._esp.set_pin_mode(self.id, 0) + elif mode == self.OUT: + self._mode = self.OUT + self._esp.set_pin_mode(self.id, 1) + else: + raise RuntimeError("Invalid mode defined") + if pull != None: + raise RuntimeError("ESP32 does not have pull-up resistors defined.") + + def value(self, val=None): + """Sets ESP32 Pin GPIO output mode. + :param val: Output level (LOW, HIGH) + """ + if val != None: + if val == self.LOW: + self._value = val + self._esp.set_digital_write(self.id, 0) + elif val == self.HIGH: + self._value = val + self._esp.set_digital_write(self.id, 1) + else: + raise RuntimeError("Invalid value for pin") + else: + raise AttributeError("ESP32SPI does not allow for a digital input.") + + def __repr__(self): + return str(self.id) + + +class DigitalInOut(): + """Mock DigitalIO CircuitPython API Implementation for ESP32SPI. + Provides access to ESP_SPIcontrol methods. + """ + _pin = None + def __init__(self, esp, pin): + self._esp = esp + self._pin = Pin(pin, self._esp) + print('id:', self._pin.id) + self._direction = Direction.INPUT + + def deinit(self): + self._pin = None + + def __exit__(self): + self.deinit() + + @property + def direction(self): + return self.__direction + + @direction.setter + def direction(self, dir): + self.__direction = dir + if dir is Direction.OUTPUT: + self._pin.init(mode=Pin.OUT) + self.value = False + self.drive_mode = DriveMode.PUSH_PULL + elif dir is Direction.INPUT: + self._pin.init(mode=Pin.IN) + self.pull = None + else: + raise AttributeError("Not a Direction") + + @property + def value(self): + return self._pin.value() is 1 + + @value.setter + def value(self, val): + if self.direction is Direction.OUTPUT: + self._pin.value(1 if val else 0) + else: + raise AttributeError("Not an output") \ No newline at end of file From 777289474f963711b53d46d9199ad6c42e17d138 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 6 Jun 2019 12:44:53 -0400 Subject: [PATCH 10/37] add valid pin tupleset check before initialization, raise error --- adafruit_esp32spi/digitalio.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index b03da8c..8e01b19 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -49,19 +49,32 @@ class Pull: Pull.UP = Pull() Pull.DOWN = Pull() +# ESP32-WROOM GPIO Pins + + class Pin: IN = const(0x00) OUT = const(0x01) LOW = const(0x00) HIGH = const(0x01) id = None - _value = LOW + _value = LOW _mode = IN - def __init__(self, esp_pin_number, esp): - self.id = esp_pin_number + ESP32_GPIO_PINS = set([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_pin, esp): + if esp_pin in self.ESP32_GPIO_PINS: + self.id = esp_pin + else: + raise AttributeError("Pin %d is not a valid ESP32 GPIO Pin."%esp_pin) self._esp = esp - + def init(self, mode=IN, pull=None): """Initalizes a pre-defined pin. :param mode: Pin mode (IN, OUT, LOW, HIGH) @@ -79,7 +92,7 @@ def init(self, mode=IN, pull=None): raise RuntimeError("Invalid mode defined") if pull != None: raise RuntimeError("ESP32 does not have pull-up resistors defined.") - + def value(self, val=None): """Sets ESP32 Pin GPIO output mode. :param val: Output level (LOW, HIGH) From 00e7f97453a4cd257cb6739f69132e5d79d087d1 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 6 Jun 2019 13:01:43 -0400 Subject: [PATCH 11/37] drop all pull functionality since we dont have it defined in adafruit_esp32spi.py --- adafruit_esp32spi/digitalio.py | 41 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index 8e01b19..b9f28bf 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -28,6 +28,7 @@ """ from micropython import const +# Enums class DriveMode(): PUSH_PULL = None OPEN_DRAIN = None @@ -42,16 +43,6 @@ class Direction: Direction.INPUT = Direction() Direction.OUTPUT = Direction() -class Pull: - UP = None - DOWN = None - -Pull.UP = Pull() -Pull.DOWN = Pull() - -# ESP32-WROOM GPIO Pins - - class Pin: IN = const(0x00) OUT = const(0x01) @@ -67,7 +58,6 @@ class Pin: 21, 22, 23, 25, 26, 27, 32, 33]) - def __init__(self, esp_pin, esp): if esp_pin in self.ESP32_GPIO_PINS: self.id = esp_pin @@ -75,10 +65,9 @@ def __init__(self, esp_pin, esp): raise AttributeError("Pin %d is not a valid ESP32 GPIO Pin."%esp_pin) self._esp = esp - def init(self, mode=IN, pull=None): + def init(self, mode=IN): """Initalizes a pre-defined pin. - :param mode: Pin mode (IN, OUT, LOW, HIGH) - :param pull: Pull value (PULL_NONE, PULL_UP, PULL_DOWN) + :param mode: Pin mode (IN, OUT, LOW, HIGH). """ print('pin init') if mode != None: @@ -90,8 +79,6 @@ def init(self, mode=IN, pull=None): self._esp.set_pin_mode(self.id, 1) else: raise RuntimeError("Invalid mode defined") - if pull != None: - raise RuntimeError("ESP32 does not have pull-up resistors defined.") def value(self, val=None): """Sets ESP32 Pin GPIO output mode. @@ -107,13 +94,13 @@ def value(self, val=None): else: raise RuntimeError("Invalid value for pin") else: - raise AttributeError("ESP32SPI does not allow for a digital input.") + raise NotImplementedError("digitalRead not currently implemented in esp32spi") def __repr__(self): return str(self.id) - class DigitalInOut(): + """Mock DigitalIO CircuitPython API Implementation for ESP32SPI. Provides access to ESP_SPIcontrol methods. """ @@ -143,7 +130,6 @@ def direction(self, dir): self.drive_mode = DriveMode.PUSH_PULL elif dir is Direction.INPUT: self._pin.init(mode=Pin.IN) - self.pull = None else: raise AttributeError("Not a Direction") @@ -156,4 +142,19 @@ def value(self, val): if self.direction is Direction.OUTPUT: self._pin.value(1 if val else 0) else: - raise AttributeError("Not an output") \ No newline at end of file + raise AttributeError("Not an output") + + @property + def drive_mode(self): + if self.direction is Direction.OUTPUT: + return self.__drive_mode + else: + raise AttributeError("Not an output") + + @drive_mode.setter + def drive_mode(self, mode): + self.__drive_mode = mode + if mode is DriveMode.OPEN_DRAIN: + self._pin.init(mode=Pin.OPEN_DRAIN) + elif mode is DriveMode.PUSH_PULL: + self._pin.init(mode=Pin.OUT) \ No newline at end of file From 5e97cb1fcd152bcf22055e53eeb376e336f820eb Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 6 Jun 2019 15:01:22 -0400 Subject: [PATCH 12/37] add switch_to_x methods, docstrings --- adafruit_esp32spi/digitalio.py | 90 ++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index b9f28bf..2c4fb57 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -28,36 +28,30 @@ """ from micropython import const -# Enums -class DriveMode(): - PUSH_PULL = None - OPEN_DRAIN = None - -DriveMode.PUSH_PULL = DriveMode() -DriveMode.OPEN_DRAIN = DriveMode() - -class Direction: - INPUT = None - OUTPUT = None - -Direction.INPUT = Direction() -Direction.OUTPUT = Direction() - class Pin: IN = const(0x00) OUT = const(0x01) LOW = const(0x00) HIGH = const(0x01) - id = None _value = LOW _mode = IN + id = None ESP32_GPIO_PINS = set([0, 1, 2, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33]) + """ + Implementation of CircuitPython API Pin Handling + for ESP32SPI. + + :param int esp_pin: Valid ESP32 GPIO Pin, predefined in ESP32_GPIO_PINS. + :param ESP_SPIcontrol esp: The ESP object we are using. + NOTE: This class does not currently implement reading digital pins + or the use of internal pull-up resistors. + """ def __init__(self, esp_pin, esp): if esp_pin in self.ESP32_GPIO_PINS: self.id = esp_pin @@ -67,9 +61,8 @@ def __init__(self, esp_pin, esp): def init(self, mode=IN): """Initalizes a pre-defined pin. - :param mode: Pin mode (IN, OUT, LOW, HIGH). + :param mode: Pin mode (IN, OUT, LOW, HIGH). Defaults to IN. """ - print('pin init') if mode != None: if mode == self.IN: self._mode = self.IN @@ -82,7 +75,7 @@ def init(self, mode=IN): def value(self, val=None): """Sets ESP32 Pin GPIO output mode. - :param val: Output level (LOW, HIGH) + :param val: Pin output level (LOW, HIGH) """ if val != None: if val == self.LOW: @@ -99,30 +92,64 @@ def value(self, val=None): def __repr__(self): return str(self.id) + +class DriveMode(): + PUSH_PULL = None + OPEN_DRAIN = None +DriveMode.PUSH_PULL = DriveMode() +DriveMode.OPEN_DRAIN = DriveMode() + + +class Direction(): + INPUT = None + OUTPUT = None +Direction.INPUT = Direction() +Direction.OUTPUT = Direction() + + class DigitalInOut(): + """Implementation of DigitalIO module for ESP32SPI. - """Mock DigitalIO CircuitPython API Implementation for ESP32SPI. - Provides access to ESP_SPIcontrol methods. + :param ESP_SPIcontrol esp: The ESP object we are using. + :param int pin: Valid ESP32 GPIO Pin, predefined in ESP32_GPIO_PINS. """ _pin = None def __init__(self, esp, pin): self._esp = esp self._pin = Pin(pin, self._esp) - print('id:', self._pin.id) - self._direction = Direction.INPUT + self.direction = Direction.INPUT + + def __exit__(self): + self.deinit() def deinit(self): self._pin = None + + 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. + """ + self.direction = Direction.OUTPUT + self.value = value + self._drive_mode = drive_mode - def __exit__(self): - self.deinit() + 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("Digital reads are not currently supported in ESP32SPI.") @property def direction(self): + """Returns the pin's direction.""" return self.__direction @direction.setter def direction(self, dir): + """Sets the direction of the pin. + :param Direction dir: Pin direction (Direction.OUTPUT or Direction.INPUT) + """ self.__direction = dir if dir is Direction.OUTPUT: self._pin.init(mode=Pin.OUT) @@ -135,10 +162,16 @@ def direction(self, dir): @property def value(self): + """Returns the digital logic level value of the pin.""" return self._pin.value() is 1 @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. + """ if self.direction is Direction.OUTPUT: self._pin.value(1 if val else 0) else: @@ -146,6 +179,7 @@ def value(self, val): @property def drive_mode(self): + """Returns pin drive mode.""" if self.direction is Direction.OUTPUT: return self.__drive_mode else: @@ -153,8 +187,12 @@ 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 + """ self.__drive_mode = mode if mode is DriveMode.OPEN_DRAIN: self._pin.init(mode=Pin.OPEN_DRAIN) elif mode is DriveMode.PUSH_PULL: - self._pin.init(mode=Pin.OUT) \ No newline at end of file + self._pin.init(mode=Pin.OUT) From 6a0c036995ead0074581b3932f3f907a78dc9332 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 6 Jun 2019 15:31:49 -0400 Subject: [PATCH 13/37] pylinting - 8.79/10, look at drivemode/direction classes... --- adafruit_esp32spi/digitalio.py | 73 +++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index 2c4fb57..a675c4e 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -1,6 +1,6 @@ # The MIT License (MIT) # -# Copyright (c) 2019 Brent Rubell for Adafruit +# Copyright (c) 2019 Brent Rubell for Adafruit Industries # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -29,19 +29,6 @@ from micropython import const class Pin: - IN = const(0x00) - OUT = const(0x01) - LOW = const(0x00) - HIGH = const(0x01) - _value = LOW - _mode = IN - id = None - - ESP32_GPIO_PINS = set([0, 1, 2, 4, 5, - 12, 13, 14, 15, - 16, 17, 18, 19, - 21, 22, 23, 25, - 26, 27, 32, 33]) """ Implementation of CircuitPython API Pin Handling for ESP32SPI. @@ -52,9 +39,24 @@ class Pin: NOTE: This class does not currently implement reading digital pins or the use of internal pull-up resistors. """ + #pylint: disable=invalid-name + IN = const(0x00) + OUT = const(0x01) + LOW = const(0x00) + HIGH = const(0x01) + _value = LOW + _mode = IN + pin_id = None + + ESP32_GPIO_PINS = set([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_pin, esp): if esp_pin in self.ESP32_GPIO_PINS: - self.id = esp_pin + self.pin_id = esp_pin else: raise AttributeError("Pin %d is not a valid ESP32 GPIO Pin."%esp_pin) self._esp = esp @@ -63,13 +65,13 @@ def init(self, mode=IN): """Initalizes a pre-defined pin. :param mode: Pin mode (IN, OUT, LOW, HIGH). Defaults to IN. """ - if mode != None: + if mode is not None: if mode == self.IN: self._mode = self.IN - self._esp.set_pin_mode(self.id, 0) + self._esp.set_pin_mode(self.pin_id, 0) elif mode == self.OUT: self._mode = self.OUT - self._esp.set_pin_mode(self.id, 1) + self._esp.set_pin_mode(self.pin_id, 1) else: raise RuntimeError("Invalid mode defined") @@ -77,30 +79,32 @@ def value(self, val=None): """Sets ESP32 Pin GPIO output mode. :param val: Pin output level (LOW, HIGH) """ - if val != None: + if val is not None: if val == self.LOW: self._value = val - self._esp.set_digital_write(self.id, 0) + self._esp.set_digital_write(self.pin_id, 0) elif val == self.HIGH: self._value = val - self._esp.set_digital_write(self.id, 1) + self._esp.set_digital_write(self.pin_id, 1) else: raise RuntimeError("Invalid value for pin") else: raise NotImplementedError("digitalRead not currently implemented in esp32spi") def __repr__(self): - return str(self.id) - + return str(self.pin_id) +@staticmethod class DriveMode(): + """DriveMode Enum.""" PUSH_PULL = None OPEN_DRAIN = None DriveMode.PUSH_PULL = DriveMode() DriveMode.OPEN_DRAIN = DriveMode() - +@staticmethod class Direction(): + """DriveMode Enum.""" INPUT = None OUTPUT = None Direction.INPUT = Direction() @@ -119,13 +123,17 @@ def __init__(self, esp, pin): self._pin = Pin(pin, self._esp) self.direction = Direction.INPUT - def __exit__(self): + def __enter__(self): + return self + + def __exit__(self, exception_type, exception_value, traceback): self.deinit() def deinit(self): + """De-initializes the pin object.""" self._pin = None - def switch_to_output(self, value=False, drive_mode= DriveMode.PUSH_PULL): + 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. @@ -133,7 +141,7 @@ def switch_to_output(self, value=False, drive_mode= DriveMode.PUSH_PULL): self.direction = Direction.OUTPUT self.value = value self._drive_mode = drive_mode - + 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. @@ -146,16 +154,16 @@ def direction(self): return self.__direction @direction.setter - def direction(self, dir): + def direction(self, pin_dir): """Sets the direction of the pin. :param Direction dir: Pin direction (Direction.OUTPUT or Direction.INPUT) """ - self.__direction = dir - if dir is Direction.OUTPUT: + self.__direction = pin_dir + if pin_dir is Direction.OUTPUT: self._pin.init(mode=Pin.OUT) self.value = False self.drive_mode = DriveMode.PUSH_PULL - elif dir is Direction.INPUT: + elif pin_dir is Direction.INPUT: self._pin.init(mode=Pin.IN) else: raise AttributeError("Not a Direction") @@ -182,8 +190,7 @@ def drive_mode(self): """Returns pin drive mode.""" if self.direction is Direction.OUTPUT: return self.__drive_mode - else: - raise AttributeError("Not an output") + raise AttributeError("Not an output") @drive_mode.setter def drive_mode(self, mode): From 4923344d95d8a41dd01b5da6ea140cbcd04171eb Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 6 Jun 2019 16:30:27 -0400 Subject: [PATCH 14/37] checking in digitalio, ready --- adafruit_esp32spi/digitalio.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index a675c4e..eb90caf 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -94,7 +94,7 @@ def value(self, val=None): def __repr__(self): return str(self.pin_id) -@staticmethod +# pylint: disable = too-few-public-methods class DriveMode(): """DriveMode Enum.""" PUSH_PULL = None @@ -102,7 +102,7 @@ class DriveMode(): DriveMode.PUSH_PULL = DriveMode() DriveMode.OPEN_DRAIN = DriveMode() -@staticmethod + class Direction(): """DriveMode Enum.""" INPUT = None @@ -118,6 +118,7 @@ class DigitalInOut(): :param int pin: Valid ESP32 GPIO Pin, predefined in ESP32_GPIO_PINS. """ _pin = None + #pylint: disable = attribute-defined-outside-init def __init__(self, esp, pin): self._esp = esp self._pin = Pin(pin, self._esp) @@ -138,9 +139,9 @@ def switch_to_output(self, value=False, drive_mode=DriveMode.PUSH_PULL): :param bool value: Default mode to set upon switching. :param DriveMode drive_mode: Drive mode for the output. """ - self.direction = Direction.OUTPUT - self.value = value + self._direction = Direction.OUTPUT self._drive_mode = drive_mode + self.value = value def switch_to_input(self, pull=None): """Sets the pull and then switch to read in digital values. @@ -189,7 +190,7 @@ def value(self, val): def drive_mode(self): """Returns pin drive mode.""" if self.direction is Direction.OUTPUT: - return self.__drive_mode + return self._drive_mode raise AttributeError("Not an output") @drive_mode.setter @@ -200,6 +201,6 @@ def drive_mode(self, mode): """ self.__drive_mode = mode if mode is DriveMode.OPEN_DRAIN: - self._pin.init(mode=Pin.OPEN_DRAIN) + raise NotImplementedError('Drive mode %s not implemented in ESP32SPI.'%mode) elif mode is DriveMode.PUSH_PULL: self._pin.init(mode=Pin.OUT) From 8599c0124b87cd4b4b5b9a8c4f6171861c229ac7 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 6 Jun 2019 17:16:23 -0400 Subject: [PATCH 15/37] add credit to where credit is due :) --- adafruit_esp32spi/digitalio.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index eb90caf..49f5c35 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -24,7 +24,10 @@ ============================== DigitalIO for ESP32 over SPI. -* Author(s): Brent Rubell +* 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 micropython import const From 6fcb231a477ef3ac213ea6cccc7002c5e426a5c2 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 7 Jun 2019 10:45:45 -0400 Subject: [PATCH 16/37] Adding pwmout back in --- adafruit_esp32spi/PWMOut.py | 109 ++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100755 adafruit_esp32spi/PWMOut.py diff --git a/adafruit_esp32spi/PWMOut.py b/adafruit_esp32spi/PWMOut.py new file mode 100755 index 0000000..c4598ea --- /dev/null +++ b/adafruit_esp32spi/PWMOut.py @@ -0,0 +1,109 @@ +# The MIT License (MIT) +# +# Copyright (c) 2019 Brent Rubell for Adafruit Industries +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +`PWMOut` +============================== +PWMOut CircuitPython API for ESP32SPI. + +* Author(s): Brent Rubell +""" + +class PWMOut(): + ESP32_PWM_PINS = set([0, 1, 2, 4, 5, + 12, 13, 14, 15, + 16, 17, 18, 19, + 21, 22, 23, 25, + 26, 27, 32, 33]) + """ + Implementation of CircuitPython PWMOut for ESP32SPI. + + :param int esp_pin: Valid ESP32 GPIO Pin, predefined in ESP32_GPIO_PINS. + :param ESP_SPIcontrol esp: The ESP object we are using. + :param int duty_cycle: The fraction of each pulse which is high, 16-bit. + :param int frequency: The target frequency in Hertz (32-bit). + :param bool variable_frequency: True if the frequency will change over time. + """ + 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: + raise AttributeError("Pin %d is not a valid ESP32 GPIO Pin."%esp_pin) + self._esp = esp + self._duty_cycle = duty_cycle + self._freq = frequency + self._var_freq = variable_frequency + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, exc_traceback): + self.deinit() + + def deinit(self): + """De-initalize the PWMOut object.""" + self._duty_cycle = 0 + self._freq = 0 + self._pwm_pin = None + + def _is_deinited(self): + if self._pwm_pin is None: + raise ValueError("PWMOut Object has been deinitialized and can no longer " + "be used. Create a new PWMOut object.") + + @property + def duty_cycle(self): + """Returns the PWMOut object's duty cycle as a + ratio from 0.0 to 1.0.""" + self._is_deinited() + return self._duty_cycle + + @duty_cycle.setter + def duty_cycle(self, duty_cycle): + """Sets the PWMOut duty cycle. + :param float duty_cycle: Between 0.0 (low) and 1.0 (high). + :param int duty_cycle: Between 0 (low) and 1 (high). + """ + self._is_deinited() + if not isinstance(duty_cycle, (int, float)): + raise TypeError("Invalid duty_cycle, should be int or float.") + + duty_cycle /= 65535.0 + if not 0.0 <= duty_cycle <= 1.0: + raise ValueError("Invalid duty_cycle, should be between 0.0 and 1.0") + self._esp.set_analog_write(self._pwm_pin, duty_cycle) + + @property + def frequency(self): + """Returns the PWMOut object's frequency value.""" + self._is_deinited() + raise NotImplementedError("PWMOut Frequency not implemented in ESP32SPI") + + @frequency.setter + def frequency(self, freq): + """Sets the PWMOut object's frequency value. + :param int freq: 32-bit value that dictates the PWM frequency in Hertz. + NOTE: Only writeable when constructed with variable_Frequency=True. + """ + self._is_deinited() + raise NotImplementedError("PWMOut Frequency not implemented in ESP32SPI") + + From 64ca443967cd971da1bfc43d4bc72773446bfa06 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 7 Jun 2019 11:00:38 -0400 Subject: [PATCH 17/37] correct pin in attrerror, fixup docstrings --- adafruit_esp32spi/PWMOut.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/adafruit_esp32spi/PWMOut.py b/adafruit_esp32spi/PWMOut.py index c4598ea..2eea9e5 100755 --- a/adafruit_esp32spi/PWMOut.py +++ b/adafruit_esp32spi/PWMOut.py @@ -28,11 +28,6 @@ """ class PWMOut(): - ESP32_PWM_PINS = set([0, 1, 2, 4, 5, - 12, 13, 14, 15, - 16, 17, 18, 19, - 21, 22, 23, 25, - 26, 27, 32, 33]) """ Implementation of CircuitPython PWMOut for ESP32SPI. @@ -42,11 +37,16 @@ class PWMOut(): :param int frequency: The target frequency in Hertz (32-bit). :param bool variable_frequency: True if the frequency will change over time. """ + ESP32_PWM_PINS = set([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): if pwm_pin in self.ESP32_PWM_PINS: self._pwm_pin = pwm_pin else: - raise AttributeError("Pin %d is not a valid ESP32 GPIO Pin."%esp_pin) + raise AttributeError("Pin %d is not a valid ESP32 GPIO Pin."%pwm_pin) self._esp = esp self._duty_cycle = duty_cycle self._freq = frequency @@ -54,7 +54,7 @@ def __init__(self, esp, pwm_pin, *, frequency=500, duty_cycle=0, variable_freque def __enter__(self): return self - + def __exit__(self, exc_type, exc_value, exc_traceback): self.deinit() @@ -63,7 +63,7 @@ def deinit(self): self._duty_cycle = 0 self._freq = 0 self._pwm_pin = None - + def _is_deinited(self): if self._pwm_pin is None: raise ValueError("PWMOut Object has been deinitialized and can no longer " @@ -75,7 +75,7 @@ def duty_cycle(self): ratio from 0.0 to 1.0.""" self._is_deinited() return self._duty_cycle - + @duty_cycle.setter def duty_cycle(self, duty_cycle): """Sets the PWMOut duty cycle. @@ -85,7 +85,7 @@ def duty_cycle(self, duty_cycle): self._is_deinited() if not isinstance(duty_cycle, (int, float)): raise TypeError("Invalid duty_cycle, should be int or float.") - + duty_cycle /= 65535.0 if not 0.0 <= duty_cycle <= 1.0: raise ValueError("Invalid duty_cycle, should be between 0.0 and 1.0") @@ -96,7 +96,7 @@ def frequency(self): """Returns the PWMOut object's frequency value.""" self._is_deinited() raise NotImplementedError("PWMOut Frequency not implemented in ESP32SPI") - + @frequency.setter def frequency(self, freq): """Sets the PWMOut object's frequency value. @@ -105,5 +105,3 @@ def frequency(self, freq): """ self._is_deinited() raise NotImplementedError("PWMOut Frequency not implemented in ESP32SPI") - - From c91622442bac0f2c34fe8e36c9601f038ac37eb1 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 7 Jun 2019 11:14:12 -0400 Subject: [PATCH 18/37] set freq --- adafruit_esp32spi/PWMOut.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/PWMOut.py b/adafruit_esp32spi/PWMOut.py index 2eea9e5..d44c5c8 100755 --- a/adafruit_esp32spi/PWMOut.py +++ b/adafruit_esp32spi/PWMOut.py @@ -65,6 +65,7 @@ def deinit(self): self._pwm_pin = None def _is_deinited(self): + """Checks if PWMOut object has been previously de-initalized""" if self._pwm_pin is None: raise ValueError("PWMOut Object has been deinitialized and can no longer " "be used. Create a new PWMOut object.") @@ -85,7 +86,6 @@ def duty_cycle(self, duty_cycle): self._is_deinited() if not isinstance(duty_cycle, (int, float)): raise TypeError("Invalid duty_cycle, should be int or float.") - duty_cycle /= 65535.0 if not 0.0 <= duty_cycle <= 1.0: raise ValueError("Invalid duty_cycle, should be between 0.0 and 1.0") @@ -104,4 +104,5 @@ def frequency(self, freq): NOTE: Only writeable when constructed with variable_Frequency=True. """ self._is_deinited() + self._freq = freq raise NotImplementedError("PWMOut Frequency not implemented in ESP32SPI") From 596b879ab4f3633087976e776f892caf1eb3f8e9 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 7 Jun 2019 11:17:02 -0400 Subject: [PATCH 19/37] frequency should return, not raise --- adafruit_esp32spi/PWMOut.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/PWMOut.py b/adafruit_esp32spi/PWMOut.py index d44c5c8..fbdbc05 100755 --- a/adafruit_esp32spi/PWMOut.py +++ b/adafruit_esp32spi/PWMOut.py @@ -95,7 +95,7 @@ def duty_cycle(self, duty_cycle): def frequency(self): """Returns the PWMOut object's frequency value.""" self._is_deinited() - raise NotImplementedError("PWMOut Frequency not implemented in ESP32SPI") + return self._freq @frequency.setter def frequency(self, freq): From d21b70993af0c4e92838456c07df15e73fa62e24 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 11 Jun 2019 10:32:35 -0400 Subject: [PATCH 20/37] add an externally defined rgbled status_led to _wifimanager --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 14 ++++++++++---- examples/esp32spi_aio_post.py | 9 ++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 9906847..7146693 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -42,8 +42,9 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2): """ :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 or DotStar (default=None) - :type status_pixel: NeoPixel or DotStar + :param status_pixel: (Optional) The pixel device - A NeoPixel, DotStar, + or RGB LED (default=None) + :type status_pixel: NeoPixel, DotStar, or RGB LED :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) """ # Read the settings @@ -54,6 +55,9 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2): self.attempts = attempts requests.set_interface(self._esp) self.statuspix = status_pixel + self._is_rgb_led = False + if hasattr(self.statuspix, 'color'): + self._is_rgb_led = True self.pixel_status(0) def reset(self): @@ -214,13 +218,15 @@ def ip_address(self): def pixel_status(self, value): """ - Change Status NeoPixel if it was defined + Change Status NeoPixel/Dotstar/RGBLED if it was defined :param value: The value to set the Board's status LED to :type value: int or 3-value tuple """ - if self.statuspix: + if self.statuspix and not self._is_rgb_led: self.statuspix.fill(value) + else: + self.statuspix.color = value def signal_strength(self): """ diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index bdf395c..dfbf194 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -30,7 +30,14 @@ """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) +# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) +# Uncomment below for an externally defined RGB LED +# 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 From aeae91ec1dcf18884d2d2560f6866741b7941d08 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 11 Jun 2019 12:11:30 -0400 Subject: [PATCH 21/37] test the pixel attributes within pixel_status --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 7146693..f0acae2 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -55,9 +55,6 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2): self.attempts = attempts requests.set_interface(self._esp) self.statuspix = status_pixel - self._is_rgb_led = False - if hasattr(self.statuspix, 'color'): - self._is_rgb_led = True self.pixel_status(0) def reset(self): @@ -218,15 +215,16 @@ def ip_address(self): def pixel_status(self, value): """ - Change Status NeoPixel/Dotstar/RGBLED if it was defined + Change Status Pixel if it was defined :param value: The value to set the Board's status LED to :type value: int or 3-value tuple """ - if self.statuspix and not self._is_rgb_led: - self.statuspix.fill(value) - else: - self.statuspix.color = value + if self.statuspix: + if hasattr(self.statuspix, 'color'): + self.statuspix.color = value + else: + self.statuspix.fill(value) def signal_strength(self): """ From 0d7c5b5c24d70419900fcc2ae3aba32234db3a33 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sun, 19 May 2019 11:30:35 -0700 Subject: [PATCH 22/37] Adding WPA2 Enterprise support to the WiFi manager library --- .../adafruit_esp32spi_wifimanager.py | 60 ++++++++++++++----- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index f0acae2..201e24c 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -38,7 +38,7 @@ class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection """ - def __init__(self, esp, secrets, status_pixel=None, attempts=2): + def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): """ :param ESP_SPIcontrol esp: The ESP object we are using :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) @@ -46,13 +46,19 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2): or RGB LED (default=None) :type status_pixel: NeoPixel, DotStar, or RGB LED :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) + :param int con_type: (Optional) Type of WiFi connection to make: normal=1, WPA2 Enterprise=2 """ # Read the settings self._esp = esp self.debug = False self.ssid = secrets['ssid'] self.password = secrets['password'] + self.ent_ssid = secrets['ent_ssid'] + self.ent_ident = secrets['ent_ident'] + self.ent_user = secrets['ent_user'] + self.ent_passwd = secrets['ent_passwd'] self.attempts = attempts + self.con_type = con_type requests.set_interface(self._esp) self.statuspix = status_pixel self.pixel_status(0) @@ -77,21 +83,45 @@ def connect(self): for access_pt in self._esp.scan_networks(): print("\t%s\t\tRSSI: %d" % (str(access_pt['ssid'], 'utf-8'), access_pt['rssi'])) failure_count = 0 - while not self._esp.is_connected: - try: - if self.debug: - print("Connecting to AP...") - self.pixel_status((100, 0, 0)) - self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) - failure_count = 0 - self.pixel_status((0, 100, 0)) - except (ValueError, RuntimeError) as error: - print("Failed to connect, retrying\n", error) - failure_count += 1 - if failure_count >= self.attempts: + if self.con_type == 1: + while not self._esp.is_connected: + try: + if self.debug: + print("Connecting to AP...") + self.pixel_status((100, 0, 0)) + self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) failure_count = 0 - self.reset() - continue + self.pixel_status((0, 100, 0)) + except (ValueError, RuntimeError) as error: + print("Failed to connect, retrying\n", error) + failure_count += 1 + if failure_count >= self.attempts: + failure_count = 0 + self.reset() + continue + elif self.con_type == 2: + self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) + self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) + self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) + self._esp.wifi_set_entpassword(bytes(self.ent_passwd, 'utf-8')) + self._esp.wifi_set_entenable() + while not self._esp.is_connected: + try: + if self.debug: + print("Connecting to WPA2 Enterprise AP...") + self.pixel_status((100, 0, 0)) + failure_count = 0 + self.pixel_status((0, 100, 0)) + except (ValueError, RuntimeError) as error: + print("Failed to connect, retrying\n", error) + failure_count += 1 + if failure_count >= self.attempts: + failure_count = 0 + self.reset() + continue + else: + print("Invalid connection type! Exiting...") + exit(1) def get(self, url, **kw): """ From 15ea3cc4803fcffaaf723fb9519c1695de2c0ea7 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sun, 19 May 2019 15:18:06 -0700 Subject: [PATCH 23/37] Added an enum-like class for the WiFi connection type and refactored the code --- .../adafruit_esp32spi_wifimanager.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 201e24c..d2c2cf3 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -34,11 +34,22 @@ from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_requests as requests +class WiFiConnType: # pylint: disable=too-few-public-methods + """An enum-like class representing the different types of WiFi connections + that can be made. The values can be referenced like ``WiFiConnType.normal``. + Possible values are + - ``ThermocoupleType.normal`` + - ``ThermocoupleType.enterprise`` + """ + # pylint: disable=invalid-name + normal = 1 + enterprise = 2 + class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection """ - def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): + def __init__(self, esp, secrets, status_pixel=None, attempts=2, wificonntype=WiFiConnType.normal): """ :param ESP_SPIcontrol esp: The ESP object we are using :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) @@ -46,7 +57,9 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): or RGB LED (default=None) :type status_pixel: NeoPixel, DotStar, or RGB LED :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) - :param int con_type: (Optional) Type of WiFi connection to make: normal=1, WPA2 Enterprise=2 + :param const con_type: (Optional) Type of WiFi connection: normal=1, WPA2 Enterprise=2 + :param ~adafruit_esp32spi_wifimanager.WiFiConnType wificonntype: The type of WiFi \ + connection to make. The default is "normal". """ # Read the settings self._esp = esp @@ -58,7 +71,7 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): self.ent_user = secrets['ent_user'] self.ent_passwd = secrets['ent_passwd'] self.attempts = attempts - self.con_type = con_type + self.wificonntype = wificonntype requests.set_interface(self._esp) self.statuspix = status_pixel self.pixel_status(0) @@ -83,7 +96,7 @@ def connect(self): for access_pt in self._esp.scan_networks(): print("\t%s\t\tRSSI: %d" % (str(access_pt['ssid'], 'utf-8'), access_pt['rssi'])) failure_count = 0 - if self.con_type == 1: + if self.wificonntype == WiFiConnType.normal: while not self._esp.is_connected: try: if self.debug: @@ -99,7 +112,7 @@ def connect(self): failure_count = 0 self.reset() continue - elif self.con_type == 2: + elif self.wificonntype == WiFiConnType.enterprise: self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) From 1eca01c473ef2202980d89ec04d77fbfc13ce2ca Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Tue, 21 May 2019 20:09:02 -0700 Subject: [PATCH 24/37] Replaced enum-like class with 2 constants; various fix-ups based on PR reviews; added WPA2 Enterprise version of aio example script --- .../adafruit_esp32spi_wifimanager.py | 30 ++++------ examples/esp32spi_wpa2ent_aio_post.py | 57 +++++++++++++++++++ 2 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 examples/esp32spi_wpa2ent_aio_post.py diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index d2c2cf3..6472a98 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -31,25 +31,18 @@ # pylint: disable=no-name-in-module +from micropython import const from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_requests as requests -class WiFiConnType: # pylint: disable=too-few-public-methods - """An enum-like class representing the different types of WiFi connections - that can be made. The values can be referenced like ``WiFiConnType.normal``. - Possible values are - - ``ThermocoupleType.normal`` - - ``ThermocoupleType.enterprise`` - """ - # pylint: disable=invalid-name - normal = 1 - enterprise = 2 - class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection """ - def __init__(self, esp, secrets, status_pixel=None, attempts=2, wificonntype=WiFiConnType.normal): + NORMAL = const(1) + ENTERPRISE = const(2) + + def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type=NORMAL): """ :param ESP_SPIcontrol esp: The ESP object we are using :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) @@ -69,9 +62,9 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, wificonntype=WiF self.ent_ssid = secrets['ent_ssid'] self.ent_ident = secrets['ent_ident'] self.ent_user = secrets['ent_user'] - self.ent_passwd = secrets['ent_passwd'] + self.ent_password = secrets['ent_password'] self.attempts = attempts - self.wificonntype = wificonntype + self._connection_type = connection_type requests.set_interface(self._esp) self.statuspix = status_pixel self.pixel_status(0) @@ -96,7 +89,7 @@ def connect(self): for access_pt in self._esp.scan_networks(): print("\t%s\t\tRSSI: %d" % (str(access_pt['ssid'], 'utf-8'), access_pt['rssi'])) failure_count = 0 - if self.wificonntype == WiFiConnType.normal: + if self._connection_type == ESPSPI_WiFiManager.NORMAL: while not self._esp.is_connected: try: if self.debug: @@ -112,11 +105,11 @@ def connect(self): failure_count = 0 self.reset() continue - elif self.wificonntype == WiFiConnType.enterprise: + elif self._connection_type == ESPSPI_WiFiManager.ENTERPRISE: self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) - self._esp.wifi_set_entpassword(bytes(self.ent_passwd, 'utf-8')) + self._esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) self._esp.wifi_set_entenable() while not self._esp.is_connected: try: @@ -133,8 +126,7 @@ def connect(self): self.reset() continue else: - print("Invalid connection type! Exiting...") - exit(1) + raise TypeError("Invalid WiFi connection type specified") def get(self, url, **kw): """ diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py new file mode 100644 index 0000000..bd23a3b --- /dev/null +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -0,0 +1,57 @@ +import time +import board +import busio +from digitalio import DigitalInOut +import neopixel +from adafruit_esp32spi import adafruit_esp32spi +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import ESPSPI_WiFiManager + +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 + +# 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) +"""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) +wifi = ESPSPI_WiFiManager(esp, secrets, status_light, connection_type=ESPSPI_WiFiManager.ENTERPRISE) + +counter = 0 + +while True: + try: + print("Posting data...", end='') + data = counter + feed = 'test' + payload = {'value':data} + response = wifi.post( + "https://io.adafruit.com/api/v2/"+secrets['aio_username']+"/feeds/"+feed+"/data", + json=payload, + headers={"X-AIO-KEY":secrets['aio_key']}) + print(response.json()) + response.close() + counter = counter + 1 + print("OK") + except (ValueError, RuntimeError) as e: + print("Failed to get data, retrying\n", e) + wifi.reset() + continue + response = None + time.sleep(15) From 1ff8edf80bfa448a86336c0bc0f99fe2e837e932 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sun, 16 Jun 2019 15:55:44 -0700 Subject: [PATCH 25/37] Refactored wifimanager connect function into 3 separate functions; refactored loading of WPA2 Enterprise secrets so if they're not defined, we silently move on; tweaked the two WPA2 examples to use the newer way of defining board pins --- .../adafruit_esp32spi_wifimanager.py | 104 +++++++++++------- examples/esp32spi_wpa2ent_aio_post.py | 20 ++-- examples/esp32spi_wpa2ent_simpletest.py | 21 ++-- 3 files changed, 87 insertions(+), 58 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 6472a98..6f7c944 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -31,6 +31,7 @@ # pylint: disable=no-name-in-module +from time import sleep from micropython import const from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_requests as requests @@ -42,6 +43,7 @@ class ESPSPI_WiFiManager: NORMAL = const(1) ENTERPRISE = const(2) +# pylint: disable=too-many-arguments def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type=NORMAL): """ :param ESP_SPIcontrol esp: The ESP object we are using @@ -59,16 +61,27 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type= self.debug = False self.ssid = secrets['ssid'] self.password = secrets['password'] - self.ent_ssid = secrets['ent_ssid'] - self.ent_ident = secrets['ent_ident'] - self.ent_user = secrets['ent_user'] - self.ent_password = secrets['ent_password'] self.attempts = attempts self._connection_type = connection_type requests.set_interface(self._esp) self.statuspix = status_pixel self.pixel_status(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'] +# pylint: enable=too-many-arguments + def reset(self): """ Perform a hard reset on the ESP32 @@ -88,46 +101,59 @@ 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" % (str(access_pt['ssid'], 'utf-8'), access_pt['rssi'])) - failure_count = 0 if self._connection_type == ESPSPI_WiFiManager.NORMAL: - while not self._esp.is_connected: - try: - if self.debug: - print("Connecting to AP...") - self.pixel_status((100, 0, 0)) - self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) - failure_count = 0 - self.pixel_status((0, 100, 0)) - except (ValueError, RuntimeError) as error: - print("Failed to connect, retrying\n", error) - failure_count += 1 - if failure_count >= self.attempts: - failure_count = 0 - self.reset() - continue + self.connect_normal() elif self._connection_type == ESPSPI_WiFiManager.ENTERPRISE: - self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) - self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) - self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) - self._esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) - self._esp.wifi_set_entenable() - while not self._esp.is_connected: - try: - if self.debug: - print("Connecting to WPA2 Enterprise AP...") - self.pixel_status((100, 0, 0)) - failure_count = 0 - self.pixel_status((0, 100, 0)) - except (ValueError, RuntimeError) as error: - print("Failed to connect, retrying\n", error) - failure_count += 1 - if failure_count >= self.attempts: - failure_count = 0 - self.reset() - continue + self.connect_enterprise() else: raise TypeError("Invalid WiFi connection type specified") + def connect_normal(self): + """ + Attempt a regular style WiFi connection + """ + while not self._esp.is_connected: + try: + if self.debug: + print("Connecting to AP...") + self.pixel_status((100, 0, 0)) + self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) + failure_count = 0 + self.pixel_status((0, 100, 0)) + except (ValueError, RuntimeError) as error: + print("Failed to connect, retrying\n", error) + failure_count += 1 + if failure_count >= self.attempts: + failure_count = 0 + self.reset() + continue + + def connect_enterprise(self): + """ + Attempt an enterprise style WiFi connection + """ + self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) + self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) + self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) + self._esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) + self._esp.wifi_set_entenable() + while not self._esp.is_connected: + try: + if self.debug: + print("Waiting for the ESP32 to connect to the WPA2 Enterprise AP...") + self.pixel_status((100, 0, 0)) + sleep(1) + failure_count = 0 + self.pixel_status((0, 100, 0)) + sleep(1) + except (ValueError, RuntimeError) as error: + print("Failed to connect, retrying\n", error) + failure_count += 1 + if failure_count >= self.attempts: + failure_count = 0 + self.reset() + continue + def get(self, url, **kw): """ Pass the Get request to requests and update status LED diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index bd23a3b..2123c05 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -15,15 +15,17 @@ print("WiFi secrets are kept in secrets.py, please add them there!") raise -# 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) +# ESP32 setup +# If your board does define the three pins listed below, +# you can set the correct pins in the second block +try: + esp32_cs = DigitalInOut(board.ESP_CS) + esp32_ready = DigitalInOut(board.ESP_BUSY) + esp32_reset = DigitalInOut(board.ESP_RESET) +except AttributeError: + 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) diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index d8d2a14..2eb06b6 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -25,16 +25,17 @@ def normalize(v): print("ESP32 SPI WPA2 Enterprise test") -# For running on the PyPortal, use this block -esp32_cs = DigitalInOut(board.ESP_CS) -esp32_ready = DigitalInOut(board.ESP_BUSY) -esp32_reset = DigitalInOut(board.ESP_RESET) - -# For a board that doesn't have the ESP pin definitions, use this block and -# set the pins as needed. -#esp32_cs = DigitalInOut(board.D8) -#esp32_ready = DigitalInOut(board.D5) -#esp32_reset = DigitalInOut(board.D7) +# ESP32 setup +# If your board does define the three pins listed below, +# you can set the correct pins in the second block +try: + esp32_cs = DigitalInOut(board.ESP_CS) + esp32_ready = DigitalInOut(board.ESP_BUSY) + esp32_reset = DigitalInOut(board.ESP_RESET) +except AttributeError: + 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) From 4190bc3469a987030a0f24600ab9d4a578f3866c Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Tue, 18 Jun 2019 17:35:11 -0700 Subject: [PATCH 26/37] fix the failure_count issue...sorry about that! --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 6f7c944..5bf0e3a 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -112,6 +112,7 @@ def connect_normal(self): """ Attempt a regular style WiFi connection """ + failure_count = 0 while not self._esp.is_connected: try: if self.debug: @@ -132,6 +133,7 @@ def connect_enterprise(self): """ Attempt an enterprise style WiFi connection """ + failure_count = 0 self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) From 54bcb5a53ad338f7b33a937ea1459b708800c2c8 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 11 Jul 2019 12:06:53 -0400 Subject: [PATCH 27/37] make ._esp public --- .../adafruit_esp32spi_wifimanager.py | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index f0acae2..6b889d2 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -48,12 +48,12 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2): :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) """ # Read the settings - self._esp = esp + self.esp = esp self.debug = False self.ssid = secrets['ssid'] self.password = secrets['password'] self.attempts = attempts - requests.set_interface(self._esp) + requests.set_interface(self.esp) self.statuspix = status_pixel self.pixel_status(0) @@ -63,26 +63,26 @@ def reset(self): """ if self.debug: print("Resetting ESP32") - self._esp.reset() + self.esp.reset() def connect(self): """ Attempt to connect to WiFi using the current settings """ if self.debug: - if self._esp.status == adafruit_esp32spi.WL_IDLE_STATUS: + if self.esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode") - 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("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'])) failure_count = 0 - while not self._esp.is_connected: + while not self.esp.is_connected: try: if self.debug: print("Connecting to AP...") self.pixel_status((100, 0, 0)) - self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) + self.esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) failure_count = 0 self.pixel_status((0, 100, 0)) except (ValueError, RuntimeError) as error: @@ -105,7 +105,7 @@ def get(self, url, **kw): :return: The response from the request :rtype: Response """ - if not self._esp.is_connected: + if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) return_val = requests.get(url, **kw) @@ -124,7 +124,7 @@ def post(self, url, **kw): :return: The response from the request :rtype: Response """ - if not self._esp.is_connected: + if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) return_val = requests.post(url, **kw) @@ -142,7 +142,7 @@ def put(self, url, **kw): :return: The response from the request :rtype: Response """ - if not self._esp.is_connected: + if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) return_val = requests.put(url, **kw) @@ -161,7 +161,7 @@ def patch(self, url, **kw): :return: The response from the request :rtype: Response """ - if not self._esp.is_connected: + if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) return_val = requests.patch(url, **kw) @@ -180,7 +180,7 @@ def delete(self, url, **kw): :return: The response from the request :rtype: Response """ - if not self._esp.is_connected: + if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) return_val = requests.delete(url, **kw) @@ -196,10 +196,10 @@ def ping(self, host, ttl=250): :return: The response time in milliseconds :rtype: int """ - if not self._esp.is_connected: + if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) - response_time = self._esp.ping(host, ttl=ttl) + response_time = self.esp.ping(host, ttl=ttl) self.pixel_status(0) return response_time @@ -207,11 +207,11 @@ def ip_address(self): """ Returns a formatted local IP address, update status pixel. """ - if not self._esp.is_connected: + if not self.esp.is_connected: self.connect() self.pixel_status((0, 0, 100)) self.pixel_status(0) - return self._esp.pretty_ip(self._esp.ip_address) + return self.esp.pretty_ip(self.esp.ip_address) def pixel_status(self, value): """ @@ -230,6 +230,6 @@ def signal_strength(self): """ Returns receiving signal strength indicator in dBm """ - if not self._esp.is_connected: + if not self.esp.is_connected: self.connect() - return self._esp.rssi() + return self.esp.rssi() From 1e77ef5e54f86e3adfc4d040405174eda4f2c565 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sat, 13 Jul 2019 11:50:22 -0700 Subject: [PATCH 28/37] merged conflicts --- .../adafruit_esp32spi_wifimanager.py | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 6b889d2..a10939d 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -38,7 +38,7 @@ class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection """ - def __init__(self, esp, secrets, status_pixel=None, attempts=2): + def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): """ :param ESP_SPIcontrol esp: The ESP object we are using :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) @@ -46,14 +46,20 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2): or RGB LED (default=None) :type status_pixel: NeoPixel, DotStar, or RGB LED :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) + :param int con_type: (Optional) Type of WiFi connection to make: normal=1, WPA2 Enterprise=2 """ # Read the settings self.esp = esp self.debug = False self.ssid = secrets['ssid'] self.password = secrets['password'] + self.ent_ssid = secrets['ent_ssid'] + self.ent_ident = secrets['ent_ident'] + self.ent_user = secrets['ent_user'] + self.ent_passwd = secrets['ent_passwd'] self.attempts = attempts requests.set_interface(self.esp) + self.con_type = con_type self.statuspix = status_pixel self.pixel_status(0) @@ -76,6 +82,17 @@ 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" % (str(access_pt['ssid'], 'utf-8'), access_pt['rssi'])) + if self._connection_type == ESPSPI_WiFiManager.NORMAL: + self.connect_normal() + elif self._connection_type == ESPSPI_WiFiManager.ENTERPRISE: + self.connect_enterprise() + else: + raise TypeError("Invalid WiFi connection type specified") + + def connect_normal(self): + """ + Attempt a regular style WiFi connection + """ failure_count = 0 while not self.esp.is_connected: try: @@ -93,6 +110,33 @@ def connect(self): self.reset() continue + def connect_enterprise(self): + """ + Attempt an enterprise style WiFi connection + """ + failure_count = 0 + self.esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) + self.esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) + self.esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) + self.esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) + self.esp.wifi_set_entenable() + while not self.esp.is_connected: + try: + if self.debug: + print("Waiting for the ESP32 to connect to the WPA2 Enterprise AP...") + self.pixel_status((100, 0, 0)) + sleep(1) + failure_count = 0 + self.pixel_status((0, 100, 0)) + sleep(1) + except (ValueError, RuntimeError) as error: + print("Failed to connect, retrying\n", error) + failure_count += 1 + if failure_count >= self.attempts: + failure_count = 0 + self.reset() + continue + def get(self, url, **kw): """ Pass the Get request to requests and update status LED From a492dda93d83cdfbf7e7112fb6391b738b6e1d09 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sat, 13 Jul 2019 11:53:09 -0700 Subject: [PATCH 29/37] merged conflicts --- .../adafruit_esp32spi_wifimanager.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index a10939d..fa02a07 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -34,11 +34,22 @@ from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_requests as requests +class WiFiConnType: # pylint: disable=too-few-public-methods + """An enum-like class representing the different types of WiFi connections + that can be made. The values can be referenced like ``WiFiConnType.normal``. + Possible values are + - ``ThermocoupleType.normal`` + - ``ThermocoupleType.enterprise`` + """ + # pylint: disable=invalid-name + normal = 1 + enterprise = 2 + class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection """ - def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): + def __init__(self, esp, secrets, status_pixel=None, attempts=2, wificonntype=WiFiConnType.normal): """ :param ESP_SPIcontrol esp: The ESP object we are using :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) @@ -46,7 +57,9 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): or RGB LED (default=None) :type status_pixel: NeoPixel, DotStar, or RGB LED :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) - :param int con_type: (Optional) Type of WiFi connection to make: normal=1, WPA2 Enterprise=2 + :param const con_type: (Optional) Type of WiFi connection: normal=1, WPA2 Enterprise=2 + :param ~adafruit_esp32spi_wifimanager.WiFiConnType wificonntype: The type of WiFi \ + connection to make. The default is "normal". """ # Read the settings self.esp = esp @@ -58,8 +71,8 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, con_type=1): self.ent_user = secrets['ent_user'] self.ent_passwd = secrets['ent_passwd'] self.attempts = attempts + self._connection_type = connection_type requests.set_interface(self.esp) - self.con_type = con_type self.statuspix = status_pixel self.pixel_status(0) From bce6bfa28bfbb5e01ffec5d8f26780ece2e4fdbf Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sat, 13 Jul 2019 11:55:01 -0700 Subject: [PATCH 30/37] merged conflicts --- .../adafruit_esp32spi_wifimanager.py | 19 ++----- examples/esp32spi_wpa2ent_aio_post.py | 57 +++++++++++++++++++ 2 files changed, 63 insertions(+), 13 deletions(-) create mode 100644 examples/esp32spi_wpa2ent_aio_post.py diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index fa02a07..03cad16 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -31,25 +31,18 @@ # pylint: disable=no-name-in-module +from micropython import const from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_requests as requests -class WiFiConnType: # pylint: disable=too-few-public-methods - """An enum-like class representing the different types of WiFi connections - that can be made. The values can be referenced like ``WiFiConnType.normal``. - Possible values are - - ``ThermocoupleType.normal`` - - ``ThermocoupleType.enterprise`` - """ - # pylint: disable=invalid-name - normal = 1 - enterprise = 2 - class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection """ - def __init__(self, esp, secrets, status_pixel=None, attempts=2, wificonntype=WiFiConnType.normal): + NORMAL = const(1) + ENTERPRISE = const(2) + + def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type=NORMAL): """ :param ESP_SPIcontrol esp: The ESP object we are using :param dict secrets: The WiFi and Adafruit IO secrets dict (See examples) @@ -69,7 +62,7 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, wificonntype=WiF self.ent_ssid = secrets['ent_ssid'] self.ent_ident = secrets['ent_ident'] self.ent_user = secrets['ent_user'] - self.ent_passwd = secrets['ent_passwd'] + self.ent_password = secrets['ent_password'] self.attempts = attempts self._connection_type = connection_type requests.set_interface(self.esp) diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py new file mode 100644 index 0000000..bd23a3b --- /dev/null +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -0,0 +1,57 @@ +import time +import board +import busio +from digitalio import DigitalInOut +import neopixel +from adafruit_esp32spi import adafruit_esp32spi +from adafruit_esp32spi.adafruit_esp32spi_wifimanager import ESPSPI_WiFiManager + +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 + +# 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) +"""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) +wifi = ESPSPI_WiFiManager(esp, secrets, status_light, connection_type=ESPSPI_WiFiManager.ENTERPRISE) + +counter = 0 + +while True: + try: + print("Posting data...", end='') + data = counter + feed = 'test' + payload = {'value':data} + response = wifi.post( + "https://io.adafruit.com/api/v2/"+secrets['aio_username']+"/feeds/"+feed+"/data", + json=payload, + headers={"X-AIO-KEY":secrets['aio_key']}) + print(response.json()) + response.close() + counter = counter + 1 + print("OK") + except (ValueError, RuntimeError) as e: + print("Failed to get data, retrying\n", e) + wifi.reset() + continue + response = None + time.sleep(15) From cbc790133d3344f3f4f33391adcc5e60b4b2909d Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sat, 13 Jul 2019 11:56:19 -0700 Subject: [PATCH 31/37] merged conflicts --- .../adafruit_esp32spi_wifimanager.py | 21 +++++++++++++++---- examples/esp32spi_wpa2ent_aio_post.py | 20 ++++++++++-------- examples/esp32spi_wpa2ent_simpletest.py | 21 ++++++++++--------- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 03cad16..0477278 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -31,6 +31,7 @@ # pylint: disable=no-name-in-module +from time import sleep from micropython import const from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_requests as requests @@ -42,6 +43,7 @@ class ESPSPI_WiFiManager: NORMAL = const(1) ENTERPRISE = const(2) +# pylint: disable=too-many-arguments def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type=NORMAL): """ :param ESP_SPIcontrol esp: The ESP object we are using @@ -59,16 +61,27 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type= self.debug = False self.ssid = secrets['ssid'] self.password = secrets['password'] - self.ent_ssid = secrets['ent_ssid'] - self.ent_ident = secrets['ent_ident'] - self.ent_user = secrets['ent_user'] - self.ent_password = secrets['ent_password'] self.attempts = attempts self._connection_type = connection_type requests.set_interface(self.esp) self.statuspix = status_pixel self.pixel_status(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'] +# pylint: enable=too-many-arguments + def reset(self): """ Perform a hard reset on the ESP32 diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index bd23a3b..2123c05 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -15,15 +15,17 @@ print("WiFi secrets are kept in secrets.py, please add them there!") raise -# 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) +# ESP32 setup +# If your board does define the three pins listed below, +# you can set the correct pins in the second block +try: + esp32_cs = DigitalInOut(board.ESP_CS) + esp32_ready = DigitalInOut(board.ESP_BUSY) + esp32_reset = DigitalInOut(board.ESP_RESET) +except AttributeError: + 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) diff --git a/examples/esp32spi_wpa2ent_simpletest.py b/examples/esp32spi_wpa2ent_simpletest.py index d8d2a14..2eb06b6 100644 --- a/examples/esp32spi_wpa2ent_simpletest.py +++ b/examples/esp32spi_wpa2ent_simpletest.py @@ -25,16 +25,17 @@ def normalize(v): print("ESP32 SPI WPA2 Enterprise test") -# For running on the PyPortal, use this block -esp32_cs = DigitalInOut(board.ESP_CS) -esp32_ready = DigitalInOut(board.ESP_BUSY) -esp32_reset = DigitalInOut(board.ESP_RESET) - -# For a board that doesn't have the ESP pin definitions, use this block and -# set the pins as needed. -#esp32_cs = DigitalInOut(board.D8) -#esp32_ready = DigitalInOut(board.D5) -#esp32_reset = DigitalInOut(board.D7) +# ESP32 setup +# If your board does define the three pins listed below, +# you can set the correct pins in the second block +try: + esp32_cs = DigitalInOut(board.ESP_CS) + esp32_ready = DigitalInOut(board.ESP_BUSY) + esp32_reset = DigitalInOut(board.ESP_RESET) +except AttributeError: + 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) From 447955a76fa3e18b2a39ce4b729bddba6465bf6a Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sat, 13 Jul 2019 12:00:07 -0700 Subject: [PATCH 32/37] merged conflicts --- .../adafruit_esp32spi_wifimanager.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 0477278..69715bc 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -61,6 +61,10 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type= self.debug = False self.ssid = secrets['ssid'] self.password = secrets['password'] + self.ent_ssid = secrets['ent_ssid'] + self.ent_ident = secrets['ent_ident'] + self.ent_user = secrets['ent_user'] + self.ent_passwd = secrets['ent_passwd'] self.attempts = attempts self._connection_type = connection_type requests.set_interface(self.esp) @@ -113,12 +117,12 @@ def connect_normal(self): Attempt a regular style WiFi connection """ failure_count = 0 - while not self.esp.is_connected: + while not self._esp.is_connected: try: if self.debug: print("Connecting to AP...") self.pixel_status((100, 0, 0)) - self.esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) + self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) failure_count = 0 self.pixel_status((0, 100, 0)) except (ValueError, RuntimeError) as error: @@ -134,12 +138,12 @@ def connect_enterprise(self): Attempt an enterprise style WiFi connection """ failure_count = 0 - self.esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) - self.esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) - self.esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) - self.esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) - self.esp.wifi_set_entenable() - while not self.esp.is_connected: + self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) + self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) + self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) + self._esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) + self._esp.wifi_set_entenable() + while not self._esp.is_connected: try: if self.debug: print("Waiting for the ESP32 to connect to the WPA2 Enterprise AP...") From 0c07ceb51ca728e25084587613d786b2c9573422 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sat, 13 Jul 2019 12:02:08 -0700 Subject: [PATCH 33/37] merged conflicts --- .../adafruit_esp32spi_wifimanager.py | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 69715bc..add762f 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -36,6 +36,17 @@ from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_requests as requests +class WiFiConnType: # pylint: disable=too-few-public-methods + """An enum-like class representing the different types of WiFi connections + that can be made. The values can be referenced like ``WiFiConnType.normal``. + Possible values are + - ``ThermocoupleType.normal`` + - ``ThermocoupleType.enterprise`` + """ + # pylint: disable=invalid-name + normal = 1 + enterprise = 2 + class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection @@ -117,12 +128,12 @@ def connect_normal(self): Attempt a regular style WiFi connection """ failure_count = 0 - while not self._esp.is_connected: + while not self.esp.is_connected: try: if self.debug: print("Connecting to AP...") self.pixel_status((100, 0, 0)) - self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) + self.esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) failure_count = 0 self.pixel_status((0, 100, 0)) except (ValueError, RuntimeError) as error: @@ -138,12 +149,12 @@ def connect_enterprise(self): Attempt an enterprise style WiFi connection """ failure_count = 0 - self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) - self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) - self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) - self._esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) - self._esp.wifi_set_entenable() - while not self._esp.is_connected: + self.esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) + self.esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) + self.esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) + self.esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) + self.esp.wifi_set_entenable() + while not self.esp.is_connected: try: if self.debug: print("Waiting for the ESP32 to connect to the WPA2 Enterprise AP...") From 5931c1ba1e78ed066bce9fb3923bffe032d58893 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sat, 13 Jul 2019 12:05:13 -0700 Subject: [PATCH 34/37] merged conflicts --- .../adafruit_esp32spi_wifimanager.py | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index add762f..a1f16fb 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -36,17 +36,6 @@ from adafruit_esp32spi import adafruit_esp32spi import adafruit_esp32spi.adafruit_esp32spi_requests as requests -class WiFiConnType: # pylint: disable=too-few-public-methods - """An enum-like class representing the different types of WiFi connections - that can be made. The values can be referenced like ``WiFiConnType.normal``. - Possible values are - - ``ThermocoupleType.normal`` - - ``ThermocoupleType.enterprise`` - """ - # pylint: disable=invalid-name - normal = 1 - enterprise = 2 - class ESPSPI_WiFiManager: """ A class to help manage the Wifi connection @@ -75,7 +64,7 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type= self.ent_ssid = secrets['ent_ssid'] self.ent_ident = secrets['ent_ident'] self.ent_user = secrets['ent_user'] - self.ent_passwd = secrets['ent_passwd'] + self.ent_password = secrets['ent_password'] self.attempts = attempts self._connection_type = connection_type requests.set_interface(self.esp) @@ -128,12 +117,12 @@ def connect_normal(self): Attempt a regular style WiFi connection """ failure_count = 0 - while not self.esp.is_connected: + while not self._esp.is_connected: try: if self.debug: print("Connecting to AP...") self.pixel_status((100, 0, 0)) - self.esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) + self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) failure_count = 0 self.pixel_status((0, 100, 0)) except (ValueError, RuntimeError) as error: @@ -149,12 +138,12 @@ def connect_enterprise(self): Attempt an enterprise style WiFi connection """ failure_count = 0 - self.esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) - self.esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) - self.esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) - self.esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) - self.esp.wifi_set_entenable() - while not self.esp.is_connected: + self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) + self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) + self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) + self._esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) + self._esp.wifi_set_entenable() + while not self._esp.is_connected: try: if self.debug: print("Waiting for the ESP32 to connect to the WPA2 Enterprise AP...") From 7bc0ec66648e40e2da7e7c549b4b59c9c3aadf92 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sat, 13 Jul 2019 11:28:12 -0700 Subject: [PATCH 35/37] merged conflicts --- .../adafruit_esp32spi_wifimanager.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index a1f16fb..6152d29 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -117,12 +117,12 @@ def connect_normal(self): Attempt a regular style WiFi connection """ failure_count = 0 - while not self._esp.is_connected: + while not self.esp.is_connected: try: if self.debug: print("Connecting to AP...") self.pixel_status((100, 0, 0)) - self._esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) + self.esp.connect_AP(bytes(self.ssid, 'utf-8'), bytes(self.password, 'utf-8')) failure_count = 0 self.pixel_status((0, 100, 0)) except (ValueError, RuntimeError) as error: @@ -138,12 +138,12 @@ def connect_enterprise(self): Attempt an enterprise style WiFi connection """ failure_count = 0 - self._esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) - self._esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) - self._esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) - self._esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) - self._esp.wifi_set_entenable() - while not self._esp.is_connected: + self.esp.wifi_set_network(bytes(self.ent_ssid, 'utf-8')) + self.esp.wifi_set_entidentity(bytes(self.ent_ident, 'utf-8')) + self.esp.wifi_set_entusername(bytes(self.ent_user, 'utf-8')) + self.esp.wifi_set_entpassword(bytes(self.ent_password, 'utf-8')) + self.esp.wifi_set_entenable() + while not self.esp.is_connected: try: if self.debug: print("Waiting for the ESP32 to connect to the WPA2 Enterprise AP...") From bb679e8d8fc9d33b5d88b71036b2e750db656200 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sun, 14 Jul 2019 16:08:38 -0700 Subject: [PATCH 36/37] fix a regression due to the rebase'ing... --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 6152d29..2ace634 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -57,17 +57,13 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type= connection to make. The default is "normal". """ # Read the settings - self.esp = esp + self._esp = esp self.debug = False self.ssid = secrets['ssid'] self.password = secrets['password'] - self.ent_ssid = secrets['ent_ssid'] - self.ent_ident = secrets['ent_ident'] - self.ent_user = secrets['ent_user'] - self.ent_password = secrets['ent_password'] self.attempts = attempts self._connection_type = connection_type - requests.set_interface(self.esp) + requests.set_interface(self._esp) self.statuspix = status_pixel self.pixel_status(0) From 5c7a735c651ed4e867fa566fd2042f0386399676 Mon Sep 17 00:00:00 2001 From: Dustin Mollo Date: Sun, 14 Jul 2019 16:14:26 -0700 Subject: [PATCH 37/37] more fix-ups from rebase; fixed param defs in __init__ --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 2ace634..28b08b0 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -52,18 +52,16 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2, connection_type= or RGB LED (default=None) :type status_pixel: NeoPixel, DotStar, or RGB LED :param int attempts: (Optional) Failed attempts before resetting the ESP32 (default=2) - :param const con_type: (Optional) Type of WiFi connection: normal=1, WPA2 Enterprise=2 - :param ~adafruit_esp32spi_wifimanager.WiFiConnType wificonntype: The type of WiFi \ - connection to make. The default is "normal". + :param const connection_type: (Optional) Type of WiFi connection: NORMAL or ENTERPRISE """ # Read the settings - self._esp = esp + self.esp = esp self.debug = False self.ssid = secrets['ssid'] self.password = secrets['password'] self.attempts = attempts self._connection_type = connection_type - requests.set_interface(self._esp) + requests.set_interface(self.esp) self.statuspix = status_pixel self.pixel_status(0)