This version is just a basic tide time information viewer. It shows the times when the daily high and low times will occur. Typically there will be two of each per day.
Let's get the code loaded up and running first, since that's more fun. We'll discuss how the parsing works after that.
Add CircuitPython Code and Assets
In the embedded code element below, click on the Download Project Bundle button, and save the .zip archive file to your computer.
Then uncompress the.zip file, it will unpack to a folder named PyPortal_Tides.
Copy the contents of the PyPortal_Tides directory to your PyPortal CIRCUITPY drive.

Editing the Code
At the top of the code, find the line that sets the station ID and change it for your location:
STATION_ID = "9447130" # tide location, find yours here: https://tidesandcurrents.noaa.gov/
Note that it is entered as a string, not a number. So don't remove the quotation marks.
# SPDX-FileCopyrightText: 2019 Carter Nelson for Adafruit Industries # # SPDX-License-Identifier: MIT import time import board from adafruit_pyportal import PyPortal from adafruit_bitmap_font import bitmap_font from adafruit_display_text.label import Label # --| USER CONFIG |-------------------------- STATION_ID = ( "9447130" # tide location, find yours here: https://tidesandcurrents.noaa.gov/ ) HI_COLOR = 0x00FF00 # high tide times color LO_COLOR = 0x11FFFF # low tide times color DATE_COLOR = 0xFFFFFF # date and time color # ------------------------------------------- # pylint: disable=line-too-long DATA_SOURCE = ( "https://api.tidesandcurrents.noaa.gov/api/prod/datagetter?date=today&product=predictions&datum=mllw&interval=hilo&format=json&units=metric&time_zone=lst_ldt&station=" + STATION_ID ) DATA_LOCATION = ["predictions"] # gotta have one of these pyportal = PyPortal(status_neopixel=board.NEOPIXEL, default_bg="/images/tides_bg.bmp") # Connect to the internet and get local time pyportal.get_local_time() # Setup tide times font tide_font = bitmap_font.load_font("/fonts/cq-mono-30.bdf") tide_font.load_glyphs(b"1234567890:") # Setup date and time font date_font = bitmap_font.load_font("/fonts/Arial-12.bdf") date_font.load_glyphs(b"1234567890-") # Labels setup HI_LABELS = [ Label(tide_font, text="00:00", color=HI_COLOR, x=40, y=80), Label(tide_font, text="00:00", color=HI_COLOR, x=40, y=165), ] LO_LABELS = [ Label(tide_font, text="00:00", color=LO_COLOR, x=180, y=80), Label(tide_font, text="00:00", color=LO_COLOR, x=180, y=165), ] DATE_LABEL = Label(date_font, text="0000-00-00 00:00:00", color=DATE_COLOR, x=75, y=228) # Add all the labels to the display for label in HI_LABELS + LO_LABELS + [DATE_LABEL]: pyportal.graphics.splash.append(label) def get_tide_info(): """Fetch JSON tide time info and return it.""" # Get raw JSON data raw_info = pyportal.network.fetch_data(DATA_SOURCE, json_path=DATA_LOCATION) # Return will be a dictionary of lists containing tide times new_tide_info = {"H": [], "L": []} # Parse out the tide time info for info in raw_info[0]: tide_type = info["type"] tide_time = info["t"].split(" ")[1] new_tide_info[tide_type].append(tide_time) return new_tide_info def update_display(time_info, update_tides=False): """Update the display with current info.""" # Tide time info if update_tides: # out with the old for tide_label in HI_LABELS + LO_LABELS: tide_label.text = "" # in with the new for i, hi_time in enumerate(tide_info["H"]): HI_LABELS[i].text = hi_time for i, lo_time in enumerate(tide_info["L"]): LO_LABELS[i].text = lo_time # Date and time DATE_LABEL.text = "{:04}-{:02}-{:02} {:02}:{:02}:{:02}".format( time_info.tm_year, time_info.tm_mon, time_info.tm_mday, time_info.tm_hour, time_info.tm_min, time_info.tm_sec, ) # First run update tide_info = get_tide_info() current_time = time.localtime() update_display(current_time, True) current_yday = current_time.tm_yday # Update daily while True: current_time = time.localtime() new_tides = False if current_time.tm_yday != current_yday: # new day, time to update tide_info = get_tide_info() new_tides = True current_yday = current_time.tm_yday update_display(current_time, new_tides) time.sleep(0.5)
{ "predictions" : [ {"t":"2019-04-15 02:55", "v":"3.401", "type":"H"},{"t":"2019-04-15 09:01", "v":"1.586", "type":"L"},{"t":"2019-04-15 14:04", "v":"2.780", "type":"H"},{"t":"2019-04-15 20:33", "v":"0.111", "type":"L"} ]}
All of the data mangling work is done in the function get_tide_info()
. So let's walk through that.
When we setup our PyPortal
object, we told it we want the information rooted at predictions
. Once that is setup, along with providing the URL, to connect to the Internet and retrieve the data we simply call fetch()
from the PyPortal library.
raw_info = pyportal.fetch()
Now we need to parse out the data in raw_info
. We could come up with various ways of storing the results, but here we use a dictionary of lists. This will have an "H" entry which will contain the times for the high tides and an "L" entry which will contain the times for the low tides.
This choice of keys for the dictionary is not arbitrary. It was chosen to match the type values in the return results. That way we can use those directly as the dictionary keys.
We set this up initially with blank entries for the lists:
new_tide_info = {"H":[], "L":[]}
Then we loop over each entry and parse the data. We use type
as is for the key. We don't want the date part of the t entry, so we split it on the space and save only the second part - the time.
for info in raw_info: tide_type = info["type"] tide_time = info["t"].split(" ")[1] new_tide_info[tide_type].append(tide_time)
Done! Now new_tide_info
has what we want, so we return it.
return new_tide_info
The rest of the code just displays these results. The very bottom of the code is a loop that runs for ever. Once a day it will go and fetch the new tide data.
Page last edited January 21, 2025
Text editor powered by tinymce.