Skip to content

Commit 7df38a4

Browse files
authored
Merge pull request #4 from ladyada/master
startup sound, AP settings notification text, allow background solid fill
2 parents 34d9bb6 + 6f73a61 commit 7df38a4

File tree

2 files changed

+63
-33
lines changed

2 files changed

+63
-33
lines changed

adafruit_pyportal.py

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

7979
# pylint: disable=line-too-long
80-
IMAGE_CONVERTER_SERVICE = "http://res.cloudinary.com/schmarty/image/fetch/w_320,h_240,c_fill,f_bmp/"
80+
IMAGE_CONVERTER_SERVICE = "https://res.cloudinary.com/schmarty/image/fetch/w_320,h_240,c_fill,f_bmp/"
8181
#IMAGE_CONVERTER_SERVICE = "http://ec2-107-23-37-170.compute-1.amazonaws.com/rx/ofmt_bmp,rz_320x240/"
8282
TIME_SERVICE_IPADDR = "http://worldtimeapi.org/api/ip"
8383
TIME_SERVICE_LOCATION = "http://worldtimeapi.org/api/timezone/"
@@ -107,7 +107,8 @@ class PyPortal:
107107
:param regexp_path: The list of regexp strings to get data out (use a single regexp group). Can
108108
be list of regexps for multiple data points. Defaults to ``None`` to not
109109
use regexp.
110-
:param default_bg: The path to your default background image file. Defaults to ``None``.
110+
:param default_bg: The path to your default background image file or a hex color.
111+
Defaults to 0x000000.
111112
:param status_neopixel: The pin for the status NeoPixel. Use ``board.NEOPIXEL`` for the on-board
112113
NeoPixel. Defaults to ``None``, no status LED
113114
:param str text_font: The path to your font file for your data text display.
@@ -137,7 +138,7 @@ class PyPortal:
137138
"""
138139
# pylint: disable=too-many-instance-attributes, too-many-locals, too-many-branches, too-many-statements
139140
def __init__(self, *, url=None, json_path=None, regexp_path=None,
140-
default_bg=None, status_neopixel=None,
141+
default_bg=0x000000, status_neopixel=None,
141142
text_font=None, text_position=None, text_color=0x808080,
142143
text_wrap=False, text_maxlen=0,
143144
image_json_path=None, image_resize=None, image_position=None,
@@ -208,6 +209,7 @@ def __init__(self, *, url=None, json_path=None, regexp_path=None,
208209
raise RuntimeError("Was not able to find ESP32")
209210

210211
requests.set_interface(self._esp)
212+
self._connect_esp()
211213

212214
if self._debug:
213215
print("Init SD Card")
@@ -220,6 +222,11 @@ def __init__(self, *, url=None, json_path=None, regexp_path=None,
220222
except OSError as error:
221223
print("No SD card found:", error)
222224

225+
try:
226+
self.play_file("pyportal_startup.wav")
227+
except OSError:
228+
pass # they deleted the file, no biggie!
229+
223230
if self._debug:
224231
print("Init display")
225232
self.splash = displayio.Group(max_size=5)
@@ -303,34 +310,39 @@ def __init__(self, *, url=None, json_path=None, regexp_path=None,
303310
# pylint: enable=no-member
304311

305312
self.set_backlight(1.0) # turn on backlight
313+
306314
gc.collect()
307315

308-
def set_background(self, filename):
316+
def set_background(self, file_or_color):
309317
"""The background image to a bitmap file.
310318
311-
:param filename: The name of the chosen background image file.
319+
:param file_or_color: The filename of the chosen background image, or a hex color.
312320
313321
"""
314-
print("Set background to ", filename)
315-
try:
322+
print("Set background to ", file_or_color)
323+
while self._bg_group:
316324
self._bg_group.pop()
317-
except IndexError:
318-
pass # s'ok, we'll fix to test once we can
319325

320-
if not filename:
326+
if not file_or_color:
321327
return # we're done, no background desired
322328
if self._bg_file:
323329
self._bg_file.close()
324-
self._bg_file = open(filename, "rb")
325-
background = displayio.OnDiskBitmap(self._bg_file)
326-
try:
330+
if isinstance(file_or_color, str): # its a filenme:
331+
self._bg_file = open(file_or_color, "rb")
332+
background = displayio.OnDiskBitmap(self._bg_file)
327333
self._bg_sprite = displayio.TileGrid(background,
328334
pixel_shader=displayio.ColorConverter(),
329335
position=(0, 0))
330-
except AttributeError:
331-
self._bg_sprite = displayio.Sprite(background, pixel_shader=displayio.ColorConverter(),
332-
position=(0, 0))
333-
336+
elif isinstance(file_or_color, int):
337+
# Make a background color fill
338+
color_bitmap = displayio.Bitmap(320, 240, 1)
339+
color_palette = displayio.Palette(1)
340+
color_palette[0] = file_or_color
341+
self._bg_sprite = displayio.TileGrid(color_bitmap,
342+
pixel_shader=color_palette,
343+
position=(0, 0))
344+
else:
345+
raise RuntimeError("Unknown type of background")
334346
self._bg_group.append(self._bg_sprite)
335347
board.DISPLAY.refresh_soon()
336348
gc.collect()
@@ -449,8 +461,8 @@ def play_file(file_name):
449461
450462
"""
451463
#self._speaker_enable.value = True
452-
with audioio.AudioOut(board.AUDIO_OUT) as audio:
453-
with open(file_name, "rb") as file:
464+
with open(file_name, "rb") as file:
465+
with audioio.AudioOut(board.AUDIO_OUT) as audio:
454466
with audioio.WaveFile(file) as wavefile:
455467
audio.play(wavefile)
456468
while audio.playing:
@@ -475,17 +487,24 @@ def get_local_time(self, location=None):
475487
# pylint: enable=line-too-long
476488
self._connect_esp()
477489
api_url = None
478-
if not location:
479-
api_url = TIME_SERVICE_IPADDR
480-
else:
490+
if secrets['timezone']:
491+
location = secrets['timezone']
492+
if location:
493+
print("Getting time for timezone", location)
481494
api_url = TIME_SERVICE_LOCATION + location
482-
response = requests.get(api_url)
483-
time_json = response.json()
484-
current_time = time_json['datetime']
485-
year_day = time_json['day_of_year']
486-
week_day = time_json['day_of_week']
487-
is_dst = time_json['dst']
495+
else: # we'll try to figure it out from the IP address
496+
print("Getting time from IP address")
497+
api_url = TIME_SERVICE_IPADDR
488498

