20
20
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
# THE SOFTWARE.
22
22
"""
23
- `adafruit_espatcontrol`
23
+ `adafruit_espatcontrol.adafruit_espatcontrol `
24
24
====================================================
25
25
26
26
Use the ESP AT command sent to communicate with the Interwebs.
@@ -60,20 +60,6 @@ class OKError(Exception):
60
60
"""The exception thrown when we didn't get acknowledgement to an AT command"""
61
61
pass
62
62
63
- class ESP_ATcontrol_socket :
64
- """A 'socket' compatible interface thru the ESP AT command set"""
65
- def __init__ (self , esp ):
66
- self ._esp = esp
67
-
68
- def getaddrinfo (self , host , port , # pylint: disable=too-many-arguments
69
- family = 0 , socktype = 0 , proto = 0 , flags = 0 ): # pylint: disable=unused-argument
70
- """Given a hostname and a port name, return a 'socket.getaddrinfo'
71
- compatible list of tuples. Honestly, we ignore anything but host & port"""
72
- if not isinstance (port , int ):
73
- raise RuntimeError ("port must be an integer" )
74
- ipaddr = self ._esp .nslookup (host )
75
- return [(family , socktype , proto , '' , (ipaddr , port ))]
76
-
77
63
class ESP_ATcontrol :
78
64
"""A wrapper for AT commands to a connected ESP8266 or ESP32 module to do
79
65
some very basic internetting. The ESP module must be pre-programmed with
@@ -147,55 +133,18 @@ def begin(self):
147
133
except OKError :
148
134
pass #retry
149
135
150
- def request_url (self , url , ssl = False , request_type = "GET" ):
151
- """Send an HTTP request to the URL. If the URL starts with https://
152
- we will force SSL and use port 443. Otherwise, you can select whether
153
- you want ssl by passing in a flag."""
154
- if url .startswith ("https://" ):
155
- ssl = True
156
- url = url [8 :]
157
- if url .startswith ("http://" ):
158
- url = url [7 :]
159
- domain , path = url .split ('/' , 1 )
160
- path = '/' + path
161
- port = 80
162
- conntype = self .TYPE_TCP
163
- if ssl :
164
- conntype = self .TYPE_SSL
165
- port = 443
166
- if not self .socket_connect (conntype , domain , port , keepalive = 10 , retries = 3 ):
167
- raise RuntimeError ("Failed to connect to host" )
168
- request = request_type + " " + path + " HTTP/1.1\r \n "
169
- request += "Host: " + domain + "\r \n "
170
- request += "User-Agent: " + self .USER_AGENT + "\r \n "
171
- request += "\r \n "
172
- try :
173
- self .socket_send (bytes (request , 'utf-8' ))
174
- except RuntimeError :
175
- raise
176
-
177
- reply = self .socket_receive (timeout = 3 ).split (b'\r \n ' )
178
- if self ._debug :
179
- print (reply )
180
- try :
181
- headerbreak = reply .index (b'' )
182
- except ValueError :
183
- raise RuntimeError ("Reponse wasn't valid HTML" )
184
- header = reply [0 :headerbreak ]
185
- data = b'\r \n ' .join (reply [headerbreak + 1 :]) # put back the way it was
186
- self .socket_disconnect ()
187
- return (header , data )
188
-
189
136
def connect (self , settings ):
190
137
"""Repeatedly try to connect to an access point with the details in
191
138
the passed in 'settings' dictionary. Be sure 'ssid' and 'password' are
192
139
defined in the settings dict! If 'timezone' is set, we'll also configure
193
140
SNTP"""
194
141
# Connect to WiFi if not already
142
+ retries = 3
195
143
while True :
196
144
try :
197
- if not self ._initialized :
145
+ if not self ._initialized or retries == 0 :
198
146
self .begin ()
147
+ retries = 3
199
148
AP = self .remote_AP # pylint: disable=invalid-name
200
149
print ("Connected to" , AP [0 ])
201
150
if AP [0 ] != settings ['ssid' ]:
@@ -210,6 +159,7 @@ def connect(self, settings):
210
159
return # yay!
211
160
except (RuntimeError , OKError ) as exp :
212
161
print ("Failed to connect, retrying\n " , exp )
162
+ retries -= 1
213
163
continue
214
164
215
165
# *************************** SOCKET SETUP ****************************
@@ -223,10 +173,6 @@ def cipmux(self):
223
173
return int (reply [8 :])
224
174
raise RuntimeError ("Bad response to CIPMUX?" )
225
175
226
- def socket (self ):
227
- """Create a 'socket' object"""
228
- return ESP_ATcontrol_socket (self )
229
-
230
176
def socket_connect (self , conntype , remote , remote_port , * , keepalive = 10 , retries = 1 ):
231
177
"""Open a socket. conntype can be TYPE_TCP, TYPE_UDP, or TYPE_SSL. Remote
232
178
can be an IP address or DNS (we'll do the lookup for you. Remote port
@@ -283,10 +229,11 @@ def socket_send(self, buffer, timeout=1):
283
229
return True
284
230
285
231
def socket_receive (self , timeout = 5 ):
286
- # pylint: disable=too-many-nested-blocks
232
+ # pylint: disable=too-many-nested-blocks, too-many-branches
287
233
"""Check for incoming data over the open socket, returns bytes"""
288
234
incoming_bytes = None
289
- bundle = b''
235
+ bundle = []
236
+ toread = 0
290
237
gc .collect ()
291
238
i = 0 # index into our internal packet
292
239
stamp = time .monotonic ()
@@ -312,6 +259,9 @@ def socket_receive(self, timeout=5):
312
259
except ValueError :
313
260
raise RuntimeError ("Parsing error during receive" , ipd )
314
261
i = 0 # reset the input buffer now that we know the size
262
+ elif i > 20 :
263
+ i = 0 # Hmm we somehow didnt get a proper +IPD packet? start over
264
+
315
265
else :
316
266
self .hw_flow (False ) # stop the flow
317
267
# read as much as we can!
@@ -322,11 +272,22 @@ def socket_receive(self, timeout=5):
322
272
if i == incoming_bytes :
323
273
#print(self._ipdpacket[0:i])
324
274
gc .collect ()
325
- bundle += self ._ipdpacket [0 :i ]
275
+ bundle .append (self ._ipdpacket [0 :i ])
276
+ gc .collect ()
326
277
i = incoming_bytes = 0
327
278
else : # no data waiting
328
279
self .hw_flow (True ) # start the floooow
329
- return bundle
280
+ totalsize = sum ([len (x ) for x in bundle ])
281
+ ret = bytearray (totalsize )
282
+ i = 0
283
+ for x in bundle :
284
+ for char in x :
285
+ ret [i ] = char
286
+ i += 1
287
+ for x in bundle :
288
+ del x
289
+ gc .collect ()
290
+ return ret
330
291
331
292
def socket_disconnect (self ):
332
293
"""Close any open socket, if there is one"""
@@ -371,6 +332,7 @@ def is_connected(self):
371
332
self .begin ()
372
333
try :
373
334
self .echo (False )
335
+ self .baudrate = self .baudrate
374
336
stat = self .status
375
337
if stat in (self .STATUS_APCONNECTED ,
376
338
self .STATUS_SOCKETOPEN ,
0 commit comments