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.root_group.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.