01234567890123456789012345678901234567890123456789012345678901234567890123456789
341342343344345346347348349350351352353354355356357358359360 361362363 364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 397398399400 401402403404405406407408409410411412413414415416417418419420 421422423424425426427428429430431432433434435436437438439440 674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714 24872488248924902491249224932494249524962497249824992500250125022503250425052506 25072508 25092510251125122513251425152516251725182519252025212522252325242525252625272528 | <----SKIPPED LINES----> DAYS_OF_WEEK = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] # AIRCRAFT_LENGTH[''] = AIRCRAFT_LENGTH = {} # in meters AIRCRAFT_LENGTH['Airbus A220-100 (twin-jet)'] = 35 AIRCRAFT_LENGTH['Airbus A300F4-600 (twin-jet)'] = 54.08 AIRCRAFT_LENGTH['Airbus A319 (twin-jet)'] = 33.84 AIRCRAFT_LENGTH['Airbus A320 (twin-jet)'] = 37.57 AIRCRAFT_LENGTH['Airbus A320neo (twin-jet)'] = 37.57 AIRCRAFT_LENGTH['Airbus A321 (twin-jet)'] = 44.51 AIRCRAFT_LENGTH['Airbus A321neo (twin-jet)'] = 44.51 AIRCRAFT_LENGTH['Airbus A330-200 (twin-jet)'] = 58.82 AIRCRAFT_LENGTH['Airbus A330-300 (twin-jet)'] = 63.67 AIRCRAFT_LENGTH['Airbus A340-300 (quad-jet)'] = 63.69 AIRCRAFT_LENGTH['Airbus A350-1000 (twin-jet)'] = 73.79 AIRCRAFT_LENGTH['Airbus A350-900 (twin-jet)'] = 66.8 AIRCRAFT_LENGTH['Airbus A380-800 (quad-jet)'] = 72.72 AIRCRAFT_LENGTH['Antonov An-124 Ruslan (quad-jet)'] = 69.1 AIRCRAFT_LENGTH['Beechcraft Beechjet (twin-jet)'] = 14.76 AIRCRAFT_LENGTH['Beechcraft Bonanza (33) (piston-single)'] = 7.65 AIRCRAFT_LENGTH['Beechcraft Super King Air 200 (twin-turboprop)'] = 13.31 AIRCRAFT_LENGTH['Beechcraft Super King Air 350 (twin-turboprop)'] = 14.22 AIRCRAFT_LENGTH['Beechcraft King Air 90 (twin-turboprop)'] = 10.82 AIRCRAFT_LENGTH['Boeing 737-400 (twin-jet)'] = 36.4 AIRCRAFT_LENGTH['Boeing 737-700 (twin-jet)'] = 33.63 AIRCRAFT_LENGTH['Boeing 737-800 (twin-jet)'] = 39.47 AIRCRAFT_LENGTH['Boeing 737-900 (twin-jet)'] = 42.11 AIRCRAFT_LENGTH['Boeing 747-100 (quad-jet)'] = 70.66 AIRCRAFT_LENGTH['Boeing 747-400 (quad-jet)'] = 70.66 AIRCRAFT_LENGTH['Boeing 747-8 (quad-jet)'] = 76.25 AIRCRAFT_LENGTH['Boeing 757-200 (twin-jet)'] = 47.3 AIRCRAFT_LENGTH['Boeing 757-300 (twin-jet)'] = 54.4 AIRCRAFT_LENGTH['Boeing 767-200 (twin-jet)'] = 48.51 AIRCRAFT_LENGTH['Boeing 767-300 (twin-jet)'] = 54.94 AIRCRAFT_LENGTH['Boeing 777 (twin-jet)'] = (63.73 + 73.86) / 2 AIRCRAFT_LENGTH['Boeing 777-200 (twin-jet)'] = 63.73 AIRCRAFT_LENGTH['Boeing 777-200LR/F (twin-jet)'] = 63.73 AIRCRAFT_LENGTH['Boeing 777-300ER (twin-jet)'] = 73.86 AIRCRAFT_LENGTH['Boeing 787-10 (twin-jet)'] = 68.28 AIRCRAFT_LENGTH['Boeing 787-8 (twin-jet)'] = 56.72 AIRCRAFT_LENGTH['Boeing 787-9 (twin-jet)'] = 62.81 AIRCRAFT_LENGTH['Bombardier Challenger 300 (twin-jet)'] = 20.92 AIRCRAFT_LENGTH['Bombardier Global 5000 (twin-jet)'] = 29.5 AIRCRAFT_LENGTH['Bombardier Global Express (twin-jet)'] = (29.5 + 30.3) / 2 AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-200 (twin-jet)'] = 26.77 AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-700 (twin-jet)'] = 32.3 AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-900 (twin-jet)'] = 36.2 AIRCRAFT_LENGTH['Canadair Challenger (twin-jet)'] = 20.9 AIRCRAFT_LENGTH['Canadair Challenger 350 (twin-jet)'] = 20.9 AIRCRAFT_LENGTH['Cessna Caravan (single-turboprop)'] = 11.46 AIRCRAFT_LENGTH['Cessna Citation CJ1 (twin-jet)'] = 12.98 AIRCRAFT_LENGTH['Cessna Citation CJ2+ (twin-jet)'] = 14.53 AIRCRAFT_LENGTH['Cessna Citation CJ3 (twin-jet)'] = 15.59 AIRCRAFT_LENGTH['Cessna Citation Excel/XLS (twin-jet)'] = 16.0 AIRCRAFT_LENGTH['Cessna Citation II (twin-jet)'] = 14.54 AIRCRAFT_LENGTH['Cessna Citation Latitude (twin-jet)'] = 18.97 AIRCRAFT_LENGTH['Cessna Citation Sovereign (twin-jet)'] = 19.35 AIRCRAFT_LENGTH['Cessna Citation V (twin-jet)'] = 14.91 AIRCRAFT_LENGTH['Cessna Citation X (twin-jet)'] = 22.04 AIRCRAFT_LENGTH['Cessna Citation Mustang (twin-jet)'] = 12.37 AIRCRAFT_LENGTH['Cessna Skyhawk (piston-single)'] = 8.28 AIRCRAFT_LENGTH['Cessna Skylane (piston-single)'] = 8.84 AIRCRAFT_LENGTH['Cessna T206 Turbo Stationair (piston-single)'] = 8.61 AIRCRAFT_LENGTH['Cirrus SR-22 (piston-single)'] = 7.92 AIRCRAFT_LENGTH['Dassault Falcon 900 (tri-jet)'] = 20.21 AIRCRAFT_LENGTH['Dassault Falcon 2000 (twin-jet)'] = 20.23 AIRCRAFT_LENGTH['Embraer 170/175 (twin-jet)'] = (29.90 + 31.68) / 2 AIRCRAFT_LENGTH['Embraer Phenom 300 (twin-jet)'] = 15.9 AIRCRAFT_LENGTH['Embraer ERJ-135 (twin-jet)'] = 26.33 AIRCRAFT_LENGTH['Embraer ERJ-145 (twin-jet)'] = 29.87 AIRCRAFT_LENGTH['Embraer Legacy 450 (twin-jet)'] = 19.69 AIRCRAFT_LENGTH['EMBRAER 175 (long wing) (twin-jet)'] = 31.68 AIRCRAFT_LENGTH['Eurocopter EC-635 (twin-turboshaft)'] = 10.21 AIRCRAFT_LENGTH['IAI Gulfstream G280 (twin-jet)'] = 20.3 AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G550 (twin-jet)'] = 29.39 AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream IV (twin-jet)'] = 26.92 AIRCRAFT_LENGTH['Learjet 35 (twin-jet)'] = 14.83 AIRCRAFT_LENGTH['Learjet 45 (twin-jet)'] = 17.68 AIRCRAFT_LENGTH['McDonnell Douglas MD-11 (tri-jet)'] = 61.6 AIRCRAFT_LENGTH['Pilatus PC-12 (single-turboprop)'] = 14.4 def Log(message, file=None, rolling=None): """Write a message to a logfile along with a timestamp. Args: message: string message to write file: string representing file name and, if needed, path to the file to write to rolling: name of file that will keep only the last n files of file """ # can't define as a default parameter because LOGFILE name is potentially # modified based on SIMULATION flag if not file: file = LOGFILE # special case: for the main logfile, we always keep a rolling log if not rolling and file == LOGFILE: rolling = ROLLING_LOGFILE <----SKIPPED LINES----> haversines, relating the sides and angles of spherical triangles. Reference: https://en.wikipedia.org/wiki/Haversine_formula Args: pos1: a 2-tuple defining (lat, lon) in decimal degrees pos2: a 2-tuple defining (lat, lon) in decimal degrees Returns: Distance between two points in meters. """ is_numeric = [isinstance(x, numbers.Number) for x in (*pos1, *pos2)] if False in is_numeric: return None lat1, lon1, lat2, lon2 = [math.radians(x) for x in (*pos1, *pos2)] hav = (math.sin((lat2 - lat1) / 2.0)**2 + math.cos(lat1) * math.cos(lat2) * math.sin((lon2 - lon1) / 2.0)**2) distance = 2 * RADIUS * math.asin(math.sqrt(hav)) # Note: though pyproj has this, having trouble installing on rpi #az12, az21, distance = g.inv(lon1, lat1, lon2, lat2) return distance def SpeedInMeters(speed_in_knots): """Converts speed in knots to speed in meters per second.""" return speed_in_knots * METERS_PER_SECOND_IN_KNOTS def MetersTraveled(speed_in_knots, seconds): """Converts speed in knots to distance in meters given elapsed sec.""" return SpeedInMeters(speed_in_knots) * seconds def ClosestKnownLocation(flight, seconds): """Returns the most recent location observation from a flight. Flights in the flight dictionary have their path maintained over all the time that the radio continues to observe the flight. This function identifies the <----SKIPPED LINES----> is an easier-to-read and more faithful representation of how the message will be displayed. The transformations are to add blank lines to the message to make it consistent number of lines, and to add border to the sides & top / bottom of the message. Args: lines: list of strings that comprise the message splitflap: boolean, True if directed for splitflap display; false if directed to screen Returns: String - which includes embedded new line characters, borders, etc. as described above, that can be printed to screen as the message. """ divider = '+' + '-'*SPLITFLAP_CHARS_PER_LINE + '+' border_character = '|' append_character = '\n' if splitflap: border_character = '' append_character = '' for unused_n in range(SPLITFLAP_LINE_COUNT-len(lines)): lines.append('') # convert escaped character codes potentially embedded in personal # message to something that can be displayed well on screen, albeit # the colors for {63}..{69} aren't captured in plain text # see https://docs.vestaboard.com/characters escaped_characters = ( ('{62}', u'\u00b0'), ('{63}', u'\u2588'), # red ('{64}', u'\u2588'), # orange ('{65}', u'\u2588'), # yellow ('{66}', u'\u2588'), # green ('{67}', u'\u2588'), # blue ('{68}', u'\u2588'), # violet ('{69}', u'\u2588')) # red lines = [ border_character + line.ljust(SPLITFLAP_CHARS_PER_LINE).upper() + <----SKIPPED LINES----> |
01234567890123456789012345678901234567890123456789012345678901234567890123456789
341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719 2492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537 | <----SKIPPED LINES----> DAYS_OF_WEEK = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] # AIRCRAFT_LENGTH[''] = AIRCRAFT_LENGTH = {} # in meters AIRCRAFT_LENGTH['Airbus A220-100 (twin-jet)'] = 35 AIRCRAFT_LENGTH['Airbus A300F4-600 (twin-jet)'] = 54.08 AIRCRAFT_LENGTH['Airbus A319 (twin-jet)'] = 33.84 AIRCRAFT_LENGTH['Airbus A320 (twin-jet)'] = 37.57 AIRCRAFT_LENGTH['Airbus A320neo (twin-jet)'] = 37.57 AIRCRAFT_LENGTH['Airbus A321 (twin-jet)'] = 44.51 AIRCRAFT_LENGTH['Airbus A321neo (twin-jet)'] = 44.51 AIRCRAFT_LENGTH['Airbus A330-200 (twin-jet)'] = 58.82 AIRCRAFT_LENGTH['Airbus A330-300 (twin-jet)'] = 63.67 AIRCRAFT_LENGTH['Airbus A340-300 (quad-jet)'] = 63.69 AIRCRAFT_LENGTH['Airbus A350-1000 (twin-jet)'] = 73.79 AIRCRAFT_LENGTH['Airbus A350-900 (twin-jet)'] = 66.8 AIRCRAFT_LENGTH['Airbus A380-800 (quad-jet)'] = 72.72 AIRCRAFT_LENGTH['Antonov An-124 Ruslan (quad-jet)'] = 69.1 AIRCRAFT_LENGTH['Beechcraft Beechjet (twin-jet)'] = 14.76 AIRCRAFT_LENGTH['Beechcraft Bonanza (33) (piston-single)'] = 7.65 AIRCRAFT_LENGTH['Beechcraft Premier 1 (twin-jet)'] = 14.02 AIRCRAFT_LENGTH['Beechcraft Super King Air 200 (twin-turboprop)'] = 13.31 AIRCRAFT_LENGTH['Beechcraft Super King Air 350 (twin-turboprop)'] = 14.22 AIRCRAFT_LENGTH['Beechcraft King Air 90 (twin-turboprop)'] = 10.82 AIRCRAFT_LENGTH['Boeing 777-300 (twin-jet)'] = 33.4 AIRCRAFT_LENGTH['Boeing 737-400 (twin-jet)'] = 36.4 AIRCRAFT_LENGTH['Boeing 737-700 (twin-jet)'] = 33.63 AIRCRAFT_LENGTH['Boeing 737-800 (twin-jet)'] = 39.47 AIRCRAFT_LENGTH['Boeing 737-900 (twin-jet)'] = 42.11 AIRCRAFT_LENGTH['Boeing 747-100 (quad-jet)'] = 70.66 AIRCRAFT_LENGTH['Boeing 747-400 (quad-jet)'] = 70.66 AIRCRAFT_LENGTH['Boeing 747-8 (quad-jet)'] = 76.25 AIRCRAFT_LENGTH['Boeing 757-200 (twin-jet)'] = 47.3 AIRCRAFT_LENGTH['Boeing 757-300 (twin-jet)'] = 54.4 AIRCRAFT_LENGTH['Boeing 767-200 (twin-jet)'] = 48.51 AIRCRAFT_LENGTH['Boeing 767-300 (twin-jet)'] = 54.94 AIRCRAFT_LENGTH['Boeing 777 (twin-jet)'] = (63.73 + 73.86) / 2 AIRCRAFT_LENGTH['Boeing 777-200 (twin-jet)'] = 63.73 AIRCRAFT_LENGTH['Boeing 777-200LR/F (twin-jet)'] = 63.73 AIRCRAFT_LENGTH['Boeing 777-300ER (twin-jet)'] = 73.86 AIRCRAFT_LENGTH['Boeing 787-10 (twin-jet)'] = 68.28 AIRCRAFT_LENGTH['Boeing 787-8 (twin-jet)'] = 56.72 AIRCRAFT_LENGTH['Boeing 787-9 (twin-jet)'] = 62.81 AIRCRAFT_LENGTH['Bombardier Challenger 300 (twin-jet)'] = 20.92 AIRCRAFT_LENGTH['Bombardier Global 5000 (twin-jet)'] = 29.5 AIRCRAFT_LENGTH['Bombardier Global Express (twin-jet)'] = (29.5 + 30.3) / 2 AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-200 (twin-jet)'] = 26.77 AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-700 (twin-jet)'] = 32.3 AIRCRAFT_LENGTH['Canadair Regional Jet CRJ-900 (twin-jet)'] = 36.2 AIRCRAFT_LENGTH['Canadair Challenger (twin-jet)'] = 20.9 AIRCRAFT_LENGTH['Canadair Challenger 350 (twin-jet)'] = 20.9 AIRCRAFT_LENGTH['Cessna Caravan (single-turboprop)'] = 11.46 AIRCRAFT_LENGTH['Cessna Citation CJ1 (twin-jet)'] = 12.98 AIRCRAFT_LENGTH['Cessna Citation CJ2+ (twin-jet)'] = 14.53 AIRCRAFT_LENGTH['Cessna Citation CJ3 (twin-jet)'] = 15.59 AIRCRAFT_LENGTH['Cessna Citation Excel/XLS (twin-jet)'] = 16.0 AIRCRAFT_LENGTH['Cessna Citation II (twin-jet)'] = 14.54 AIRCRAFT_LENGTH['Cessna Citation Latitude (twin-jet)'] = 18.97 AIRCRAFT_LENGTH['Cessna Citation Longitude (twin-jet)'] = 22.3 AIRCRAFT_LENGTH['Cessna Citation Sovereign (twin-jet)'] = 19.35 AIRCRAFT_LENGTH['Cessna Citation V (twin-jet)'] = 14.91 AIRCRAFT_LENGTH['Cessna Citation X (twin-jet)'] = 22.04 AIRCRAFT_LENGTH['Cessna Citation Mustang (twin-jet)'] = 12.37 AIRCRAFT_LENGTH['Cessna Conquest 2 (twin-turboprop)'] = 11.89 AIRCRAFT_LENGTH['Cessna Skyhawk (piston-single)'] = 8.28 AIRCRAFT_LENGTH['Cessna Skylane (piston-single)'] = 8.84 AIRCRAFT_LENGTH['Cessna T206 Turbo Stationair (piston-single)'] = 8.61 AIRCRAFT_LENGTH['Cirrus SR-22 (piston-single)'] = 7.92 AIRCRAFT_LENGTH['Dassault Falcon 900 (tri-jet)'] = 20.21 AIRCRAFT_LENGTH['Dassault Falcon 2000 (twin-jet)'] = 20.23 AIRCRAFT_LENGTH['Embraer 170/175 (twin-jet)'] = (29.90 + 31.68) / 2 AIRCRAFT_LENGTH['Embraer Phenom 300 (twin-jet)'] = 15.9 AIRCRAFT_LENGTH['Embraer ERJ-135 (twin-jet)'] = 26.33 AIRCRAFT_LENGTH['Embraer ERJ-145 (twin-jet)'] = 29.87 AIRCRAFT_LENGTH['Embraer Legacy 450 (twin-jet)'] = 19.69 AIRCRAFT_LENGTH['EMBRAER 175 (long wing) (twin-jet)'] = 31.68 AIRCRAFT_LENGTH['Eurocopter EC-635 (twin-turboshaft)'] = 10.21 AIRCRAFT_LENGTH['IAI Gulfstream G280 (twin-jet)'] = 20.3 AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G550 (twin-jet)'] = 29.39 AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream IV (twin-jet)'] = 26.92 AIRCRAFT_LENGTH['Learjet 35 (twin-jet)'] = 14.83 AIRCRAFT_LENGTH['Learjet 45 (twin-jet)'] = 17.68 AIRCRAFT_LENGTH['McDonnell Douglas MD-11 (tri-jet)'] = 61.6 AIRCRAFT_LENGTH['Pilatus PC-12 (single-turboprop)'] = 14.4 AIRCRAFT_LENGTH['Rockwell Turbo Commander 690 (twin-turboprop)'] = 11.22 def Log(message, file=None, rolling=None): """Write a message to a logfile along with a timestamp. Args: message: string message to write file: string representing file name and, if needed, path to the file to write to rolling: name of file that will keep only the last n files of file """ # can't define as a default parameter because LOGFILE name is potentially # modified based on SIMULATION flag if not file: file = LOGFILE # special case: for the main logfile, we always keep a rolling log if not rolling and file == LOGFILE: rolling = ROLLING_LOGFILE <----SKIPPED LINES----> haversines, relating the sides and angles of spherical triangles. Reference: https://en.wikipedia.org/wiki/Haversine_formula Args: pos1: a 2-tuple defining (lat, lon) in decimal degrees pos2: a 2-tuple defining (lat, lon) in decimal degrees Returns: Distance between two points in meters. """ is_numeric = [isinstance(x, numbers.Number) for x in (*pos1, *pos2)] if False in is_numeric: return None lat1, lon1, lat2, lon2 = [math.radians(x) for x in (*pos1, *pos2)] hav = (math.sin((lat2 - lat1) / 2.0)**2 + math.cos(lat1) * math.cos(lat2) * math.sin((lon2 - lon1) / 2.0)**2) distance = 2 * RADIUS * math.asin(math.sqrt(hav)) # Though pyproj has HaversineDistance, having trouble installing on rpi #az12, az21, distance = g.inv(lon1, lat1, lon2, lat2) return distance def SpeedInMeters(speed_in_knots): """Converts speed in knots to speed in meters per second.""" return speed_in_knots * METERS_PER_SECOND_IN_KNOTS def MetersTraveled(speed_in_knots, seconds): """Converts speed in knots to distance in meters given elapsed sec.""" return SpeedInMeters(speed_in_knots) * seconds def ClosestKnownLocation(flight, seconds): """Returns the most recent location observation from a flight. Flights in the flight dictionary have their path maintained over all the time that the radio continues to observe the flight. This function identifies the <----SKIPPED LINES----> is an easier-to-read and more faithful representation of how the message will be displayed. The transformations are to add blank lines to the message to make it consistent number of lines, and to add border to the sides & top / bottom of the message. Args: lines: list of strings that comprise the message splitflap: boolean, True if directed for splitflap display; false if directed to screen Returns: String - which includes embedded new line characters, borders, etc. as described above, that can be printed to screen as the message. """ divider = '+' + '-'*SPLITFLAP_CHARS_PER_LINE + '+' border_character = '|' append_character = '\n' if splitflap: border_character = '' # vestaboard tries to line wrap so adding a space ensures that it does not # interpret a pair of lines that end and begin with characters as one # contiguous string append_character = ' ' # Create blank lines up to the required number of lines for unused_n in range(SPLITFLAP_LINE_COUNT-len(lines)): lines.append('') # convert escaped character codes potentially embedded in personal # message to something that can be displayed well on screen, albeit # the colors for {63}..{69} aren't captured in plain text # see https://docs.vestaboard.com/characters escaped_characters = ( ('{62}', u'\u00b0'), ('{63}', u'\u2588'), # red ('{64}', u'\u2588'), # orange ('{65}', u'\u2588'), # yellow ('{66}', u'\u2588'), # green ('{67}', u'\u2588'), # blue ('{68}', u'\u2588'), # violet ('{69}', u'\u2588')) # red lines = [ border_character + line.ljust(SPLITFLAP_CHARS_PER_LINE).upper() + <----SKIPPED LINES----> |