diff --git a/adafruit_espatcontrol/adafruit_espatcontrol.py b/adafruit_espatcontrol/adafruit_espatcontrol.py index db2138f..db800e5 100644 --- a/adafruit_espatcontrol/adafruit_espatcontrol.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol.py @@ -70,8 +70,10 @@ class ESP_ATcontrol: MODE_SOFTAP = 2 MODE_SOFTAPSTATION = 3 TYPE_TCP = "TCP" + TCP_MODE = "TCP" TYPE_UDP = "UDP" TYPE_SSL = "SSL" + TLS_MODE = "SSL" STATUS_APCONNECTED = 2 STATUS_SOCKETOPEN = 3 STATUS_SOCKETCLOSED = 4 diff --git a/adafruit_espatcontrol/adafruit_espatcontrol_requests.py b/adafruit_espatcontrol/adafruit_espatcontrol_requests.py deleted file mode 100644 index 4c7ce1a..0000000 --- a/adafruit_espatcontrol/adafruit_espatcontrol_requests.py +++ /dev/null @@ -1,189 +0,0 @@ -""" -adapted from https://github.com/micropython/micropython-lib/tree/master/urequests - -micropython-lib consists of multiple modules from different sources and -authors. Each module comes under its own licensing terms. Short name of -a license can be found in a file within a module directory (usually -metadata.txt or setup.py). Complete text of each license used is provided -at https://github.com/micropython/micropython-lib/blob/master/LICENSE - -author='Paul Sokolovsky' -license='MIT' -""" - -# pylint: disable=no-name-in-module - -import gc -import adafruit_espatcontrol.adafruit_espatcontrol_socket as socket - -_the_interface = None # pylint: disable=invalid-name -def set_interface(iface): - """Helper to set the global internet interface""" - global _the_interface # pylint: disable=invalid-name, global-statement - _the_interface = iface - socket.set_interface(iface) - -class Response: - """The response from a request, contains all the headers/content""" - headers = {} - encoding = None - - def __init__(self, f): - self.raw = f - self.encoding = "utf-8" - self._cached = None - self.status_code = None - self.reason = None - - def close(self): - """Close, delete and collect the response data""" - if self.raw: - self.raw.close() - del self.raw - del self._cached - gc.collect() - - @property - def content(self): - """The HTTP content direct from the socket, as bytes""" - if self._cached is None: - try: - self._cached = self.raw.read() - finally: - self.raw.close() - self.raw = None - return self._cached - - @property - def text(self): - """The HTTP content, encoded into a string according to the HTTP - header encoding""" - return str(self.content, self.encoding) - - def json(self): - """The HTTP content, parsed into a json dictionary""" - try: - import json as json_module - except ImportError: - import ujson as json_module - return json_module.loads(self.content) - - -# pylint: disable=too-many-branches, too-many-statements, unused-argument, too-many-arguments, too-many-locals -def request(method, url, data=None, json=None, headers=None, stream=None): - """Perform an HTTP request to the given url which we will parse to determine - whether to use SSL ('https://') or not. We can also send some provided 'data' - or a json dictionary which we will stringify. 'headers' is optional HTTP headers - sent along. 'stream' is unused in this implementation""" - global _the_interface # pylint: disable=global-statement, invalid-name - - if not headers: - headers = {} - - try: - proto, dummy, host, path = url.split("/", 3) - except ValueError: - proto, dummy, host = url.split("/", 2) - path = "" - if proto == "http:": - port = 80 - elif proto == "https:": - port = 443 - else: - raise ValueError("Unsupported protocol: " + proto) - - if ":" in host: - host, port = host.split(":", 1) - port = int(port) - - addr_info = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)[0] - sock = socket.socket(addr_info[0], addr_info[1], addr_info[2]) - resp = Response(sock) # our response - - try: - conntype = _the_interface.TYPE_TCP - if proto == "https:": - conntype = _the_interface.TYPE_SSL - sock.connect(addr_info[-1], conntype) - sock.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) - if "Host" not in headers: - sock.write(b"Host: %s\r\n" % host) - if "User-Agent" not in headers: - sock.write(b"User-Agent: Adafruit CircuitPython\r\n") - # Iterate over keys to avoid tuple alloc - for k in headers: - sock.write(k) - sock.write(b": ") - sock.write(headers[k]) - sock.write(b"\r\n") - if json is not None: - assert data is None - try: - import json as json_module - except ImportError: - import ujson as json_module - data = json_module.dumps(json) - sock.write(b"Content-Type: application/json\r\n") - if data: - sock.write(b"Content-Length: %d\r\n" % len(data)) - sock.write(b"\r\n") - if data: - sock.write(bytes(data, 'utf-8')) - - line = sock.readline() - line = line.split(None, 2) - status = int(line[1]) - reason = "" - if len(line) > 2: - reason = line[2].rstrip() - while True: - line = sock.readline() - if not line or line == b"\r\n": - break - - title, content = line.split(b': ', 1) - if title and content: - title = str(title.lower(), 'utf-8') - content = str(content, 'utf-8') - resp.headers[title] = content - - if line.startswith(b"Transfer-Encoding:"): - if b"chunked" in line: - raise ValueError("Unsupported " + line) - elif line.startswith(b"Location:") and not 200 <= status <= 299: - raise NotImplementedError("Redirects not yet supported") - - except OSError: - sock.close() - print("how did we get here") - raise - - resp.status_code = status - resp.reason = reason - return resp -# pylint: enable=too-many-branches, too-many-statements, unused-argument -# pylint: enable=too-many-arguments, too-many-locals - -def head(url, **kw): - """Send HTTP HEAD request""" - return request("HEAD", url, **kw) - -def get(url, **kw): - """Send HTTP GET request""" - return request("GET", url, **kw) - -def post(url, **kw): - """Send HTTP POST request""" - return request("POST", url, **kw) - -def put(url, **kw): - """Send HTTP PUT request""" - return request("PUT", url, **kw) - -def patch(url, **kw): - """Send HTTP PATCH request""" - return request("PATCH", url, **kw) - -def delete(url, **kw): - """Send HTTP DELETE request""" - return request("DELETE", url, **kw) diff --git a/adafruit_espatcontrol/adafruit_espatcontrol_socket.py b/adafruit_espatcontrol/adafruit_espatcontrol_socket.py index cecbb79..9286e40 100644 --- a/adafruit_espatcontrol/adafruit_espatcontrol_socket.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol_socket.py @@ -31,6 +31,7 @@ def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None): if type != SOCK_STREAM: raise RuntimeError("Only SOCK_STREAM type supported") self._buffer = b'' + self.settimeout(0) def connect(self, address, conntype=None): """Connect the socket to the 'address' (which should be dotted quad IP). 'conntype' @@ -40,7 +41,8 @@ def connect(self, address, conntype=None): raise RuntimeError("Failed to connect to host", host) self._buffer = b'' - def write(self, data): # pylint: disable=no-self-use + + def send(self, data): # pylint: disable=no-self-use """Send some data to the socket""" _the_interface.socket_send(data) @@ -53,12 +55,12 @@ def readline(self): firstline, self._buffer = self._buffer.split(b'\r\n', 1) return firstline - def read(self, num=0): + def recv(self, num=0): """Read up to 'num' bytes from the socket, this may be buffered internally! If 'num' isnt specified, return everything in the buffer.""" if num == 0: # read as much as we can - ret = self._buffer + _the_interface.socket_receive(timeout=1) + ret = self._buffer + _the_interface.socket_receive(timeout=self._timeout) self._buffer = b'' else: ret = self._buffer[:num] @@ -68,6 +70,11 @@ def read(self, num=0): def close(self): """Close the socket, after reading whatever remains""" # read whatever's left - self._buffer = self._buffer + _the_interface.socket_receive(timeout=1) + self._buffer = self._buffer + _the_interface.socket_receive(timeout=self._timeout) _the_interface.socket_disconnect() + + def settimeout(self, value): + """Set the read timeout for sockets, if value is 0 it will block""" + self._timeout = value + # pylint: enable=unused-argument, redefined-builtin, invalid-name diff --git a/adafruit_espatcontrol/adafruit_espatcontrol_wifimanager.py b/adafruit_espatcontrol/adafruit_espatcontrol_wifimanager.py index 3136801..2fd39c8 100755 --- a/adafruit_espatcontrol/adafruit_espatcontrol_wifimanager.py +++ b/adafruit_espatcontrol/adafruit_espatcontrol_wifimanager.py @@ -31,7 +31,8 @@ # pylint: disable=no-name-in-module -import adafruit_espatcontrol.adafruit_espatcontrol_requests as requests +import adafruit_espatcontrol.adafruit_espatcontrol_socket as socket +import adafruit_requests as requests class ESPAT_WiFiManager: """ @@ -50,7 +51,7 @@ def __init__(self, esp, secrets, status_pixel=None, attempts=2): self.debug = False self.secrets = secrets self.attempts = attempts - requests.set_interface(self._esp) + requests.set_socket(socket, esp) self.statuspix = status_pixel self.pixel_status(0) diff --git a/docs/api.rst b/docs/api.rst index 659ccdf..0698504 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -7,8 +7,5 @@ .. automodule:: adafruit_espatcontrol.adafruit_espatcontrol :members: -.. automodule:: adafruit_espatcontrol.adafruit_espatcontrol_requests - :members: - .. automodule:: adafruit_espatcontrol.adafruit_espatcontrol_socket :members: diff --git a/examples/esp_atcontrol_aio_post.py b/examples/esp_atcontrol_aio_post.py index b556649..d418bdd 100644 --- a/examples/esp_atcontrol_aio_post.py +++ b/examples/esp_atcontrol_aio_post.py @@ -2,16 +2,11 @@ import board import busio from digitalio import DigitalInOut +from digitalio import Direction # ESP32 AT from adafruit_espatcontrol import adafruit_espatcontrol, adafruit_espatcontrol_wifimanager -#Use below for Most Boards -import neopixel -status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) # Uncomment for Most Boards -#Uncomment below for ItsyBitsy M4# -#import adafruit_dotstar as dotstar -#status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) # Get wifi details and more from a secrets.py file @@ -22,24 +17,16 @@ raise -# With a Metro or Feather M4 -uart = busio.UART(board.TX, board.RX, timeout=0.1) -resetpin = DigitalInOut(board.D5) -rtspin = DigitalInOut(board.D6) - # With a Particle Argon -""" RX = board.ESP_TX TX = board.ESP_RX resetpin = DigitalInOut(board.ESP_WIFI_EN) rtspin = DigitalInOut(board.ESP_CTS) uart = busio.UART(TX, RX, timeout=0.1) esp_boot = DigitalInOut(board.ESP_BOOT_MODE) -from digitalio import Direction esp_boot.direction = Direction.OUTPUT esp_boot.value = True -""" - +status_light = None print("ESP AT commands") esp = adafruit_espatcontrol.ESP_ATcontrol(uart, 115200, @@ -58,7 +45,7 @@ response = wifi.post( "https://io.adafruit.com/api/v2/"+secrets['aio_username']+"/feeds/"+feed+"/data", json=payload, - headers={bytes("X-AIO-KEY", "utf-8"):bytes(secrets['aio_key'], "utf-8")}) + headers={"X-AIO-KEY":secrets['aio_key']}) print(response.json()) response.close() counter = counter + 1 diff --git a/examples/esp_atcontrol_cheerlights.py b/examples/esp_atcontrol_cheerlights.py index 5f014ea..687ae10 100644 --- a/examples/esp_atcontrol_cheerlights.py +++ b/examples/esp_atcontrol_cheerlights.py @@ -2,6 +2,7 @@ import board import busio from digitalio import DigitalInOut +from digitalio import Direction # ESP32 SPI from adafruit_espatcontrol import adafruit_espatcontrol, adafruit_espatcontrol_wifimanager @@ -19,30 +20,17 @@ raise -#Use below for Most Boards -status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) # Uncomment for Most Boards -#Uncomment below for ItsyBitsy M4 -#import adafruit_dotstar as dotstar -#status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) - -# With a Metro or Feather M4 -uart = busio.UART(board.TX, board.RX, timeout=0.1) -resetpin = DigitalInOut(board.D5) -rtspin = DigitalInOut(board.D6) # With a Particle Argon -""" RX = board.ESP_TX TX = board.ESP_RX resetpin = DigitalInOut(board.ESP_WIFI_EN) rtspin = DigitalInOut(board.ESP_CTS) uart = busio.UART(TX, RX, timeout=0.1) esp_boot = DigitalInOut(board.ESP_BOOT_MODE) -from digitalio import Direction esp_boot.direction = Direction.OUTPUT esp_boot.value = True -""" - +status_light = None print("ESP AT commands") esp = adafruit_espatcontrol.ESP_ATcontrol(uart, 115200, diff --git a/examples/esp_atcontrol_countviewer.py b/examples/esp_atcontrol_countviewer.py index 1518c2d..d223e36 100644 --- a/examples/esp_atcontrol_countviewer.py +++ b/examples/esp_atcontrol_countviewer.py @@ -8,10 +8,12 @@ import board import busio from digitalio import DigitalInOut +from digitalio import Direction +import neopixel +import adafruit_espatcontrol.adafruit_espatcontrol_socket as socket from adafruit_espatcontrol import adafruit_espatcontrol -from adafruit_espatcontrol import adafruit_espatcontrol_requests as requests from adafruit_ht16k33 import segments -import neopixel +import adafruit_requests as requests # Get wifi details and more from a secrets.py file try: @@ -58,24 +60,16 @@ #"screen_names=adafruit" #DATA_LOCATION = [0, "followers_count"] -# on metro_m4 -uart = busio.UART(board.TX, board.RX, timeout=0.1) -resetpin = DigitalInOut(board.D5) -rtspin = DigitalInOut(board.D6) - # With a Particle Argon -""" RX = board.ESP_TX TX = board.ESP_RX resetpin = DigitalInOut(board.ESP_WIFI_EN) rtspin = DigitalInOut(board.ESP_CTS) uart = busio.UART(TX, RX, timeout=0.1) esp_boot = DigitalInOut(board.ESP_BOOT_MODE) -from digitalio import Direction esp_boot.direction = Direction.OUTPUT esp_boot.value = True -""" @@ -85,7 +79,7 @@ rts_pin=rtspin, debug=False) esp.hard_reset() -requests.set_interface(esp) +requests.set_socket(socket, esp) # Create the I2C interface. i2c = busio.I2C(board.SCL, board.SDA) diff --git a/examples/esp_atcontrol_localtime.py b/examples/esp_atcontrol_localtime.py index cd16933..ab10b96 100644 --- a/examples/esp_atcontrol_localtime.py +++ b/examples/esp_atcontrol_localtime.py @@ -2,18 +2,11 @@ import board import busio from digitalio import DigitalInOut +from digitalio import Direction import rtc -# ESP32 SPI from adafruit_espatcontrol import adafruit_espatcontrol, adafruit_espatcontrol_wifimanager -#Use below for Most Boards -import neopixel -status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) # Uncomment for Most Boards -#Uncomment below for ItsyBitsy M4 -#import adafruit_dotstar as dotstar -#status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) - # Get wifi details and more from a secrets.py file try: @@ -24,23 +17,17 @@ -# With a Metro or Feather M4 -uart = busio.UART(board.TX, board.RX, timeout=0.1) -resetpin = DigitalInOut(board.D5) -rtspin = DigitalInOut(board.D6) # With a Particle Argon -""" RX = board.ESP_TX TX = board.ESP_RX resetpin = DigitalInOut(board.ESP_WIFI_EN) rtspin = DigitalInOut(board.ESP_CTS) uart = busio.UART(TX, RX, timeout=0.1) esp_boot = DigitalInOut(board.ESP_BOOT_MODE) -from digitalio import Direction esp_boot.direction = Direction.OUTPUT esp_boot.value = True -""" +status_light = None print("ESP AT commands") diff --git a/examples/esp_atcontrol_simpletest.py b/examples/esp_atcontrol_simpletest.py index a9ce228..5742cb0 100644 --- a/examples/esp_atcontrol_simpletest.py +++ b/examples/esp_atcontrol_simpletest.py @@ -2,6 +2,7 @@ import board import busio from digitalio import DigitalInOut +from digitalio import Direction from adafruit_espatcontrol import adafruit_espatcontrol @@ -13,23 +14,16 @@ print("WiFi secrets are kept in secrets.py, please add them there!") raise -# With a Metro or Feather M4 -uart = busio.UART(board.TX, board.RX, timeout=0.1) -resetpin = DigitalInOut(board.D5) -rtspin = DigitalInOut(board.D6) # With a Particle Argon -""" RX = board.ESP_TX TX = board.ESP_RX resetpin = DigitalInOut(board.ESP_WIFI_EN) rtspin = DigitalInOut(board.ESP_CTS) uart = busio.UART(TX, RX, timeout=0.1) esp_boot = DigitalInOut(board.ESP_BOOT_MODE) -from digitalio import Direction esp_boot.direction = Direction.OUTPUT esp_boot.value = True -""" print("ESP AT commands") diff --git a/examples/esp_atcontrol_webclient.py b/examples/esp_atcontrol_webclient.py index 409599e..2d1bebc 100644 --- a/examples/esp_atcontrol_webclient.py +++ b/examples/esp_atcontrol_webclient.py @@ -2,10 +2,11 @@ import board import busio from digitalio import DigitalInOut - -# ESP32 AT +from digitalio import Direction +import adafruit_espatcontrol.adafruit_espatcontrol_socket as socket from adafruit_espatcontrol import adafruit_espatcontrol -from adafruit_espatcontrol import adafruit_espatcontrol_requests as requests +import adafruit_requests as requests + # Get wifi details and more from a secrets.py file try: @@ -15,23 +16,16 @@ raise -# With a Metro or Feather M4 -uart = busio.UART(board.TX, board.RX, timeout=0.1) -resetpin = DigitalInOut(board.D5) -rtspin = DigitalInOut(board.D6) - # With a Particle Argon -""" RX = board.ESP_TX TX = board.ESP_RX resetpin = DigitalInOut(board.ESP_WIFI_EN) rtspin = DigitalInOut(board.ESP_CTS) uart = busio.UART(TX, RX, timeout=0.1) esp_boot = DigitalInOut(board.ESP_BOOT_MODE) -from digitalio import Direction esp_boot.direction = Direction.OUTPUT esp_boot.value = True -""" + print("ESP AT commands") @@ -44,7 +38,7 @@ print("Resetting ESP module") esp.hard_reset() -requests.set_interface(esp) +requests.set_socket(socket, esp) while True: try: