153 lines
5.0 KiB
Python
153 lines
5.0 KiB
Python
import requests
|
|
import pandas as pd
|
|
import sqlite3
|
|
import tkinter as tk
|
|
from tkinter import ttk
|
|
import folium
|
|
from requests.adapters import HTTPAdapter
|
|
from requests.packages.urllib3.util.retry import Retry
|
|
|
|
# Function to fetch flight data from OpenSky Network API with retries and a timeout
|
|
def get_flight_data():
|
|
url = "https://opensky-network.org/api/states/all"
|
|
session = requests.Session()
|
|
retry = Retry(connect=5, backoff_factor=0.5)
|
|
adapter = HTTPAdapter(max_retries=retry)
|
|
session.mount('http://', adapter)
|
|
session.mount('https://', adapter)
|
|
|
|
try:
|
|
response = session.get(url, timeout=10)
|
|
response.raise_for_status() # Raise HTTPError for bad responses
|
|
data = response.json()
|
|
columns = [
|
|
"icao24", "callsign", "origin_country", "time_position", "last_contact",
|
|
"longitude", "latitude", "baro_altitude", "on_ground", "velocity",
|
|
"true_track", "vertical_rate", "sensors", "geo_altitude", "squawk",
|
|
"spi", "position_source"
|
|
]
|
|
df = pd.DataFrame(data["states"], columns=columns)
|
|
return df
|
|
except requests.exceptions.RequestException as e:
|
|
print(f"Error fetching data: {e}")
|
|
return pd.DataFrame() # Return an empty DataFrame in case of error
|
|
except ValueError as e:
|
|
print(f"Error processing data: {e}")
|
|
return pd.DataFrame() # Return an empty DataFrame in case of error
|
|
|
|
# Function to store flight data in SQLite database
|
|
def store_flight_data(df):
|
|
if df.empty:
|
|
print("No data to store")
|
|
return
|
|
try:
|
|
conn = sqlite3.connect('flights.db')
|
|
df.to_sql('flights', conn, if_exists='replace', index=False)
|
|
conn.close()
|
|
except sqlite3.Error as e:
|
|
print(f"Error storing data: {e}")
|
|
|
|
# Function to create a map using Folium
|
|
def create_map(df):
|
|
if df.empty:
|
|
print("No data to create map")
|
|
return
|
|
try:
|
|
m = folium.Map(location=[20, 0], zoom_start=2)
|
|
for i, row in df.iterrows():
|
|
if pd.notna(row['latitude']) and pd.notna(row['longitude']):
|
|
folium.Marker(
|
|
location=[row['latitude'], row['longitude']],
|
|
popup=row['callsign'],
|
|
).add_to(m)
|
|
m.save('flights_map.html')
|
|
print("Map has been saved as flights_map.html")
|
|
except Exception as e:
|
|
print(f"Error creating map: {e}")
|
|
|
|
# Function to display information about a specific flight
|
|
def display_specific_flight_data(df, icao24):
|
|
specific_flight = df[df['icao24'] == icao24]
|
|
if specific_flight.empty:
|
|
print(f"No data available for flight with ICAO24: {icao24}")
|
|
else:
|
|
print(specific_flight)
|
|
|
|
# Function to list available ICAO24 identifiers and callsigns
|
|
def list_available_flights(df):
|
|
if df.empty:
|
|
print("No data available")
|
|
return
|
|
available_flights = df[['icao24', 'callsign']].dropna().drop_duplicates()
|
|
print("Available ICAO24 identifiers and callsigns:")
|
|
print(available_flights)
|
|
|
|
# CLI user interaction
|
|
def main():
|
|
print("Welcome to the Flight Tracker!")
|
|
flight_data = get_flight_data()
|
|
store_flight_data(flight_data)
|
|
|
|
if flight_data.empty:
|
|
print("Unable to fetch flight data. Please check your network connection and try again later.")
|
|
return
|
|
|
|
list_available_flights(flight_data)
|
|
|
|
icao24 = input("Enter the ICAO24 identifier of the flight you want to track: ").strip().lower()
|
|
display_specific_flight_data(flight_data, icao24)
|
|
|
|
while True:
|
|
show_map = input("Do you want to see a map of the flights? (yes/no): ").strip().lower()
|
|
if show_map in ['yes', 'no']:
|
|
break
|
|
else:
|
|
print("Invalid input, please enter 'yes' or 'no'.")
|
|
|
|
if show_map == 'yes':
|
|
create_map(flight_data)
|
|
|
|
while True:
|
|
show_gui = input("Do you want to see the flight data in a GUI? (yes/no): ").strip().lower()
|
|
if show_gui in ['yes', 'no']:
|
|
break
|
|
else:
|
|
print("Invalid input, please enter 'yes' or 'no'.")
|
|
|
|
if show_gui == 'yes':
|
|
start_gui()
|
|
|
|
# Function to start the GUI
|
|
def start_gui():
|
|
def show_flight_data():
|
|
flight_data = get_flight_data()
|
|
store_flight_data(flight_data)
|
|
create_map(flight_data)
|
|
tree.delete(*tree.get_children()) # Clear existing data in the treeview
|
|
for i, row in flight_data.iterrows():
|
|
tree.insert("", "end", values=list(row))
|
|
|
|
# GUI setup using Tkinter
|
|
root = tk.Tk()
|
|
root.title("Flight Tracker")
|
|
|
|
frame = ttk.Frame(root)
|
|
frame.pack(fill="both", expand=True)
|
|
|
|
# Fetch initial flight data
|
|
flight_data = get_flight_data()
|
|
|
|
columns = list(flight_data.columns)
|
|
tree = ttk.Treeview(frame, columns=columns, show="headings")
|
|
for col in columns:
|
|
tree.heading(col, text=col)
|
|
tree.pack(fill="both", expand=True)
|
|
|
|
button = ttk.Button(root, text="Refresh Data", command=show_flight_data)
|
|
button.pack()
|
|
|
|
root.mainloop()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|