diff --git a/README.rst b/README.rst index cdd6f51..472c8d2 100644 --- a/README.rst +++ b/README.rst @@ -39,52 +39,3 @@ Contributions are welcome! Please read our `Code of Conduct `_ before contributing to help this project stay welcoming. -Building locally -================ - -Zip release files ------------------ - -To build this library locally you'll need to install the -`circuitpython-build-tools `_ package. - -.. code-block:: shell - - python3 -m venv .env - source .env/bin/activate - pip install circuitpython-build-tools - -Once installed, make sure you are in the virtual environment: - -.. code-block:: shell - - source .env/bin/activate - -Then run the build: - -.. code-block:: shell - - circuitpython-build-bundles --filename_prefix adafruit-circuitpython-pyportal --library_location . - -Sphinx documentation ------------------------ - -Sphinx is used to build the documentation based on rST files and comments in the code. First, -install dependencies (feel free to reuse the virtual environment from above): - -.. code-block:: shell - - python3 -m venv .env - source .env/bin/activate - pip install Sphinx sphinx-rtd-theme - -Now, once you have the virtual environment activated: - -.. code-block:: shell - - cd docs - sphinx-build -E -W -b html . _build/html - -This will output the documentation to ``docs/_build/html``. Open the index.html in your browser to -view them. It will also (due to -W) error out on any warning like Travis will. This is a good way to -locally verify it will pass. diff --git a/adafruit_pyportal.py b/adafruit_pyportal.py index a3daa01..4985a34 100644 --- a/adafruit_pyportal.py +++ b/adafruit_pyportal.py @@ -50,24 +50,32 @@ import busio from digitalio import DigitalInOut import pulseio -import adafruit_touchscreen import neopixel +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager +import adafruit_esp32spi.adafruit_esp32spi_socket as socket +import adafruit_requests as requests +import storage +import displayio +import audioio +import rtc +import supervisor +from adafruit_bitmap_font import bitmap_font +from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError +import adafruit_sdcard + + + +if hasattr(board, 'TOUCH_XL'): + import adafruit_touchscreen +elif hasattr(board, 'BUTTON_CLOCK'): + from adafruit_cursorcontrol.cursorcontrol import Cursor + from adafruit_cursorcontrol.cursorcontrol_cursormanager import CursorManager -from adafruit_esp32spi import adafruit_esp32spi -import adafruit_esp32spi.adafruit_esp32spi_requests as requests try: from adafruit_display_text.text_area import TextArea # pylint: disable=unused-import print("*** WARNING ***\nPlease update your library bundle to the latest 'adafruit_display_text' version as we've deprecated 'text_area' in favor of 'label'") # pylint: disable=line-too-long except ImportError: from adafruit_display_text.Label import Label -from adafruit_bitmap_font import bitmap_font - -import storage -import adafruit_sdcard -import displayio -import audioio -import rtc -import supervisor try: from secrets import secrets @@ -162,7 +170,10 @@ def __init__(self, *, url=None, headers=None, json_path=None, regexp_path=None, self._debug = debug try: - self._backlight = pulseio.PWMOut(board.TFT_BACKLIGHT) # pylint: disable=no-member + if hasattr(board, 'TFT_BACKLIGHT'): + self._backlight = pulseio.PWMOut(board.TFT_BACKLIGHT) # pylint: disable=no-member + elif hasattr(board, 'TFT_LITE'): + self._backlight = pulseio.PWMOut(board.TFT_LITE) # pylint: disable=no-member except ValueError: self._backlight = None self.set_backlight(1.0) # turn on backlight @@ -222,7 +233,12 @@ def __init__(self, *, url=None, headers=None, json_path=None, regexp_path=None, self._speaker_enable = DigitalInOut(board.SPEAKER_ENABLE) self._speaker_enable.switch_to_output(False) - self.audio = audioio.AudioOut(board.AUDIO_OUT) + if hasattr(board, 'AUDIO_OUT'): + self.audio = audioio.AudioOut(board.AUDIO_OUT) + elif hasattr(board, 'SPEAKER'): + self.audio = audioio.AudioOut(board.SPEAKER) + else: + raise AttributeError('Board does not have a builtin speaker!') try: self.play_file("pyportal_startup.wav") except OSError: @@ -258,11 +274,14 @@ def __init__(self, *, url=None, headers=None, json_path=None, regexp_path=None, self._esp.reset() else: raise RuntimeError("Was not able to find ESP32") - requests.set_interface(self._esp) + requests.set_socket(socket, self._esp) if url and not self._uselocal: self._connect_esp() + if self._debug: + print("My IP address is", self._esp.pretty_ip(self._esp.ip_address)) + # set the default background self.set_background(self._default_bg) board.DISPLAY.show(self.splash) @@ -342,20 +361,35 @@ def __init__(self, *, url=None, headers=None, json_path=None, regexp_path=None, self._image_position = (0, 0) # default to top corner if not self._image_resize: self._image_resize = (320, 240) # default to full screen + if hasattr(board, 'TOUCH_XL'): + if self._debug: + print("Init touchscreen") + # pylint: disable=no-member + self.touchscreen = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR, + board.TOUCH_YD, board.TOUCH_YU, + calibration=((5200, 59000), + (5800, 57000)), + size=(320, 240)) + # pylint: enable=no-member + + self.set_backlight(1.0) # turn on backlight + elif hasattr(board, 'BUTTON_CLOCK'): + if self._debug: + print("Init cursor") + self.mouse_cursor = Cursor(board.DISPLAY, display_group=self.splash, cursor_speed=8) + self.mouse_cursor.hide() + self.cursor = CursorManager(self.mouse_cursor) + else: + raise AttributeError('PyPortal module requires either a touchscreen or gamepad.') - if self._debug: - print("Init touchscreen") - # pylint: disable=no-member - self.touchscreen = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR, - board.TOUCH_YD, board.TOUCH_YU, - calibration=((5200, 59000), - (5800, 57000)), - size=(320, 240)) - # pylint: enable=no-member + gc.collect() - self.set_backlight(1.0) # turn on backlight + def set_headers(self, headers): + """Set the headers used by fetch(). - gc.collect() + :param headers: The new header dictionary + """ + self._headers = headers def set_background(self, file_or_color, position=None): """The background image to a bitmap file. @@ -662,6 +696,47 @@ def image_converter_url(image_url, width, height, color_depth=16): width, height, color_depth, image_url) + def push_to_io(self, feed_key, data): + # pylint: disable=line-too-long + """Push data to an adafruit.io feed + + :param str feed_key: Name of feed key to push data to. + :param data: data to send to feed + + """ + # pylint: enable=line-too-long + + try: + aio_username = secrets['aio_username'] + aio_key = secrets['aio_key'] + except KeyError: + raise KeyError("Adafruit IO secrets are kept in secrets.py, please add them there!\n\n") + + wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(self._esp, secrets, None) + io_client = IO_HTTP(aio_username, aio_key, wifi) + + while True: + try: + feed_id = io_client.get_feed(feed_key) + except AdafruitIO_RequestError: + # If no feed exists, create one + feed_id = io_client.create_new_feed(feed_key) + except RuntimeError as exception: + print("An error occured, retrying! 1 -", exception) + continue + break + + while True: + try: + io_client.send_data(feed_id['key'], data) + except RuntimeError as exception: + print("An error occured, retrying! 2 -", exception) + continue + except NameError as exception: + print(feed_id['key'], data, exception) + continue + break + def fetch(self, refresh_url=None): """Fetch data from the url we initialized with, perfom any parsing, and display text or graphics. This function does pretty much everything diff --git a/docs/conf.py b/docs/conf.py index 355f02b..ba65728 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,8 @@ autodoc_mock_imports = ["rtc", "supervisor", "pulseio", "audioio", "displayio", "neopixel", "microcontroller", "adafruit_touchscreen", "adafruit_bitmap_font", "adafruit_display_text", "adafruit_esp32spi", "secrets", - "adafruit_sdcard", "storage"] + "adafruit_sdcard", "storage", "adafruit_io", "adafruit_cursorcontrol", + "adafruit_requests"] intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'BusDevice': ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}