From 138bccbe9ee711407db52c799c416a408569f5b9 Mon Sep 17 00:00:00 2001 From: Harold De Armas Date: Wed, 29 Apr 2020 23:40:54 -0700 Subject: [PATCH 1/6] Add UDP support Writing to UDP requires separate APIs to use to append data and finalize. TCP sends and confirms per-write and finalize is a no-op. UDP appends to a buffer and finalize sends all at once. The simple socket_open method doesn't actually create a socket per https://github.com/arduino/nina-fw. Since socket_connect is a convenience method anyway, and connect doesn't really make sense for UDP, add the start_server call for UDP to that method to have a socket to write as well as read on. e.x. usage esp.socket_connect(socket_num, dest, port, esp.UDP_MODE) esp.socket_write(socket_num, buffer, esp.UDP_MODE) avail = esp.socket_available(socket_num) recv = esp.socket_read(socket_num, avail) esp.socket_close(socket_num) --- adafruit_esp32spi/adafruit_esp32spi.py | 54 ++++++++++++++++++-------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 347ea3b..8b372dd 100755 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -83,6 +83,7 @@ _GET_HOST_BY_NAME_CMD = const(0x35) _START_SCAN_NETWORKS = const(0x36) _GET_FW_VERSION_CMD = const(0x37) +_SEND_UDP_DATA_CMD = const(0x39) _GET_TIME = const(0x3B) _GET_IDX_BSSID_CMD = const(0x3C) _GET_IDX_CHAN_CMD = const(0x3D) @@ -90,6 +91,7 @@ _SEND_DATA_TCP_CMD = const(0x44) _GET_DATABUF_TCP_CMD = const(0x45) +_INSERT_DATABUF_TCP_CMD = const(0x46) _SET_ENT_IDENT_CMD = const(0x4A) _SET_ENT_UNAME_CMD = const(0x4B) _SET_ENT_PASSWD_CMD = const(0x4C) @@ -689,15 +691,19 @@ def socket_connected(self, socket_num): """Test if a socket is connected to the destination, returns boolean true/false""" return self.socket_status(socket_num) == SOCKET_ESTABLISHED - def socket_write(self, socket_num, buffer): + def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): """Write the bytearray buffer to a socket""" if self._debug: print("Writing:", buffer) self._socknum_ll[0][0] = socket_num sent = 0 - for chunk in range((len(buffer) // 64) + 1): + totalChunks = (len(buffer) // 64) + 1 + send_command = _SEND_DATA_TCP_CMD + if conn_mode == UDP_MODE: # UDP requires a different command to write + send_command = _INSERT_DATABUF_TCP_CMD + for chunk in range(totalChunks): resp = self._send_command_get_response( - _SEND_DATA_TCP_CMD, + send_command, ( self._socknum_ll[0], memoryview(buffer)[(chunk * 64) : ((chunk + 1) * 64)], @@ -706,14 +712,25 @@ def socket_write(self, socket_num, buffer): ) sent += resp[0][0] - if sent != len(buffer): - raise RuntimeError( - "Failed to send %d bytes (sent %d)" % (len(buffer), sent) - ) + if conn_mode == UDP_MODE: + # UDP verifies chunks on write, not bytes + if sent != totalChunks: + raise RuntimeError( + "Failed to write %d chunks (sent %d)" % (totalChunks, 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 data") + else: + if sent != len(buffer): + raise RuntimeError( + "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") + 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") def socket_available(self, socket_num): """Determine how many bytes are waiting to be read on the socket""" @@ -749,12 +766,17 @@ def socket_connect(self, socket_num, dest, port, conn_mode=TCP_MODE): print("*** Socket connect mode", conn_mode) self.socket_open(socket_num, dest, port, conn_mode=conn_mode) - times = time.monotonic() - while (time.monotonic() - times) < 3: # wait 3 seconds - if self.socket_connected(socket_num): - return True - time.sleep(0.01) - raise RuntimeError("Failed to establish connection") + if conn_mode == UDP_MODE: + # UDP doesn't actually establish a connection + # but the socket for writing is created via start_server + self.start_server(port, socket_num, conn_mode) + else: + times = time.monotonic() + while (time.monotonic() - times) < 3: # wait 3 seconds + if self.socket_connected(socket_num): + return True + time.sleep(0.01) + raise RuntimeError("Failed to establish connection") def socket_close(self, socket_num): """Close a socket using the ESP32's internal reference number""" From f437871fa3e75989ed968f510cf5b5c0b1d26b35 Mon Sep 17 00:00:00 2001 From: Harold De Armas Date: Thu, 30 Apr 2020 00:02:47 -0700 Subject: [PATCH 2/6] Formatting --- 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 8b372dd..3180fb5 100755 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -699,7 +699,7 @@ def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): sent = 0 totalChunks = (len(buffer) // 64) + 1 send_command = _SEND_DATA_TCP_CMD - if conn_mode == UDP_MODE: # UDP requires a different command to write + if conn_mode == UDP_MODE: # UDP requires a different command to write send_command = _INSERT_DATABUF_TCP_CMD for chunk in range(totalChunks): resp = self._send_command_get_response( From aa96dd1448a8d414f1be36a3700b565d5c8b0f9e Mon Sep 17 00:00:00 2001 From: Harold De Armas Date: Thu, 30 Apr 2020 00:13:04 -0700 Subject: [PATCH 3/6] pylint --- adafruit_esp32spi/adafruit_esp32spi.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 3180fb5..9d4d03d 100755 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -697,11 +697,11 @@ def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): print("Writing:", buffer) self._socknum_ll[0][0] = socket_num sent = 0 - totalChunks = (len(buffer) // 64) + 1 + total_chunks = (len(buffer) // 64) + 1 send_command = _SEND_DATA_TCP_CMD - if conn_mode == UDP_MODE: # UDP requires a different command to write + if conn_mode == self.UDP_MODE: # UDP requires a different command to write send_command = _INSERT_DATABUF_TCP_CMD - for chunk in range(totalChunks): + for chunk in range(total_chunks): resp = self._send_command_get_response( send_command, ( @@ -712,11 +712,11 @@ def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): ) sent += resp[0][0] - if conn_mode == UDP_MODE: + if conn_mode == self.UDP_MODE: # UDP verifies chunks on write, not bytes - if sent != totalChunks: + if sent != total_chunks: raise RuntimeError( - "Failed to write %d chunks (sent %d)" % (totalChunks, sent) + "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) @@ -766,10 +766,11 @@ def socket_connect(self, socket_num, dest, port, conn_mode=TCP_MODE): print("*** Socket connect mode", conn_mode) self.socket_open(socket_num, dest, port, conn_mode=conn_mode) - if conn_mode == UDP_MODE: + if conn_mode == self.UDP_MODE: # UDP doesn't actually establish a connection # but the socket for writing is created via start_server self.start_server(port, socket_num, conn_mode) + return True else: times = time.monotonic() while (time.monotonic() - times) < 3: # wait 3 seconds From 82edb0ab397e472dc08683bdc2beaacb6422d4d6 Mon Sep 17 00:00:00 2001 From: Harold De Armas Date: Thu, 30 Apr 2020 00:15:36 -0700 Subject: [PATCH 4/6] pylint --- adafruit_esp32spi/adafruit_esp32spi.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 9d4d03d..8480e60 100755 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -771,13 +771,13 @@ def socket_connect(self, socket_num, dest, port, conn_mode=TCP_MODE): # but the socket for writing is created via start_server self.start_server(port, socket_num, conn_mode) return True - else: - times = time.monotonic() - while (time.monotonic() - times) < 3: # wait 3 seconds - if self.socket_connected(socket_num): - return True - time.sleep(0.01) - raise RuntimeError("Failed to establish connection") + + times = time.monotonic() + while (time.monotonic() - times) < 3: # wait 3 seconds + if self.socket_connected(socket_num): + return True + time.sleep(0.01) + raise RuntimeError("Failed to establish connection") def socket_close(self, socket_num): """Close a socket using the ESP32's internal reference number""" From 2c0466f7864fb8dbeb72f070451ca2c0063c498c Mon Sep 17 00:00:00 2001 From: Harold De Armas Date: Thu, 30 Apr 2020 00:17:50 -0700 Subject: [PATCH 5/6] fix indentation for easier merge --- adafruit_esp32spi/adafruit_esp32spi.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index 8480e60..98b422a 100755 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -722,15 +722,16 @@ def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): resp = self._send_command_get_response(_SEND_UDP_DATA_CMD, self._socknum_ll) if resp[0][0] != 1: raise RuntimeError("Failed to send data") - else: - if sent != len(buffer): - raise RuntimeError( - "Failed to send %d bytes (sent %d)" % (len(buffer), sent) - ) + return - 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") + if sent != len(buffer): + raise RuntimeError( + "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") def socket_available(self, socket_num): """Determine how many bytes are waiting to be read on the socket""" From 974820a293e8c381de2cfa48b2d64865e5930888 Mon Sep 17 00:00:00 2001 From: Harold De Armas Date: Thu, 30 Apr 2020 14:04:59 -0700 Subject: [PATCH 6/6] Clarify log statemeny --- 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 98b422a..7861c15 100755 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -721,7 +721,7 @@ def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE): # 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 data") + raise RuntimeError("Failed to send UDP data") return if sent != len(buffer):