From 911445dd658f8e5b0f994bb2806f1e82ec6ff4da Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 14:50:50 +0100 Subject: [PATCH 01/23] Make these connection errors distinct from other error types. --- adafruit_esp32spi/adafruit_esp32spi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index fae4cc6..1abad64 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -751,24 +751,24 @@ def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): if conn_mode == self.UDP_MODE: # UDP verifies chunks on write, not bytes if sent != total_chunks: - raise RuntimeError( + raise ConnectionError( "Failed to write %d chunks (sent %d)" % (total_chunks, sent) ) # UDP needs to finalize with this command, does the actual sending resp = self._send_command_get_response(_SEND_UDP_DATA_CMD, self._socknum_ll) if resp[0][0] != 1: - raise RuntimeError("Failed to send UDP data") + raise ConnectionError("Failed to send UDP data") return if sent != len(buffer): self.socket_close(socket_num) - raise RuntimeError( + raise ConnectionError( "Failed to send %d bytes (sent %d)" % (len(buffer), sent) ) resp = self._send_command_get_response(_DATA_SENT_TCP_CMD, self._socknum_ll) if resp[0][0] != 1: - raise RuntimeError("Failed to verify data sent") + raise ConnectionError("Failed to verify data sent") def socket_available(self, socket_num): """Determine how many bytes are waiting to be read on the socket""" From 4455889b16af3b2b4a01e9e5fad187a160d57a64 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:02:20 +0100 Subject: [PATCH 02/23] Another OSError derived error here. --- adafruit_esp32spi/adafruit_esp32spi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 1abad64..7a2907a 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -815,7 +815,7 @@ def socket_connect(self, socket_num, dest, port, conn_mode=TCP_MODE): if self.socket_connected(socket_num): return True time.sleep(0.01) - raise RuntimeError("Failed to establish connection") + raise TimeoutError("Failed to establish connection") def socket_close(self, socket_num): """Close a socket using the ESP32's internal reference number""" From de04df15243d537045684c366aacfa5c07abcd30 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:11:45 +0100 Subject: [PATCH 03/23] These now derive also from OSError types - without timeouts being specific. --- adafruit_esp32spi/adafruit_esp32spi.py | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 7a2907a..014d69e 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -194,7 +194,7 @@ def _wait_for_ready(self): print(".", end="") time.sleep(0.05) else: - raise RuntimeError("ESP32 not responding") + raise TimeoutError("ESP32 not responding") if self._debug >= 3: print() @@ -242,7 +242,7 @@ def _send_command(self, cmd, params=None, *, param_len_16=False): if self._ready.value: # ok ready to send! break else: - raise RuntimeError("ESP32 timed out on SPI select") + raise TimeoutError("ESP32 timed out on SPI select") spi.write( self._sendbuf, start=0, end=packet_len ) # pylint: disable=no-member @@ -271,17 +271,17 @@ def _wait_spi_char(self, spi, desired): for _ in range(10): r = self._read_byte(spi) if r == _ERR_CMD: - raise RuntimeError("Error response to command") + raise BrokenPipeError("Error response to command") if r == desired: return True time.sleep(0.01) - raise RuntimeError("Timed out waiting for SPI char") + raise TimeoutError("Timed out waiting for SPI char") def _check_data(self, spi, desired): """Read a byte and verify its the value we want""" r = self._read_byte(spi) if r != desired: - raise RuntimeError("Expected %02X but got %02X" % (desired, r)) + raise BrokenPipeError("Expected %02X but got %02X" % (desired, r)) def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False): """Wait for ready, then parse the response""" @@ -294,7 +294,7 @@ def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False): if self._ready.value: # ok ready to send! break else: - raise RuntimeError("ESP32 timed out on SPI select") + raise TimeoutError("ESP32 timed out on SPI select") self._wait_spi_char(spi, _START_CMD) self._check_data(spi, cmd | _REPLY_FLAG) @@ -440,7 +440,7 @@ def set_dns_config(self, dns1, dns2): _SET_DNS_CONFIG, [b"\x00", self.unpretty_ip(dns1), self.unpretty_ip(dns2)] ) if resp[0][0] != 1: - raise RuntimeError("Failed to set dns with esp32") + raise OSError("Failed to set dns with esp32") def set_hostname(self, hostname): """Tells the ESP32 to set hostname for DHCP. @@ -449,49 +449,49 @@ def set_hostname(self, hostname): """ resp = self._send_command_get_response(_SET_HOSTNAME, [hostname.encode()]) if resp[0][0] != 1: - raise RuntimeError("Failed to set hostname with esp32") + raise OSError("Failed to set hostname with esp32") def wifi_set_network(self, ssid): """Tells the ESP32 to set the access point to the given ssid""" resp = self._send_command_get_response(_SET_NET_CMD, [ssid]) if resp[0][0] != 1: - raise RuntimeError("Failed to set network") + raise OSError("Failed to set network") def wifi_set_passphrase(self, ssid, passphrase): """Sets the desired access point ssid and passphrase""" resp = self._send_command_get_response(_SET_PASSPHRASE_CMD, [ssid, passphrase]) if resp[0][0] != 1: - raise RuntimeError("Failed to set passphrase") + raise OSError("Failed to set passphrase") def wifi_set_entidentity(self, ident): """Sets the WPA2 Enterprise anonymous identity""" resp = self._send_command_get_response(_SET_ENT_IDENT_CMD, [ident]) if resp[0][0] != 1: - raise RuntimeError("Failed to set enterprise anonymous identity") + raise OSError("Failed to set enterprise anonymous identity") def wifi_set_entusername(self, username): """Sets the desired WPA2 Enterprise username""" resp = self._send_command_get_response(_SET_ENT_UNAME_CMD, [username]) if resp[0][0] != 1: - raise RuntimeError("Failed to set enterprise username") + raise OSError("Failed to set enterprise username") def wifi_set_entpassword(self, password): """Sets the desired WPA2 Enterprise password""" resp = self._send_command_get_response(_SET_ENT_PASSWD_CMD, [password]) if resp[0][0] != 1: - raise RuntimeError("Failed to set enterprise password") + raise OSError("Failed to set enterprise password") def wifi_set_entenable(self): """Enables WPA2 Enterprise mode""" resp = self._send_command_get_response(_SET_ENT_ENABLE_CMD) if resp[0][0] != 1: - raise RuntimeError("Failed to enable enterprise mode") + raise OSError("Failed to enable enterprise mode") def _wifi_set_ap_network(self, ssid, channel): """Creates an Access point with SSID and Channel""" resp = self._send_command_get_response(_SET_AP_NET_CMD, [ssid, channel]) if resp[0][0] != 1: - raise RuntimeError("Failed to setup AP network") + raise OSError("Failed to setup AP network") def _wifi_set_ap_passphrase(self, ssid, passphrase, channel): """Creates an Access point with SSID, passphrase, and Channel""" @@ -499,7 +499,7 @@ def _wifi_set_ap_passphrase(self, ssid, passphrase, channel): _SET_AP_PASSPHRASE_CMD, [ssid, passphrase, channel] ) if resp[0][0] != 1: - raise RuntimeError("Failed to setup AP password") + raise OSError("Failed to setup AP password") @property def ssid(self): From 5abca8de61bdd02392764f43411518e6bca862bb Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:14:18 +0100 Subject: [PATCH 04/23] More error specificity --- adafruit_esp32spi/adafruit_esp32spi.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 014d69e..efd6e38 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -539,7 +539,7 @@ def is_connected(self): """Whether the ESP32 is connected to an access point""" try: return self.status == WL_CONNECTED - except RuntimeError: + except OSError: self.reset() return False @@ -548,7 +548,7 @@ def ap_listening(self): """Returns if the ESP32 is in access point mode and is listening for connections""" try: return self.status == WL_AP_LISTENING - except RuntimeError: + except OSError: self.reset() return False @@ -556,7 +556,7 @@ def disconnect(self): """Disconnect from the access point""" resp = self._send_command_get_response(_DISCONNECT_CMD) if resp[0][0] != 1: - raise RuntimeError("Failed to disconnect") + raise OSError("Failed to disconnect") def connect(self, secrets): """Connect to an access point using a secrets dictionary @@ -589,10 +589,10 @@ def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-n return stat time.sleep(0.05) if stat in (WL_CONNECT_FAILED, WL_CONNECTION_LOST, WL_DISCONNECTED): - raise RuntimeError("Failed to connect to ssid", ssid) + raise ConnectionError("Failed to connect to ssid", ssid) if stat == WL_NO_SSID_AVAIL: - raise RuntimeError("No such ssid", ssid) - raise RuntimeError("Unknown error 0x%02X" % stat) + raise ConnectionError("No such ssid", ssid) + raise OSError("Unknown error 0x%02X" % stat) def create_AP( self, ssid, password, channel=1, timeout=10 @@ -607,11 +607,11 @@ def create_AP( :param int timeout: number of seconds until we time out and fail to create AP """ if len(ssid) > 32: - raise RuntimeError("ssid must be no more than 32 characters") + raise ValueError("ssid must be no more than 32 characters") if password and (len(password) < 8 or len(password) > 64): - raise RuntimeError("password must be 8 - 63 characters") + raise ValueError("password must be 8 - 63 characters") if channel < 1 or channel > 14: - raise RuntimeError("channel must be between 1 and 14") + raise ValueError("channel must be between 1 and 14") if isinstance(channel, int): channel = bytes(channel) From 6605027da19be2345c74fb70609455fd57fc6a56 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:17:08 +0100 Subject: [PATCH 05/23] These are now in the OSError heirarchy --- adafruit_esp32spi/adafruit_esp32spi.py | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index efd6e38..2cb9369 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -377,7 +377,7 @@ def start_scan_networks(self): print("Start scan") resp = self._send_command_get_response(_START_SCAN_NETWORKS) if resp[0][0] != 1: - raise RuntimeError("Failed to start AP scan") + raise OSError("Failed to start AP scan") def get_scan_networks(self): """The results of the latest SSID scan. Returns a list of dictionaries with @@ -631,8 +631,8 @@ def create_AP( return stat time.sleep(0.05) if stat == WL_AP_FAILED: - raise RuntimeError("Failed to create AP", ssid) - raise RuntimeError("Unknown error 0x%02x" % stat) + raise ConnectionError("Failed to create AP", ssid) + raise OSError("Unknown error 0x%02x" % stat) def pretty_ip(self, ip): # pylint: disable=no-self-use, invalid-name """Converts a bytearray IP address to a dotted-quad string for printing""" @@ -652,7 +652,7 @@ def get_host_by_name(self, hostname): hostname = bytes(hostname, "utf-8") resp = self._send_command_get_response(_REQ_HOST_BY_NAME_CMD, (hostname,)) if resp[0][0] != 1: - raise RuntimeError("Failed to request hostname") + raise ConnectionError("Failed to request hostname") resp = self._send_command_get_response(_GET_HOST_BY_NAME_CMD) return resp[0] @@ -708,7 +708,7 @@ def socket_open(self, socket_num, dest, port, conn_mode=TCP_MODE): (dest, port_param, self._socknum_ll[0], (conn_mode,)), ) if resp[0][0] != 1: - raise RuntimeError("Could not connect to remote server") + raise ConnectionError("Could not connect to remote server") if conn_mode == ESP_SPIcontrol.TLS_MODE: self._tls_socket = socket_num @@ -824,7 +824,7 @@ def socket_close(self, socket_num): self._socknum_ll[0][0] = socket_num try: self._send_command_get_response(_STOP_CLIENT_TCP_CMD, self._socknum_ll) - except RuntimeError: + except OSError: pass if socket_num == self._tls_socket: self._tls_socket = None @@ -842,7 +842,7 @@ def start_server( resp = self._send_command_get_response(_START_SERVER_TCP_CMD, params) if resp[0][0] != 1: - raise RuntimeError("Could not start server") + raise OSError("Could not start server") def server_state(self, socket_num): """Get the state of the ESP32's internal reference server socket number""" @@ -863,7 +863,7 @@ def set_esp_debug(self, enabled): written to the ESP32's UART.""" resp = self._send_command_get_response(_SET_DEBUG_CMD, ((bool(enabled),),)) if resp[0][0] != 1: - raise RuntimeError("Failed to set debug mode") + raise OSError("Failed to set debug mode") def set_pin_mode(self, pin, mode): """Set the io mode for a GPIO pin. @@ -879,7 +879,7 @@ def set_pin_mode(self, pin, mode): pin_mode = mode resp = self._send_command_get_response(_SET_PIN_MODE_CMD, ((pin,), (pin_mode,))) if resp[0][0] != 1: - raise RuntimeError("Failed to set pin mode") + raise OSError("Failed to set pin mode") def set_digital_write(self, pin, value): """Set the digital output value of pin. @@ -891,7 +891,7 @@ def set_digital_write(self, pin, value): _SET_DIGITAL_WRITE_CMD, ((pin,), (value,)) ) if resp[0][0] != 1: - raise RuntimeError("Failed to write to pin") + raise OSError("Failed to write to pin") def set_analog_write(self, pin, analog_value): """Set the analog output value of pin, using PWM. @@ -904,7 +904,7 @@ def set_analog_write(self, pin, analog_value): _SET_ANALOG_WRITE_CMD, ((pin,), (value,)) ) if resp[0][0] != 1: - raise RuntimeError("Failed to write to pin") + raise OSError("Failed to write to pin") def set_digital_read(self, pin): """Get the digital input value of pin. Returns the boolean value of the pin. @@ -953,10 +953,10 @@ def get_time(self): raise ValueError("_GET_TIME returned 0") return resp_time if self.status in (WL_AP_LISTENING, WL_AP_CONNECTED): - raise RuntimeError( + raise OSError( "Cannot obtain NTP while in AP mode, must be connected to internet" ) - raise RuntimeError("Must be connected to WiFi before obtaining NTP.") + raise OSError("Must be connected to WiFi before obtaining NTP.") def set_certificate(self, client_certificate): """Sets client certificate. Must be called @@ -967,7 +967,7 @@ def set_certificate(self, client_certificate): if self._debug: print("** Setting client certificate") if self.status == WL_CONNECTED: - raise RuntimeError( + raise ValueError( "set_certificate must be called BEFORE a connection is established." ) if isinstance(client_certificate, str): @@ -977,7 +977,7 @@ def set_certificate(self, client_certificate): assert len(client_certificate) < 1300, ".PEM must be less than 1300 bytes." resp = self._send_command_get_response(_SET_CLI_CERT, (client_certificate,)) if resp[0][0] != 1: - raise RuntimeError("Failed to set client certificate") + raise OSError("Failed to set client certificate") self.set_crt = True return resp[0] @@ -990,7 +990,7 @@ def set_private_key(self, private_key): if self._debug: print("** Setting client's private key.") if self.status == WL_CONNECTED: - raise RuntimeError( + raise ValueError( "set_private_key must be called BEFORE a connection is established." ) if isinstance(private_key, str): @@ -1000,6 +1000,6 @@ def set_private_key(self, private_key): assert len(private_key) < 1700, ".PEM must be less than 1700 bytes." resp = self._send_command_get_response(_SET_PK, (private_key,)) if resp[0][0] != 1: - raise RuntimeError("Failed to set private key.") + raise OSError("Failed to set private key.") self.set_psk = True return resp[0] From d17790c85591bd0debb579e53b8bb95cce57a4b1 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:18:01 +0100 Subject: [PATCH 06/23] Make these more specific too --- adafruit_esp32spi/adafruit_esp32spi_socket.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_socket.py b/adafruit_esp32spi/adafruit_esp32spi_socket.py index c35a94b..4a8cb2b 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_socket.py +++ b/adafruit_esp32spi/adafruit_esp32spi_socket.py @@ -39,7 +39,7 @@ def getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0): """Given a hostname and a port name, return a 'socket.getaddrinfo' compatible list of tuples. Honestly, we ignore anything but host & port""" if not isinstance(port, int): - raise RuntimeError("Port must be an integer") + raise ValueError("Port must be an integer") ipaddr = _the_interface.get_host_by_name(host) return [(AF_INET, socktype, proto, "", (ipaddr, port))] @@ -56,7 +56,7 @@ def __init__( self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None, socknum=None ): if family != AF_INET: - raise RuntimeError("Only AF_INET family supported") + raise ValueError("Only AF_INET family supported") self._type = type self._buffer = b"" self._socknum = socknum if socknum else _the_interface.get_socket() @@ -74,7 +74,7 @@ def connect(self, address, conntype=None): if not _the_interface.socket_connect( self._socknum, host, port, conn_mode=conntype ): - raise RuntimeError("Failed to connect to host", host) + raise ConnectionError("Failed to connect to host", host) self._buffer = b"" def send(self, data): # pylint: disable=no-self-use @@ -105,7 +105,7 @@ def readline(self, eol=b"\r\n"): self._buffer += _the_interface.socket_read(self._socknum, avail) elif self._timeout > 0 and time.monotonic() - stamp > self._timeout: self.close() # Make sure to close socket so that we don't exhaust sockets. - raise RuntimeError("Didn't receive full response, failing out") + raise OSError("Didn't receive full response, failing out") firstline, self._buffer = self._buffer.split(eol, 1) gc.collect() return firstline From c961c09417cc6e8b3757c92b0869114dbe8f4836 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 10 May 2022 17:20:25 +0100 Subject: [PATCH 07/23] This now accepts the same set of errors - atlhough it could be more discerning --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 739f7a9..e1cccb5 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -144,7 +144,7 @@ def connect_normal(self): self.esp.connect_AP(bytes(ssid, "utf-8"), bytes(password, "utf-8")) failure_count = 0 self.pixel_status((0, 100, 0)) - except (ValueError, RuntimeError) as error: + except (ValueError, OSError) as error: print("Failed to connect, retrying\n", error) failure_count += 1 if failure_count >= self.attempts: @@ -173,7 +173,7 @@ def create_ap(self): self.esp.create_AP(bytes(self.ssid, "utf-8"), None) failure_count = 0 self.pixel_status((0, 100, 0)) - except (ValueError, RuntimeError) as error: + except (ValueError, OSError) as error: print("Failed to create access point\n", error) failure_count += 1 if failure_count >= self.attempts: @@ -203,7 +203,7 @@ def connect_enterprise(self): failure_count = 0 self.pixel_status((0, 100, 0)) sleep(1) - except (ValueError, RuntimeError) as error: + except (ValueError, OSError) as error: print("Failed to connect, retrying\n", error) failure_count += 1 if failure_count >= self.attempts: From 19e47fd5bb6fcc47da67d5f300d17d4d79649950 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:29:30 +0100 Subject: [PATCH 08/23] Make the suggested change for handling valueerrors. --- adafruit_esp32spi/adafruit_esp32spi_wifimanager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index e1cccb5..0070b94 100755 --- a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py @@ -144,7 +144,7 @@ def connect_normal(self): self.esp.connect_AP(bytes(ssid, "utf-8"), bytes(password, "utf-8")) failure_count = 0 self.pixel_status((0, 100, 0)) - except (ValueError, OSError) as error: + except OSError as error: print("Failed to connect, retrying\n", error) failure_count += 1 if failure_count >= self.attempts: @@ -173,7 +173,7 @@ def create_ap(self): self.esp.create_AP(bytes(self.ssid, "utf-8"), None) failure_count = 0 self.pixel_status((0, 100, 0)) - except (ValueError, OSError) as error: + except OSError as error: print("Failed to create access point\n", error) failure_count += 1 if failure_count >= self.attempts: @@ -203,7 +203,7 @@ def connect_enterprise(self): failure_count = 0 self.pixel_status((0, 100, 0)) sleep(1) - except (ValueError, OSError) as error: + except OSError as error: print("Failed to connect, retrying\n", error) failure_count += 1 if failure_count >= self.attempts: From fa311a1a4f7b1e0b38136a13e22b358355bbc420 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:30:37 +0100 Subject: [PATCH 09/23] These are definitely valueerrors. --- adafruit_esp32spi/digitalio.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index c935794..3e4cc15 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -61,7 +61,7 @@ def init(self, mode=IN): self._mode = self.OUT self._esp.set_pin_mode(self.pin_id, 1) else: - raise RuntimeError("Invalid mode defined") + raise ValueError("Invalid mode defined") def value(self, val=None): """Sets ESP32 Pin GPIO output mode. @@ -76,7 +76,7 @@ def value(self, val=None): self._value = val self._esp.set_digital_write(self.pin_id, 1) else: - raise RuntimeError("Invalid value for pin") + raise ValueError("Invalid value for pin") else: raise NotImplementedError( "digitalRead not currently implemented in esp32spi" From 1756c8166b47fc293d96b6963cc75293f420419f Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:32:29 +0100 Subject: [PATCH 10/23] Swap those runtime errors for OSerrors - most will be. Also removed some extraneous brackets on OSerrors. --- examples/esp32spi_simpletest.py | 2 +- examples/esp32spi_simpletest_rp2040.py | 2 +- examples/gpio/esp32spi_gpio.py | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/esp32spi_simpletest.py b/examples/esp32spi_simpletest.py index af8c2f1..7e01ad6 100644 --- a/examples/esp32spi_simpletest.py +++ b/examples/esp32spi_simpletest.py @@ -59,7 +59,7 @@ while not esp.is_connected: try: esp.connect_AP(secrets["ssid"], secrets["password"]) - except RuntimeError as e: + except OSError as e: print("could not connect to AP, retrying: ", e) continue print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) diff --git a/examples/esp32spi_simpletest_rp2040.py b/examples/esp32spi_simpletest_rp2040.py index eb52592..decd13e 100644 --- a/examples/esp32spi_simpletest_rp2040.py +++ b/examples/esp32spi_simpletest_rp2040.py @@ -42,7 +42,7 @@ while not esp.is_connected: try: esp.connect_AP(secrets["ssid"], secrets["password"]) - except RuntimeError as e: + except OSError as e: print("could not connect to AP, retrying: ", e) continue print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) diff --git a/examples/gpio/esp32spi_gpio.py b/examples/gpio/esp32spi_gpio.py index a9c857d..866fd63 100644 --- a/examples/gpio/esp32spi_gpio.py +++ b/examples/gpio/esp32spi_gpio.py @@ -94,7 +94,7 @@ def esp_init_pin_modes(din, dout): esp_init_pin_modes(ESP_D_R_PIN, ESP_D_W_PIN) esp_d_r_val = esp.set_digital_read(ESP_D_R_PIN) print("--> ESP read:", esp_d_r_val) - except (RuntimeError, AssertionError) as e: + except (OSError, AssertionError) as e: print("ESP32 Error", e) esp_reset_all() @@ -104,7 +104,7 @@ def esp_init_pin_modes(din, dout): esp_init_pin_modes(ESP_D_R_PIN, ESP_D_W_PIN) esp.set_digital_write(ESP_D_W_PIN, esp_d_w_val) print("ESP wrote:", esp_d_w_val, "--> Red LED") - except (RuntimeError) as e: + except OSError as e: print("ESP32 Error", e) esp_reset_all() @@ -121,7 +121,7 @@ def esp_init_pin_modes(din, dout): "v)", sep="", ) - except (RuntimeError, AssertionError) as e: + except (OSError, AssertionError) as e: print("ESP32 Error", e) esp_reset_all() @@ -166,7 +166,7 @@ def esp_init_pin_modes(din, dout): sep="", ) - except (RuntimeError) as e: + except OSError as e: print("ESP32 Error", e) esp_reset_all() From 39c672d42fba4fa2e496fe43f3a4e76c4e506313 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:32:44 +0100 Subject: [PATCH 11/23] More runtime error catches --- examples/esp32spi_aio_post.py | 2 +- examples/esp32spi_cheerlights.py | 2 +- examples/esp32spi_ipconfig.py | 2 +- examples/esp32spi_localtime.py | 2 +- examples/esp32spi_wpa2ent_aio_post.py | 2 +- examples/server/esp32spi_wsgiserver.py | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index b74e4e3..75cae78 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -66,7 +66,7 @@ response.close() counter = counter + 1 print("OK") - except (ValueError, RuntimeError) as e: + except (ValueError, OSError) as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index 46d75af..03ed3f3 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -54,7 +54,7 @@ value = value[key] print(value) response.close() - except (ValueError, RuntimeError) as e: + except (ValueError, OSError) as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index 01f01c8..5f67044 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -49,7 +49,7 @@ while not esp.is_connected: try: esp.connect_AP(secrets["ssid"], secrets["password"]) - except RuntimeError as e: + except OSError as e: print("could not connect to AP, retrying: ", e) continue print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index 1c27304..d610c69 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -42,7 +42,7 @@ print("Fetching json from", TIME_API) response = wifi.get(TIME_API) break - except (ValueError, RuntimeError) as e: + except (ValueError, OSError) as e: print("Failed to get data, retrying\n", e) continue diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index b6bdd99..42701c7 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -63,7 +63,7 @@ response.close() counter = counter + 1 print("OK") - except (ValueError, RuntimeError) as e: + except (ValueError, OSError) as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/server/esp32spi_wsgiserver.py b/examples/server/esp32spi_wsgiserver.py index d9f0979..af7daa2 100755 --- a/examples/server/esp32spi_wsgiserver.py +++ b/examples/server/esp32spi_wsgiserver.py @@ -213,7 +213,7 @@ def led_color(environ): # pylint: disable=unused-argument static ) ) -except (OSError) as e: +except OSError as e: raise RuntimeError( """ This example depends on a static asset directory. @@ -240,7 +240,7 @@ def led_color(environ): # pylint: disable=unused-argument try: wsgiServer.update_poll() # Could do any other background tasks here, like reading sensors - except (ValueError, RuntimeError) as e: + except (ValueError, OSError) as e: print("Failed to update server, restarting ESP32\n", e) wifi.reset() continue From 71f38569aa0c192fb08c1287bea141c34260916a Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:35:29 +0100 Subject: [PATCH 12/23] The parts that can raise assertion errors are not recoverable. --- examples/gpio/esp32spi_gpio.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gpio/esp32spi_gpio.py b/examples/gpio/esp32spi_gpio.py index 866fd63..6d7723b 100644 --- a/examples/gpio/esp32spi_gpio.py +++ b/examples/gpio/esp32spi_gpio.py @@ -94,7 +94,7 @@ def esp_init_pin_modes(din, dout): esp_init_pin_modes(ESP_D_R_PIN, ESP_D_W_PIN) esp_d_r_val = esp.set_digital_read(ESP_D_R_PIN) print("--> ESP read:", esp_d_r_val) - except (OSError, AssertionError) as e: + except OSError as e: print("ESP32 Error", e) esp_reset_all() @@ -121,7 +121,7 @@ def esp_init_pin_modes(din, dout): "v)", sep="", ) - except (OSError, AssertionError) as e: + except OSError as e: print("ESP32 Error", e) esp_reset_all() From df4112ac2209bd696449ef31d275eacfa7f1a962 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Tue, 17 May 2022 15:44:46 +0100 Subject: [PATCH 13/23] These are OSErrors - or connection errors, we got an unexpected response from the spi device. --- adafruit_esp32spi/adafruit_esp32spi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 2cb9369..2cd2d4e 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -920,7 +920,7 @@ def set_digital_read(self, pin): return False if resp[0] == 1: return True - raise ValueError( + raise OSError( "_SET_DIGITAL_READ response error: response is not boolean", resp[0] ) @@ -950,7 +950,7 @@ def get_time(self): resp = self._send_command_get_response(_GET_TIME) resp_time = struct.unpack(" Date: Tue, 17 May 2022 15:46:22 +0100 Subject: [PATCH 14/23] The value errors caught in these wouldn't be recoverable, but the OS errors may be. --- examples/esp32spi_aio_post.py | 2 +- examples/esp32spi_cheerlights.py | 2 +- examples/esp32spi_localtime.py | 2 +- examples/esp32spi_wpa2ent_aio_post.py | 2 +- examples/server/esp32spi_wsgiserver.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index 75cae78..ef24db7 100644 --- a/examples/esp32spi_aio_post.py +++ b/examples/esp32spi_aio_post.py @@ -66,7 +66,7 @@ response.close() counter = counter + 1 print("OK") - except (ValueError, OSError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/esp32spi_cheerlights.py b/examples/esp32spi_cheerlights.py index 03ed3f3..7ded593 100644 --- a/examples/esp32spi_cheerlights.py +++ b/examples/esp32spi_cheerlights.py @@ -54,7 +54,7 @@ value = value[key] print(value) response.close() - except (ValueError, OSError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/esp32spi_localtime.py b/examples/esp32spi_localtime.py index d610c69..01dd93b 100644 --- a/examples/esp32spi_localtime.py +++ b/examples/esp32spi_localtime.py @@ -42,7 +42,7 @@ print("Fetching json from", TIME_API) response = wifi.get(TIME_API) break - except (ValueError, OSError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) continue diff --git a/examples/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index 42701c7..227bf91 100644 --- a/examples/esp32spi_wpa2ent_aio_post.py +++ b/examples/esp32spi_wpa2ent_aio_post.py @@ -63,7 +63,7 @@ response.close() counter = counter + 1 print("OK") - except (ValueError, OSError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/server/esp32spi_wsgiserver.py b/examples/server/esp32spi_wsgiserver.py index af7daa2..0220d2f 100755 --- a/examples/server/esp32spi_wsgiserver.py +++ b/examples/server/esp32spi_wsgiserver.py @@ -240,7 +240,7 @@ def led_color(environ): # pylint: disable=unused-argument try: wsgiServer.update_poll() # Could do any other background tasks here, like reading sensors - except (ValueError, OSError) as e: + except OSError as e: print("Failed to update server, restarting ESP32\n", e) wifi.reset() continue From 0f3b2669aed962d8a6d0ac3327459a1400528188 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Thu, 19 May 2022 12:43:06 +0100 Subject: [PATCH 15/23] This tool, aimed at the pico, just establishes contact with the device and prints the version number and mac address. --- examples/esp32spi_get_board_details.py | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 examples/esp32spi_get_board_details.py diff --git a/examples/esp32spi_get_board_details.py b/examples/esp32spi_get_board_details.py new file mode 100644 index 0000000..547e816 --- /dev/null +++ b/examples/esp32spi_get_board_details.py @@ -0,0 +1,28 @@ +import board +import busio +import time + +from digitalio import DigitalInOut +from adafruit_esp32spi import adafruit_esp32spi + +print("ESP32 SPI hardware test") + +# PyPortal or similar; edit pins as needed + +spi = busio.SPI(board.GP14, board.GP11, board.GP12) +esp32_cs = DigitalInOut(board.GP10) +esp32_ready = DigitalInOut(board.GP9) +esp32_reset = DigitalInOut(board.GP8) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset, debug=True) + +# Fetch and print status +if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: + print("ESP32 found and in idle mode") +print("Firmware version.", esp.firmware_version) +print("MAC addr:", [hex(i) for i in esp.MAC_address]) + +time.sleep(5) + +for ap in esp.scan_networks(): + print("\t%s\t\tRSSI: %d" % (str(ap["ssid"], "utf-8"), ap["rssi"])) +print("Done!") From bf913f94127f83fb847f178aeb1ef44b4e8f7e21 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Sun, 22 May 2022 20:03:18 +0100 Subject: [PATCH 16/23] First attempt at socket stress test --- .../cp_client/cp_socket_count_client.py | 53 +++++++++++++++++++ .../pc_server/pc_socket_count_server.py | 26 +++++++++ 2 files changed, 79 insertions(+) create mode 100644 examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py create mode 100644 examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py diff --git a/examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py b/examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py new file mode 100644 index 0000000..b2cd66e --- /dev/null +++ b/examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +import time +import struct +import board +import busio +from digitalio import DigitalInOut + +from adafruit_esp32spi import adafruit_esp32spi +import adafruit_esp32spi.adafruit_esp32spi_socket as socket + +# Get wifi details and more from a secrets.py file +try: + from secrets import secrets +except ImportError: + print("WiFi secrets are kept in secrets.py, please add them there!") + raise + +print("ESP32 SPI socket count client test") + +TIMEOUT = 5 +# edit host and port to match server +HOST = "test-server.local" +PORT = 8981 + +esp32_cs = DigitalInOut(board.GP10) +esp32_ready = DigitalInOut(board.GP9) +esp32_reset = DigitalInOut(board.GP8) +spi = busio.SPI(board.GP14, board.GP11, board.GP12) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) + +# connect to wifi AP +esp.connect(secrets) + +# test for connectivity to server +print("Server ping:", esp.ping(HOST), "ms") + +# create the socket +socket.set_interface(esp) +socketaddr = socket.getaddrinfo(HOST, PORT)[0][4] +s = socket.socket() +s.settimeout(TIMEOUT) + +print("Connecting") +s.connect(socketaddr) + +while True: + # get a count from the Socket. lets receive this as 4 bytes - unpack as an int. + data = s.recv(4) + # print it + print(struct.unpack("!I", data)) + time.sleep(0.1) diff --git a/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py b/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py new file mode 100644 index 0000000..889b84a --- /dev/null +++ b/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""This runs on the PC side, as a socket server for a stress test""" +import socketserver +import itertools +import struct + +# set up the counter +counter = itertools.count(0) + +# handler +class Handler(socketserver.BaseRequestHandler): + def handle(self): + current = next(counter) + print(f"Sending {current}") + buffer = struct.pack("!I", current) + self.request.sendall(buffer) + +IP, PORT = '0.0.0.0', 8981 + +# create a server, listening on any device +with socketserver.TCPServer((IP, PORT), Handler) as server: + # listen for a connection + print(f"Will accept connections on {IP}, {PORT}") + server.serve_forever() From 17f53697591b12e2ce7dd71d74ad5f94c6e5dc25 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Sun, 22 May 2022 22:18:35 +0100 Subject: [PATCH 17/23] Needs to be reopening the socket to match the server --- .../cp_client/cp_socket_count_client.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py b/examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py index b2cd66e..e8bd4f3 100644 --- a/examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py +++ b/examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py @@ -21,7 +21,7 @@ TIMEOUT = 5 # edit host and port to match server -HOST = "test-server.local" +HOST = "192.168.1.149" PORT = 8981 esp32_cs = DigitalInOut(board.GP10) @@ -42,12 +42,14 @@ s = socket.socket() s.settimeout(TIMEOUT) -print("Connecting") -s.connect(socketaddr) while True: + print("Connecting") + s.connect(socketaddr) # get a count from the Socket. lets receive this as 4 bytes - unpack as an int. data = s.recv(4) # print it + print(f"Data length {len(data)}. Data: ", end='') print(struct.unpack("!I", data)) - time.sleep(0.1) + time.sleep(0.01) + s.close() \ No newline at end of file From 9e32e8ad5d9312d19e80b49234914a381d559b69 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Mon, 30 May 2022 08:26:30 +0100 Subject: [PATCH 18/23] Further stress tests --- .../cp_socket_count_client.py | 2 +- .../cp_socket_count_server.py | 122 ++++++++++++++++++ .../pc_client/pc_socket_count_client.py | 25 ++++ .../pc_server/pc_socket_count_server.py | 3 +- 4 files changed, 149 insertions(+), 3 deletions(-) rename examples/stress_tests/socket_client_server_stress/{cp_client => esp_rp2040_client}/cp_socket_count_client.py (99%) create mode 100644 examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py create mode 100644 examples/stress_tests/socket_client_server_stress/pc_client/pc_socket_count_client.py diff --git a/examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py b/examples/stress_tests/socket_client_server_stress/esp_rp2040_client/cp_socket_count_client.py similarity index 99% rename from examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py rename to examples/stress_tests/socket_client_server_stress/esp_rp2040_client/cp_socket_count_client.py index e8bd4f3..a634073 100644 --- a/examples/stress_tests/socket_client_server_stress/cp_client/cp_socket_count_client.py +++ b/examples/stress_tests/socket_client_server_stress/esp_rp2040_client/cp_socket_count_client.py @@ -52,4 +52,4 @@ print(f"Data length {len(data)}. Data: ", end='') print(struct.unpack("!I", data)) time.sleep(0.01) - s.close() \ No newline at end of file + s.close() diff --git a/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py b/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py new file mode 100644 index 0000000..2854439 --- /dev/null +++ b/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py @@ -0,0 +1,122 @@ +# SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +import gc +import struct +import board +import busio +from digitalio import DigitalInOut + +from adafruit_esp32spi import adafruit_esp32spi +import adafruit_esp32spi.adafruit_esp32spi_socket as socket + +# Get wifi details and more from a secrets.py file +try: + from secrets import secrets +except ImportError: + print("WiFi secrets are kept in secrets.py, please add them there!") + raise + +print("ESP32 SPI socket count server test") + +NO_SOCK_AVAIL = const(255) + +esp32_cs = DigitalInOut(board.GP10) +esp32_ready = DigitalInOut(board.GP9) +esp32_reset = DigitalInOut(board.GP8) +spi = busio.SPI(board.GP14, board.GP11, board.GP12) +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) + + +PORT = 8981 + +# connect to wifi AP +esp.connect(secrets) + +# create the socket +socket.set_interface(esp) + +class CountServer: + """Server to return counts""" + def __init__(self): + self._server_sock = socket.socket(socknum=NO_SOCK_AVAIL) + self._client_sock = socket.socket(socknum=NO_SOCK_AVAIL) + self._counter = 0 + self.port = PORT + self._debug = 3 + + def start(self): + """ + starts the server and begins listening for incoming connections. + Call update_poll in the main loop for the application callable to be + invoked on receiving an incoming request. + """ + self._server_sock = socket.socket() + esp.start_server(self.port, self._server_sock.socknum) + ip = esp.pretty_ip(esp.ip_address) + print("Server available at {0}:{1}".format(ip, self.port)) + print( + "Server status: ", + esp.server_state(self._server_sock.socknum), + ) + + def client_available(self): + """ + returns a client socket connection if available. + Otherwise, returns None + :return: the client + :rtype: Socket + """ + sock = None + if self._server_sock.socknum == NO_SOCK_AVAIL: + raise ValueError("Server has not been started, cannot check for clients!") + + if self._client_sock.socknum != NO_SOCK_AVAIL: + # check previous received client socket + if self._debug > 2: + print("checking if last client sock still valid") + if self._client_sock.connected() and self._client_sock.available(): + sock = self._client_sock + if not sock: + # check for new client sock + if self._debug > 3: + print("checking for new client sock") + client_sock_num = esp.socket_available( + self._server_sock.socknum + ) + sock = socket.socket(socknum=client_sock_num) + + if sock and sock.socknum != NO_SOCK_AVAIL: + if self._debug > 2: + print("client sock num is: ", sock.socknum) + self._client_sock = sock + return self._client_sock + + return None + + def response(self): + current = self._counter + self._counter += 1 + print(f"Sending {current}") + return struct.pack("!I", current) + + def run(self): + """ + Call this method inside your main event loop to get the server + check for new incoming client requests. + """ + while True: + self.client_available() + if self._client_sock and self._client_sock.available(): + result = self.response() + try: + self._client_sock.send(result) + gc.collect() + finally: + if self._debug > 3: + print("closing") + self._client_sock.close() + +cs = CountServer() +cs.start() +cs.run() diff --git a/examples/stress_tests/socket_client_server_stress/pc_client/pc_socket_count_client.py b/examples/stress_tests/socket_client_server_stress/pc_client/pc_socket_count_client.py new file mode 100644 index 0000000..1235bcb --- /dev/null +++ b/examples/stress_tests/socket_client_server_stress/pc_client/pc_socket_count_client.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT +"""This runs on the PC side, as a socket client for a stress test""" +import socket +import time +import struct + +# edit host and port to match server +HOST = "192.168.1.136" +PORT = 8981 + +while True: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + # print("socket ready to connect") + # print("connecting...") + s.connect((HOST, PORT)) + # get a count from the Socket. lets receive this as 4 bytes - unpack as an int. + # print("Connected. Receiving data") + s.send(bytes([1])) + data = s.recv(4) + # print it + # print(f"Data length {len(data)}. Data: ", end='') + print(struct.unpack("!I", data)) + s.detach() + time.sleep(0.01) diff --git a/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py b/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py index 889b84a..bb1d624 100644 --- a/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py +++ b/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py @@ -1,6 +1,5 @@ -# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT - """This runs on the PC side, as a socket server for a stress test""" import socketserver import itertools From 619771c3d241b103f159f4b272a2887095eb11b7 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Mon, 30 May 2022 08:27:24 +0100 Subject: [PATCH 19/23] Black formatted --- examples/esp32spi_get_board_details.py | 4 ++- .../cp_socket_count_client.py | 18 ++++++------- .../cp_socket_count_server.py | 11 ++++---- .../pc_client/pc_socket_count_client.py | 26 +++++++++---------- .../pc_server/pc_socket_count_server.py | 21 ++++++++------- 5 files changed, 42 insertions(+), 38 deletions(-) diff --git a/examples/esp32spi_get_board_details.py b/examples/esp32spi_get_board_details.py index 547e816..5fb7fe1 100644 --- a/examples/esp32spi_get_board_details.py +++ b/examples/esp32spi_get_board_details.py @@ -13,7 +13,9 @@ esp32_cs = DigitalInOut(board.GP10) esp32_ready = DigitalInOut(board.GP9) esp32_reset = DigitalInOut(board.GP8) -esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset, debug=True) +esp = adafruit_esp32spi.ESP_SPIcontrol( + spi, esp32_cs, esp32_ready, esp32_reset, debug=True +) # Fetch and print status if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: diff --git a/examples/stress_tests/socket_client_server_stress/esp_rp2040_client/cp_socket_count_client.py b/examples/stress_tests/socket_client_server_stress/esp_rp2040_client/cp_socket_count_client.py index a634073..61ab810 100644 --- a/examples/stress_tests/socket_client_server_stress/esp_rp2040_client/cp_socket_count_client.py +++ b/examples/stress_tests/socket_client_server_stress/esp_rp2040_client/cp_socket_count_client.py @@ -44,12 +44,12 @@ while True: - print("Connecting") - s.connect(socketaddr) - # get a count from the Socket. lets receive this as 4 bytes - unpack as an int. - data = s.recv(4) - # print it - print(f"Data length {len(data)}. Data: ", end='') - print(struct.unpack("!I", data)) - time.sleep(0.01) - s.close() + print("Connecting") + s.connect(socketaddr) + # get a count from the Socket. lets receive this as 4 bytes - unpack as an int. + data = s.recv(4) + # print it + print(f"Data length {len(data)}. Data: ", end="") + print(struct.unpack("!I", data)) + time.sleep(0.01) + s.close() diff --git a/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py b/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py index 2854439..726c4f9 100644 --- a/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py +++ b/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py @@ -36,8 +36,10 @@ # create the socket socket.set_interface(esp) + class CountServer: """Server to return counts""" + def __init__(self): self._server_sock = socket.socket(socknum=NO_SOCK_AVAIL) self._client_sock = socket.socket(socknum=NO_SOCK_AVAIL) @@ -70,7 +72,7 @@ def client_available(self): sock = None if self._server_sock.socknum == NO_SOCK_AVAIL: raise ValueError("Server has not been started, cannot check for clients!") - + if self._client_sock.socknum != NO_SOCK_AVAIL: # check previous received client socket if self._debug > 2: @@ -81,9 +83,7 @@ def client_available(self): # check for new client sock if self._debug > 3: print("checking for new client sock") - client_sock_num = esp.socket_available( - self._server_sock.socknum - ) + client_sock_num = esp.socket_available(self._server_sock.socknum) sock = socket.socket(socknum=client_sock_num) if sock and sock.socknum != NO_SOCK_AVAIL: @@ -93,7 +93,7 @@ def client_available(self): return self._client_sock return None - + def response(self): current = self._counter self._counter += 1 @@ -117,6 +117,7 @@ def run(self): print("closing") self._client_sock.close() + cs = CountServer() cs.start() cs.run() diff --git a/examples/stress_tests/socket_client_server_stress/pc_client/pc_socket_count_client.py b/examples/stress_tests/socket_client_server_stress/pc_client/pc_socket_count_client.py index 1235bcb..0b56e7a 100644 --- a/examples/stress_tests/socket_client_server_stress/pc_client/pc_socket_count_client.py +++ b/examples/stress_tests/socket_client_server_stress/pc_client/pc_socket_count_client.py @@ -10,16 +10,16 @@ PORT = 8981 while True: - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - # print("socket ready to connect") - # print("connecting...") - s.connect((HOST, PORT)) - # get a count from the Socket. lets receive this as 4 bytes - unpack as an int. - # print("Connected. Receiving data") - s.send(bytes([1])) - data = s.recv(4) - # print it - # print(f"Data length {len(data)}. Data: ", end='') - print(struct.unpack("!I", data)) - s.detach() - time.sleep(0.01) + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + # print("socket ready to connect") + # print("connecting...") + s.connect((HOST, PORT)) + # get a count from the Socket. lets receive this as 4 bytes - unpack as an int. + # print("Connected. Receiving data") + s.send(bytes([1])) + data = s.recv(4) + # print it + # print(f"Data length {len(data)}. Data: ", end='') + print(struct.unpack("!I", data)) + s.detach() + time.sleep(0.01) diff --git a/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py b/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py index bb1d624..ce7a76f 100644 --- a/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py +++ b/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py @@ -5,21 +5,22 @@ import itertools import struct -# set up the counter +# set up the counter counter = itertools.count(0) # handler class Handler(socketserver.BaseRequestHandler): - def handle(self): - current = next(counter) - print(f"Sending {current}") - buffer = struct.pack("!I", current) - self.request.sendall(buffer) + def handle(self): + current = next(counter) + print(f"Sending {current}") + buffer = struct.pack("!I", current) + self.request.sendall(buffer) -IP, PORT = '0.0.0.0', 8981 + +IP, PORT = "0.0.0.0", 8981 # create a server, listening on any device with socketserver.TCPServer((IP, PORT), Handler) as server: - # listen for a connection - print(f"Will accept connections on {IP}, {PORT}") - server.serve_forever() + # listen for a connection + print(f"Will accept connections on {IP}, {PORT}") + server.serve_forever() From d6e0f7b227ab2fc4eeb1f5c19d20692bd3498884 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Mon, 30 May 2022 10:33:42 +0100 Subject: [PATCH 20/23] Fix linter issues --- .../adafruit_esp32spi_wsgiserver.py | 36 +++++++++---------- examples/esp32spi_get_board_details.py | 5 ++- .../cp_socket_count_server.py | 1 + 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index 956a36c..1a32e01 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py @@ -107,7 +107,7 @@ def update_poll(self): def finish_response(self, result): """ - Called after the application callbile returns result data to respond with. + Called after the application callable returns result data to respond with. Creates the HTTP Response payload from the response_headers and results data, and sends it back to client. @@ -138,23 +138,23 @@ def client_available(self): :rtype: Socket """ sock = None - if self._server_sock.socknum != NO_SOCK_AVAIL: - if self._client_sock.socknum != NO_SOCK_AVAIL: - # check previous received client socket - if self._debug > 2: - print("checking if last client sock still valid") - if self._client_sock.connected() and self._client_sock.available(): - sock = self._client_sock - if not sock: - # check for new client sock - if self._debug > 2: - print("checking for new client sock") - client_sock_num = _the_interface.socket_available( - self._server_sock.socknum - ) - sock = socket.socket(socknum=client_sock_num) - else: - print("Server has not been started, cannot check for clients!") + if self._server_sock.socknum == NO_SOCK_AVAIL: + raise ValueError("Server has not been started, cannot check for clients!") + + if self._client_sock.socknum != NO_SOCK_AVAIL: + # check previous received client socket + if self._debug > 2: + print("checking if last client sock still valid") + if self._client_sock.connected() and self._client_sock.available(): + sock = self._client_sock + if not sock: + # check for new client sock + if self._debug > 2: + print("checking for new client sock") + client_sock_num = _the_interface.socket_available( + self._server_sock.socknum + ) + sock = socket.socket(socknum=client_sock_num) if sock and sock.socknum != NO_SOCK_AVAIL: if self._debug > 2: diff --git a/examples/esp32spi_get_board_details.py b/examples/esp32spi_get_board_details.py index 5fb7fe1..3e45c2e 100644 --- a/examples/esp32spi_get_board_details.py +++ b/examples/esp32spi_get_board_details.py @@ -1,6 +1,9 @@ +# SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +import time import board import busio -import time from digitalio import DigitalInOut from adafruit_esp32spi import adafruit_esp32spi diff --git a/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py b/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py index 726c4f9..3f2a4dd 100644 --- a/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py +++ b/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py @@ -5,6 +5,7 @@ import struct import board import busio +from micropython import const from digitalio import DigitalInOut from adafruit_esp32spi import adafruit_esp32spi From 6c126e90548836515d6a29dea49143d8915ebe9e Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Mon, 30 May 2022 10:39:51 +0100 Subject: [PATCH 21/23] Unexpected reformat here --- adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index 1a32e01..dc22763 100644 --- a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py +++ b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py @@ -151,9 +151,7 @@ def client_available(self): # check for new client sock if self._debug > 2: print("checking for new client sock") - client_sock_num = _the_interface.socket_available( - self._server_sock.socknum - ) + client_sock_num = _the_interface.socket_available(self._server_sock.socknum) sock = socket.socket(socknum=client_sock_num) if sock and sock.socknum != NO_SOCK_AVAIL: From 9b737e05de40b0091e846f10422137f5da684de2 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Wed, 1 Jun 2022 17:00:32 +0100 Subject: [PATCH 22/23] Update adafruit_esp32spi/adafruit_esp32spi.py Co-authored-by: Dan Halbert --- adafruit_esp32spi/adafruit_esp32spi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 2cd2d4e..5bac986 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -281,7 +281,7 @@ def _check_data(self, spi, desired): """Read a byte and verify its the value we want""" r = self._read_byte(spi) if r != desired: - raise BrokenPipeError("Expected %02X but got %02X" % (desired, r)) + raise RuntimeError("Expected %02X but got %02X" % (desired, r)) def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False): """Wait for ready, then parse the response""" From afbe49233dcd69049135daf3c1660887e3988146 Mon Sep 17 00:00:00 2001 From: Danny Staple Date: Wed, 1 Jun 2022 17:02:49 +0100 Subject: [PATCH 23/23] Update adafruit_esp32spi/adafruit_esp32spi.py Co-authored-by: Dan Halbert --- adafruit_esp32spi/adafruit_esp32spi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 5bac986..aa2ea99 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -271,7 +271,7 @@ def _wait_spi_char(self, spi, desired): for _ in range(10): r = self._read_byte(spi) if r == _ERR_CMD: - raise BrokenPipeError("Error response to command") + raise RuntimeError("Error response to command") if r == desired: return True time.sleep(0.01)