initial commit
This commit is contained in:
152
flight_tracker.py
Normal file
152
flight_tracker.py
Normal file
@@ -0,0 +1,152 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user