01234567890123456789012345678901234567890123456789012345678901234567890123456789
10191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059 539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454 60136014601560166017601860196020602160226023602460256026602760286029603060316032 60336034603560366037603860396040604160426043604460456046604760486049605060516052 | <----SKIPPED LINES----> file_contents = content_file.read() except IOError: if log_exception: Log('Unable to read '+filename) return '' return file_contents # because reading is ~25x more expensive than getmtime, we will only read & parse if # the getmtime is more recent than last call for this file. So this dict stores the # a tuple, the last time read & the resulting parsed return value CACHED_FILES = {} def ReadAndParseSettings(filename): """Reads given filename and then parses the resulting key-value pairs into a dict.""" global CACHED_FILES (last_read_time, settings) = CACHED_FILES.get(filename, (0, {})) if os.path.exists(filename): last_modified = os.path.getmtime(filename) if last_modified > last_read_time: setting_str = ReadFile(filename) settings = ParseSettings(setting_str) #CACHED_FILES[filename] = (last_modified, settings) # TODO - uncomment? return settings # File does not - or at least no longer - exists; so remove the cache if filename in CACHED_FILES: CACHED_FILES.pop(filename) return {} def BuildSettings(d): """Converts a dict to a string of form key1=value1;...;keyn=valuen; keys alpha sorted.""" kv_pairs = [] for key in sorted(list(d.keys())): kv_pairs.append('%s=%s' % (key, d[key])) s = ';'.join(kv_pairs) if s: # add terminating semicolon s += ';' return s <----SKIPPED LINES----> configuration: dictionary of settings message_queue: current message queue next_message_time: epoch of the next message to display to screen Returns: A 2-tuple of the (possibly-updated) message_queue and next_message_time. """ while not q.empty(): command, args = q.get() if command == 'pin': UpdateStatusLight(*args) elif command == 'replay': # a command might request info about flight to be (re)displayed, irrespective of # whether the screen is on; if so, let's put that message at the front of the message # queue, and delete any subsequent messages in queue because presumably the button # was pushed either a) when the screen was off (so no messages in queue), or b) # because the screen was on, but the last flight details got lost after other screens # that we're no longer interested in Log('Replay requested') #TODO - remove messageboard_flight_index = IdentifyFlightDisplayed( flights, configuration, display_all_hours=True) if messageboard_flight_index is not None: message_queue = [m for m in message_queue if m[0] != FLAG_MSG_INSIGHT] flight_message = CreateMessageAboutFlight(flights[messageboard_flight_index]) message_queue = [(FLAG_MSG_FLIGHT, flight_message)] next_message_time = time.time() elif command == 'histogram': if not flights: Log('Histogram requested by remote %s but no flights in memory' % str(args)) else: histogram_type, histogram_history = args message_queue.extend(MessageboardHistograms( flights, histogram_type, histogram_history, '_1', False)) elif command == 'update_configuration': Log('Writing CONFIG_FILE: %s' % str(args)) #TODO - remove WriteFile(CONFIG_FILE, *args) else: Log('Improper command from arduinos: %s / %s' % (command, args)) return message_queue, next_message_time def PublishMessage( s, subscription_id='12fd73cd-75ef-4cae-bbbf-29b2678692c1', key='c5f62d44-e30d-4c43-a43e-d4f65f4eb399', secret='b00aeb24-72f3-467c-aad2-82ba5e5266ca', timeout=3): """Publishes a text string to a Vestaboard. The message is pushed to the vestaboard splitflap display by way of its web services; see https://docs.vestaboard.com/introduction for more details. Args: <----SKIPPED LINES----> next_loop_time = time.time() + LOOP_DELAY_SECONDS # These files are read only if the version on disk has been modified more recently # than the last time it was read last_dump_json_timestamp = 0 init_timing.append((time.time(), 6)) WaitUntilKillComplete(already_running_ids) init_timing.append((time.time(), 7)) LogTimes(init_timing) Log('Finishing initialization of %d; starting radio polling loop' % os.getpid()) while (not SIMULATION or SIMULATION_COUNTER < len(DUMP_JSONS)) and not SHUTDOWN_SIGNAL: last_heartbeat_time = Heartbeat(last_heartbeat_time) new_configuration = ReadAndParseSettings(CONFIG_FILE) UpdateRollingLogSize(new_configuration) CheckForNewFilterCriteria(configuration, new_configuration, message_queue, flights) configuration = new_configuration ResetLogs(configuration) # clear the logs if requested UpdateRollingLogSize(configuration) # if this is a SIMULATION, then process every diff dump. But if it isn't a simulation, # then only read & do related processing for the next dump if the last-modified # timestamp indicates the file has been updated since it was last read. tmp_timestamp = 0 if not SIMULATION: dump_json_exists = os.path.exists(DUMP_JSON_FILE) if dump_json_exists: tmp_timestamp = os.path.getmtime(DUMP_JSON_FILE) if (SIMULATION and DumpJsonChanges()) or ( not SIMULATION and dump_json_exists and tmp_timestamp > last_dump_json_timestamp): last_dump_json_timestamp = tmp_timestamp (persistent_nearby_aircraft, flight, now, <----SKIPPED LINES----> |
01234567890123456789012345678901234567890123456789012345678901234567890123456789
10191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059 53925393539453955396539753985399540054015402540354045405540654075408540954105411 541254135414541554165417541854195420542154225423542454255426542754285429543054315432 54335434543554365437543854395440544154425443544454455446544754485449545054515452 60116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066 | <----SKIPPED LINES----> file_contents = content_file.read() except IOError: if log_exception: Log('Unable to read '+filename) return '' return file_contents # because reading is ~25x more expensive than getmtime, we will only read & parse if # the getmtime is more recent than last call for this file. So this dict stores the # a tuple, the last time read & the resulting parsed return value CACHED_FILES = {} def ReadAndParseSettings(filename): """Reads given filename and then parses the resulting key-value pairs into a dict.""" global CACHED_FILES (last_read_time, settings) = CACHED_FILES.get(filename, (0, {})) if os.path.exists(filename): last_modified = os.path.getmtime(filename) if last_modified > last_read_time: setting_str = ReadFile(filename) settings = ParseSettings(setting_str) CACHED_FILES[filename] = (last_modified, settings) return settings # File does not - or at least no longer - exists; so remove the cache if filename in CACHED_FILES: CACHED_FILES.pop(filename) return {} def BuildSettings(d): """Converts a dict to a string of form key1=value1;...;keyn=valuen; keys alpha sorted.""" kv_pairs = [] for key in sorted(list(d.keys())): kv_pairs.append('%s=%s' % (key, d[key])) s = ';'.join(kv_pairs) if s: # add terminating semicolon s += ';' return s <----SKIPPED LINES----> configuration: dictionary of settings message_queue: current message queue next_message_time: epoch of the next message to display to screen Returns: A 2-tuple of the (possibly-updated) message_queue and next_message_time. """ while not q.empty(): command, args = q.get() if command == 'pin': UpdateStatusLight(*args) elif command == 'replay': # a command might request info about flight to be (re)displayed, irrespective of # whether the screen is on; if so, let's put that message at the front of the message # queue, and delete any subsequent messages in queue because presumably the button # was pushed either a) when the screen was off (so no messages in queue), or b) # because the screen was on, but the last flight details got lost after other screens # that we're no longer interested in messageboard_flight_index = IdentifyFlightDisplayed( flights, configuration, display_all_hours=True) if messageboard_flight_index is not None: message_queue = [m for m in message_queue if m[0] != FLAG_MSG_INSIGHT] flight_message = CreateMessageAboutFlight(flights[messageboard_flight_index]) message_queue = [(FLAG_MSG_FLIGHT, flight_message)] next_message_time = time.time() elif command == 'histogram': if not flights: Log('Histogram requested by remote %s but no flights in memory' % str(args)) else: histogram_type, histogram_history = args message_queue.extend(MessageboardHistograms( flights, histogram_type, histogram_history, '_1', False)) elif command == 'update_configuration': WriteFile(CONFIG_FILE, *args) else: Log('Improper command from arduinos: %s / %s' % (command, args)) return message_queue, next_message_time def PublishMessage( s, subscription_id='12fd73cd-75ef-4cae-bbbf-29b2678692c1', key='c5f62d44-e30d-4c43-a43e-d4f65f4eb399', secret='b00aeb24-72f3-467c-aad2-82ba5e5266ca', timeout=3): """Publishes a text string to a Vestaboard. The message is pushed to the vestaboard splitflap display by way of its web services; see https://docs.vestaboard.com/introduction for more details. Args: <----SKIPPED LINES----> next_loop_time = time.time() + LOOP_DELAY_SECONDS # These files are read only if the version on disk has been modified more recently # than the last time it was read last_dump_json_timestamp = 0 init_timing.append((time.time(), 6)) WaitUntilKillComplete(already_running_ids) init_timing.append((time.time(), 7)) LogTimes(init_timing) Log('Finishing initialization of %d; starting radio polling loop' % os.getpid()) while (not SIMULATION or SIMULATION_COUNTER < len(DUMP_JSONS)) and not SHUTDOWN_SIGNAL: last_heartbeat_time = Heartbeat(last_heartbeat_time) new_configuration = ReadAndParseSettings(CONFIG_FILE) UpdateRollingLogSize(new_configuration) CheckForNewFilterCriteria(configuration, new_configuration, message_queue, flights) if 'setting_screen_enabled' not in configuration and 'setting_screen_enabled' in new_configuration: Log('setting_screen_enabled changed from NOT PRESENT to ON') if 'setting_screen_enabled' in configuration and 'setting_screen_enabled' not in new_configuration: Log('setting_screen_enabled changed from ON to NOT PRESENT') last_configuration = configuration configuration = new_configuration ResetLogs(configuration) # clear the logs if requested UpdateRollingLogSize(configuration) # if this is a SIMULATION, then process every diff dump. But if it isn't a simulation, # then only read & do related processing for the next dump if the last-modified # timestamp indicates the file has been updated since it was last read. tmp_timestamp = 0 if not SIMULATION: dump_json_exists = os.path.exists(DUMP_JSON_FILE) if dump_json_exists: tmp_timestamp = os.path.getmtime(DUMP_JSON_FILE) if (SIMULATION and DumpJsonChanges()) or ( not SIMULATION and dump_json_exists and tmp_timestamp > last_dump_json_timestamp): last_dump_json_timestamp = tmp_timestamp (persistent_nearby_aircraft, flight, now, <----SKIPPED LINES----> |