Skip to content

Commit d2f90ee

Browse files
committed
Update OpenSky-Network Public Single Flight API Example with Connection Manager
1 parent 7106d2f commit d2f90ee

File tree

1 file changed

+145
-103
lines changed

1 file changed

+145
-103
lines changed
Lines changed: 145 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
# SPDX-FileCopyrightText: 2023 DJDevon3
1+
# SPDX-FileCopyrightText: 2024 DJDevon3
22
# SPDX-License-Identifier: MIT
3-
# Coded for Circuit Python 8.1
4-
# Adafruit Feather ESP32-S3 OpenSkyNetwork_Public_API_Example
5-
import json
3+
# Coded for Circuit Python 8.2.x
4+
"""OpenSky-Network.org Single Flight Public API Example"""
5+
# pylint: disable=import-error
6+
67
import os
7-
import ssl
88
import time
99

10-
import socketpool
10+
import adafruit_connection_manager
1111
import wifi
1212

1313
import adafruit_requests
@@ -17,121 +17,163 @@
1717
# All active flights JSON: https://opensky-network.org/api/states/all PICK ONE!
1818
# JSON order: transponder, callsign, country
1919
# ACTIVE transpondes only, for multiple "c822af&icao24=cb3993&icao24=c63923"
20-
transponder = "ab1644"
20+
TRANSPONDER = "88044d"
2121

22-
# Initialize WiFi Pool (There can be only 1 pool & top of script)
23-
pool = socketpool.SocketPool(wifi.radio)
22+
# Get WiFi details, ensure these are setup in settings.toml
23+
ssid = os.getenv("CIRCUITPY_WIFI_SSID")
24+
password = os.getenv("CIRCUITPY_WIFI_PASSWORD")
2425

25-
# Time between API refreshes
26+
# API Polling Rate
2627
# 900 = 15 mins, 1800 = 30 mins, 3600 = 1 hour
27-
# OpenSky-Networks will temp ban your IP for too many daily requests.
28+
# OpenSky-Networks IP bans for too many requests, check rate limit.
2829
# https://openskynetwork.github.io/opensky-api/rest.html#limitations
29-
sleep_time = 1800
30+
SLEEP_TIME = 1800
3031

31-
# Get WiFi details, ensure these are setup in settings.toml
32-
ssid = os.getenv("CIRCUITPY_WIFI_SSID")
33-
password = os.getenv("CIRCUITPY_WIFI_PASSWORD")
32+
# Set debug to True for full JSON response.
33+
# WARNING: makes credentials visible
34+
DEBUG = False
35+
36+
# Initalize Wifi, Socket Pool, Request Session
37+
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
38+
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio)
39+
requests = adafruit_requests.Session(pool, ssl_context)
3440

3541
# Requests URL - icao24 is their endpoint required for a transponder
3642
# example https://opensky-network.org/api/states/all?icao24=a808c5
37-
OPENSKY_SOURCE = "https://opensky-network.org/api/states/all?" + "icao24=" + transponder
43+
OPENSKY_SOURCE = "https://opensky-network.org/api/states/all?" + "icao24=" + TRANSPONDER
3844

3945

40-
# Converts seconds to human readable minutes/hours/days
41-
def time_calc(input_time): # input_time in seconds
46+
def time_calc(input_time):
47+
"""Converts seconds to minutes/hours/days"""
4248
if input_time < 60:
43-
sleep_int = input_time
44-
time_output = f"{sleep_int:.0f} seconds"
45-
elif 60 <= input_time < 3600:
46-
sleep_int = input_time / 60
47-
time_output = f"{sleep_int:.0f} minutes"
48-
elif 3600 <= input_time < 86400:
49-
sleep_int = input_time / 60 / 60
50-
time_output = f"{sleep_int:.1f} hours"
51-
else:
52-
sleep_int = input_time / 60 / 60 / 24
53-
time_output = f"{sleep_int:.1f} days"
54-
return time_output
49+
return f"{input_time:.0f} seconds"
50+
if input_time < 3600:
51+
return f"{input_time / 60:.0f} minutes"
52+
if input_time < 86400:
53+
return f"{input_time / 60 / 60:.0f} hours"
54+
return f"{input_time / 60 / 60 / 24:.1f} days"
5555

5656

5757
def _format_datetime(datetime):
58-
return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format(
59-
datetime.tm_mon,
60-
datetime.tm_mday,
61-
datetime.tm_year,
62-
datetime.tm_hour,
63-
datetime.tm_min,
64-
datetime.tm_sec,
58+
"""F-String formatted struct time conversion"""
59+
return (
60+
f"{datetime.tm_mon:02}/"
61+
+ f"{datetime.tm_mday:02}/"
62+
+ f"{datetime.tm_year:02} "
63+
+ f"{datetime.tm_hour:02}:"
64+
+ f"{datetime.tm_min:02}:"
65+
+ f"{datetime.tm_sec:02}"
6566
)
6667

6768

68-
# Connect to Wi-Fi
69-
print("\n===============================")
70-
print("Connecting to WiFi...")
71-
requests = adafruit_requests.Session(pool, ssl.create_default_context())
72-
while not wifi.radio.ipv4_address:
73-
try:
74-
wifi.radio.connect(ssid, password)
75-
except ConnectionError as e:
76-
print("Connection Error:", e)
77-
print("Retrying in 10 seconds")
78-
time.sleep(10)
79-
print("Connected!\n")
80-
8169
while True:
82-
debug_request = True # Set true to see full request
83-
if debug_request:
84-
print("Full API GET URL: ", OPENSKY_SOURCE)
85-
print("===============================")
70+
# Connect to Wi-Fi
71+
print("\nConnecting to WiFi...")
72+
while not wifi.radio.ipv4_address:
73+
try:
74+
wifi.radio.connect(ssid, password)
75+
except ConnectionError as e:
76+
print("❌ Connection Error:", e)
77+
print("Retrying in 10 seconds")
78+
print("✅ Wifi!")
79+
8680
try:
87-
print("\nAttempting to GET OpenSky-Network Stats!")
88-
opensky_response = requests.get(url=OPENSKY_SOURCE)
89-
osn_json = opensky_response.json()
90-
except (ConnectionError, ValueError, NameError) as e:
91-
print("Host No Response Error:", e)
92-
93-
# Print Full JSON to Serial
94-
debug_response = False # Set true to see full response
95-
if debug_response:
96-
dump_object = json.dumps(osn_json)
97-
print("JSON Dump: ", dump_object)
98-
99-
# Print to Serial
100-
osn_debug_keys = True # Set true to print Serial data
101-
if osn_debug_keys:
81+
print(" | Attempting to GET OpenSky-Network Single Public Flight JSON!")
82+
print(" | Website Credentials NOT Required! Less daily calls than Private.")
10283
try:
103-
osn_flight = osn_json["time"]
104-
print("Current Unix Time: ", osn_flight)
105-
106-
current_struct_time = time.localtime(osn_flight)
107-
current_date = "{}".format(_format_datetime(current_struct_time))
108-
print(f"Unix to Readable Time: {current_date}")
109-
110-
osn_single_flight_data = osn_json["states"]
111-
if osn_single_flight_data is not None:
112-
print("Flight Data: ", osn_single_flight_data)
113-
transponder = osn_json["states"][0][0]
114-
print("Transponder: ", transponder)
115-
callsign = osn_json["states"][0][1]
116-
print("Callsign: ", callsign)
117-
country = osn_json["states"][0][2]
118-
print("Flight Country: ", country)
84+
opensky_response = requests.get(url=OPENSKY_SOURCE)
85+
opensky_json = opensky_response.json()
86+
except ConnectionError as e:
87+
print("Connection Error:", e)
88+
print("Retrying in 10 seconds")
89+
90+
print(" | ✅ OpenSky-Network Public JSON!")
91+
92+
if DEBUG:
93+
print("Full API GET URL: ", OPENSKY_SOURCE)
94+
print(opensky_json)
95+
96+
# ERROR MESSAGE RESPONSES
97+
if "timestamp" in opensky_json:
98+
osn_timestamp = opensky_json["timestamp"]
99+
print(f"❌ Timestamp: {osn_timestamp}")
100+
101+
if "message" in opensky_json:
102+
osn_message = opensky_json["message"]
103+
print(f"❌ Message: {osn_message}")
104+
105+
if "error" in opensky_json:
106+
osn_error = opensky_json["error"]
107+
print(f"❌ Error: {osn_error}")
108+
109+
if "path" in opensky_json:
110+
osn_path = opensky_json["path"]
111+
print(f"❌ Path: {osn_path}")
112+
113+
if "status" in opensky_json:
114+
osn_status = opensky_json["status"]
115+
print(f"❌ Status: {osn_status}")
116+
117+
# Current flight data for single callsign (right now)
118+
osn_single_flight_data = opensky_json["states"]
119+
120+
if osn_single_flight_data is not None:
121+
if DEBUG:
122+
print(f" | | Single Flight Public Data: {osn_single_flight_data}")
123+
124+
last_contact = opensky_json["states"][0][4]
125+
# print(f" | | Last Contact Unix Time: {last_contact}")
126+
lc_struct_time = time.localtime(last_contact)
127+
lc_readable_time = f"{_format_datetime(lc_struct_time)}"
128+
print(f" | | Last Contact: {lc_readable_time}")
129+
130+
flight_transponder = opensky_json["states"][0][0]
131+
print(f" | | Transponder: {flight_transponder}")
132+
133+
callsign = opensky_json["states"][0][1]
134+
print(f" | | Callsign: {callsign}")
135+
136+
squawk = opensky_json["states"][0][14]
137+
print(f" | | Squawk: {squawk}")
138+
139+
country = opensky_json["states"][0][2]
140+
print(f" | | Origin: {country}")
141+
142+
longitude = opensky_json["states"][0][5]
143+
print(f" | | Longitude: {longitude}")
144+
145+
latitude = opensky_json["states"][0][6]
146+
print(f" | | Latitude: {latitude}")
147+
148+
# Return Air Flight data if not on ground
149+
on_ground = opensky_json["states"][0][8]
150+
if on_ground is True:
151+
print(f" | | On Ground: {on_ground}")
119152
else:
120-
print("This flight has no active data or you're polling too fast.")
121-
print(
122-
"Read: https://openskynetwork.github.io/opensky-api/rest.html#limitations"
123-
)
124-
print(
125-
"Public Limits: 10 second max poll rate & 400 weighted calls daily"
126-
)
127-
128-
print("\nFinished!")
129-
print("Board Uptime: ", time_calc(time.monotonic()))
130-
print("Next Update: ", time_calc(sleep_time))
131-
time.sleep(sleep_time)
132-
print("===============================")
133-
134-
except (ConnectionError, ValueError, NameError) as e:
135-
print("OSN Connection Error:", e)
136-
print("Next Retry: ", time_calc(sleep_time))
137-
time.sleep(sleep_time)
153+
altitude = opensky_json["states"][0][7]
154+
print(f" | | Barometric Altitude: {altitude}")
155+
156+
velocity = opensky_json["states"][0][9]
157+
if velocity != "null":
158+
print(f" | | Velocity: {velocity}")
159+
160+
vertical_rate = opensky_json["states"][0][11]
161+
if vertical_rate != "null":
162+
print(f" | | Vertical Rate: {vertical_rate}")
163+
else:
164+
print("This flight has no active data or you're polling too fast.")
165+
print("Public Limits: 10 second max poll & 400 weighted calls daily")
166+
167+
opensky_response.close()
168+
print("✂️ Disconnected from OpenSky-Network API")
169+
170+
print("\nFinished!")
171+
print(f"Board Uptime: {time_calc(time.monotonic())}")
172+
print(f"Next Update: {time_calc(SLEEP_TIME)}")
173+
print("===============================")
174+
175+
except (ValueError, RuntimeError) as e:
176+
print(f"Failed to get data, retrying\n {e}")
177+
time.sleep(60)
178+
break
179+
time.sleep(SLEEP_TIME)

0 commit comments

Comments
 (0)