@@ -127,6 +127,8 @@ def __init__(self, spi, cs_pin, ready_pin, reset_pin, gpio0_pin, *, debug=False)
127
127
self ._debug = debug
128
128
self ._buffer = bytearray (10 )
129
129
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 #
130
132
131
133
self ._spi_device = SPIDevice (spi , cs_pin , baudrate = 8000000 )
132
134
self ._cs = cs_pin
@@ -155,41 +157,57 @@ def reset(self):
155
157
156
158
def _wait_for_ready (self ):
157
159
"""Wait until the ready pin goes low"""
158
- if self ._debug :
160
+ if self ._debug >= 3 :
159
161
print ("Wait for ESP32 ready" , end = '' )
160
162
times = time .monotonic ()
161
163
while (time .monotonic () - times ) < 10 : # wait up to 10 seconds
162
164
if not self ._ready .value : # we're ready!
163
165
break
164
- if self ._debug :
166
+ if self ._debug >= 3 :
165
167
print ('.' , end = '' )
168
+ time .sleep (0.05 )
166
169
else :
167
170
raise RuntimeError ("ESP32 not responding" )
168
- if self ._debug :
171
+ if self ._debug >= 3 :
169
172
print ()
170
173
171
174
172
175
def _send_command (self , cmd , params = None , * , param_len_16 = False ):
173
176
"""Send over a command with a list of parameters"""
177
+
174
178
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 )
180
196
181
197
# handle parameters here
198
+ ptr = 3
182
199
for i , param in enumerate (params ):
183
200
if self ._debug >= 2 :
184
201
print ("\t Sending param #%d is %d bytes long" % (i , len (param )))
185
202
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
193
211
194
212
self ._wait_for_ready ()
195
213
with self ._spi_device as spi :
@@ -199,17 +217,25 @@ def _send_command(self, cmd, params=None, *, param_len_16=False):
199
217
break
200
218
else :
201
219
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 ] ])
205
223
206
224
def _read_byte (self , spi ):
207
225
"""Read one byte from SPI"""
208
226
spi .readinto (self ._pbuf )
209
- if self ._debug >= 2 :
227
+ if self ._debug >= 3 :
210
228
print ("\t \t Read:" , hex (self ._pbuf [0 ]))
211
229
return self ._pbuf [0 ]
212
230
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
+
213
239
def _wait_spi_char (self , spi , desired ):
214
240
"""Read a byte with a time-out, and if we get it, check that its what we expect"""
215
241
times = time .monotonic ()
@@ -247,19 +273,18 @@ def _wait_response_cmd(self, cmd, num_responses=None, *, param_len_16=False):
247
273
else :
248
274
num_responses = self ._read_byte (spi )
249
275
for num in range (num_responses ):
250
- response = []
251
276
param_len = self ._read_byte (spi )
252
277
if param_len_16 :
253
278
param_len <<= 8
254
279
param_len |= self ._read_byte (spi )
255
280
if self ._debug >= 2 :
256
281
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 )
260
285
self ._check_data (spi , _END_CMD )
261
286
262
- if self ._debug :
287
+ if self ._debug >= 2 :
263
288
print ("Read %d: " % len (responses [0 ]), responses )
264
289
return responses
265
290
@@ -280,7 +305,7 @@ def status(self):
280
305
print ("Connection status" )
281
306
resp = self ._send_command_get_response (_GET_CONN_STATUS_CMD )
282
307
if self ._debug :
283
- print ("Status :" , resp [0 ][0 ])
308
+ print ("Conn status :" , resp [0 ][0 ])
284
309
return resp [0 ][0 ] # one byte response
285
310
286
311
@property
@@ -317,9 +342,9 @@ def get_scan_networks(self):
317
342
APs = [] # pylint: disable=invalid-name
318
343
for i , name in enumerate (names ):
319
344
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 ]
321
346
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 ]
323
348
a_p ['encryption' ] = encr [0 ]
324
349
APs .append (a_p )
325
350
return APs
@@ -428,7 +453,7 @@ def get_host_by_name(self, hostname):
428
453
print ("*** Get host by name" )
429
454
if isinstance (hostname , str ):
430
455
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 ,) )
432
457
if resp [0 ][0 ] != 1 :
433
458
raise RuntimeError ("Failed to request hostname" )
434
459
resp = self ._send_command_get_response (_GET_HOST_BY_NAME_CMD )
@@ -441,7 +466,7 @@ def ping(self, dest, ttl=250):
441
466
dest = self .get_host_by_name (dest )
442
467
# ttl must be between 0 and 255
443
468
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 )) )
445
470
return struct .unpack ('<H' , resp [0 ])[0 ]
446
471
447
472
def get_socket (self ):
@@ -462,17 +487,18 @@ def socket_open(self, socket_num, dest, port, conn_mode=TCP_MODE):
462
487
using the ESP32's internal reference number. By default we use
463
488
'conn_mode' TCP_MODE but can also use UDP_MODE or TLS_MODE
464
489
(dest must be hostname for TLS_MODE!)"""
490
+ self ._socknum_ll [0 ][0 ] = socket_num
465
491
if self ._debug :
466
492
print ("*** Open socket" )
467
493
port_param = struct .pack ('>H' , port )
468
494
if isinstance (dest , str ): # use the 5 arg version
469
495
dest = bytes (dest , 'utf-8' )
470
496
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 ,)) )
473
499
else : # ip address, use 4 arg vesion
474
500
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 ,)) )
476
502
if resp [0 ][0 ] != 1 :
477
503
raise RuntimeError ("Could not connect to remote server" )
478
504
@@ -481,7 +507,8 @@ def socket_status(self, socket_num):
481
507
SOCKET_SYN_SENT, SOCKET_SYN_RCVD, SOCKET_ESTABLISHED, SOCKET_FIN_WAIT_1,
482
508
SOCKET_FIN_WAIT_2, SOCKET_CLOSE_WAIT, SOCKET_CLOSING, SOCKET_LAST_ACK, or
483
509
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 )
485
512
return resp [0 ][0 ]
486
513
487
514
def socket_connected (self , socket_num ):
@@ -492,35 +519,38 @@ def socket_write(self, socket_num, buffer):
492
519
"""Write the bytearray buffer to a socket"""
493
520
if self ._debug :
494
521
print ("Writing:" , buffer )
522
+ self ._socknum_ll [0 ][0 ] = socket_num
495
523
resp = self ._send_command_get_response (_SEND_DATA_TCP_CMD ,
496
- [[ socket_num ], buffer ] ,
524
+ ( self . _socknum_ll [ 0 ], buffer ) ,
497
525
sent_param_len_16 = True )
498
526
499
527
sent = resp [0 ][0 ]
500
528
if sent != len (buffer ):
501
529
raise RuntimeError ("Failed to send %d bytes (sent %d)" % (len (buffer ), sent ))
502
530
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 )
504
532
if resp [0 ][0 ] != 1 :
505
533
raise RuntimeError ("Failed to verify data sent" )
506
534
507
535
def socket_available (self , socket_num ):
508
536
"""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 )
510
539
reply = struct .unpack ('<H' , resp [0 ])[0 ]
511
540
if self ._debug :
512
- print ("%d bytes available" % reply )
541
+ print ("ESPSocket: %d bytes available" % reply )
513
542
return reply
514
543
515
544
def socket_read (self , socket_num , size ):
516
545
"""Read up to 'size' bytes from the socket number. Returns a bytearray"""
517
546
if self ._debug :
518
- print ("Reading %d bytes from socket with status %d" %
547
+ print ("Reading %d bytes from ESP socket with status %d" %
519
548
(size , self .socket_status (socket_num )))
549
+ self ._socknum_ll [0 ][0 ] = socket_num
520
550
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 )) ,
522
552
sent_param_len_16 = True , recv_param_len_16 = True )
523
- return resp [0 ]
553
+ return bytes ( resp [0 ])
524
554
525
555
def socket_connect (self , socket_num , dest , port , conn_mode = TCP_MODE ):
526
556
"""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):
540
570
541
571
def socket_close (self , socket_num ):
542
572
"""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 )
544
575
if resp [0 ][0 ] != 1 :
545
576
raise RuntimeError ("Failed to close socket" )
0 commit comments