From 96a1380ef4b25d55ffbe148a01f8cb0aa3cd9ab2 Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:10:38 -0400 Subject: [PATCH 1/6] add rocketlaunch.live free API example The free API returns data on the next 5 scheduled rocket launches. One of the nice features of this API is any key:value that does not have data will return a string of "None". This almost eliminates all key:value errors. --- .../requests_wifi_api_rocketlaunch_live.py | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py diff --git a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py new file mode 100644 index 0000000..0460e5c --- /dev/null +++ b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py @@ -0,0 +1,114 @@ +# SPDX-FileCopyrightText: 2024 DJDevon3 +# SPDX-License-Identifier: MIT +# Coded for Circuit Python 8.2.x +"""RocketLaunch.Live API Example""" + +import gc +import os +import ssl +import time +import socketpool +import wifi +import adafruit_requests + +# Initialize WiFi Pool (There can be only 1 pool & top of script) +pool = socketpool.SocketPool(wifi.radio) + +# Time between API refreshes +# 900 = 15 mins, 1800 = 30 mins, 3600 = 1 hour +sleep_time = 43200 + +# Get WiFi details, ensure these are setup in settings.toml +ssid = os.getenv("WIFI_SSID") +password = os.getenv("WIFI_PASSWORD") + + +# Converts seconds in minutes/hours/days +def time_calc(input_time): + if input_time < 60: + sleep_int = input_time + time_output = f"{sleep_int:.0f} seconds" + elif 60 <= input_time < 3600: + sleep_int = input_time / 60 + time_output = f"{sleep_int:.0f} minutes" + elif 3600 <= input_time < 86400: + sleep_int = input_time / 60 / 60 + time_output = f"{sleep_int:.0f} hours" + elif 86400 <= input_time < 432000: + sleep_int = input_time / 60 / 60 / 24 + time_output = f"{sleep_int:.1f} days" + else: # if > 5 days convert float to int & display whole days + sleep_int = input_time / 60 / 60 / 24 + time_output = f"{sleep_int:.0f} days" + return time_output + + +# Free Public API, no token or header required +ROCKETLAUNCH_SOURCE = "https://fdo.rocketlaunch.live/json/launches/next/1" + +# Connect to Wi-Fi +print("\n===============================") +print("Connecting to WiFi...") +requests = adafruit_requests.Session(pool, ssl.create_default_context()) +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") + time.sleep(10) + gc.collect() +print("✅ WiFi!") +print("===============================") + +while True: + try: + # Print Request to Serial + print("Attempting to GET RocketLaunch.Live JSON!") + debug_rocketlaunch_full_response = False + + rocketlaunch_response = requests.get(url=ROCKETLAUNCH_SOURCE) + try: + rocketlaunch_json = rocketlaunch_response.json() + except ConnectionError as e: + print("❌ Connection Error:", e) + print("Retrying in 10 seconds") + if debug_rocketlaunch_full_response: + print("Full API GET URL: ", ROCKETLAUNCH_SOURCE) + print(rocketlaunch_json) + + print("✅ RocketLaunch.Live JSON!") + rocketlaunch_flightname = str(rocketlaunch_json["result"][0]["name"]) + print(f" | Flight Name: {rocketlaunch_flightname}") + rocketlaunch_provider = str(rocketlaunch_json["result"][0]["provider"]["name"]) + print(f" | Provider: {rocketlaunch_provider}") + rocketlaunch_vehiclename = str( + rocketlaunch_json["result"][0]["vehicle"]["name"] + ) + print(f" | Vehicle Name: {rocketlaunch_vehiclename}") + + rocketlaunch_winopen = str(rocketlaunch_json["result"][0]["win_open"]) + rocketlaunch_winclose = str(rocketlaunch_json["result"][0]["win_close"]) + print(f" | Window: {rocketlaunch_winopen} to {rocketlaunch_winclose}") + + rocketlaunch_sitename = str( + rocketlaunch_json["result"][0]["pad"]["location"]["name"] + ) + print(f" | Launch Site: {rocketlaunch_sitename}") + + rocketlaunch_mission = str( + rocketlaunch_json["result"][0]["mission_description"] + ) + if rocketlaunch_mission != "None": + print(f" | Mission: {rocketlaunch_mission}") + + print("\nFinished!") + print("Board Uptime: ", time.monotonic()) + print("Next Update in: ", time_calc(sleep_time)) + print("===============================") + gc.collect() + except (ValueError, RuntimeError) as e: + print("Failed to get data, retrying\n", e) + time.sleep(60) + continue + time.sleep(sleep_time) From 40e0c177d4a56f1c9c83ab36ef5cde5f0953bda8 Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:31:01 -0400 Subject: [PATCH 2/6] pre-commit, black, pylint seems like it wants these changes but might still fail on pylint and unsure why. --- examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py index 0460e5c..4939365 100644 --- a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py +++ b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py @@ -7,8 +7,10 @@ import os import ssl import time + import socketpool import wifi + import adafruit_requests # Initialize WiFi Pool (There can be only 1 pool & top of script) From ac1e119d8276de6844358850bdaa1dfb3fb02af5 Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Fri, 15 Mar 2024 02:08:37 -0400 Subject: [PATCH 3/6] Changed to Connection Manager refactored with Connection Manager, added pretty hierarchy serial view. --- .../requests_wifi_api_rocketlaunch_live.py | 111 ++++++++++-------- 1 file changed, 59 insertions(+), 52 deletions(-) diff --git a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py index 4939365..d9d04ec 100644 --- a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py +++ b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py @@ -3,19 +3,12 @@ # Coded for Circuit Python 8.2.x """RocketLaunch.Live API Example""" -import gc import os -import ssl import time - -import socketpool import wifi - +import adafruit_connection_manager import adafruit_requests -# Initialize WiFi Pool (There can be only 1 pool & top of script) -pool = socketpool.SocketPool(wifi.radio) - # Time between API refreshes # 900 = 15 mins, 1800 = 30 mins, 3600 = 1 hour sleep_time = 43200 @@ -45,72 +38,86 @@ def time_calc(input_time): return time_output -# Free Public API, no token or header required +# Publicly available data no header required +# The number at the end is the amount of launches (max 5 free api) ROCKETLAUNCH_SOURCE = "https://fdo.rocketlaunch.live/json/launches/next/1" -# Connect to Wi-Fi -print("\n===============================") -print("Connecting to WiFi...") -requests = adafruit_requests.Session(pool, ssl.create_default_context()) -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") - time.sleep(10) - gc.collect() -print("✅ WiFi!") -print("===============================") +# 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) while True: + # 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 Request to Serial - print("Attempting to GET RocketLaunch.Live JSON!") + print(" | Attempting to GET RocketLaunch.Live JSON!") + time.sleep(2) debug_rocketlaunch_full_response = False - rocketlaunch_response = requests.get(url=ROCKETLAUNCH_SOURCE) try: + rocketlaunch_response = requests.get(url=ROCKETLAUNCH_SOURCE) rocketlaunch_json = rocketlaunch_response.json() except ConnectionError as e: - print("❌ Connection Error:", e) + print("Connection Error:", e) print("Retrying in 10 seconds") + print(" | ✅ RocketLaunch.Live JSON!") + if debug_rocketlaunch_full_response: print("Full API GET URL: ", ROCKETLAUNCH_SOURCE) print(rocketlaunch_json) - print("✅ RocketLaunch.Live JSON!") - rocketlaunch_flightname = str(rocketlaunch_json["result"][0]["name"]) - print(f" | Flight Name: {rocketlaunch_flightname}") - rocketlaunch_provider = str(rocketlaunch_json["result"][0]["provider"]["name"]) - print(f" | Provider: {rocketlaunch_provider}") - rocketlaunch_vehiclename = str( - rocketlaunch_json["result"][0]["vehicle"]["name"] - ) - print(f" | Vehicle Name: {rocketlaunch_vehiclename}") - - rocketlaunch_winopen = str(rocketlaunch_json["result"][0]["win_open"]) - rocketlaunch_winclose = str(rocketlaunch_json["result"][0]["win_close"]) - print(f" | Window: {rocketlaunch_winopen} to {rocketlaunch_winclose}") - - rocketlaunch_sitename = str( - rocketlaunch_json["result"][0]["pad"]["location"]["name"] - ) - print(f" | Launch Site: {rocketlaunch_sitename}") - - rocketlaunch_mission = str( - rocketlaunch_json["result"][0]["mission_description"] - ) - if rocketlaunch_mission != "None": - print(f" | Mission: {rocketlaunch_mission}") + # JSON Endpoints + RLFN = str(rocketlaunch_json["result"][0]["name"]) + RLWO = str(rocketlaunch_json["result"][0]["win_open"]) + TMINUS = str(rocketlaunch_json["result"][0]["t0"]) + RLWC = str(rocketlaunch_json["result"][0]["win_close"]) + RLP = str(rocketlaunch_json["result"][0]["provider"]["name"]) + RLVN = str(rocketlaunch_json["result"][0]["vehicle"]["name"]) + RLPN = str(rocketlaunch_json["result"][0]["pad"]["name"]) + RLLS = str(rocketlaunch_json["result"][0]["pad"]["location"]["name"]) + RLLD = str(rocketlaunch_json["result"][0]["launch_description"]) + RLM = str(rocketlaunch_json["result"][0]["mission_description"]) + RLDATE = str(rocketlaunch_json["result"][0]["date_str"]) + + # Print to serial & display label if endpoint not "None" + if RLDATE != "None": + print(f" | | Date: {RLDATE}") + if RLFN != "None": + print(f" | | Flight: {RLFN}") + if RLP != "None": + print(f" | | Provider: {RLP}") + if RLVN != "None": + print(f" | | Vehicle: {RLVN}") + if RLWO != "None": + print(f" | | Window: {RLWO} to {RLWC}") + elif TMINUS != "None": + print(f" | | Window: {TMINUS} to {RLWC}") + if RLLS != "None": + print(f" | | Site: {RLLS}") + if RLPN != "None": + print(f" | | Pad: {RLPN}") + if RLLD != "None": + print(f" | | Description: {RLLD}") + if RLM != "None": + print(f" | | Mission: {RLM}") print("\nFinished!") print("Board Uptime: ", time.monotonic()) print("Next Update in: ", time_calc(sleep_time)) print("===============================") - gc.collect() + except (ValueError, RuntimeError) as e: print("Failed to get data, retrying\n", e) time.sleep(60) - continue + break time.sleep(sleep_time) From fb7fcedbc6807302d3a09ba25c1c97dc6dbd9c57 Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Fri, 15 Mar 2024 02:15:44 -0400 Subject: [PATCH 4/6] ran isort manually This is going to be thing now. --- examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py index d9d04ec..d85163b 100644 --- a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py +++ b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py @@ -5,9 +5,10 @@ import os import time -import wifi + import adafruit_connection_manager import adafruit_requests +import wifi # Time between API refreshes # 900 = 15 mins, 1800 = 30 mins, 3600 = 1 hour From ef79fed9cba394637c08f34eccfc679f819fc2e8 Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Fri, 15 Mar 2024 02:24:29 -0400 Subject: [PATCH 5/6] this isort thing is driving me nuts --- examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py index d85163b..768d57d 100644 --- a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py +++ b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py @@ -5,7 +5,6 @@ import os import time - import adafruit_connection_manager import adafruit_requests import wifi From c11f4919c070e35ccb8d87bbd4a0cc34652f952c Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Fri, 15 Mar 2024 02:39:13 -0400 Subject: [PATCH 6/6] isnt the point of isort to fix import sorting? --- examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py index 768d57d..dc497a4 100644 --- a/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py +++ b/examples/wifi/expanded/requests_wifi_api_rocketlaunch_live.py @@ -5,10 +5,12 @@ import os import time + import adafruit_connection_manager -import adafruit_requests import wifi +import adafruit_requests + # Time between API refreshes # 900 = 15 mins, 1800 = 30 mins, 3600 = 1 hour sleep_time = 43200