From 1635b7b0fe21bacdfa6e43b22a8c918737b26448 Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Mon, 29 May 2023 04:04:19 -0400 Subject: [PATCH 1/8] Add OpenSky-Network API example Free public limit is 100 calls per day and maximum of 60 seconds each or you'll get temp banned. You get 4000 calls if you login but I haven't figured out how with a microcontroller yet. They have no token system and their API is primarily built for python & curl. It's a foot in the door for public access to flight data. --- .../requests_api_openskynetwork_public.py | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 examples/requests_api_openskynetwork_public.py diff --git a/examples/requests_api_openskynetwork_public.py b/examples/requests_api_openskynetwork_public.py new file mode 100644 index 0000000..abcc698 --- /dev/null +++ b/examples/requests_api_openskynetwork_public.py @@ -0,0 +1,141 @@ +# SPDX-FileCopyrightText: 2023 DJDevon3 +# SPDX-License-Identifier: MIT +# Coded for Circuit Python 8.1 +"""DJDevon3 Adafruit Feather ESP32-S3 OpenSkyNetwork_API_Example""" +import os +import time +import ssl +import json +import wifi +import socketpool +import adafruit_requests + +# No developer account necessary for this API +# OpenSky-Networks.org REST API: https://openskynetwork.github.io/opensky-api/rest.html +# All active flights JSON: https://opensky-network.org/api/states/all +# JSON order: transponder, callsign, country +# ACTIVE transponder you want data from +transponder = "ab1644" + +# 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 +# OpenSky-Networks will temp ban your IP for too many requests, there is a public rate limit. +# https://openskynetwork.github.io/opensky-api/rest.html#limitations +sleep_time = 1800 + +# this example uses settings.toml for credentials +# timezone offset is in seconds plus or minus GMT +ssid = os.getenv('AP_SSID') +appw = os.getenv('AP_PASSWORD') +timezone = os.getenv('timezone') +tz_offset_seconds = os.getenv('timezone_offset') + +# https://opensky-network.org/api/states/all +# example https://opensky-network.org/api/states/all?icao24=a808c5 +# You can use states/own to pull your owned craft data without rate limit. +OPENSKY_SOURCE = ( + "https://opensky-network.org/api/states/all?" + + "icao24=" + + transponder +) + +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:.1f} 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 + +def _format_datetime(datetime): + return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format( + datetime.tm_mon, + datetime.tm_mday, + datetime.tm_year, + datetime.tm_hour, + datetime.tm_min, + datetime.tm_sec, + ) + +# 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, appw) + except ConnectionError as e: + print("Connection Error:", e) + print("Retrying in 10 seconds") + time.sleep(10) +print("Connected!\n") + +while True: + debug_request = True # Set true to see full request + if debug_request: + print("Full API GET URL: ", OPENSKY_SOURCE) + print("===============================") + try: + print("\nAttempting to GET OpenSky-Network Stats!") + opensky_response = requests.get(url=OPENSKY_SOURCE) + osn_json = opensky_response.json() + except (ConnectionError, ValueError, NameError) as e: + print("Host No Response Error:", e) + + # Print Full JSON to Serial + debug_response = False # Set true to see full response + if debug_response: + dump_object = json.dumps(osn_json) + print("JSON Dump: ", dump_object) + + # Print to Serial + osn_debug_keys = True # Set true to print Serial data + if osn_debug_keys: + try: + osn_flight = osn_json['time'] + print("Current Unix Time: ", osn_flight) + + current_struct_time = time.localtime(osn_flight) + current_date = "{}".format(_format_datetime(current_struct_time)) + print(f"Unix to Readable Time: {current_date}") + + osn_single_flight_data = osn_json['states'] + if osn_single_flight_data is not None: + print("Flight Data: ", osn_single_flight_data) + transponder = osn_json['states'][0][0] + print("Transponder: ", transponder) + callsign = osn_json['states'][0][1] + print("Callsign: ", callsign) + country = osn_json['states'][0][2] + print("Flight Country: ", country) + else: + print("This flight has no active data or you're polling too fast.") + print("You will eventually get temp banned for polling too fast!") + print("Please read: https://openskynetwork.github.io/opensky-api/rest.html#limitations") + print("Public Limits: 10 second max poll rate & 400 weighted calls daily") + print("There is no JSON error, states/all html page will say \"Too many requests\" and the script will fail ") + + print("\nFinished!") + print("Board Uptime: ", time_calc(time.monotonic())) + print("Next Update: ", time_calc(sleep_time)) + time.sleep(sleep_time) + print("===============================") + + except (ConnectionError, ValueError, NameError) as e: + print("OSN Connection Error:", e) + print("You are likely banned for 24 hours") + print("Next Retry: ", time_calc(sleep_time)) + time.sleep(sleep_time) \ No newline at end of file From 626605f695b98f9c33c3e5b51157b2168eb9608d Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Mon, 29 May 2023 04:08:42 -0400 Subject: [PATCH 2/8] i want to give black a black eye i forget every single time --- .../requests_api_openskynetwork_public.py | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/examples/requests_api_openskynetwork_public.py b/examples/requests_api_openskynetwork_public.py index abcc698..54c1776 100644 --- a/examples/requests_api_openskynetwork_public.py +++ b/examples/requests_api_openskynetwork_public.py @@ -28,19 +28,16 @@ # this example uses settings.toml for credentials # timezone offset is in seconds plus or minus GMT -ssid = os.getenv('AP_SSID') -appw = os.getenv('AP_PASSWORD') -timezone = os.getenv('timezone') -tz_offset_seconds = os.getenv('timezone_offset') +ssid = os.getenv("AP_SSID") +appw = os.getenv("AP_PASSWORD") +timezone = os.getenv("timezone") +tz_offset_seconds = os.getenv("timezone_offset") # https://opensky-network.org/api/states/all # example https://opensky-network.org/api/states/all?icao24=a808c5 # You can use states/own to pull your owned craft data without rate limit. -OPENSKY_SOURCE = ( - "https://opensky-network.org/api/states/all?" - + "icao24=" - + transponder -) +OPENSKY_SOURCE = "https://opensky-network.org/api/states/all?" + "icao24=" + transponder + def time_calc(input_time): if input_time < 60: @@ -60,6 +57,7 @@ def time_calc(input_time): time_output = f"{sleep_int:.0f} days" return time_output + def _format_datetime(datetime): return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format( datetime.tm_mon, @@ -70,6 +68,7 @@ def _format_datetime(datetime): datetime.tm_sec, ) + # Connect to Wi-Fi print("\n===============================") print("Connecting to WiFi...") @@ -105,37 +104,43 @@ def _format_datetime(datetime): osn_debug_keys = True # Set true to print Serial data if osn_debug_keys: try: - osn_flight = osn_json['time'] + osn_flight = osn_json["time"] print("Current Unix Time: ", osn_flight) - + current_struct_time = time.localtime(osn_flight) current_date = "{}".format(_format_datetime(current_struct_time)) print(f"Unix to Readable Time: {current_date}") - osn_single_flight_data = osn_json['states'] + osn_single_flight_data = osn_json["states"] if osn_single_flight_data is not None: print("Flight Data: ", osn_single_flight_data) - transponder = osn_json['states'][0][0] + transponder = osn_json["states"][0][0] print("Transponder: ", transponder) - callsign = osn_json['states'][0][1] + callsign = osn_json["states"][0][1] print("Callsign: ", callsign) - country = osn_json['states'][0][2] + country = osn_json["states"][0][2] print("Flight Country: ", country) else: print("This flight has no active data or you're polling too fast.") print("You will eventually get temp banned for polling too fast!") - print("Please read: https://openskynetwork.github.io/opensky-api/rest.html#limitations") - print("Public Limits: 10 second max poll rate & 400 weighted calls daily") - print("There is no JSON error, states/all html page will say \"Too many requests\" and the script will fail ") - + print( + "Please read: https://openskynetwork.github.io/opensky-api/rest.html#limitations" + ) + print( + "Public Limits: 10 second max poll rate & 400 weighted calls daily" + ) + print( + 'There is no JSON error, states/all html page will say "Too many requests" and the script will fail ' + ) + print("\nFinished!") - print("Board Uptime: ", time_calc(time.monotonic())) + print("Board Uptime: ", time_calc(time.monotonic())) print("Next Update: ", time_calc(sleep_time)) time.sleep(sleep_time) print("===============================") - + except (ConnectionError, ValueError, NameError) as e: print("OSN Connection Error:", e) print("You are likely banned for 24 hours") print("Next Retry: ", time_calc(sleep_time)) - time.sleep(sleep_time) \ No newline at end of file + time.sleep(sleep_time) From 3092a6e83c9a1bf55d5b55555555db1cb0c9a8fb Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Mon, 29 May 2023 04:13:30 -0400 Subject: [PATCH 3/8] pylint too --- examples/requests_api_openskynetwork_public.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/requests_api_openskynetwork_public.py b/examples/requests_api_openskynetwork_public.py index 54c1776..a6e0de4 100644 --- a/examples/requests_api_openskynetwork_public.py +++ b/examples/requests_api_openskynetwork_public.py @@ -124,14 +124,11 @@ def _format_datetime(datetime): print("This flight has no active data or you're polling too fast.") print("You will eventually get temp banned for polling too fast!") print( - "Please read: https://openskynetwork.github.io/opensky-api/rest.html#limitations" + "Read: https://openskynetwork.github.io/opensky-api/rest.html#limitations" ) print( "Public Limits: 10 second max poll rate & 400 weighted calls daily" ) - print( - 'There is no JSON error, states/all html page will say "Too many requests" and the script will fail ' - ) print("\nFinished!") print("Board Uptime: ", time_calc(time.monotonic())) From b642f141825fe0d09e9583f87ecc0029ce92f9e9 Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Mon, 29 May 2023 06:34:43 -0400 Subject: [PATCH 4/8] Add OpenSkyNetwork Private API Website login required, uses circuitpython_base64 library for encoding. Allows for 4000 calls per day on any active available transponder in their network (about 40K aircraft). This was a somewhat requested API I took on.. and succeeded. --- .../requests_api_openskynetwork_private.py | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 examples/requests_api_openskynetwork_private.py diff --git a/examples/requests_api_openskynetwork_private.py b/examples/requests_api_openskynetwork_private.py new file mode 100644 index 0000000..c4d1bbd --- /dev/null +++ b/examples/requests_api_openskynetwork_private.py @@ -0,0 +1,153 @@ +# SPDX-FileCopyrightText: 2023 DJDevon3 +# SPDX-License-Identifier: MIT +# Coded for Circuit Python 8.1 +# DJDevon3 ESP32-S3 OpenSkyNetwork_Private_API_Example + +import os +import time +import ssl +import json +import wifi +import socketpool +import adafruit_requests +import circuitpython_base64 as base64 + +# OpenSky-Network.org Login required for this API +# REST API: https://openskynetwork.github.io/opensky-api/rest.html +# All active flights JSON: https://opensky-network.org/api/states/all # PICK ONE! :) +# JSON order: transponder, callsign, country +# ACTIVE transpondes only, for multiple "c822af&icao24=cb3993&icao24=c63923" +transponder = "7c6b2d" + +# 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 +# OpenSky-Networks IP bans for too many requests, check rate limit. +# https://openskynetwork.github.io/opensky-api/rest.html#limitations +sleep_time = 1800 + +# this example uses settings.toml for credentials +# timezone offset is in seconds plus or minus GMT +ssid = os.getenv("AP_SSID") +appw = os.getenv("AP_PASSWORD") +osnu = os.getenv("OSN_Username") +osnp = os.getenv("OSN_Password") + +osn_cred = str(osnu) + ":" + str(osnp) +bytes_to_encode = b" " + str(osn_cred) + " " +base64_string = base64.encodebytes(bytes_to_encode) +basepw = repr(base64_string)[2:-1] + +Debug_Auth = False # STREAMER WARNING this will show your credentials! +if Debug_Auth: + osn_cred = str(osnu) + ":" + str(osnp) + bytes_to_encode = b" " + str(osn_cred) + " " + print(repr(bytes_to_encode)) + base64_string = base64.encodebytes(bytes_to_encode) + print(repr(base64_string)[2:-1]) + basepw = repr(base64_string)[2:-1] + print("Decoded Bytes:", str(basepw)) + +# OSN requires your username:password to be base64 encoded +# so technically it's not transmitted in the clear but w/e +osn_header = {"Authorization": "Basic " + str(basepw)} +OPENSKY_SOURCE = "https://opensky-network.org/api/states/all?" + "icao24=" + transponder + + +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:.1f} 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 + + +def _format_datetime(datetime): + return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format( + datetime.tm_mon, + datetime.tm_mday, + datetime.tm_year, + datetime.tm_hour, + datetime.tm_min, + datetime.tm_sec, + ) + + +# Connect to Wi-Fi +print("\n===============================") +print("Connecting to WiFi...") +request = adafruit_requests.Session(pool, ssl.create_default_context()) +while not wifi.radio.ipv4_address: + try: + wifi.radio.connect(ssid, appw) + except ConnectionError as e: + print("Connection Error:", e) + print("Retrying in 10 seconds") + time.sleep(10) +print("Connected!\n") + +while True: + # STREAMER WARNING this will show your credentials! + debug_request = False # Set true to see full request + if debug_request: + print("Full API HEADER: ", str(osn_header)) + print("Full API GET URL: ", OPENSKY_SOURCE) + print("===============================") + + print("\nAttempting to GET OpenSky-Network Data!") + opensky_response = request.get(url=OPENSKY_SOURCE, headers=osn_header).json() + # Print Full JSON to Serial (doesn't show credentials) + debug_response = False # Set true to see full response + if debug_response: + dump_object = json.dumps(opensky_response) + print("JSON Dump: ", dump_object) + + # Print to Serial + osn_debug_keys = True # Set true to print Serial data + if osn_debug_keys: + try: + osn_flight = opensky_response["time"] + print("Current Unix Time: ", osn_flight) + + current_struct_time = time.localtime(osn_flight) + current_date = "{}".format(_format_datetime(current_struct_time)) + print(f"Unix to Readable Time: {current_date}") + + # Current flight data for single callsign (right now) + osn_single_flight_data = opensky_response["states"] + + if osn_single_flight_data is not None: + print("Flight Data: ", osn_single_flight_data) + transponder = opensky_response["states"][0][0] + print("Transponder: ", transponder) + callsign = opensky_response["states"][0][1] + print("Callsign: ", callsign) + country = opensky_response["states"][0][2] + print("Flight Country: ", country) + else: + print("Flight has no active data or you're polling too fast.") + + print("\nFinished!") + print("Board Uptime: ", time_calc(time.monotonic())) + print("Next Update: ", time_calc(sleep_time)) + time.sleep(sleep_time) + print("===============================") + + except (ConnectionError, ValueError, NameError) as e: + print("OSN Connection Error:", e) + print("You are likely banned for 24 hours") + print("Next Retry: ", time_calc(sleep_time)) + time.sleep(sleep_time) From 02b5f85d421df35c4dc367f05ef7115852547eef Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Mon, 29 May 2023 06:39:08 -0400 Subject: [PATCH 5/8] ok sometimes pylint is very helpful rearranged imports to make pylint happy --- examples/requests_api_openskynetwork_private.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/requests_api_openskynetwork_private.py b/examples/requests_api_openskynetwork_private.py index c4d1bbd..47e65d4 100644 --- a/examples/requests_api_openskynetwork_private.py +++ b/examples/requests_api_openskynetwork_private.py @@ -9,8 +9,8 @@ import json import wifi import socketpool -import adafruit_requests import circuitpython_base64 as base64 +import adafruit_requests # OpenSky-Network.org Login required for this API # REST API: https://openskynetwork.github.io/opensky-api/rest.html From f1492972a368b20ba4f64236e338578a62326ea9 Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Mon, 29 May 2023 21:46:23 -0400 Subject: [PATCH 6/8] added OpenSky Geographic Area Shows all flight traffic in a lat/lon area. This one is really neat! --- ...equests_api_openskynetwork_private_area.py | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 examples/requests_api_openskynetwork_private_area.py diff --git a/examples/requests_api_openskynetwork_private_area.py b/examples/requests_api_openskynetwork_private_area.py new file mode 100644 index 0000000..fa69a3c --- /dev/null +++ b/examples/requests_api_openskynetwork_private_area.py @@ -0,0 +1,187 @@ +# SPDX-FileCopyrightText: 2023 DJDevon3 +# SPDX-License-Identifier: MIT +# Coded for Circuit Python 8.1 +# DJDevon3 ESP32-S3 OpenSkyNetwork_Private__Area_API_Example + +import os +import time +import ssl +import json +import wifi +import socketpool +import circuitpython_base64 as base64 +import adafruit_requests + +# OpenSky-Network.org Login required for this API +# REST API: https://openskynetwork.github.io/opensky-api/rest.html +# All active flights JSON: https://opensky-network.org/api/states/all # PICK ONE! :) + +# Retrieves all traffic within a geographic area (Orlando example) +latmin = "27.22" # east bounding box +latmax = "28.8" # west bounding box +lonmin = "-81.46" # north bounding box +lonmax = "-80.40" # south bounding box + +# 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 +# OpenSky-Networks IP bans for too many requests, check rate limit. +# https://openskynetwork.github.io/opensky-api/rest.html#limitations +sleep_time = 1800 + +# this example uses settings.toml for credentials +# No token required, only website login +ssid = os.getenv("AP_SSID") +appw = os.getenv("AP_PASSWORD") +osnu = os.getenv("OSN_Username") +osnp = os.getenv("OSN_Password") + +osn_cred = str(osnu) + ":" + str(osnp) +bytes_to_encode = b" " + str(osn_cred) + " " +base64_string = base64.encodebytes(bytes_to_encode) +basepw = repr(base64_string)[2:-1] + +Debug_Auth = False # STREAMER WARNING this will show your credentials! +if Debug_Auth: + osn_cred = str(osnu) + ":" + str(osnp) + bytes_to_encode = b" " + str(osn_cred) + " " + print(repr(bytes_to_encode)) + base64_string = base64.encodebytes(bytes_to_encode) + print(repr(base64_string)[2:-1]) + basepw = repr(base64_string)[2:-1] + print("Decoded Bytes:", str(basepw)) + +# OSN requires your username:password to be base64 encoded +# so technically it's not transmitted in the clear but w/e +osn_header = {"Authorization": "Basic " + str(basepw)} + +# Example of all traffic over Florida, geographic areas cost less per call. +# https://opensky-network.org/api/states/all?lamin=25.21&lomin=-84.36&lamax=30.0&lomax=-78.40 +OPENSKY_SOURCE = ( + "https://opensky-network.org/api/states/all?" + + "lamin=" + + latmin + + "&lomin=" + + lonmin + + "&lamax=" + + latmax + + "&lomax=" + + lonmax +) + + +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:.1f} 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 + + +def _format_datetime(datetime): + return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format( + datetime.tm_mon, + datetime.tm_mday, + datetime.tm_year, + datetime.tm_hour, + datetime.tm_min, + datetime.tm_sec, + ) + + +# Connect to Wi-Fi +print("\n===============================") +print("Connecting to WiFi...") +request = adafruit_requests.Session(pool, ssl.create_default_context()) +while not wifi.radio.ipv4_address: + try: + wifi.radio.connect(ssid, appw) + except ConnectionError as e: + print("Connection Error:", e) + print("Retrying in 10 seconds") + time.sleep(10) +print("Connected!\n") + +while True: + # STREAMER WARNING this will show your credentials! + debug_request = False # Set true to see full request + if debug_request: + print("Full API HEADER: ", str(osn_header)) + print("Full API GET URL: ", OPENSKY_SOURCE) + print("===============================") + + print("\nAttempting to GET OpenSky-Network Data!") + opensky_response = request.get(url=OPENSKY_SOURCE, headers=osn_header).json() + # Print Full JSON to Serial (doesn't show credentials) + debug_response = False # Set true to see full response + if debug_response: + dump_object = json.dumps(opensky_response) + print("JSON Dump: ", dump_object) + + # Print to Serial + osn_debug_keys = True # Set true to print Serial data + if osn_debug_keys: + try: + osn_flight = opensky_response["time"] + print("Current Unix Time: ", osn_flight) + + current_struct_time = time.localtime(osn_flight) + current_date = "{}".format(_format_datetime(current_struct_time)) + print(f"Unix to Readable Time: {current_date}") + + # Current flight data for single callsign (right now) + osn_all_flights = opensky_response["states"] + + if osn_all_flights is not None: + # print("Flight Data: ", osn_all_flights) + for flights in osn_all_flights: + osn_t = f"Trans:{flights[0]} " + osn_c = f"Sign:{flights[1]} " + osn_o = f"Origin:{flights[2]} " + osn_tm = f"Time:{flights[3]} " + osn_l = f"Last:{flights[4]} " + osn_lo = f"Lon:{flights[5]} " + osn_la = f"Lat:{flights[6]} " + osn_ba = f"BaroAlt:{flights[7]} " + osn_g = f"Ground:{flights[8]} " + osn_v = f"Vel:{flights[9]} " + osn_h = f"Head:{flights[10]} " + osn_vr = f"VertRate:{flights[11]} " + osn_s = f"Sens:{flights[12]} " + osn_ga = f"GeoAlt:{flights[13]} " + osn_sq = f"Squawk:{flights[14]} " + osn_pr = f"Task:{flights[15]} " + osn_ps = f"PosSys:{flights[16]} " + osn_ca = f"Cat:{flights[16]} " + # This is just because pylint complains about long lines + string1 = f"{osn_t}{osn_c}{osn_o}{osn_tm}{osn_l}{osn_lo}" + string2 = f"{osn_la}{osn_ba}{osn_g}{osn_v}{osn_h}{osn_vr}" + string3 = f"{osn_s}{osn_ga}{osn_sq}{osn_pr}{osn_ps}{osn_ca}" + print(f"{string1}{string2}{string3}") + else: + print("Flight has no active data or you're polling too fast.") + + print("\nFinished!") + print("Board Uptime: ", time_calc(time.monotonic())) + print("Next Update: ", time_calc(sleep_time)) + time.sleep(sleep_time) + print("===============================") + + except (ConnectionError, ValueError, NameError) as e: + print("OSN Connection Error:", e) + print("You are likely banned for 24 hours") + print("Next Retry: ", time_calc(sleep_time)) + time.sleep(sleep_time) From 722ab305749a3dce55674bcf61f6d8a6857d4d18 Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Tue, 13 Jun 2023 11:18:34 -0400 Subject: [PATCH 7/8] Fixing reviewer requested changes Removed unused timezone vars and assorted script clean up. Changed var for base64cred to be more obvious that a base64 encode is required in the request header. --- .../requests_api_openskynetwork_private.py | 34 ++++++++---------- ...equests_api_openskynetwork_private_area.py | 36 ++++++++----------- .../requests_api_openskynetwork_public.py | 31 ++++++---------- 3 files changed, 40 insertions(+), 61 deletions(-) diff --git a/examples/requests_api_openskynetwork_private.py b/examples/requests_api_openskynetwork_private.py index 47e65d4..e51b390 100644 --- a/examples/requests_api_openskynetwork_private.py +++ b/examples/requests_api_openskynetwork_private.py @@ -38,7 +38,7 @@ osn_cred = str(osnu) + ":" + str(osnp) bytes_to_encode = b" " + str(osn_cred) + " " base64_string = base64.encodebytes(bytes_to_encode) -basepw = repr(base64_string)[2:-1] +base64cred = repr(base64_string)[2:-1] Debug_Auth = False # STREAMER WARNING this will show your credentials! if Debug_Auth: @@ -47,16 +47,17 @@ print(repr(bytes_to_encode)) base64_string = base64.encodebytes(bytes_to_encode) print(repr(base64_string)[2:-1]) - basepw = repr(base64_string)[2:-1] - print("Decoded Bytes:", str(basepw)) + base64cred = repr(base64_string)[2:-1] + print("Decoded Bytes:", str(base64cred)) -# OSN requires your username:password to be base64 encoded -# so technically it's not transmitted in the clear but w/e -osn_header = {"Authorization": "Basic " + str(basepw)} +# Requests URL - icao24 is their endpoint required for a transponder +# example https://opensky-network.org/api/states/all?icao24=a808c5 +# OSN private requires your username:password to be base64 encoded +osn_header = {"Authorization": "Basic " + str(base64cred)} OPENSKY_SOURCE = "https://opensky-network.org/api/states/all?" + "icao24=" + transponder - -def time_calc(input_time): +# Converts seconds to human readable minutes/hours/days +def time_calc(input_time): # input_time in seconds if input_time < 60: sleep_int = input_time time_output = f"{sleep_int:.0f} seconds" @@ -66,15 +67,11 @@ def time_calc(input_time): elif 3600 <= input_time < 86400: sleep_int = input_time / 60 / 60 time_output = f"{sleep_int:.1f} hours" - elif 86400 <= input_time < 432000: + else: 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 - def _format_datetime(datetime): return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format( datetime.tm_mon, @@ -85,7 +82,6 @@ def _format_datetime(datetime): datetime.tm_sec, ) - # Connect to Wi-Fi print("\n===============================") print("Connecting to WiFi...") @@ -101,7 +97,7 @@ def _format_datetime(datetime): while True: # STREAMER WARNING this will show your credentials! - debug_request = False # Set true to see full request + debug_request = False # Set True to see full request if debug_request: print("Full API HEADER: ", str(osn_header)) print("Full API GET URL: ", OPENSKY_SOURCE) @@ -109,14 +105,15 @@ def _format_datetime(datetime): print("\nAttempting to GET OpenSky-Network Data!") opensky_response = request.get(url=OPENSKY_SOURCE, headers=osn_header).json() + # Print Full JSON to Serial (doesn't show credentials) - debug_response = False # Set true to see full response + debug_response = False # Set True to see full response if debug_response: dump_object = json.dumps(opensky_response) print("JSON Dump: ", dump_object) - # Print to Serial - osn_debug_keys = True # Set true to print Serial data + # Key:Value Serial Debug (doesn't show credentials) + osn_debug_keys = True # Set True to print Serial data if osn_debug_keys: try: osn_flight = opensky_response["time"] @@ -148,6 +145,5 @@ def _format_datetime(datetime): except (ConnectionError, ValueError, NameError) as e: print("OSN Connection Error:", e) - print("You are likely banned for 24 hours") print("Next Retry: ", time_calc(sleep_time)) time.sleep(sleep_time) diff --git a/examples/requests_api_openskynetwork_private_area.py b/examples/requests_api_openskynetwork_private_area.py index fa69a3c..49185b3 100644 --- a/examples/requests_api_openskynetwork_private_area.py +++ b/examples/requests_api_openskynetwork_private_area.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 DJDevon3 # SPDX-License-Identifier: MIT # Coded for Circuit Python 8.1 -# DJDevon3 ESP32-S3 OpenSkyNetwork_Private__Area_API_Example +# DJDevon3 ESP32-S3 OpenSkyNetwork_Private_Area_API_Example import os import time @@ -12,9 +12,8 @@ import circuitpython_base64 as base64 import adafruit_requests -# OpenSky-Network.org Login required for this API +# OpenSky-Network.org Website Login required for this API # REST API: https://openskynetwork.github.io/opensky-api/rest.html -# All active flights JSON: https://opensky-network.org/api/states/all # PICK ONE! :) # Retrieves all traffic within a geographic area (Orlando example) latmin = "27.22" # east bounding box @@ -41,7 +40,7 @@ osn_cred = str(osnu) + ":" + str(osnp) bytes_to_encode = b" " + str(osn_cred) + " " base64_string = base64.encodebytes(bytes_to_encode) -basepw = repr(base64_string)[2:-1] +base64cred = repr(base64_string)[2:-1] Debug_Auth = False # STREAMER WARNING this will show your credentials! if Debug_Auth: @@ -50,14 +49,14 @@ print(repr(bytes_to_encode)) base64_string = base64.encodebytes(bytes_to_encode) print(repr(base64_string)[2:-1]) - basepw = repr(base64_string)[2:-1] - print("Decoded Bytes:", str(basepw)) + base64cred = repr(base64_string)[2:-1] + print("Decoded Bytes:", str(base64cred)) # OSN requires your username:password to be base64 encoded # so technically it's not transmitted in the clear but w/e -osn_header = {"Authorization": "Basic " + str(basepw)} +osn_header = {"Authorization": "Basic " + str(base64cred)} -# Example of all traffic over Florida, geographic areas cost less per call. +# Example request of all traffic over Florida, geographic areas cost less per call. # https://opensky-network.org/api/states/all?lamin=25.21&lomin=-84.36&lamax=30.0&lomax=-78.40 OPENSKY_SOURCE = ( "https://opensky-network.org/api/states/all?" @@ -71,8 +70,8 @@ + lonmax ) - -def time_calc(input_time): +# Converts seconds to human readable minutes/hours/days +def time_calc(input_time): # input_time in seconds if input_time < 60: sleep_int = input_time time_output = f"{sleep_int:.0f} seconds" @@ -82,15 +81,11 @@ def time_calc(input_time): elif 3600 <= input_time < 86400: sleep_int = input_time / 60 / 60 time_output = f"{sleep_int:.1f} hours" - elif 86400 <= input_time < 432000: + else: 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 - def _format_datetime(datetime): return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format( datetime.tm_mon, @@ -101,7 +96,6 @@ def _format_datetime(datetime): datetime.tm_sec, ) - # Connect to Wi-Fi print("\n===============================") print("Connecting to WiFi...") @@ -117,7 +111,7 @@ def _format_datetime(datetime): while True: # STREAMER WARNING this will show your credentials! - debug_request = False # Set true to see full request + debug_request = False # Set True to see full request if debug_request: print("Full API HEADER: ", str(osn_header)) print("Full API GET URL: ", OPENSKY_SOURCE) @@ -125,14 +119,15 @@ def _format_datetime(datetime): print("\nAttempting to GET OpenSky-Network Data!") opensky_response = request.get(url=OPENSKY_SOURCE, headers=osn_header).json() + # Print Full JSON to Serial (doesn't show credentials) - debug_response = False # Set true to see full response + debug_response = False # Set True to see full response if debug_response: dump_object = json.dumps(opensky_response) print("JSON Dump: ", dump_object) - # Print to Serial - osn_debug_keys = True # Set true to print Serial data + # Key:Value Serial Debug (doesn't show credentials) + osn_debug_keys = True # Set True to print Serial data if osn_debug_keys: try: osn_flight = opensky_response["time"] @@ -182,6 +177,5 @@ def _format_datetime(datetime): except (ConnectionError, ValueError, NameError) as e: print("OSN Connection Error:", e) - print("You are likely banned for 24 hours") print("Next Retry: ", time_calc(sleep_time)) time.sleep(sleep_time) diff --git a/examples/requests_api_openskynetwork_public.py b/examples/requests_api_openskynetwork_public.py index a6e0de4..41b4a18 100644 --- a/examples/requests_api_openskynetwork_public.py +++ b/examples/requests_api_openskynetwork_public.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 DJDevon3 # SPDX-License-Identifier: MIT # Coded for Circuit Python 8.1 -"""DJDevon3 Adafruit Feather ESP32-S3 OpenSkyNetwork_API_Example""" +# Adafruit Feather ESP32-S3 OpenSkyNetwork_Public_API_Example import os import time import ssl @@ -10,11 +10,11 @@ import socketpool import adafruit_requests -# No developer account necessary for this API +# No login necessary for Public API. Drastically reduced daily limit vs Private # OpenSky-Networks.org REST API: https://openskynetwork.github.io/opensky-api/rest.html -# All active flights JSON: https://opensky-network.org/api/states/all +# All active flights JSON: https://opensky-network.org/api/states/all PICK ONE! # JSON order: transponder, callsign, country -# ACTIVE transponder you want data from +# ACTIVE transpondes only, for multiple "c822af&icao24=cb3993&icao24=c63923" transponder = "ab1644" # Initialize WiFi Pool (There can be only 1 pool & top of script) @@ -22,24 +22,20 @@ # Time between API refreshes # 900 = 15 mins, 1800 = 30 mins, 3600 = 1 hour -# OpenSky-Networks will temp ban your IP for too many requests, there is a public rate limit. +# OpenSky-Networks will temp ban your IP for too many daily requests. # https://openskynetwork.github.io/opensky-api/rest.html#limitations sleep_time = 1800 -# this example uses settings.toml for credentials -# timezone offset is in seconds plus or minus GMT +# Wifi credentials pulled from settings.toml ssid = os.getenv("AP_SSID") appw = os.getenv("AP_PASSWORD") -timezone = os.getenv("timezone") -tz_offset_seconds = os.getenv("timezone_offset") -# https://opensky-network.org/api/states/all +# Requests URL - icao24 is their endpoint required for a transponder # example https://opensky-network.org/api/states/all?icao24=a808c5 -# You can use states/own to pull your owned craft data without rate limit. OPENSKY_SOURCE = "https://opensky-network.org/api/states/all?" + "icao24=" + transponder - -def time_calc(input_time): +# Converts seconds to human readable minutes/hours/days +def time_calc(input_time): # input_time in seconds if input_time < 60: sleep_int = input_time time_output = f"{sleep_int:.0f} seconds" @@ -49,15 +45,11 @@ def time_calc(input_time): elif 3600 <= input_time < 86400: sleep_int = input_time / 60 / 60 time_output = f"{sleep_int:.1f} hours" - elif 86400 <= input_time < 432000: + else: 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 - def _format_datetime(datetime): return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format( datetime.tm_mon, @@ -68,7 +60,6 @@ def _format_datetime(datetime): datetime.tm_sec, ) - # Connect to Wi-Fi print("\n===============================") print("Connecting to WiFi...") @@ -122,7 +113,6 @@ def _format_datetime(datetime): print("Flight Country: ", country) else: print("This flight has no active data or you're polling too fast.") - print("You will eventually get temp banned for polling too fast!") print( "Read: https://openskynetwork.github.io/opensky-api/rest.html#limitations" ) @@ -138,6 +128,5 @@ def _format_datetime(datetime): except (ConnectionError, ValueError, NameError) as e: print("OSN Connection Error:", e) - print("You are likely banned for 24 hours") print("Next Retry: ", time_calc(sleep_time)) time.sleep(sleep_time) From 72a3536df845314ae05bf7be1b0b640c629f879f Mon Sep 17 00:00:00 2001 From: DJDevon3 <49322231+DJDevon3@users.noreply.github.com> Date: Tue, 13 Jun 2023 14:19:51 -0400 Subject: [PATCH 8/8] ran black again --- examples/requests_api_openskynetwork_private.py | 5 ++++- examples/requests_api_openskynetwork_private_area.py | 5 ++++- examples/requests_api_openskynetwork_public.py | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/requests_api_openskynetwork_private.py b/examples/requests_api_openskynetwork_private.py index e51b390..a69eba8 100644 --- a/examples/requests_api_openskynetwork_private.py +++ b/examples/requests_api_openskynetwork_private.py @@ -56,6 +56,7 @@ osn_header = {"Authorization": "Basic " + str(base64cred)} OPENSKY_SOURCE = "https://opensky-network.org/api/states/all?" + "icao24=" + transponder + # Converts seconds to human readable minutes/hours/days def time_calc(input_time): # input_time in seconds if input_time < 60: @@ -72,6 +73,7 @@ def time_calc(input_time): # input_time in seconds time_output = f"{sleep_int:.1f} days" return time_output + def _format_datetime(datetime): return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format( datetime.tm_mon, @@ -82,6 +84,7 @@ def _format_datetime(datetime): datetime.tm_sec, ) + # Connect to Wi-Fi print("\n===============================") print("Connecting to WiFi...") @@ -105,7 +108,7 @@ def _format_datetime(datetime): print("\nAttempting to GET OpenSky-Network Data!") opensky_response = request.get(url=OPENSKY_SOURCE, headers=osn_header).json() - + # Print Full JSON to Serial (doesn't show credentials) debug_response = False # Set True to see full response if debug_response: diff --git a/examples/requests_api_openskynetwork_private_area.py b/examples/requests_api_openskynetwork_private_area.py index 49185b3..e474e48 100644 --- a/examples/requests_api_openskynetwork_private_area.py +++ b/examples/requests_api_openskynetwork_private_area.py @@ -70,6 +70,7 @@ + lonmax ) + # Converts seconds to human readable minutes/hours/days def time_calc(input_time): # input_time in seconds if input_time < 60: @@ -86,6 +87,7 @@ def time_calc(input_time): # input_time in seconds time_output = f"{sleep_int:.1f} days" return time_output + def _format_datetime(datetime): return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format( datetime.tm_mon, @@ -96,6 +98,7 @@ def _format_datetime(datetime): datetime.tm_sec, ) + # Connect to Wi-Fi print("\n===============================") print("Connecting to WiFi...") @@ -119,7 +122,7 @@ def _format_datetime(datetime): print("\nAttempting to GET OpenSky-Network Data!") opensky_response = request.get(url=OPENSKY_SOURCE, headers=osn_header).json() - + # Print Full JSON to Serial (doesn't show credentials) debug_response = False # Set True to see full response if debug_response: diff --git a/examples/requests_api_openskynetwork_public.py b/examples/requests_api_openskynetwork_public.py index 41b4a18..e114cb7 100644 --- a/examples/requests_api_openskynetwork_public.py +++ b/examples/requests_api_openskynetwork_public.py @@ -34,6 +34,7 @@ # example https://opensky-network.org/api/states/all?icao24=a808c5 OPENSKY_SOURCE = "https://opensky-network.org/api/states/all?" + "icao24=" + transponder + # Converts seconds to human readable minutes/hours/days def time_calc(input_time): # input_time in seconds if input_time < 60: @@ -50,6 +51,7 @@ def time_calc(input_time): # input_time in seconds time_output = f"{sleep_int:.1f} days" return time_output + def _format_datetime(datetime): return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format( datetime.tm_mon, @@ -60,6 +62,7 @@ def _format_datetime(datetime): datetime.tm_sec, ) + # Connect to Wi-Fi print("\n===============================") print("Connecting to WiFi...")