@@ -127,6 +127,8 @@ def __init__(self, spi, cs_pin, ready_pin, reset_pin, gpio0_pin, *, debug=False)
127127 self ._debug = debug
128128 self ._buffer = bytearray (10 )
129129 self ._pbuf = bytearray (1 ) # buffer for param read
130+ self ._sendbuf = bytearray (256 ) # buffer for command sending
131+ self ._socknum_ll = [[0 ]] # pre-made list of list of socket #
130132
131133 self ._spi_device = SPIDevice (spi , cs_pin , baudrate = 8000000 )
132134 self ._cs = cs_pin
@@ -155,41 +157,57 @@ def reset(self):
155157
156158 def _wait_for_ready (self ):
157159 """Wait until the ready pin goes low"""
158- if self ._debug :
160+ if self ._debug >= 3 :
159161 print ("Wait for ESP32 ready" , end = '' )
160162 times = time .monotonic ()
161163 while (time .monotonic () - times ) < 10 : # wait up to 10 seconds
162164 if not self ._ready .value : # we're ready!
163165 break
164- if self ._debug :
166+ if self ._debug >= 3 :
165167 print ('.' , end = '' )
168+ time .sleep (0.05 )
166169 else :
167170 raise RuntimeError ("ESP32 not responding" )
168- if self ._debug :
171+ if self ._debug >= 3 :
169172 print ()
170173
171174
172175 def _send_command (self , cmd , params = None , * , param_len_16 = False ):
173176 """Send over a command with a list of parameters"""
177+
174178 if not params :
175- params = []
176- packet = []
177- packet .append (_START_CMD )
178- packet .append (cmd & ~ _REPLY_FLAG )
179- packet .append (len (params ))
179+ params = ()
180+
181+ packet_len = 4 # header + end byte
182+ for i , param in enumerate (params ):
183+ packet_len += len (param ) # parameter
184+ packet_len += 1 # size byte
185+ if param_len_16 :
186+ packet_len += 1 # 2 of em here!
187+ while packet_len % 4 != 0 :
188+ packet_len += 1
189+ # we may need more space
190+ if packet_len > len (self ._sendbuf ):
191+ self ._sendbuf = bytearray (packet_len )
192+
193+ self ._sendbuf [0 ] = _START_CMD
194+ self ._sendbuf [1 ] = cmd & ~ _REPLY_FLAG
195+ self ._sendbuf [2 ] = len (params )
180196
181197 # handle parameters here
198+ ptr = 3
182199 for i , param in enumerate (params ):
183200 if self ._debug >= 2 :
184201 print ("\t Sending param #%d is %d bytes long" % (i , len (param )))
185202 if param_len_16 :
186- packet .append ((len (param ) >> 8 ) & 0xFF )
187- packet .append (len (param ) & 0xFF )
188- packet += (param )
189-
190- packet .append (_END_CMD )
191- while len (packet ) % 4 != 0 :
192- packet .append (0xFF )
203+ self ._sendbuf [ptr ] = (len (param ) >> 8 ) & 0xFF
204+ ptr += 1
205+ self ._sendbuf [ptr ] = len (param ) & 0xFF
206+ ptr += 1
207+ for i , p in enumerate (param ):
208+ self ._sendbuf [ptr + i ] = p
209+ ptr += len (param )
210+ self ._sendbuf [ptr ] = _END_CMD
193211
194212 self ._wait_for_ready ()
195213 with self ._spi_device as spi :
@@ -199,17 +217,25 @@ def _send_command(self, cmd, params=None, *, param_len_16=False):
199217 break
200218 else :
201219 raise RuntimeError ("ESP32 timed out on SPI select" )
202- spi .write (bytearray ( packet ) ) # pylint: disable=no-member
203- if self ._debug :
204- print ("Wrote: " , [hex (b ) for b in packet ])
220+ spi .write (self . _sendbuf , start = 0 , end = packet_len ) # pylint: disable=no-member
221+ if self ._debug >= 3 :
222+ print ("Wrote: " , [hex (b ) for b in self . _sendbuf [ 0 : packet_len ] ])
205223
206224 def _read_byte (self , spi ):
207225 """Read one byte from SPI"""
208226 spi .readinto (self ._pbuf )
209- if self ._debug >= 2 :
227+ if self ._debug >= 3 :
210228 print ("\t \t Read:" , hex (self ._pbuf [0 ]))
211229 return self ._pbuf [0 ]
212230
231+ def _read_bytes (self , spi , buffer , start = 0 , end = None ):
232+ """Read many bytes from SPI"""
233+ if not end :
234+ end = len (buffer )
235+ spi .readinto (buffer , start = start , end = end )
236+ if self ._debug >= 3 :
237+ print ("\t \t Read:" , [hex (i ) for i in buffer ])
238+
213239 def _wait_spi_char (self , spi , desired ):
214240 """Read a byte with a time-out, and if we get it, check that its what we expect"""
215241 times = time .monotonic ()
@@ -247,19 +273,18 @@ def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False):
247273 else :
248274 num_responses = self ._read_byte (spi )
249275 for num in range (num_responses ):
250- response = []
251276 param_len = self ._read_byte (spi )
252277 if param_len_16 :
253278 param_len <<= 8
254279 param_len |= self ._read_byte (spi )
255280 if self ._debug >= 2 :
256281 print ("\t Parameter #%d length is %d" % (num , param_len ))
257- for _ in range (param_len ):
258- response . append ( self ._read_byte (spi ) )
259- responses .append (bytes ( response ) )
282+ response = bytearray (param_len )
283+ self ._read_bytes (spi , response )
284+ responses .append (response )
260285 self ._check_data (spi , _END_CMD )
261286
262- if self ._debug :
287+ if self ._debug >= 2 :
263288 print ("Read %d: " % len (responses [0 ]), responses )
264289 return responses
265290
@@ -280,7 +305,7 @@ def status(self):
280305 print ("Connection status" )
281306 resp = self ._send_command_get_response (_GET_CONN_STATUS_CMD )
282307 if self ._debug :
283- print ("Status :" , resp [0 ][0 ])
308+ print ("Conn status :" , resp [0 ][0 ])
284309 return resp [0 ][0 ] # one byte response
285310
286311 @property
@@ -317,9 +342,9 @@ def get_scan_networks(self):
317342 APs = [] # pylint: disable=invalid-name
318343 for i , name in enumerate (names ):
319344 a_p = {'ssid' : name }
320- rssi = self ._send_command_get_response (_GET_IDX_RSSI_CMD , [[ i ]] )[0 ]
345+ rssi = self ._send_command_get_response (_GET_IDX_RSSI_CMD , (( i ,),) )[0 ]
321346 a_p ['rssi' ] = struct .unpack ('<i' , rssi )[0 ]
322- encr = self ._send_command_get_response (_GET_IDX_ENCT_CMD , [[ i ]] )[0 ]
347+ encr = self ._send_command_get_response (_GET_IDX_ENCT_CMD , (( i ,),) )[0 ]
323348 a_p ['encryption' ] = encr [0 ]
324349 APs .append (a_p )
325350 return APs
@@ -428,7 +453,7 @@ def get_host_by_name(self, hostname):
428453 print ("*** Get host by name" )
429454 if isinstance (hostname , str ):
430455 hostname = bytes (hostname , 'utf-8' )
431- resp = self ._send_command_get_response (_REQ_HOST_BY_NAME_CMD , [ hostname ] )
456+ resp = self ._send_command_get_response (_REQ_HOST_BY_NAME_CMD , ( hostname ,) )
432457 if resp [0 ][0 ] != 1 :
433458 raise RuntimeError ("Failed to request hostname" )
434459 resp = self ._send_command_get_response (_GET_HOST_BY_NAME_CMD )
@@ -441,7 +466,7 @@ def ping(self, dest, ttl=250):
441466 dest = self .get_host_by_name (dest )
442467 # ttl must be between 0 and 255
443468 ttl = max (0 , min (ttl , 255 ))
444- resp = self ._send_command_get_response (_PING_CMD , [ dest , [ ttl ]] )
469+ resp = self ._send_command_get_response (_PING_CMD , ( dest , ( ttl )) )
445470 return struct .unpack ('<H' , resp [0 ])[0 ]
446471
447472 def get_socket (self ):
@@ -462,17 +487,18 @@ def socket_open(self, socket_num, dest, port, conn_mode=TCP_MODE):
462487 using the ESP32's internal reference number. By default we use
463488 'conn_mode' TCP_MODE but can also use UDP_MODE or TLS_MODE
464489 (dest must be hostname for TLS_MODE!)"""
490+ self ._socknum_ll [0 ][0 ] = socket_num
465491 if self ._debug :
466492 print ("*** Open socket" )
467493 port_param = struct .pack ('>H' , port )
468494 if isinstance (dest , str ): # use the 5 arg version
469495 dest = bytes (dest , 'utf-8' )
470496 resp = self ._send_command_get_response (_START_CLIENT_TCP_CMD ,
471- [ dest , b'\x00 \x00 \x00 \x00 ' ,
472- port_param , [ socket_num ], [ conn_mode ]] )
497+ ( dest , b'\x00 \x00 \x00 \x00 ' ,
498+ port_param , self . _socknum_ll [ 0 ], ( conn_mode ,)) )
473499 else : # ip address, use 4 arg vesion
474500 resp = self ._send_command_get_response (_START_CLIENT_TCP_CMD ,
475- [ dest , port_param , [ socket_num ], [ conn_mode ]] )
501+ ( dest , port_param , self . _socknum_ll [ 0 ], ( conn_mode ,)) )
476502 if resp [0 ][0 ] != 1 :
477503 raise RuntimeError ("Could not connect to remote server" )
478504
@@ -481,7 +507,8 @@ def socket_status(self, socket_num):
481507 SOCKET_SYN_SENT, SOCKET_SYN_RCVD, SOCKET_ESTABLISHED, SOCKET_FIN_WAIT_1,
482508 SOCKET_FIN_WAIT_2, SOCKET_CLOSE_WAIT, SOCKET_CLOSING, SOCKET_LAST_ACK, or
483509 SOCKET_TIME_WAIT"""
484- resp = self ._send_command_get_response (_GET_CLIENT_STATE_TCP_CMD , [[socket_num ]])
510+ self ._socknum_ll [0 ][0 ] = socket_num
511+ resp = self ._send_command_get_response (_GET_CLIENT_STATE_TCP_CMD , self ._socknum_ll )
485512 return resp [0 ][0 ]
486513
487514 def socket_connected (self , socket_num ):
@@ -492,35 +519,38 @@ def socket_write(self, socket_num, buffer):
492519 """Write the bytearray buffer to a socket"""
493520 if self ._debug :
494521 print ("Writing:" , buffer )
522+ self ._socknum_ll [0 ][0 ] = socket_num
495523 resp = self ._send_command_get_response (_SEND_DATA_TCP_CMD ,
496- [[ socket_num ], buffer ] ,
524+ ( self . _socknum_ll [ 0 ], buffer ) ,
497525 sent_param_len_16 = True )
498526
499527 sent = resp [0 ][0 ]
500528 if sent != len (buffer ):
501529 raise RuntimeError ("Failed to send %d bytes (sent %d)" % (len (buffer ), sent ))
502530
503- resp = self ._send_command_get_response (_DATA_SENT_TCP_CMD , [[ socket_num ]] )
531+ resp = self ._send_command_get_response (_DATA_SENT_TCP_CMD , self . _socknum_ll )
504532 if resp [0 ][0 ] != 1 :
505533 raise RuntimeError ("Failed to verify data sent" )
506534
507535 def socket_available (self , socket_num ):
508536 """Determine how many bytes are waiting to be read on the socket"""
509- resp = self ._send_command_get_response (_AVAIL_DATA_TCP_CMD , [[socket_num ]])
537+ self ._socknum_ll [0 ][0 ] = socket_num
538+ resp = self ._send_command_get_response (_AVAIL_DATA_TCP_CMD , self ._socknum_ll )
510539 reply = struct .unpack ('<H' , resp [0 ])[0 ]
511540 if self ._debug :
512- print ("%d bytes available" % reply )
541+ print ("ESPSocket: %d bytes available" % reply )
513542 return reply
514543
515544 def socket_read (self , socket_num , size ):
516545 """Read up to 'size' bytes from the socket number. Returns a bytearray"""
517546 if self ._debug :
518- print ("Reading %d bytes from socket with status %d" %
547+ print ("Reading %d bytes from ESP socket with status %d" %
519548 (size , self .socket_status (socket_num )))
549+ self ._socknum_ll [0 ][0 ] = socket_num
520550 resp = self ._send_command_get_response (_GET_DATABUF_TCP_CMD ,
521- [[ socket_num ], [ size & 0xFF , (size >> 8 ) & 0xFF ]] ,
551+ ( self . _socknum_ll [ 0 ], ( size & 0xFF , (size >> 8 ) & 0xFF )) ,
522552 sent_param_len_16 = True , recv_param_len_16 = True )
523- return resp [0 ]
553+ return bytes ( resp [0 ])
524554
525555 def socket_connect (self , socket_num , dest , port , conn_mode = TCP_MODE ):
526556 """Open and verify we connected a socket to a destination IP address or hostname
@@ -540,6 +570,7 @@ def socket_connect(self, socket_num, dest, port, conn_mode=TCP_MODE):
540570
541571 def socket_close (self , socket_num ):
542572 """Close a socket using the ESP32's internal reference number"""
543- resp = self ._send_command_get_response (_STOP_CLIENT_TCP_CMD , [[socket_num ]])
573+ self ._socknum_ll [0 ][0 ] = socket_num
574+ resp = self ._send_command_get_response (_STOP_CLIENT_TCP_CMD , self ._socknum_ll )
544575 if resp [0 ][0 ] != 1 :
545576 raise RuntimeError ("Failed to close socket" )
0 commit comments