Skip to content

Commit 97a59c1

Browse files
committed
fix tcp bulk transfer bug, socket timeout setter, streaming data from socket, and a max transfer size
1 parent b0f8490 commit 97a59c1

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

adafruit_esp32spi/adafruit_esp32spi.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def __init__(self, spi, cs_pin, ready_pin, reset_pin, gpio0_pin, *, debug=False)
128128
self._buffer = bytearray(10)
129129
self._pbuf = bytearray(1) # buffer for param read
130130

131-
self._spi_device = SPIDevice(spi, cs_pin, baudrate=4000000)
131+
self._spi_device = SPIDevice(spi, cs_pin, baudrate=8000000)
132132
self._cs = cs_pin
133133
self._ready = ready_pin
134134
self._reset = reset_pin
@@ -163,7 +163,6 @@ def _wait_for_ready(self):
163163
break
164164
if self._debug:
165165
print('.', end='')
166-
time.sleep(0.01)
167166
else:
168167
raise RuntimeError("ESP32 not responding")
169168
if self._debug:
@@ -261,7 +260,7 @@ def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False):
261260
self._check_data(spi, _END_CMD)
262261

263262
if self._debug:
264-
print("Read: ", responses)
263+
print("Read %d: " % len(responses[0]), responses)
265264
return responses
266265

267266
def _send_command_get_response(self, cmd, params=None, *,
@@ -508,11 +507,17 @@ def socket_write(self, socket_num, buffer):
508507
def socket_available(self, socket_num):
509508
"""Determine how many bytes are waiting to be read on the socket"""
510509
resp = self._send_command_get_response(_AVAIL_DATA_TCP_CMD, [[socket_num]])
511-
return struct.unpack('<H', resp[0])[0]
510+
reply = struct.unpack('<H', resp[0])[0]
511+
if self._debug:
512+
print("%d bytes available" % reply)
513+
return reply
512514

513515
def socket_read(self, socket_num, size):
514516
"""Read up to 'size' bytes from the socket number. Returns a bytearray"""
515-
resp = self._send_command_get_response(_GET_DATABUF_TCP_CMD, [[socket_num], [size]],
517+
if self._debug:
518+
print("Reading %d bytes from socket with status %d" % (size, self.socket_status(socket_num)))
519+
resp = self._send_command_get_response(_GET_DATABUF_TCP_CMD,
520+
[[socket_num], [size & 0xFF, (size >> 8) & 0xFF]],
516521
sent_param_len_16=True, recv_param_len_16=True)
517522
return resp[0]
518523

adafruit_esp32spi/adafruit_esp32spi_requests.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def __init__(self, sock):
6767
self._cached = None
6868
self.status_code = None
6969
self.reason = None
70+
self._read_so_far = 0
7071

7172
def close(self):
7273
"""Close, delete and collect the response data"""
@@ -105,13 +106,25 @@ def json(self):
105106
import ujson
106107
return ujson.loads(self.content)
107108

109+
def iter_content(self, chunk_size=1, decode_unicode=False):
110+
if decode_unicode:
111+
raise NotImplementedError("Unicode not supported")
112+
113+
while True:
114+
chunk = self.socket.read(chunk_size)
115+
if chunk and len(chunk) > 0:
116+
yield chunk
117+
else:
118+
return
108119

109120
# pylint: disable=too-many-branches, too-many-statements, unused-argument, too-many-arguments, too-many-locals
110-
def request(method, url, data=None, json=None, headers=None, stream=None):
121+
def request(method, url, data=None, json=None, headers=None, stream=False):
111122
"""Perform an HTTP request to the given url which we will parse to determine
112123
whether to use SSL ('https://') or not. We can also send some provided 'data'
113124
or a json dictionary which we will stringify. 'headers' is optional HTTP headers
114-
sent along. 'stream' is unused in this implementation"""
125+
sent along. 'stream' will determine if we buffer everything, or whether to only
126+
read only when requested
127+
"""
115128
global _the_interface # pylint: disable=global-statement, invalid-name
116129

117130
if not headers:
@@ -139,6 +152,8 @@ def request(method, url, data=None, json=None, headers=None, stream=None):
139152
sock = socket.socket(addr_info[0], addr_info[1], addr_info[2])
140153
resp = Response(sock) # our response
141154

155+
sock.settimeout(1) # 1 second timeout
156+
142157
try:
143158
if proto == "https:":
144159
conntype = _the_interface.TLS_MODE

adafruit_esp32spi/adafruit_esp32spi_socket.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"""
3131

3232

33-
33+
import time
3434
from micropython import const
3535

3636
_the_interface = None # pylint: disable=invalid-name
@@ -63,6 +63,7 @@ def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None):
6363
raise RuntimeError("Only SOCK_STREAM type supported")
6464
self._buffer = b''
6565
self._socknum = _the_interface.get_socket()
66+
self.settimeout(0)
6667

6768
def connect(self, address, conntype=None):
6869
"""Connect the socket to the 'address' (which can be 32bit packed IP or
@@ -81,7 +82,7 @@ def readline(self):
8182
"""Attempt to return as many bytes as we can up to but not including '\r\n'"""
8283
while b'\r\n' not in self._buffer:
8384
# there's no line already in there, read some more
84-
avail = _the_interface.socket_available(self._socknum)
85+
avail = min(_the_interface.socket_available(self._socknum), 4000)
8586
if avail:
8687
self._buffer += _the_interface.socket_read(self._socknum, avail)
8788
firstline, self._buffer = self._buffer.split(b'\r\n', 1)
@@ -90,21 +91,28 @@ def readline(self):
9091
def read(self, size=0):
9192
"""Read up to 'size' bytes from the socket, this may be buffered internally!
9293
If 'size' isnt specified, return everything in the buffer."""
93-
avail = _the_interface.socket_available(self._socknum)
94-
if avail:
95-
self._buffer += _the_interface.socket_read(self._socknum, avail)
9694
if size == 0: # read as much as we can at the moment
95+
avail = min(_the_interface.socket_available(self._socknum), 4000)
96+
if avail:
97+
self._buffer += _the_interface.socket_read(self._socknum, avail)
9798
ret = self._buffer
9899
self._buffer = b''
99100
return ret
101+
stamp = time.monotonic()
100102
while len(self._buffer) < size:
101-
avail = _the_interface.socket_available(self._socknum)
103+
avail = min(_the_interface.socket_available(self._socknum), 4000)
102104
if avail:
103-
self._buffer += _the_interface.socket_read(self._socknum, avail)
105+
stamp = time.monotonic()
106+
self._buffer += _the_interface.socket_read(self._socknum, min(size, avail))
107+
if time.monotonic() - stamp > self._timeout:
108+
break
104109
ret = self._buffer[:size]
105110
self._buffer = self._buffer[size:]
106111
return ret
107112

113+
def settimeout(self, value):
114+
self._timeout = value
115+
108116
def close(self):
109117
"""Close the socket, after reading whatever remains"""
110118
_the_interface.socket_close(self._socknum)

0 commit comments

Comments
 (0)