-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add Queue-Times API Example #182
Changes from 2 commits
44f40c3
5b86eb1
0a772cf
c32d582
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# SPDX-FileCopyrightText: 2024 DJDevon3 | ||
# SPDX-License-Identifier: MIT | ||
# Coded for Circuit Python 9.x | ||
"""Queue-Times.com API Example""" | ||
|
||
import os | ||
import time | ||
|
||
import adafruit_connection_manager | ||
import wifi | ||
|
||
import adafruit_requests | ||
|
||
# Initalize Wifi, Socket Pool, Request Session | ||
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio) | ||
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio) | ||
requests = adafruit_requests.Session(pool, ssl_context) | ||
|
||
# Time between API refreshes | ||
# 900 = 15 mins, 1800 = 30 mins, 3600 = 1 hour | ||
SLEEP_TIME = 300 | ||
|
||
# Get WiFi details, ensure these are setup in settings.toml | ||
ssid = os.getenv("CIRCUITPY_WIFI_SSID") | ||
password = os.getenv("CIRCUITPY_WIFI_PASSWORD") | ||
|
||
# Publicly Open API (no credentials required) | ||
QTIMES_SOURCE = "https://queue-times.com/parks/16/queue_times.json" | ||
|
||
|
||
def time_calc(input_time): | ||
"""Converts seconds to minutes/hours/days""" | ||
if input_time < 60: | ||
return f"{input_time:.0f} seconds" | ||
if input_time < 3600: | ||
return f"{input_time / 60:.0f} minutes" | ||
if input_time < 86400: | ||
return f"{input_time / 60 / 60:.0f} hours" | ||
return f"{input_time / 60 / 60 / 24:.1f} days" | ||
|
||
|
||
qtimes_json = {} | ||
while True: | ||
now = time.monotonic() | ||
# Connect to Wi-Fi | ||
print("\n===============================") | ||
print("Connecting to WiFi...") | ||
while not wifi.radio.ipv4_address: | ||
try: | ||
wifi.radio.connect(ssid, password) | ||
except ConnectionError as e: | ||
print("❌ Connection Error:", e) | ||
print("Retrying in 10 seconds") | ||
print("✅ WiFi!") | ||
|
||
try: | ||
print(" | Attempting to GET Queue-Times JSON!") | ||
try: | ||
qtimes_response = requests.get(url=QTIMES_SOURCE) | ||
qtimes_json = qtimes_response.json() | ||
except ConnectionError as e: | ||
print("Connection Error:", e) | ||
print("Retrying in 10 seconds") | ||
print(" | ✅ Queue-Times JSON!") | ||
|
||
DEBUG_QTIMES = False | ||
if DEBUG_QTIMES: | ||
print("Full API GET URL: ", QTIMES_SOURCE) | ||
print(qtimes_json) | ||
qtimes_response.close() | ||
print("✂️ Disconnected from Queue-Times API") | ||
|
||
print("\nFinished!") | ||
print(f"Board Uptime: {time_calc(time.monotonic())}") | ||
print(f"Next Update: {time_calc(SLEEP_TIME)}") | ||
print("===============================") | ||
except (ValueError, RuntimeError) as e: | ||
print("Failed to get data, retrying\n", e) | ||
time.sleep(60) | ||
break | ||
|
||
# Loop infinitely until its time to re-poll | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This extra loop that is printing the results over and over again until it's time to fetch new data confused me. At first I thought it was actually retching new data all the time and worried about rate limit problem with the server, but I did eventually realize it's not actually fetching, just re-printing the same data in a loop while it waits for the next time to fetch. I'm in favor of removing that loop and just printing the results once. By printing them over and over it feels like it's implying to the user that there is new data to see when it's actually just printing the same data again. It also makes it a little hard to hone in on a specific ride if they are interested in one. (Though they of course could modify it to print a single one, granted.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @FoamyGuy Yes, that is specifically the way they requested it to behave. I suppose printing a "last updated" timestamp would make sense but would take up precious screen real estate. It makes less sense on a huge 3.5" TFT. The project intention is for a portable SSD1306 with a lipo battery on a watch band. In the real script it will attempt to reconnect (via a tethered phone hotspot) every 5 minutes. Perhaps I could improve upon the code comments to specify that's the intention of this particular example? If you gave one device to each kid and it only worked within range of the hotspot it could ensure that your kids will want to stay close enough to ensure the device works so they get ride updates too. It's a brilliant incentive for your kids to want to stay close to you in a theme park. Maybe change the text color after an update so that every new update is unmistakably new? That would serve as an indicator of new content without taking up any screen real estate but a display is not included in this example. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am still in favor of removing the looping behavior from the example here. That sounds like a neat project and they can definitely still use it that way if they'd like. I could also see a world where someone might want to "favorite" certain rides to get information about them more prominently or even some alerts based on the data returned. I believe that in it's usage as an example here the continued printing of the same data over and over makes it more confusing because it's difficult to tell what is happening and when there is actually new data. None of the rest of the examples in this repo behave that way, they're all either "single shot" fetching once and ending, or repeating in a loop that fetches every X minutes or seconds and prints the current data then waits until it's time to run again. I believe it's best to have this example match that behavior and only print the data once after it's been fetched. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @FoamyGuy sounds good. I have the example that the person wanted in my personal repo, and linked them there, and they already have that one. Turning it into a single use "code done running" sounds good to me. |
||
if time.monotonic() - now <= SLEEP_TIME: | ||
for land in qtimes_json["lands"]: | ||
qtimes_lands = str(land["name"]) | ||
print(f" | | Lands: {qtimes_lands}") | ||
time.sleep(1) | ||
|
||
# Loop through each ride in the land | ||
for ride in land["rides"]: | ||
qtimes_rides = str(ride["name"]) | ||
qtimes_queuetime = str(ride["wait_time"]) | ||
qtimes_isopen = str(ride["is_open"]) | ||
|
||
print(f" | | Ride: {qtimes_rides}") | ||
print(f" | | Queue Time: {qtimes_queuetime} Minutes") | ||
if qtimes_isopen == "False": | ||
print(" | | Status: Closed") | ||
elif qtimes_isopen == "True": | ||
print(" | | Status: Open") | ||
else: | ||
print(" | | Status: Unknown") | ||
|
||
time.sleep(1) # delay between list items | ||
else: # When its time to poll, break to top of while True loop. | ||
break |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.