@@ -17,14 +17,25 @@ class ESP_SPIcontrol:
1717 GET_CURR_ENCT_CMD = const (0x26 )
1818
1919 SCAN_NETWORKS = const (0x27 )
20+ GET_SOCKET_CMD = const (0x3F )
21+ GET_STATE_TCP_CMD = const (0x29 )
22+ DATA_SENT_TCP_CMD = const (0x2A )
23+ AVAIL_DATA_TCP_CMD = const (0x2B )
24+ GET_DATA_TCP_CMD = const (0x2C )
25+ START_CLIENT_TCP_CMD = const (0x2D )
26+ STOP_CLIENT_TCP_CMD = const (0x2E )
27+ GET_CLIENT_STATE_TCP_CMD = const (0x2F )
28+ DISCONNECT_CMD = const (0x30 )
2029 GET_IDX_RSSI_CMD = const (0x32 )
2130 GET_IDX_ENCT_CMD = const (0x33 )
2231 REQ_HOST_BY_NAME_CMD = const (0x34 )
2332 GET_HOST_BY_NAME_CMD = const (0x35 )
2433 START_SCAN_NETWORKS = const (0x36 )
34+ GET_FW_VERSION_CMD = const (0x37 )
2535 PING_CMD = const (0x3E )
2636
27- GET_FW_VERSION_CMD = const (0x37 )
37+ SEND_DATA_TCP_CMD = const (0x44 )
38+
2839
2940 START_CMD = const (0xE0 )
3041 END_CMD = const (0xEE )
@@ -39,6 +50,20 @@ class ESP_SPIcontrol:
3950 WL_SCAN_COMPLETED = const (2 )
4051 WL_CONNECTED = const (3 )
4152
53+ SOCKET_CLOSED = const (0 )
54+ SOCKET_LISTEN = const (1 )
55+ SOCKET_SYN_SENT = const (2 )
56+ SOCKET_SYN_RCVD = const (3 )
57+ SOCKET_ESTABLISHED = const (4 )
58+ SOCKET_FIN_WAIT_1 = const (5 )
59+ SOCKET_FIN_WAIT_2 = const (6 )
60+ SOCKET_CLOSE_WAIT = const (7 )
61+ SOCKET_CLOSING = const (8 )
62+ SOCKET_LAST_ACK = const (9 )
63+ SOCKET_TIME_WAIT = const (10 )
64+
65+ TCP_MODE = const (0 )
66+
4267 def __init__ (self , spi , cs_pin , ready_pin , reset_pin , gpio0_pin , * , debug = False ):
4368 self ._debug = debug
4469 self ._buffer = bytearray (10 )
@@ -96,7 +121,7 @@ def wait_for_slave_select(self):
96121 self .wait_for_slave_ready ()
97122 self .spi_slave_select ()
98123
99- def send_command (self , cmd , params = None ):
124+ def send_command (self , cmd , params = None , * , param_len_16 = False ):
100125 if not params :
101126 params = []
102127 packet = []
@@ -105,8 +130,12 @@ def send_command(self, cmd, params=None):
105130 packet .append (len (params ))
106131
107132 # handle parameters here
108- for param in params :
109- packet .append (len (param ))
133+ for i , param in enumerate (params ):
134+ if self ._debug :
135+ print ("sending param #%d is %d bytes long" % (i , len (param )))
136+ if param_len_16 :
137+ packet .append ((len (param ) >> 8 ) & 0xFF )
138+ packet .append (len (param ) & 0xFF )
110139 packet += (param )
111140
112141 packet .append (END_CMD )
@@ -167,8 +196,8 @@ def wait_response_cmd(self, cmd, num_responses=None):
167196 self .slave_deselect ()
168197 return responses
169198
170- def send_command_get_response (self , cmd , params = None , * , reply_params = 1 ):
171- self .send_command (cmd , params )
199+ def send_command_get_response (self , cmd , params = None , * , reply_params = 1 , param_len_16 = False ):
200+ self .send_command (cmd , params , param_len_16 = param_len_16 )
172201 return self .wait_response_cmd (cmd , reply_params )
173202
174203 @property
@@ -275,7 +304,13 @@ def connect_AP(self, ssid, password):
275304 def pretty_ip (self , ip ):
276305 return "%d.%d.%d.%d" % (ip [0 ], ip [1 ], ip [2 ], ip [3 ])
277306
307+ def unpretty_ip (self , ip ):
308+ octets = [int (x ) for x in ip .split ('.' )]
309+ return bytes (octets )
310+
278311 def get_host_by_name (self , hostname ):
312+ if self ._debug :
313+ print ("*** Get host by name" )
279314 if isinstance (hostname , str ):
280315 hostname = bytes (hostname , 'utf-8' )
281316 resp = self .send_command_get_response (REQ_HOST_BY_NAME_CMD , [hostname ])
@@ -285,10 +320,57 @@ def get_host_by_name(self, hostname):
285320 return resp [0 ]
286321
287322 def ping (self , dest , ttl = 250 ):
288- self ._debug = True
289323 if isinstance (dest , str ): # convert to IP address
290324 dest = self .get_host_by_name (dest )
291325 # ttl must be between 0 and 255
292326 ttl = max (0 , min (ttl , 255 ))
293327 resp = self .send_command_get_response (PING_CMD , [dest , [ttl ]])
294328 return struct .unpack ('<H' , resp [0 ])[0 ]
329+
330+ def get_socket (self ):
331+ if self ._debug :
332+ print ("*** Get socket" )
333+ resp = self .send_command_get_response (GET_SOCKET_CMD )
334+ resp = resp [0 ][0 ]
335+ if resp == 255 :
336+ raise RuntimeError ("No sockets available" )
337+ return resp
338+
339+ def start_client (self , dest , ip , port , socket_num , conn_mode = TCP_MODE ):
340+ if self ._debug :
341+ print ("*** Start Client" )
342+ port_param = struct .pack ('>H' , port )
343+ resp = self .send_command_get_response (START_CLIENT_TCP_CMD ,
344+ [ip , port_param ,
345+ [socket_num ], [conn_mode ]])
346+ if resp [0 ][0 ] != 1 :
347+ raise RuntimeError ("Could not connect to remote server" )
348+
349+ def socket_status (self , socket_num ):
350+ resp = self .send_command_get_response (GET_CLIENT_STATE_TCP_CMD , [[socket_num ]])
351+ return resp [0 ][0 ]
352+
353+ def socket_connected (self , socket_num ):
354+ return self .socket_status (socket_num ) == SOCKET_ESTABLISHED
355+
356+ def socket_write (self , socket_num , buffer ):
357+ resp = self .send_command_get_response (SEND_DATA_TCP_CMD ,
358+ [[socket_num ], buffer ],
359+ param_len_16 = True )
360+ print (resp )
361+
362+ def socket_connect (self , dest , port ):
363+ if self ._debug :
364+ print ("*** Socket connect" )
365+ if isinstance (dest , str ): # convert to IP address
366+ dest = self .get_host_by_name (dest )
367+ self .sock_num = self .get_socket ()
368+ print ("Socket #%d" % self .sock_num )
369+
370+ self .start_client (dest , dest , port , self .sock_num )
371+ times = time .monotonic ()
372+ while (time .monotonic () - times ) < 3 : # wait 3 seconds
373+ if self .socket_connected (self .sock_num ):
374+ return
375+ time .sleep (0.01 )
376+ raise RuntimeError ("Failed to establish connection" )
0 commit comments