- A landing event is previously below 10k feet and (previously getting data, no longer getting data and previously not on the ground) or (now on the ground and previously not on the ground).
- Given the coordinates of the aircraft the nearest airport is found in an airport database from <https://ourairports.com/data> the distance is calculated using the Haversine formula. The state, region and country are also found in this database with the airport.
- At the time of takeoff a takeoff time is set, which is referenced in the landing event to calculate approximate total flight time.
- A Static map image is created based off location name. (Google Static Maps API) or a screenshot of <https://global.adsbexchange.com/> is created using Selenium/ChromeDriver. The selected plane is locked on in the screenshot.
- A Static map image is created based off location name. (Google Static Maps API) or a screenshot of <https://globe.theairtraffic.com/> is created using Selenium/ChromeDriver. The selected plane is locked on in the screenshot.
- If the landing event or takeoff event is true, It will output to any of the following built-in output methods. (Twitter, Pushbullet, and Discord can all be setup and enabled in each plane's config file). Outputs the location name, map, image, and flight time on landing. (Tweepy and "Pushbullet.py" and Discord_webhooks)
Notify if configured planes have taken off or landed using Python with <ahref="https://opensky-network.org/">OpenSky</a>(free) or <ahref="https://www.adsbexchange.com/">ADSBExchange</a> Data(paid but much better), outputs location of takeoff location of landing and takeoff by reverse lookup of coordinates.
Notify if configured planes have taken off or landed using Python with <ahref="https://opensky-network.org/">OpenSky</a>(free) or <ahref="https://www.adsbexchange.com/">ADSBExchange</a> Data(paid, declining data, and run by clowns), outputs location of takeoff location of landing and takeoff by reverse lookup of coordinates.
@ -15,15 +15,16 @@ Notify if configured planes have taken off or landed using Python with <a href="
### Background
I made this program so I could track Elon Musk's Jet and share with others of his whereabouts on Twitter. [![Twitter Follow](https://img.shields.io/twitter/follow/ElonJet.svg?style=social)](https://twitter.com/ElonJet) I have now Expanded and run multiple accounts for multiple planes, a list of the accounts here [plane-notify Twitter List](https://twitter.com/i/lists/1307414615316467715)
I made this program so I could track Elon Musk's Jet and share his whereabouts with others orginally on Twitter (but now suspended, but now also on other platforms). I have now expanded and run multiple accounts for multiple planes, a list of the accounts can be found here <https://grndcntrl.net/links>
### Contributing
I'm open to any help or suggestions, I realize there are many better ways to improve this program and better ways to get this program to work properly, Im only a noob. I'll accept pull requests. If you'd like to discuss join <https://JacksTech.net/Discord>
I'm open to any help or suggestions, I realize there are many better ways to improve this program and better ways to get this program to work properly, I'm only a noob. I'll accept pull requests. If you'd like to discuss join <https://discord.gg/groundcontrol>
### [Algorithm](PseudoCode.md)
## Setup / Install
- Install using the following steps or use Docker, scroll down to the Docker section.
### Make sure Python/PIP is installed
@ -42,12 +43,15 @@ pipenv install
### Install Selenium / ChromeDriver or setup Google Static Maps
Selenium/ChromeDriver is used to take a screenshot of the plane on globe.adsbexchange.com. Or use Google Static Maps, which can cost money if overused(No tutorial use <https://developers.google.com/maps/documentation/maps-static/get-api-key> to get to a key).
#### Chromium
Selenium/ChromeDriver is used to take a screenshot of the plane on globe.theairtraffic.com. Or use Google Static Maps, which can cost money if overused(No tutorial use <https://developers.google.com/maps/documentation/maps-static/get-api-key> to get to a key).
These output methods once installed can be configured in the planes config you create, using the example plane1.ini
@ -67,6 +71,7 @@ cd plane-notify
### Configure main config file with keys and URLs (mainconf.ini) in the configs directory
- Copy `mainconf.ini.example` to `mainconf.ini` andCopy `plane1.ini.example` to `plane1.ini`. `plane1.ini` can change names as long as it ends with the ini extension
- Edit them with nano or vi on the running machine or on your pc and transfer the config to where you will be running the bot
- Pick between OpenSky and ADS-B Exchange
- The OpenSky API is free for everyone but the data is not as good as ADS-B Exchange. The ADS-B Exchange API is not free and this program will not work for the Rapid API from ADS-B Exchange. It only works with the API that they give when you have a partnership with ADS-B Exchange. It is not cheap to get the ADS-B Exchange full API, Don't contact them unless you are ready to pay.
fuel_message=f"~ {gallons} gallons ({lters} liters). \n~ {lbs} lbs ({kgs} kg) of jet fuel used. \n~ ${cost} cost of fuel. \n~ {fuel_info['c02_tons']} tons of CO2 emissions."
fuel_message=f"\n~ {gallons} gallons ({lters} liters). \n~ {lbs} lbs ({kgs} kg) of jet fuel used. \n~ ${cost} cost of fuel. \n~ {fuel_info['c02_tons']} tons of CO2 emissions."
distance_message=f"{'{:,}'.format(round(distance_mi))} mile ({'{:,}'.format(round(distance_nm))} NM) flight from {nearest_from_airport['iata_code']ifnearest_from_airport['iata_code']!=''elsenearest_from_airport['ident']} to {nearest_airport_dict['iata_code']ifnearest_airport_dict['iata_code']!=''elsenearest_airport_dict['ident']}\n"
@ -497,14 +509,13 @@ class Plane:
fuel_message=fuel_message(fuel_info)
ifself.config.getboolean('DISCORD','ENABLE'):
dis_message=f"{self.dis_title}{distance_message}\nFlight Fuel Info ```{fuel_message}```".strip()
message=f"Doing touch and goes at {nearest_airport_dict['icao']}"
@ -776,8 +786,8 @@ class Plane:
message=f"Circling {round(nearest_airport_dict['distance_mi'],2)}mi {cardinal} of {nearest_airport_dict['icao']}, {nearest_airport_dict['name']} at {self.alt_ft}ft. "