High Low Tide Times Viewer

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 Zip link, 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's CIRCUITPY drive, and then be sure to rename pp_tides.py to code.py so it will automatically run when the PyPortal restarts.

Editing the Code

At the top of the code, find the line that sets the station ID and change it for your location:

Download: file
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.

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://tidesandcurrents.noaa.gov/api/datagetter?date=today&product=predictions&datum=mllw&interval=hilo&format=json&units=metric&time_zone=lst_ldt&station="+STATION_ID
DATA_LOCATION = ["predictions"]

# determine the current working directory needed so we know where to find files
cwd = ("/"+__file__).rsplit('/', 1)[0]
pyportal = PyPortal(url=DATA_SOURCE,
                    json_path=DATA_LOCATION,
                    status_neopixel=board.NEOPIXEL,
                    default_bg=cwd+"/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(cwd+"/fonts/cq-mono-30.bdf")
tide_font.load_glyphs(b'1234567890:')

# Setup date and time font
date_font = bitmap_font.load_font(cwd+"/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.splash.append(label)

def get_tide_info():
    """Fetch JSON tide time info and return it."""

    # Get raw JSON data
    raw_info = pyportal.fetch()

    # 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:
        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)

    board.DISPLAY.refresh_soon()

# 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)

How It Works

As mentioned previously, the JSON data we need to deal with looks like this:

Download: file
{ "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.

Download: file
    raw_data = pyportal.fetch()

Now we need to parse out the data in raw_data. 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:

Download: file
    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.

Download: file
    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.

Download: file
    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.

This guide was first published on Apr 17, 2019. It was last updated on Apr 17, 2019. This page (High Low Tide Times Viewer) was last updated on Jun 17, 2019.