499+
try:
500+
response = requests.get(api_url)
501+
time_json = response.json()
502+
current_time = time_json['datetime']
503+
year_day = time_json['day_of_year']
504+
week_day = time_json['day_of_week']
505+
is_dst = time_json['dst']
506+
except KeyError:
507+
raise KeyError("Was unable to lookup the time, try setting secrets['timezone'] according to http://worldtimeapi.org/timezones") # pylint: disable=line-too-long
489508
the_date, the_time = current_time.split('T')
490509
year, month, mday = [int(x) for x in the_date.split('-')]
491510
the_time = the_time.split('.')[0]
@@ -542,12 +561,22 @@ def wget(self, url, filename, *, chunk_size=12000):
542561
def _connect_esp(self):
543562
self.neo_status((0, 0, 100))
544563
while not self._esp.is_connected:
545-
if self._debug:
546-
print("Connecting to AP")
547564
# secrets dictionary must contain 'ssid' and 'password' at a minimum
565+
print("Connecting to AP", secrets['ssid'])
566+
if secrets['ssid'] == 'CHANGE ME' or secrets['ssid'] == 'CHANGE ME':
567+
print("*"*45)
568+
print("Please update the 'secrets.py' file on your")
569+
print("CIRCUITPY drive to include your local access")
570+
print("point SSID name in 'ssid' and SSID password")
571+
print("in 'password'. Then save to reload!")
572+
print("*"*45)
548573
self.neo_status((100, 0, 0)) # red = not connected
549-
self._esp.connect(secrets)
550-
574+
try:
575+
self._esp.connect(secrets)
576+
except RuntimeError as error:
577+
print("Cound not connect to internet", error)
578+
print("Retrying in 3 seconds...")
579+
time.sleep(3)
551580
def fetch(self):
552581
"""Fetch data from the url we initialized with, perfom any parsing,
553582
and display text or graphics. This function does pretty much everything"""
@@ -719,7 +748,8 @@ def show_QR(self, qr_data, qr_size=128, position=None): # pylint: disable=inval
719748

720749
for b in range(BLOCK_SIZE):
721750
# load this line of data in, as many time as block size
722-
qr_bitmap._load_row(Y_OFFSET + y*BLOCK_SIZE+b, line) # pylint: disable=protected-access
751+
for i, byte in enumerate(line):
752+
qr_bitmap[Y_OFFSET + y*BLOCK_SIZE+b + i] = byte
723753
# pylint: enable=invalid-name
724754

725755
# display the bitmap using our palette

examples/pyportal_startup.wav

84.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)