Skip to content

Commit c8bb625

Browse files
authored
Merge pull request #167 from dhalbert/compatible-socket
Compatible socket
2 parents 2e74c68 + c5b6203 commit c8bb625

File tree

7 files changed

+24
-717
lines changed

7 files changed

+24
-717
lines changed

adafruit_esp32spi/adafruit_esp32spi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ def socket_available(self, socket_num):
793793
return reply
794794

795795
def socket_read(self, socket_num, size):
796-
"""Read up to 'size' bytes from the socket number. Returns a bytearray"""
796+
"""Read up to 'size' bytes from the socket number. Returns a bytes"""
797797
if self._debug:
798798
print(
799799
"Reading %d bytes from ESP socket with status %d"

adafruit_esp32spi/adafruit_esp32spi_socket.py

Lines changed: 23 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -88,80 +88,15 @@ def send(self, data): # pylint: disable=no-self-use
8888
_the_interface.socket_write(self._socknum, data, conn_mode=conntype)
8989
gc.collect()
9090

91-
def write(self, data):
92-
"""Sends data to the socket.
93-
NOTE: This method is deprecated and will be removed.
94-
"""
95-
self.send(data)
96-
97-
def readline(self, eol=b"\r\n"):
98-
"""Attempt to return as many bytes as we can up to but not including
99-
end-of-line character (default is '\\r\\n')"""
100-
101-
# print("Socket readline")
102-
stamp = time.monotonic()
103-
while eol not in self._buffer:
104-
# there's no line already in there, read some more
105-
avail = self.available()
106-
if avail:
107-
self._buffer += _the_interface.socket_read(self._socknum, avail)
108-
elif self._timeout > 0 and time.monotonic() - stamp > self._timeout:
109-
self.close() # Make sure to close socket so that we don't exhaust sockets.
110-
raise OSError("Didn't receive full response, failing out")
111-
firstline, self._buffer = self._buffer.split(eol, 1)
112-
gc.collect()
113-
return firstline
114-
115-
def recv(self, bufsize=0):
91+
def recv(self, bufsize: int) -> bytes:
11692
"""Reads some bytes from the connected remote address. Will only return
11793
an empty string after the configured timeout.
11894
11995
:param int bufsize: maximum number of bytes to receive
12096
"""
121-
# print("Socket read", bufsize)
122-
if bufsize == 0: # read as much as we can at the moment
123-
while True:
124-
avail = self.available()
125-
if avail:
126-
self._buffer += _the_interface.socket_read(self._socknum, avail)
127-
else:
128-
break
129-
gc.collect()
130-
ret = self._buffer
131-
self._buffer = b""
132-
gc.collect()
133-
return ret
134-
stamp = time.monotonic()
135-
136-
to_read = bufsize - len(self._buffer)
137-
received = []
138-
while to_read > 0:
139-
# print("Bytes to read:", to_read)
140-
avail = self.available()
141-
if avail:
142-
stamp = time.monotonic()
143-
recv = _the_interface.socket_read(self._socknum, min(to_read, avail))
144-
received.append(recv)
145-
to_read -= len(recv)
146-
gc.collect()
147-
elif received:
148-
# We've received some bytes but no more are available. So return
149-
# what we have.
150-
break
151-
if self._timeout > 0 and time.monotonic() - stamp > self._timeout:
152-
break
153-
# print(received)
154-
self._buffer += b"".join(received)
155-
156-
ret = None
157-
if len(self._buffer) == bufsize:
158-
ret = self._buffer
159-
self._buffer = b""
160-
else:
161-
ret = self._buffer[:bufsize]
162-
self._buffer = self._buffer[bufsize:]
163-
gc.collect()
164-
return ret
97+
buf = bytearray(bufsize)
98+
self.recv_into(buf, bufsize)
99+
return bytes(buf)
165100

166101
def recv_into(self, buffer, nbytes: int = 0):
167102
"""Read bytes from the connected remote address into a given buffer.
@@ -178,7 +113,7 @@ def recv_into(self, buffer, nbytes: int = 0):
178113
num_to_read = len(buffer) if nbytes == 0 else nbytes
179114
num_read = 0
180115
while num_to_read > 0:
181-
num_avail = self.available()
116+
num_avail = self._available()
182117
if num_avail > 0:
183118
last_read_time = time.monotonic()
184119
bytes_read = _the_interface.socket_read(
@@ -192,33 +127,28 @@ def recv_into(self, buffer, nbytes: int = 0):
192127
break
193128
# No bytes yet, or more bytes requested.
194129
if self._timeout > 0 and time.monotonic() - last_read_time > self._timeout:
195-
break
130+
raise timeout("timed out")
196131
return num_read
197132

198-
def read(self, size=0):
199-
"""Read up to 'size' bytes from the socket, this may be buffered internally!
200-
If 'size' isnt specified, return everything in the buffer.
201-
NOTE: This method is deprecated and will be removed.
202-
"""
203-
return self.recv(size)
204-
205133
def settimeout(self, value):
206-
"""Set the read timeout for sockets, if value is 0 it will block"""
134+
"""Set the read timeout for sockets.
135+
If value is 0 socket reads will block until a message is available.
136+
"""
207137
self._timeout = value
208138

209-
def available(self):
139+
def _available(self):
210140
"""Returns how many bytes of data are available to be read (up to the MAX_PACKET length)"""
211-
if self.socknum != NO_SOCKET_AVAIL:
141+
if self._socknum != NO_SOCKET_AVAIL:
212142
return min(_the_interface.socket_available(self._socknum), MAX_PACKET)
213143
return 0
214144

215-
def connected(self):
145+
def _connected(self):
216146
"""Whether or not we are connected to the socket"""
217-
if self.socknum == NO_SOCKET_AVAIL:
147+
if self._socknum == NO_SOCKET_AVAIL:
218148
return False
219-
if self.available():
149+
if self._available():
220150
return True
221-
status = _the_interface.socket_status(self.socknum)
151+
status = _the_interface.socket_status(self._socknum)
222152
result = status not in (
223153
adafruit_esp32spi.SOCKET_LISTEN,
224154
adafruit_esp32spi.SOCKET_CLOSED,
@@ -234,14 +164,17 @@ def connected(self):
234164
self._socknum = NO_SOCKET_AVAIL
235165
return result
236166

237-
@property
238-
def socknum(self):
239-
"""The socket number"""
240-
return self._socknum
241-
242167
def close(self):
243168
"""Close the socket, after reading whatever remains"""
244169
_the_interface.socket_close(self._socknum)
245170

246171

172+
class timeout(TimeoutError):
173+
"""TimeoutError class. An instance of this error will be raised by recv_into() if
174+
the timeout has elapsed and we haven't received any data yet."""
175+
176+
def __init__(self, msg):
177+
super().__init__(msg)
178+
179+
247180
# pylint: enable=unused-argument, redefined-builtin, invalid-name

0 commit comments

Comments
 (0)