|
50 | 50 | import busio
|
51 | 51 | from digitalio import DigitalInOut
|
52 | 52 | import pulseio
|
53 |
| -import adafruit_touchscreen |
54 | 53 | import neopixel
|
| 54 | +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager |
| 55 | +import adafruit_esp32spi.adafruit_esp32spi_socket as socket |
| 56 | +import adafruit_requests as requests |
| 57 | +import storage |
| 58 | +import displayio |
| 59 | +import audioio |
| 60 | +import rtc |
| 61 | +import supervisor |
| 62 | +from adafruit_bitmap_font import bitmap_font |
| 63 | +from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError |
| 64 | +import adafruit_sdcard |
| 65 | + |
| 66 | + |
| 67 | + |
| 68 | +if hasattr(board, 'TOUCH_XL'): |
| 69 | + import adafruit_touchscreen |
| 70 | +elif hasattr(board, 'BUTTON_CLOCK'): |
| 71 | + from adafruit_cursorcontrol.cursorcontrol import Cursor |
| 72 | + from adafruit_cursorcontrol.cursorcontrol_cursormanager import CursorManager |
55 | 73 |
|
56 |
| -from adafruit_esp32spi import adafruit_esp32spi |
57 |
| -import adafruit_esp32spi.adafruit_esp32spi_requests as requests |
58 | 74 | try:
|
59 | 75 | from adafruit_display_text.text_area import TextArea # pylint: disable=unused-import
|
60 | 76 | 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
|
61 | 77 | except ImportError:
|
62 | 78 | from adafruit_display_text.Label import Label
|
63 |
| -from adafruit_bitmap_font import bitmap_font |
64 |
| - |
65 |
| -import storage |
66 |
| -import adafruit_sdcard |
67 |
| -import displayio |
68 |
| -import audioio |
69 |
| -import rtc |
70 |
| -import supervisor |
71 | 79 |
|
72 | 80 | try:
|
73 | 81 | from secrets import secrets
|
@@ -165,7 +173,10 @@ def __init__(self, *, url=None, headers=None, json_path=None, regexp_path=None,
|
165 | 173 | self._debug = debug
|
166 | 174 |
|
167 | 175 | try:
|
168 |
| - self._backlight = pulseio.PWMOut(board.TFT_BACKLIGHT) # pylint: disable=no-member |
| 176 | + if hasattr(board, 'TFT_BACKLIGHT'): |
| 177 | + self._backlight = pulseio.PWMOut(board.TFT_BACKLIGHT) # pylint: disable=no-member |
| 178 | + elif hasattr(board, 'TFT_LITE'): |
| 179 | + self._backlight = pulseio.PWMOut(board.TFT_LITE) # pylint: disable=no-member |
169 | 180 | except ValueError:
|
170 | 181 | self._backlight = None
|
171 | 182 | self.set_backlight(1.0) # turn on backlight
|
@@ -225,7 +236,12 @@ def __init__(self, *, url=None, headers=None, json_path=None, regexp_path=None,
|
225 | 236 |
|
226 | 237 | self._speaker_enable = DigitalInOut(board.SPEAKER_ENABLE)
|
227 | 238 | self._speaker_enable.switch_to_output(False)
|
228 |
| - self.audio = audioio.AudioOut(board.AUDIO_OUT) |
| 239 | + if hasattr(board, 'AUDIO_OUT'): |
| 240 | + self.audio = audioio.AudioOut(board.AUDIO_OUT) |
| 241 | + elif hasattr(board, 'SPEAKER'): |
| 242 | + self.audio = audioio.AudioOut(board.SPEAKER) |
| 243 | + else: |
| 244 | + raise AttributeError('Board does not have a builtin speaker!') |
229 | 245 | try:
|
230 | 246 | self.play_file("pyportal_startup.wav")
|
231 | 247 | except OSError:
|
@@ -261,11 +277,14 @@ def __init__(self, *, url=None, headers=None, json_path=None, regexp_path=None,
|
261 | 277 | self._esp.reset()
|
262 | 278 | else:
|
263 | 279 | raise RuntimeError("Was not able to find ESP32")
|
264 |
| - requests.set_interface(self._esp) |
| 280 | + requests.set_socket(socket, self._esp) |
265 | 281 |
|
266 | 282 | if url and not self._uselocal:
|
267 | 283 | self._connect_esp()
|
268 | 284 |
|
| 285 | + if self._debug: |
| 286 | + print("My IP address is", self._esp.pretty_ip(self._esp.ip_address)) |
| 287 | + |
269 | 288 | # set the default background
|
270 | 289 | self.set_background(self._default_bg)
|
271 | 290 | board.DISPLAY.show(self.splash)
|
@@ -353,20 +372,35 @@ def __init__(self, *, url=None, headers=None, json_path=None, regexp_path=None,
|
353 | 372 | self._image_position = (0, 0) # default to top corner
|
354 | 373 | if not self._image_resize:
|
355 | 374 | self._image_resize = (320, 240) # default to full screen
|
| 375 | + if hasattr(board, 'TOUCH_XL'): |
| 376 | + if self._debug: |
| 377 | + print("Init touchscreen") |
| 378 | + # pylint: disable=no-member |
| 379 | + self.touchscreen = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR, |
| 380 | + board.TOUCH_YD, board.TOUCH_YU, |
| 381 | + calibration=((5200, 59000), |
| 382 | + (5800, 57000)), |
| 383 | + size=(320, 240)) |
| 384 | + # pylint: enable=no-member |
| 385 | + |
| 386 | + self.set_backlight(1.0) # turn on backlight |
| 387 | + elif hasattr(board, 'BUTTON_CLOCK'): |
| 388 | + if self._debug: |
| 389 | + print("Init cursor") |
| 390 | + self.mouse_cursor = Cursor(board.DISPLAY, display_group=self.splash, cursor_speed=8) |
| 391 | + self.mouse_cursor.hide() |
| 392 | + self.cursor = CursorManager(self.mouse_cursor) |
| 393 | + else: |
| 394 | + raise AttributeError('PyPortal module requires either a touchscreen or gamepad.') |
356 | 395 |
|
357 |
| - if self._debug: |
358 |
| - print("Init touchscreen") |
359 |
| - # pylint: disable=no-member |
360 |
| - self.touchscreen = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR, |
361 |
| - board.TOUCH_YD, board.TOUCH_YU, |
362 |
| - calibration=((5200, 59000), |
363 |
| - (5800, 57000)), |
364 |
| - size=(320, 240)) |
365 |
| - # pylint: enable=no-member |
| 396 | + gc.collect() |
366 | 397 |
|
367 |
| - self.set_backlight(1.0) # turn on backlight |
| 398 | + def set_headers(self, headers): |
| 399 | + """Set the headers used by fetch(). |
368 | 400 |
|
369 |
| - gc.collect() |
| 401 | + :param headers: The new header dictionary |
| 402 | + """ |
| 403 | + self._headers = headers |
370 | 404 |
|
371 | 405 | def set_background(self, file_or_color, position=None):
|
372 | 406 | """The background image to a bitmap file.
|
@@ -673,6 +707,47 @@ def image_converter_url(image_url, width, height, color_depth=16):
|
673 | 707 | width, height,
|
674 | 708 | color_depth, image_url)
|
675 | 709 |
|
| 710 | + def push_to_io(self, feed_key, data): |
| 711 | + # pylint: disable=line-too-long |
| 712 | + """Push data to an adafruit.io feed |
| 713 | +
|
| 714 | + :param str feed_key: Name of feed key to push data to. |
| 715 | + :param data: data to send to feed |
| 716 | +
|
| 717 | + """ |
| 718 | + # pylint: enable=line-too-long |
| 719 | + |
| 720 | + try: |
| 721 | + aio_username = secrets['aio_username'] |
| 722 | + aio_key = secrets['aio_key'] |
| 723 | + except KeyError: |
| 724 | + raise KeyError("Adafruit IO secrets are kept in secrets.py, please add them there!\n\n") |
| 725 | + |
| 726 | + wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(self._esp, secrets, None) |
| 727 | + io_client = IO_HTTP(aio_username, aio_key, wifi) |
| 728 | + |
| 729 | + while True: |
| 730 | + try: |
| 731 | + feed_id = io_client.get_feed(feed_key) |
| 732 | + except AdafruitIO_RequestError: |
| 733 | + # If no feed exists, create one |
| 734 | + feed_id = io_client.create_new_feed(feed_key) |
| 735 | + except RuntimeError as exception: |
| 736 | + print("An error occured, retrying! 1 -", exception) |
| 737 | + continue |
| 738 | + break |
| 739 | + |
| 740 | + while True: |
| 741 | + try: |
| 742 | + io_client.send_data(feed_id['key'], data) |
| 743 | + except RuntimeError as exception: |
| 744 | + print("An error occured, retrying! 2 -", exception) |
| 745 | + continue |
| 746 | + except NameError as exception: |
| 747 | + print(feed_id['key'], data, exception) |
| 748 | + continue |
| 749 | + break |
| 750 | + |
676 | 751 | def fetch(self, refresh_url=None):
|
677 | 752 | """Fetch data from the url we initialized with, perfom any parsing,
|
678 | 753 | and display text or graphics. This function does pretty much everything
|
|
0 commit comments