Skip to content

Add some of the recent improvements from PyPortal #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 6, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 73 additions & 7 deletions adafruit_matrixportal/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import os
import time
import gc
from micropython import const
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError
import adafruit_requests as requests
Expand Down Expand Up @@ -70,6 +71,14 @@
STATUS_DATA_RECEIVED = (0, 0, 100)
STATUS_OFF = (0, 0, 0)

CONTENT_TEXT = const(1)
CONTENT_JSON = const(2)
CONTENT_IMAGE = const(3)


class HttpError(Exception):
"""HTTP Specific Error"""


class Network:
"""Class representing the Adafruit RGB Matrix Portal.
Expand Down Expand Up @@ -223,9 +232,32 @@ def wget(self, url, filename, *, chunk_size=12000):
self.neo_status(STATUS_FETCHING)
response = requests.get(url, stream=True)

headers = {}
for title, content in response.headers.items():
headers[title.lower()] = content

if response.status_code == 200:
print("Reply is OK!")
self.neo_status((0, 0, 100)) # green = got data
else:
if self._debug:
if "content-length" in headers:
print("Content-Length: {}".format(int(headers["content-length"])))
if "date" in headers:
print("Date: {}".format(headers["date"]))
self.neo_status((100, 0, 0)) # red = http error
raise HttpError(
"Code {}: {}".format(
response.status_code, response.reason.decode("utf-8")
)
)

if self._debug:
print(response.headers)
content_length = int(response.headers["content-length"])
if "content-length" in headers:
content_length = int(headers["content-length"])
else:
raise RuntimeError("Content-Length missing from headers")
remaining = content_length
print("Saving data to ", filename)
stamp = time.monotonic()
Expand Down Expand Up @@ -392,8 +424,6 @@ def fetch(self, url, *, headers=None, timeout=10):
gc.collect()
response = requests.get(url, headers=headers, timeout=timeout)
gc.collect()
self.neo_status(STATUS_DATA_RECEIVED) # green = got data
print("Reply is OK!")

return response

Expand All @@ -403,10 +433,40 @@ def fetch_data(
"""Fetch data from the specified url and perfom any parsing"""
json_out = None
values = []
content_type = CONTENT_TEXT

response = self.fetch(url, headers=headers, timeout=timeout)

if json_path is not None:
headers = {}
for title, content in response.headers.items():
headers[title.lower()] = content
gc.collect()
if self._debug:
print("Headers:", headers)
if response.status_code == 200:
print("Reply is OK!")
self.neo_status(STATUS_DATA_RECEIVED) # green = got data
if "content-type" in headers:
if "image/" in headers["content-type"]:
content_type = CONTENT_IMAGE
elif "application/json" in headers["content-type"]:
content_type = CONTENT_JSON
elif "application/javascript" in headers["content-type"]:
content_type = CONTENT_JSON
else:
if self._debug:
if "content-length" in headers:
print("Content-Length: {}".format(int(headers["content-length"])))
if "date" in headers:
print("Date: {}".format(headers["date"]))
self.neo_status((100, 0, 0)) # red = http error
raise HttpError(
"Code {}: {}".format(
response.status_code, response.reason.decode("utf-8")
)
)

if content_type == CONTENT_JSON and json_path is not None:
if isinstance(json_path, (list, tuple)) and (
not json_path or not isinstance(json_path[0], (list, tuple))
):
Expand Down Expand Up @@ -436,18 +496,24 @@ def fetch_data(
raise

# extract desired text/values from json
if json_path:
if json_out and json_path:
for path in json_path:
try:
values.append(self.json_traverse(json_out, path))
except KeyError:
print(json_out)
raise
elif regexp_path:
elif content_type == CONTENT_TEXT and regexp_path:
for regexp in regexp_path:
values.append(re.search(regexp, response.text).group(1))
else:
values = response.text
if json_out:
# No path given, so return JSON as string for compatibility
import json # pylint: disable=import-outside-toplevel

values = json.dumps(response.json())
else:
values = response.text

# we're done with the requests object, lets delete it so we can do more!
json_out = None
Expand Down