# the current working directory (where this file is) cwd = ("/" + __file__).rsplit('/', 1)[0] pyportal = PyPortal(url=DATA_SOURCE, json_path=(LIKES_LOCATION, VIEWS_LOCATION), status_neopixel=board.NEOPIXEL, default_bg=cwd + "/hackster_background.bmp", text_font=cwd + "/fonts/Arial-Bold-24.bdf", text_position=((80, 75), (80, 145)), text_color=(0x0000FF, 0x000000), caption_text=CAPTION, caption_font=cwd + "/fonts/Arial-12.bdf", caption_position=(20, 200), caption_color=0x000000) # track the last value so we can play a sound when it updates last_likes = 0 while True: try: likes, views = pyportal.fetch() print("Views", views, "Likes", likes) if last_likes < likes: # ooh it went up! print("New respect!") pyportal.play_file(cwd + "/coin.wav") last_likes = likes except RuntimeError as e: print("Some error occured, retrying! -", e) time.sleep(60)
DATA_SOURCE = "https://api.github.com/repos/adafruit/circuitpython" STARS_COUNT = ["stargazers_count"] REPO_NAME = ["full_name"] # the current working directory (where this file is) cwd = ("/" + __file__).rsplit("/", 1)[0] pyportal = PyPortal( url=DATA_SOURCE, json_path=(REPO_NAME, STARS_COUNT), status_neopixel=board.NEOPIXEL, default_bg=cwd + "/bgs/terminal.bmp", text_font=cwd + "/fonts/Helvetica-Bold-24.bdf", text_position=((20, 160), (20, 280)), # quote location # author location text_color=(0xFFFFFF, 0xF291C7), # quote text color # author text color text_wrap=(30, 0), # characters to wrap for quote # no wrap for author text_maxlen=(180, 30), # max text size for quote & author debug=True, ) # speed up projects with lots of text by preloading the font! pyportal.preload_font() while True: try: value = pyportal.fetch() print("Response is", value) except (ValueError, RuntimeError) as e: print("Some error occured, retrying! -", e) time.sleep(60)
text_position=(4, HEIGHT - 9), text_color=0xFFFFFF) circle = Circle(WIDTH - 8, HEIGHT - 7, 5, fill=0) pyportal.splash.append(circle) loopcount = 0 errorcount = 0 while True: response = None try: circle.fill = 0xFF0000 itemid = random.randint(1, IMAGECOUNT) # itemid = 20 # portrait mode example # itemid = 21 # landscape mode example print("retrieving url:", APIURL + str(itemid)) response = pyportal.fetch(APIURL + str(itemid)) circle.fill = 0 print("Response is", response) loopcount = loopcount + 1 except (RuntimeError, KeyError, TypeError) as e: print("An error occured, retrying! -", e) print("loop counter:", loopcount) assert errorcount < 20, "Too many errors, stopping" errorcount = errorcount + 1 time.sleep(60) continue errorcount = 0 stamp = time.monotonic() # wait 5 minutes before getting again
for i, filename in enumerate(imagefiles): imagefiles[i] = cwd + "/backgrounds/" + filename print("Image files found: ", imagefiles) pyportal = PyPortal( url=DATA_SOURCE, json_path=TEXT_LOCATION, status_neopixel=board.NEOPIXEL, default_bg=imagefiles[0], text_font=cwd + "/fonts/Arial-Italic-12.bdf", text_position=(25, 20), text_color=0xFFFFFF, text_wrap=35, # character to wrap around text_maxlen=280, # cut off characters ) pyportal.preload_font() while True: response = None try: pyportal.set_background(random.choice(imagefiles)) response = pyportal.fetch() print("Response is", response) except (IndexError, RuntimeError, ValueError) as e: print("Some error occured, retrying! -", e) # next tweet should be random! tweet_idx = random.randint(0, NUM_TWEETS) TEXT_LOCATION[3] = tweet_idx time.sleep(60)
# determine the current working directory # needed so we know where to find files cwd = ("/" + __file__).rsplit('/', 1)[0] url = 'https://api.twitter.com/1.1/statuses/user_timeline.json?count=1&screen_name=' + username # Initialize the pyportal object and let us know what data to fetch and where # to display it pyportal = PyPortal( url=url, json_path=(0, 'text'), status_neopixel=board.NEOPIXEL, default_bg=cwd + '/twitter_background.bmp', # external_spi=spi, # esp=esp, text_font=cwd + '/fonts/Helvetica-Bold-16.bdf', text_position=(20, 60), text_color=0xFFFFFF, text_wrap=35, caption_text='@' + username, caption_font=cwd + '/fonts/Helvetica-Bold-16.bdf', caption_position=(5, 210), caption_color=0x808080) bearer_token = get_bearer_token() pyportal.set_headers({'Authorization': 'Bearer ' + bearer_token}) while True: pyportal.fetch() time.sleep(3600) # check every hour
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries # # SPDX-License-Identifier: MIT # NOTE: Make sure you've created your secrets.py file before running this example # https://learn.adafruit.com/adafruit-pyportal/internet-connect#whats-a-secrets-file-17-2 import board from adafruit_pyportal import PyPortal # Set a data source URL TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html" # Create the PyPortal object pyportal = PyPortal(url=TEXT_URL, status_neopixel=board.NEOPIXEL) # Set display to show REPL board.DISPLAY.show(None) # Go get that data print("Fetching text from", TEXT_URL) data = pyportal.fetch() # Print out what we got print("-" * 40) print(data) print("-" * 40)
caption_font=CAPTION_FONT_FILE) canvas = displayio.Group(max_size=36) pyportal.splash.append(canvas) AQI_font = bitmap_font.load_font(AQI_FONT_FILE) Footer_font = bitmap_font.load_font(FOOTER_FONT_FILE) status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.1) status_light[0] = (00, 0, 00) #status_light[0] = (30, 00, 00, 10) while True: worst = 0 json_payload = '' try: json_payload = pyportal.fetch() raw_data = json.loads(json_payload) except (ValueError, RuntimeError) as ex: print('Error: ', ex) if isinstance(ex, ValueError): print('JSON:', json_payload) print('Retrying in 10 minutes') time.sleep(600) continue while len(canvas) > 0: canvas.pop() pyportal.set_caption(('Air Quality Index'), (70, 20), 0xFFFFFF) xpos = 20 ypos = 80
timeval = time.localtime() #add leading zeros to the day and month today = str(timeval.tm_year) + "{:02d}".format( timeval.tm_mon) + "{:02d}".format(timeval.tm_mday) day = "{:02d}".format(timeval.tm_mday) DATA_SOURCE = "https://tidesandcurrents.noaa.gov/api/datagetter?begin_date=" + today DATA_SOURCE += "&end_date=" + today DATA_SOURCE += "&station=" + STATION DATA_SOURCE += "&product=predictions&datum=mllw&units=english&time_zone=lst_ldt&application=web_services&format=json" # Test URL # I chose the MLLW (Mean Low Low water) dataum as this is the "normal" set of predictions # https://tidesandcurrents.noaa.gov/api/datagetter?begin_date=20190419&end_date=20190419&station=8441241&product=predictions&datum=mllw&units=english&time_zone=lst_ldt&application=web_services&format=json print(DATA_SOURCE) update_clock = None value = pyportal.fetch( DATA_SOURCE ) #modified pyportal to allow us to call the fetch AFTER we set the time to use the in the URL since the tide predicion use of date=today returns tomorrow after GMT midnight value = json.loads( value) #load the predictions into a python list/array/structure thingy hx = 0 #define the highlow array as 4 empty slots highlow = [None] * 4 # for x in range(240): # Used to debug and read all of the predictions # v = value['predictions'][x]['v'] # t = value['predictions'][x]['t'] # print ("{} {} {}".format(x,t,v)) #loop through the tide prediction and figure out the 2 highs and 2 lows we will do this by looking at the next and previous predictions to see if we are in a peak or valley for x in range(240): # print(x)
pyportal = PyPortal(url=DATA_SOURCE, json_path=(DATA_LOCATION1, DATA_LOCATION2), status_neopixel=board.NEOPIXEL, default_bg=cwd+"/youtube_background.bmp", text_font=cwd+"/fonts/Collegiate-50.bdf", text_position=((100, 85), (180, 130)), text_color=(0xFFFFFF, 0xFFFFFF), caption_text=CAPTION, caption_font=cwd+"/fonts/Collegiate-24.bdf", caption_position=(40, 200), caption_color=0xFFFFFF) # track the last value so we can play a sound when it updates last_subs = 0 while True: try: views, subs = pyportal.fetch() subs = int(subs) views = int(views) print("Subscribers:", subs) print("Views:", views) if last_subs < subs: # ooh it went up! print("New subscriber!") pyportal.play_file(cwd+"/coin.wav") last_subs = subs except RuntimeError as e: print("Some error occured, retrying! -", e) time.sleep(60)
regular expression search to locate the number of online discord users, then display it on a screen. If you can find something that spits out text, we can display it! """ import time import board from adafruit_pyportal import PyPortal from adafruit_portalbase.network import CONTENT_TEXT # Set up where we'll be fetching data from DATA_SOURCE = "https://img.shields.io/discord/327254708534116352.svg" # a regular expression for finding the data within the SVG xml text! DATA_LOCATION = [r">([0-9]+ online)<"] cwd = ("/" + __file__).rsplit('/', 1)[0] pyportal = PyPortal(url=DATA_SOURCE, regexp_path=DATA_LOCATION, status_neopixel=board.NEOPIXEL, default_bg=cwd + "/discord_background.bmp", text_font=cwd + "/fonts/Collegiate-50.bdf", text_position=(70, 216), text_color=0x000000) while True: try: value = pyportal.fetch(force_content_type=CONTENT_TEXT) print("Response is", value) except RuntimeError as e: print("Some error occured, retrying! -", e) time.sleep(60)
caption_font=cwd + "/fonts/Collegiate-24.bdf", caption_position=(10, 220), caption_color=0x000000) # track the last value so we can play a sound when it updates last_follower = 0 while True: # Followers: # A limitation of the PyPortal object is it must have an equal number of # text objects and json fields. So in this case, get some dummy information, # then replace the text with the word followers after. It's a bit ugly. # Alternatively, do this outside of a pyportal object manually. try: pyportal._json_path = main_json_path dummy, followers = pyportal.fetch(MAIN_DATA_SOURCE) pyportal.set_text("Followers:", index=0) followers = int(followers) print("followers:", followers) if last_follower < followers: # another follower print("New Follower!") pyportal.play_file(cwd + "/coin.wav") last_follower = followers except RuntimeError as e: print("Some error occured, retrying! -", e) except ValueError as e: print("Value error occured, retrying! -", e) except: print("An unknown error occured, retrying!") time.sleep(30)
if view_live != i + 1: switch_view(i + 1) while ts.touch_point: pass gc.collect() # Space View if (view_live == 1 and (my_time > check_space)): gc.collect check_space = my_time + 3600 # 1 hour people = [] launches = [] gc.collect try: json_data = json.loads( pyportal.fetch( refresh_url="http://api.open-notify.org/astros.json")) for path in (['number'], ['people']): people.append(PyPortal._json_traverse(json_data, path)) del json_data gc.collect() space_data.text = "There are " + str(people[0]) + " in space." for person in people[1]: space_data.text = space_data.text + "\n " + person[ "name"] + "(" + person["craft"] + ")" del people gc.collect() json_data = json.loads( pyportal.fetch( refresh_url= "https://fdo.rocketlaunch.live/json/launches/next/2"))
time.sleep(linger) except RuntimeError as e: print("Some error occured, skipping this iteration! -", e) continue pyportal.splash.pop() # While there are some differences, could probably refactor the three segments # below into one function call # Display weather # only query the weather every 10 minutes (and on first run) pyportal.set_background(cwd + "/wx_bitmap.bmp") time.sleep(2) try: if (not weather_refresh) or (time.monotonic() - weather_refresh) > 600: wx = pyportal.fetch(WX_DATA_SOURCE) print("Response is", wx) weather_refresh = time.monotonic() text_group, background_file = openweather_graphics.wx_graphics( medium_font=medium_font, large_font=large_font, small_font=small_font, weather=wx) pyportal.set_background(cwd + background_file) pyportal.splash.append(text_group) # Display for 14 seconds, then empty the pyportal.splash group so it can be loaded with new display info time.sleep(long_linger) except RuntimeError as e: print("Some error occured, skipping this iteration! -", e) continue pyportal.splash.pop()
class StationPortal(): def __init__(self): self.pyportal = PyPortal( url= f"https://api.composer.nprstations.org/v1/widget/{STATION_PLAYLIST_UCS}/now?format=json", status_neopixel=board.NEOPIXEL, default_bg=0x000000 # cwd + "/station_background.bmp", ) self.show_text = Label(text_font, max_glyphs=40) self.host_text = Label(text_font, max_glyphs=40) self.track_text = Label(text_font, max_glyphs=40) self.artist_text = Label(text_font, max_glyphs=40) self.show_text.color = 0xFFFFFF self.host_text.color = 0xFFFFFF self.track_text.color = 0xFFFFFF self.artist_text.color = 0xF05423 self.show_text.x = 20 self.host_text.x = 20 self.track_text.x = 20 self.artist_text.x = 20 self.show_text.y = 35 self.host_text.y = 55 self.track_text.y = 90 self.artist_text.y = 110 self.pyportal.splash.append(self.show_text) self.pyportal.splash.append(self.host_text) self.pyportal.splash.append(self.track_text) self.pyportal.splash.append(self.artist_text) # placeholder for album art tilegroup, index 5 self.pyportal.splash.append(displayio.Group()) self.artworkTileGroupIndex = 5 # append station slug last so that if it fails, it doens't throw off the sprite indices station_slug = f"{cwd}/{STATION_PLAYLIST_UCS}_slug.bmp" try: self.slug_file = open(station_slug, "rb") slug_bitmap = displayio.OnDiskBitmap(self.slug_file) self.pyportal.splash.append( displayio.TileGrid(slug_bitmap, pixel_shader=displayio.ColorConverter(), width=1, height=1, x=190, y=170)) except OSError as e: print( f"Unable to open station slug bitmap, station_slug: {station_slug}" ) self.cover_file = None self.track_id = None def fetch(self): values = self.pyportal.fetch() data = json.loads(values) print("Fetched new data, type:", type(data)) print("data:", data) if ("onNow" not in data): print("Invalid data payload") return if ("program" in data["onNow"]): self._updateShow(data["onNow"]["program"]) if ("song" in data["onNow"]): curr_track = data["onNow"]["song"] curr_track_id = curr_track["_id"] if (self.track_id != curr_track_id): print(f"Loading new track, id: {curr_track_id}") self._updateTrack(curr_track) self.track_id = curr_track_id else: self._setTrack("Track currently unavailable") self._setArtist(None) self._updateCoverart(None) def _updateShow(self, curr_program): if "name" in curr_program: self._setShow(curr_program["name"]) else: self._setShow(STATION_DEFAULT_SHOW_NAME) if "hosts" in curr_program and len(curr_program["hosts"]) > 0: if len(curr_program["hosts"]) > 1: self._setHost(curr_program["hosts"][0]["name"] + " et al") elif curr_program["hosts"][0]["name"]: # test for empty self._setHost(curr_program["hosts"][0]["name"]) else: self._setHost(STATION_DEFAULT_HOST_NAME) else: self._setHost(STATION_DEFAULT_HOST_NAME) def _updateTrack(self, curr_track): if "trackName" in curr_track: self._setTrack(curr_track["trackName"]) else: self._setTrack("Unknown Title") if "artistName" in curr_track: self._setArtist(curr_track["artistName"]) else: self._setArtist("Unknown Artist") if "imageURL" in curr_track: self._updateCoverart(curr_track["imageURL"]) elif "artworkUrl100" in curr_track: self._updateCoverart(curr_track["artworkUrl100"]) else: self._updateCoverart(None) def _setShow(self, val): if (val == None): self.show_text.text = "" if (len(val) > 30): self.show_text.text = (val)[0:30] + "..." else: self.show_text.text = val def _setHost(self, val): if (val == None): self.host_text.text = "" elif (len(val) > 30): self.host_text.text = "with " + (val)[0:30] + "..." else: self.host_text.text = "with " + val def _setTrack(self, val): if (val == None): self.track_text.text = "" elif (len(val) > 30): self.track_text.text = (val)[0:30] + "..." else: self.track_text.text = val def _setArtist(self, val): if (val == None): self.artist_text.text = "" elif (len(val) > 30): self.artist_text.text = ("by " + val)[0:30] + "..." else: self.artist_text.text = "by " + val def _updateCoverart(self, source_url): cover_filename = "/sd/cover-image.bmp" cover_bitmap = None if (source_url): try: image_url = self.pyportal.image_converter_url( source_url, 100, 100) print(f"Converting image, image_url: {image_url}") self.pyportal.wget(image_url, cover_filename, chunk_size=512) if (self.cover_file): self.cover_file.close() self.cover_file = open(cover_filename, "rb") cover_bitmap = displayio.OnDiskBitmap(self.cover_file) except (OSError, KeyError, Exception) as e: print(f"Error rendering cover art, source_url: {source_url}") if (cover_bitmap == None): cover_bitmap = displayio.Bitmap(100, 100, 1) cover_bitmap.fill(0x0) self.pyportal.splash[self.artworkTileGroupIndex] = displayio.TileGrid( cover_bitmap, pixel_shader=displayio.ColorConverter(), width=1, height=1, x=23, y=130)
""" dsl_status = fritz_status.get_dsl_status() if dsl_status["connected"]: status_icon_controller.set_dsl_status(True) current_dsl_check_period = 15 else: status_icon_controller.set_dsl_status(False) current_dsl_check_period = 2 last_dsl_check = time.monotonic() # Load new quote every hour if last_quote_check + 3600 < time.monotonic(): try: quote_json = pyportal.fetch() quote_text = '"' + quote_json[0] + '" - ' + quote_json[1] quote = pyportal.wrap_nicely(quote_text, 40) # Only show quotes with 4 lines ore less if len(quote) <= 4: new_quote = "" test = "" for w in quote: new_quote += "\n" + w test += "M\n" quote_font_hight.text = test # Odd things happen without this glyph_box = quote_font_hight.bounding_box quote_label.text = "" # Odd things happen without this quote_label.text = new_quote except MemoryError: