Skip to content

Commit 138bccb

Browse files
committed
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)
1 parent 3cf7b8a commit 138bccb

File tree

1 file changed

+38
-16
lines changed

1 file changed

+38
-16
lines changed

adafruit_esp32spi/adafruit_esp32spi.py

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,15 @@
8383
_GET_HOST_BY_NAME_CMD = const(0x35)
8484
_START_SCAN_NETWORKS = const(0x36)
8585
_GET_FW_VERSION_CMD = const(0x37)
86+
_SEND_UDP_DATA_CMD = const(0x39)
8687
_GET_TIME = const(0x3B)
8788
_GET_IDX_BSSID_CMD = const(0x3C)
8889
_GET_IDX_CHAN_CMD = const(0x3D)
8990
_PING_CMD = const(0x3E)
9091

9192
_SEND_DATA_TCP_CMD = const(0x44)
9293
_GET_DATABUF_TCP_CMD = const(0x45)
94+
_INSERT_DATABUF_TCP_CMD = const(0x46)
9395
_SET_ENT_IDENT_CMD = const(0x4A)
9496
_SET_ENT_UNAME_CMD = const(0x4B)
9597
_SET_ENT_PASSWD_CMD = const(0x4C)
@@ -689,15 +691,19 @@ def socket_connected(self, socket_num):
689691
"""Test if a socket is connected to the destination, returns boolean true/false"""
690692
return self.socket_status(socket_num) == SOCKET_ESTABLISHED
691693

692-
def socket_write(self, socket_num, buffer):
694+
def socket_write(self, socket_num, buffer, conn_mode=TCP_MODE):
693695
"""Write the bytearray buffer to a socket"""
694696
if self._debug:
695697
print("Writing:", buffer)
696698
self._socknum_ll[0][0] = socket_num
697699
sent = 0
698-
for chunk in range((len(buffer) // 64) + 1):
700+
totalChunks = (len(buffer) // 64) + 1
701+
send_command = _SEND_DATA_TCP_CMD
702+
if conn_mode == UDP_MODE: # UDP requires a different command to write
703+
send_command = _INSERT_DATABUF_TCP_CMD
704+
for chunk in range(totalChunks):
699705
resp = self._send_command_get_response(
700-
_SEND_DATA_TCP_CMD,
706+
send_command,
701707
(
702708
self._socknum_ll[0],
703709
memoryview(buffer)[(chunk * 64) : ((chunk + 1) * 64)],
@@ -706,14 +712,25 @@ def socket_write(self, socket_num, buffer):
706712
)
707713
sent += resp[0][0]
708714

709-
if sent != len(buffer):
710-
raise RuntimeError(
711-
"Failed to send %d bytes (sent %d)" % (len(buffer), sent)
712-
)
715+
if conn_mode == UDP_MODE:
716+
# UDP verifies chunks on write, not bytes
717+
if sent != totalChunks:
718+
raise RuntimeError(
719+
"Failed to write %d chunks (sent %d)" % (totalChunks, sent)
720+
)
721+
# UDP needs to finalize with this command, does the actual sending
722+
resp = self._send_command_get_response(_SEND_UDP_DATA_CMD, self._socknum_ll)
723+
if resp[0][0] != 1:
724+
raise RuntimeError("Failed to send data")
725+
else:
726+
if sent != len(buffer):
727+
raise RuntimeError(
728+
"Failed to send %d bytes (sent %d)" % (len(buffer), sent)
729+
)
713730

714-
resp = self._send_command_get_response(_DATA_SENT_TCP_CMD, self._socknum_ll)
715-
if resp[0][0] != 1:
716-
raise RuntimeError("Failed to verify data sent")
731+
resp = self._send_command_get_response(_DATA_SENT_TCP_CMD, self._socknum_ll)
732+
if resp[0][0] != 1:
733+
raise RuntimeError("Failed to verify data sent")
717734

718735
def socket_available(self, socket_num):
719736
"""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):
749766
print("*** Socket connect mode", conn_mode)
750767

751768
self.socket_open(socket_num, dest, port, conn_mode=conn_mode)
752-
times = time.monotonic()
753-
while (time.monotonic() - times) < 3: # wait 3 seconds
754-
if self.socket_connected(socket_num):
755-
return True
756-
time.sleep(0.01)
757-
raise RuntimeError("Failed to establish connection")
769+
if conn_mode == UDP_MODE:
770+
# UDP doesn't actually establish a connection
771+
# but the socket for writing is created via start_server
772+
self.start_server(port, socket_num, conn_mode)
773+
else:
774+
times = time.monotonic()
775+
while (time.monotonic() - times) < 3: # wait 3 seconds
776+
if self.socket_connected(socket_num):
777+
return True
778+
time.sleep(0.01)
779+
raise RuntimeError("Failed to establish connection")
758780

759781
def socket_close(self, socket_num):
760782
"""Close a socket using the ESP32's internal reference number"""

0 commit comments

Comments
 (0)