diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index fae4cc6..aa2ea99 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 @@ -275,7 +275,7 @@ def _wait_spi_char(self, spi, desired): 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""" @@ -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) @@ -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 @@ -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): @@ -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) @@ -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 @@ -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""" @@ -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""" @@ -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. @@ -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,13 +950,13 @@ def get_time(self): resp = self._send_command_get_response(_GET_TIME) resp_time = struct.unpack(" 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 diff --git a/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py b/adafruit_esp32spi/adafruit_esp32spi_wifimanager.py index 739f7a9..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, RuntimeError) 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, RuntimeError) 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, RuntimeError) as error: + except OSError as error: print("Failed to connect, retrying\n", error) failure_count += 1 if failure_count >= self.attempts: diff --git a/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py b/adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py index 956a36c..dc22763 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,21 @@ 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/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" diff --git a/examples/esp32spi_aio_post.py b/examples/esp32spi_aio_post.py index b74e4e3..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, RuntimeError) 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 46d75af..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, RuntimeError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/esp32spi_get_board_details.py b/examples/esp32spi_get_board_details.py new file mode 100644 index 0000000..3e45c2e --- /dev/null +++ b/examples/esp32spi_get_board_details.py @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +import time +import board +import busio + +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!") 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..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, RuntimeError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) continue 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/esp32spi_wpa2ent_aio_post.py b/examples/esp32spi_wpa2ent_aio_post.py index b6bdd99..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, RuntimeError) as e: + except OSError as e: print("Failed to get data, retrying\n", e) wifi.reset() continue diff --git a/examples/gpio/esp32spi_gpio.py b/examples/gpio/esp32spi_gpio.py index a9c857d..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 (RuntimeError, AssertionError) as e: + except OSError 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 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() diff --git a/examples/server/esp32spi_wsgiserver.py b/examples/server/esp32spi_wsgiserver.py index d9f0979..0220d2f 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 OSError as e: print("Failed to update server, restarting ESP32\n", e) wifi.reset() continue 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 new file mode 100644 index 0000000..61ab810 --- /dev/null +++ b/examples/stress_tests/socket_client_server_stress/esp_rp2040_client/cp_socket_count_client.py @@ -0,0 +1,55 @@ +# 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 = "192.168.1.149" +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) + + +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() 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..3f2a4dd --- /dev/null +++ b/examples/stress_tests/socket_client_server_stress/esp_rp2040_server/cp_socket_count_server.py @@ -0,0 +1,124 @@ +# SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +import gc +import struct +import board +import busio +from micropython import const +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..0b56e7a --- /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 new file mode 100644 index 0000000..ce7a76f --- /dev/null +++ b/examples/stress_tests/socket_client_server_stress/pc_server/pc_socket_count_server.py @@ -0,0 +1,26 @@ +# 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 +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()