01234567890123456789012345678901234567890123456789012345678901234567890123456789
50125013501450155016501750185019502050215022502350245025502650275028502950305031 50325033503450355036503750385039504050415042504350445045504650475048504950505051 54085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448 54555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495 56415642564356445645564656475648564956505651565256535654565556565657565856595660 5661566256635664566556665667566856695670567156725673567456755676567756785679568056815682 56835684568556865687568856895690569156925693569456955696569756985699570057015702 61986199620062016202620362046205620662076208620962106211621262136214621562166217 621862196220622162226223622462256226622762286229623062316232623362346235623662376238 | <----SKIPPED LINES----> global PICKLE_FLIGHTS PICKLE_FLIGHTS = PrependFileName(PICKLE_FLIGHTS, SIMULATION_PREFIX) filenames = UnpickleObjectFromFile(PICKLE_FLIGHTS, True, max_days=None, filenames=True) for file in filenames: ClearFile(file) global PICKLE_DASHBOARD PICKLE_DASHBOARD = PrependFileName(PICKLE_DASHBOARD, SIMULATION_PREFIX) filenames = UnpickleObjectFromFile(PICKLE_DASHBOARD, True, max_days=None, filenames=True) for file in filenames: ClearFile(file) def SimulationEnd(message_queue, flights, screens): """Clears message buffer, exercises histograms, and other misc test & status code. Args: message_queue: List of flight messages that have not yet been printed. flights: List of flights dictionaries. """ if flights: histogram = { 'type': 'both', 'histogram':'all', 'histogram_history':'30d', 'histogram_max_screens': '_2', 'histogram_data_summary': 'on'} message_queue.extend(TriggerHistograms(flights, histogram)) while message_queue: ManageMessageQueue(message_queue, 0, {'setting_delay': 0}, screens) SaveFlightsByAltitudeDistanceCSV(flights) SaveFlightsToCSV(flights) # repickle to a new .pk with full track info file_parts = PICKLE_FLIGHTS.split('.') new_pickle_file = '.'.join([file_parts[0] + '_full_path', file_parts[1]]) RemoveFile(new_pickle_file) for flight in flights: <----SKIPPED LINES----> """ last_flight = {} if flights: last_flight = flights[-1] if SIMULATION: now = json_desc_dict['now'] else: now = time.time() additional_attributes = {} today = EpochDisplayTime(now, '%x') flight_count_today = len([1 for f in flights if DisplayTime(f, '%x') == today]) additional_attributes['flight_count_today'] = flight_count_today additional_attributes['simulation'] = SIMULATION additional_attributes['last_flight_available'] = LastFlightAvailable( flights, screen_history) Log('last_flight_available: %s' % str(additional_attributes['last_flight_available'])) # TODO - remove after debugging message = (last_flight, json_desc_dict, configuration, additional_attributes) try: if 'enable_servos' in configuration: to_servo_q.put(message, block=False) if 'enable_remote' in configuration: to_remote_q.put(message, block=False) except queue.Full: msg = 'Message queues to Arduinos full - trigger shutdown' Log(msg) global SHUTDOWN_SIGNAL SHUTDOWN_SIGNAL = msg def ProcessArduinoCommmands(q, flights, configuration, message_queue, next_message_time): """Executes the commands enqueued by the arduinos. The commands on the queue q are of the form (command, args), where command is an identifier indicating the type of instruction, and the args is a possibly empty tuple with the attributes to follow thru. <----SKIPPED LINES----> flights: list of flights 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 insight messages in queue replayed_flight_index = IdentifyFlightDisplayed( flights, configuration, display_all_hours=True) Log('Replay requested; re-displaying flight index %s' % str(replayed_flight_index)) #TODO - change to flight number once working if replayed_flight_index is not None: message_queue = DeleteMessageTypes(message_queue, (FLAG_MSG_INSIGHT, )) replayed_flight = flights[replayed_flight_index] flight_message = CreateMessageAboutFlight(replayed_flight) message_queue.insert(0, (FLAG_MSG_FLIGHT, flight_message, replayed_flight)) 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': <----SKIPPED LINES----> minute_of_day = MinuteOfDay() if ( not message_queue and 'personal_message_enabled' in configuration and configuration['personal_message'] and minute_of_day <= configuration['personal_off_time'] and minute_of_day > configuration['personal_on_time'] + 1): message = configuration['personal_message'] lines = [TruncateEscapedLine(l) for l in message.split('\n')[:SPLITFLAP_LINE_COUNT]] message_queue.append((FLAG_MSG_PERSONAL, lines)) Log('Personal message added to queue: %s' % str(lines)) def ManageMessageQueue(message_queue, next_message_time, configuration, screens): """Check time & if appropriate, display next message from queue. Args: message_queue: FIFO list of message tuples of (message type, message string). next_message_time: epoch at which next message should be displayed configuration: dictionary of configuration attributes. Returns: Next_message_time, potentially updated if a message has been displayed, or unchanged if no message was displayed. """ if message_queue and (time.time() >= next_message_time or SIMULATION): if SIMULATION: # drain the queue because the messages come so fast messages_to_display = list(message_queue) # passed by reference, so clear it out since we drained it to the display del message_queue[:] else: # display only one message, being mindful of the display timing messages_to_display = [message_queue.pop(0)] for message in messages_to_display: message_text = message[1] if isinstance(message_text, str): message_text = textwrap.wrap(message_text, width=SPLITFLAP_CHARS_PER_LINE) display_message = Screenify(message_text, False) Log(display_message, file=ALL_MESSAGE_FILE) # Saving this to disk allows us to identify persistently whats currently on the screen PickleObjectToFile(message, PICKLE_SCREENS, True) screens.append(message) MaintainRollingWebLog(display_message, 25) if not SIMULATION: splitflap_message = Screenify(message_text, True) PublishMessage(splitflap_message) next_message_time = time.time() + configuration['setting_delay'] return next_message_time def DeleteMessageTypes(q, types_to_delete): """Delete messages from the queue if type is in the iterable types.""" if VERBOSE: messages_to_delete = [m for m in q if m[0] in types_to_delete] if messages_to_delete: Log('Deleting messages from queue due to new-found plane: %s' % messages_to_delete) updated_q = [m for m in q if m[0] not in types_to_delete] return updated_q <----SKIPPED LINES----> if SIMULATION: if now: simulated_hour = EpochDisplayTime(now, '%Y-%m-%d %H:00%z') if simulated_hour != prev_simulated_hour: print(simulated_hour) prev_simulated_hour = simulated_hour histogram = ReadAndParseSettings(HISTOGRAM_CONFIG_FILE) RemoveFile(HISTOGRAM_CONFIG_FILE) # We also need to make sure there are flights on which to generate a histogram! Why # might there not be any flights? Primarily during a simulation, if there's a # lingering histogram file at the time of history restart. if histogram and not flights: Log('Histogram requested (%s) but no flights in memory' % histogram) if histogram and flights: message_queue.extend(TriggerHistograms(flights, histogram)) # check time & if appropriate, display next message from queue next_message_time = ManageMessageQueue(message_queue, next_message_time, configuration, screen_history) reboot = CheckRebootNeeded(startup_time, message_queue, json_desc_dict, configuration) CheckTemperature() if not SIMULATION: time.sleep(max(0, next_loop_time - time.time())) next_loop_time = time.time() + LOOP_DELAY_SECONDS else: SIMULATION_COUNTER += 1 if simulation_slowdown: SimulationSlowdownNearFlight(flights, persistent_nearby_aircraft) if SIMULATION: SimulationEnd(message_queue, flights, screen_history) PerformGracefulShutdown((to_remote_q, to_servo_q, to_main_q), shutdown, reboot) if __name__ == "__main__": #interrupt, as in ctrl-c <----SKIPPED LINES----> |
01234567890123456789012345678901234567890123456789012345678901234567890123456789
50125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052 54095410541154125413541454155416541754185419542054215422542354245425542654275428 54295430543154325433543454355436543754385439544054415442544354445445544654475448 54555456545754585459546054615462546354645465546654675468546954705471547254735474 54755476547754785479548054815482548354845485548654875488548954905491549254935494 5640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703 619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240 | <----SKIPPED LINES----> global PICKLE_FLIGHTS PICKLE_FLIGHTS = PrependFileName(PICKLE_FLIGHTS, SIMULATION_PREFIX) filenames = UnpickleObjectFromFile(PICKLE_FLIGHTS, True, max_days=None, filenames=True) for file in filenames: ClearFile(file) global PICKLE_DASHBOARD PICKLE_DASHBOARD = PrependFileName(PICKLE_DASHBOARD, SIMULATION_PREFIX) filenames = UnpickleObjectFromFile(PICKLE_DASHBOARD, True, max_days=None, filenames=True) for file in filenames: ClearFile(file) def SimulationEnd(message_queue, flights, screens): """Clears message buffer, exercises histograms, and other misc test & status code. Args: message_queue: List of flight messages that have not yet been printed. flights: List of flights dictionaries. screens: List of past screens displayed to splitflap screen. """ if flights: histogram = { 'type': 'both', 'histogram':'all', 'histogram_history':'30d', 'histogram_max_screens': '_2', 'histogram_data_summary': 'on'} message_queue.extend(TriggerHistograms(flights, histogram)) while message_queue: ManageMessageQueue(message_queue, 0, {'setting_delay': 0}, screens) SaveFlightsByAltitudeDistanceCSV(flights) SaveFlightsToCSV(flights) # repickle to a new .pk with full track info file_parts = PICKLE_FLIGHTS.split('.') new_pickle_file = '.'.join([file_parts[0] + '_full_path', file_parts[1]]) RemoveFile(new_pickle_file) for flight in flights: <----SKIPPED LINES----> """ last_flight = {} if flights: last_flight = flights[-1] if SIMULATION: now = json_desc_dict['now'] else: now = time.time() additional_attributes = {} today = EpochDisplayTime(now, '%x') flight_count_today = len([1 for f in flights if DisplayTime(f, '%x') == today]) additional_attributes['flight_count_today'] = flight_count_today additional_attributes['simulation'] = SIMULATION additional_attributes['last_flight_available'] = LastFlightAvailable( flights, screen_history) message = (last_flight, json_desc_dict, configuration, additional_attributes) try: if 'enable_servos' in configuration: to_servo_q.put(message, block=False) if 'enable_remote' in configuration: to_remote_q.put(message, block=False) except queue.Full: msg = 'Message queues to Arduinos full - trigger shutdown' Log(msg) global SHUTDOWN_SIGNAL SHUTDOWN_SIGNAL = msg def ProcessArduinoCommmands(q, flights, configuration, message_queue, next_message_time): """Executes the commands enqueued by the arduinos. The commands on the queue q are of the form (command, args), where command is an identifier indicating the type of instruction, and the args is a possibly empty tuple with the attributes to follow thru. <----SKIPPED LINES----> flights: list of flights 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 insight messages in queue replayed_flight_index = IdentifyFlightDisplayed( flights, configuration, display_all_hours=True) if replayed_flight_index is not None: message_queue = DeleteMessageTypes(message_queue, (FLAG_MSG_INSIGHT, )) replayed_flight = flights[replayed_flight_index] flight_message = CreateMessageAboutFlight(replayed_flight) message_queue.insert(0, (FLAG_MSG_FLIGHT, flight_message, replayed_flight)) 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': <----SKIPPED LINES----> minute_of_day = MinuteOfDay() if ( not message_queue and 'personal_message_enabled' in configuration and configuration['personal_message'] and minute_of_day <= configuration['personal_off_time'] and minute_of_day > configuration['personal_on_time'] + 1): message = configuration['personal_message'] lines = [TruncateEscapedLine(l) for l in message.split('\n')[:SPLITFLAP_LINE_COUNT]] message_queue.append((FLAG_MSG_PERSONAL, lines)) Log('Personal message added to queue: %s' % str(lines)) def ManageMessageQueue(message_queue, next_message_time, configuration, screens): """Check time & if appropriate, display next message from queue. Args: message_queue: FIFO list of message tuples of (message type, message string). next_message_time: epoch at which next message should be displayed configuration: dictionary of configuration attributes. screens: List of past screens displayed to splitflap screen. Returns: Next_message_time, potentially updated if a message has been displayed, or unchanged if no message was displayed. """ if message_queue and (time.time() >= next_message_time or SIMULATION): if SIMULATION: # drain the queue because the messages come so fast messages_to_display = list(message_queue) # passed by reference, so clear it out since we drained it to the display del message_queue[:] else: # display only one message, being mindful of the display timing messages_to_display = [message_queue.pop(0)] for message in messages_to_display: message_text = message[1] if isinstance(message_text, str): message_text = textwrap.wrap(message_text, width=SPLITFLAP_CHARS_PER_LINE) display_message = Screenify(message_text, False) Log(display_message, file=ALL_MESSAGE_FILE) # Saving this to disk allows us to identify # persistently whats currently on the screen PickleObjectToFile(message, PICKLE_SCREENS, True) screens.append(message) MaintainRollingWebLog(display_message, 25) if not SIMULATION: splitflap_message = Screenify(message_text, True) PublishMessage(splitflap_message) next_message_time = time.time() + configuration['setting_delay'] return next_message_time def DeleteMessageTypes(q, types_to_delete): """Delete messages from the queue if type is in the iterable types.""" if VERBOSE: messages_to_delete = [m for m in q if m[0] in types_to_delete] if messages_to_delete: Log('Deleting messages from queue due to new-found plane: %s' % messages_to_delete) updated_q = [m for m in q if m[0] not in types_to_delete] return updated_q <----SKIPPED LINES----> if SIMULATION: if now: simulated_hour = EpochDisplayTime(now, '%Y-%m-%d %H:00%z') if simulated_hour != prev_simulated_hour: print(simulated_hour) prev_simulated_hour = simulated_hour histogram = ReadAndParseSettings(HISTOGRAM_CONFIG_FILE) RemoveFile(HISTOGRAM_CONFIG_FILE) # We also need to make sure there are flights on which to generate a histogram! Why # might there not be any flights? Primarily during a simulation, if there's a # lingering histogram file at the time of history restart. if histogram and not flights: Log('Histogram requested (%s) but no flights in memory' % histogram) if histogram and flights: message_queue.extend(TriggerHistograms(flights, histogram)) # check time & if appropriate, display next message from queue next_message_time = ManageMessageQueue( message_queue, next_message_time, configuration, screen_history) reboot = CheckRebootNeeded(startup_time, message_queue, json_desc_dict, configuration) CheckTemperature() if not SIMULATION: time.sleep(max(0, next_loop_time - time.time())) next_loop_time = time.time() + LOOP_DELAY_SECONDS else: SIMULATION_COUNTER += 1 if simulation_slowdown: SimulationSlowdownNearFlight(flights, persistent_nearby_aircraft) if SIMULATION: SimulationEnd(message_queue, flights, screen_history) PerformGracefulShutdown((to_remote_q, to_servo_q, to_main_q), shutdown, reboot) if __name__ == "__main__": #interrupt, as in ctrl-c <----SKIPPED LINES----> |