Skip to content

Commit 9bfe2e9

Browse files
authored
Merge pull request #5 from ladyada/master
add text transform, reliable image converter
2 parents 7df38a4 + 6086ce3 commit 9bfe2e9

File tree

1 file changed

+53
-31
lines changed

1 file changed

+53
-31
lines changed

adafruit_pyportal.py

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@
7777
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PyPortal.git"
7878

7979
# pylint: disable=line-too-long
80-
IMAGE_CONVERTER_SERVICE = "https://res.cloudinary.com/schmarty/image/fetch/w_320,h_240,c_fill,f_bmp/"
81-
#IMAGE_CONVERTER_SERVICE = "http://ec2-107-23-37-170.compute-1.amazonaws.com/rx/ofmt_bmp,rz_320x240/"
80+
# you'll need to pass in an io username, width, height, format (bit depth), io key, and then url!
81+
IMAGE_CONVERTER_SERVICE = "https://io.adafruit.com/api/v2/%s/integrations/image-formatter?x-aio-key=%s&width=%d&height=%d&output=BMP%d&url=%s"
82+
8283
TIME_SERVICE_IPADDR = "http://worldtimeapi.org/api/ip"
8384
TIME_SERVICE_LOCATION = "http://worldtimeapi.org/api/timezone/"
8485
LOCALFILE = "local.txt"
@@ -119,6 +120,7 @@ class PyPortal:
119120
:param text_wrap: Whether or not to wrap text (for long text data chunks). Defaults to
120121
``False``, no wrapping.
121122
:param text_maxlen: The max length of the text for text wrapping. Defaults to 0.
123+
:param text_transform: A function that will be called on the text before display
122124
:param image_json_path: The JSON traversal path for a background image to display. Defaults to
123125
``None``.
124126
:param image_resize: What size to resize the image we got from the json_path, make this a tuple
@@ -140,7 +142,7 @@ class PyPortal:
140142
def __init__(self, *, url=None, json_path=None, regexp_path=None,
141143
default_bg=0x000000, status_neopixel=None,
142144
text_font=None, text_position=None, text_color=0x808080,
143-
text_wrap=False, text_maxlen=0,
145+
text_wrap=False, text_maxlen=0, text_transform=None,
144146
image_json_path=None, image_resize=None, image_position=None,
145147
caption_text=None, caption_font=None, caption_position=None,
146148
caption_color=0x808080,
@@ -181,17 +183,11 @@ def __init__(self, *, url=None, json_path=None, regexp_path=None,
181183
# Make ESP32 connection
182184
if self._debug:
183185
print("Init ESP32")
184-
# pylint: disable=no-member
185-
esp32_cs = DigitalInOut(microcontroller.pin.PB14)
186-
esp32_ready = DigitalInOut(microcontroller.pin.PB16)
187-
esp32_gpio0 = DigitalInOut(microcontroller.pin.PB15)
188-
esp32_reset = DigitalInOut(microcontroller.pin.PB17)
189-
#esp32_ready = DigitalInOut(board.ESP_BUSY)
190-
#esp32_gpio0 = DigitalInOut(board.ESP_GPIO0)
191-
#esp32_reset = DigitalInOut(board.ESP_RESET)
192-
#esp32_cs = DigitalInOut(board.ESP_CS)
186+
esp32_ready = DigitalInOut(board.ESP_BUSY)
187+
esp32_gpio0 = DigitalInOut(board.ESP_GPIO0)
188+
esp32_reset = DigitalInOut(board.ESP_RESET)
189+
esp32_cs = DigitalInOut(board.ESP_CS)
193190
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
194-
# pylint: enable=no-member
195191

196192
if not self._uselocal:
197193
self._esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready,
@@ -222,6 +218,10 @@ def __init__(self, *, url=None, json_path=None, regexp_path=None,
222218
except OSError as error:
223219
print("No SD card found:", error)
224220

221+
self._speaker_enable = DigitalInOut(board.SPEAKER_ENABLE)
222+
self._speaker_enable.switch_to_output(False)
223+
self.audio = audioio.AudioOut(board.AUDIO_OUT)
224+
225225
try:
226226
self.play_file("pyportal_startup.wav")
227227
except OSError:
@@ -256,17 +256,21 @@ def __init__(self, *, url=None, json_path=None, regexp_path=None,
256256
text_wrap = [0] * num
257257
if not text_maxlen:
258258
text_maxlen = [0] * num
259+
if not text_transform:
260+
text_transform = [None] * num
259261
else:
260262
num = 1
261263
text_position = (text_position,)
262264
text_color = (text_color,)
263265
text_wrap = (text_wrap,)
264266
text_maxlen = (text_maxlen,)
267+
text_transform = (text_transform,)
265268
self._text = [None] * num
266269
self._text_color = [None] * num
267270
self._text_position = [None] * num
268271
self._text_wrap = [None] * num
269272
self._text_maxlen = [None] * num
273+
self._text_transform = [None] * num
270274
self._text_font = bitmap_font.load_font(text_font)
271275
if self._debug:
272276
print("Loading font glyphs")
@@ -282,6 +286,7 @@ def __init__(self, *, url=None, json_path=None, regexp_path=None,
282286
self._text_position[i] = text_position[i]
283287
self._text_wrap[i] = text_wrap[i]
284288
self._text_maxlen[i] = text_maxlen[i]
289+
self._text_transform[i] = text_transform[i]
285290
else:
286291
self._text_font = None
287292
self._text = None
@@ -453,21 +458,23 @@ def neo_status(self, value):
453458
if self.neopix:
454459
self.neopix.fill(value)
455460

456-
@staticmethod
457-
def play_file(file_name):
461+
def play_file(self, file_name, wait_to_finish=True):
458462
"""Play a wav file.
459463
460464
:param str file_name: The name of the wav file to play on the speaker.
461465
462466
"""
463-
#self._speaker_enable.value = True
464-
with open(file_name, "rb") as file:
465-
with audioio.AudioOut(board.AUDIO_OUT) as audio:
466-
with audioio.WaveFile(file) as wavefile:
467-
audio.play(wavefile)
468-
while audio.playing:
469-
pass
470-
#self._speaker_enable.value = False
467+
board.DISPLAY.wait_for_frame()
468+
wavfile = open(file_name, "rb")
469+
wavedata = audioio.WaveFile(wavfile)
470+
self._speaker_enable.value = True
471+
self.audio.play(wavedata)
472+
if not wait_to_finish:
473+
return
474+
while self.audio.playing:
475+
pass
476+
wavfile.close()
477+
self._speaker_enable.value = False
471478

472479
@staticmethod
473480
def _json_traverse(json, path):
@@ -487,8 +494,7 @@ def get_local_time(self, location=None):
487494
# pylint: enable=line-too-long
488495
self._connect_esp()
489496
api_url = None
490-
if secrets['timezone']:
491-
location = secrets['timezone']
497+
location = secrets.get('timezone', location)
492498
if location:
493499
print("Getting time for timezone", location)
494500
api_url = TIME_SERVICE_LOCATION + location
@@ -624,7 +630,11 @@ def fetch(self):
624630
# extract desired text/values from json
625631
if self._json_path:
626632
for path in self._json_path:
627-
values.append(PyPortal._json_traverse(json_out, path))
633+
try:
634+
values.append(PyPortal._json_traverse(json_out, path))
635+
except KeyError:
636+
print(json_out)
637+
raise
628638
elif self._regexp_path:
629639
for regexp in self._regexp_path:
630640
values.append(re.search(regexp, r.text).group(1))
@@ -644,9 +654,17 @@ def fetch(self):
644654
gc.collect()
645655

646656
if image_url:
657+
try:
658+
aio_username = secrets['aio_username']
659+
aio_key = secrets['aio_key']
660+
except KeyError:
661+
raise KeyError("\n\nOur image converter service require a login/password to rate-limit. Please register for a freeadafruit.io account and place the user/key in your secrets file under 'aio_username' and 'aio_key'")# pylint: disable=line-too-long
647662
try:
648663
print("original URL:", image_url)
649-
image_url = IMAGE_CONVERTER_SERVICE+image_url
664+
image_url = IMAGE_CONVERTER_SERVICE % (aio_username, aio_key,
665+
self._image_resize[0],
666+
self._image_resize[1],
667+
16, image_url)
650668
print("convert URL:", image_url)
651669
# convert image to bitmap and cache
652670
#print("**not actually wgetting**")
@@ -676,10 +694,14 @@ def fetch(self):
676694
if self._text:
677695
for i in range(len(self._text)):
678696
string = None
679-
try:
680-
string = "{:,d}".format(int(values[i]))
681-
except (TypeError, ValueError):
682-
string = values[i] # ok its a string
697+
if self._text_transform[i]:
698+
func = self._text_transform[i]
699+
string = func(values[i])
700+
else:
701+
try:
702+
string = "{:,d}".format(int(values[i]))
703+
except (TypeError, ValueError):
704+
string = values[i] # ok its a string
683705
if self._debug:
684706
print("Drawing text", string)
685707
if self._text_wrap[i]:

0 commit comments

Comments
 (0)