01234567890123456789012345678901234567890123456789012345678901234567890123456789
171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 14071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456 1457 1458145914601461146214631464 14651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487 49814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021 52385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305 530653075308530953105311531253135314531553165317531853195320532153225323532453255326 53895390539153925393539453955396539753985399540054015402540354045405540654075408 54095410541154125413541454155416541754185419542054215422542354245425542654275428 | <----SKIPPED LINES----> FLAG_INSIGHT_FIRST_ORIGIN = 7 FLAG_INSIGHT_FIRST_AIRLINE = 8 FLAG_INSIGHT_FIRST_AIRCRAFT = 9 FLAG_INSIGHT_LONGEST_DELAY = 10 FLAG_INSIGHT_FLIGHT_DELAY_FREQUENCY = 11 FLAG_INSIGHT_FLIGHT_DELAY_TIME = 12 FLAG_INSIGHT_AIRLINE_DELAY_FREQUENCY = 13 FLAG_INSIGHT_AIRLINE_DELAY_TIME = 14 FLAG_INSIGHT_DESTINATION_DELAY_FREQUENCY = 15 FLAG_INSIGHT_DESTINATION_DELAY_TIME = 16 FLAG_INSIGHT_HOUR_DELAY_FREQUENCY = 17 FLAG_INSIGHT_HOUR_DELAY_TIME = 18 FLAG_INSIGHT_DATE_DELAY_FREQUENCY = 19 FLAG_INSIGHT_DATE_DELAY_TIME = 20 INSIGHT_TYPES = 21 TEMP_FAN_TURN_ON_CELSIUS = 65 TEMP_FAN_TURN_OFF_CELSIUS = 55 # GPIO relay connections # format: (GPIO pin, true message, false message, relay number, description) GPIO_ERROR_VESTABOARD_CONNECTION = ( 22, 'ERROR: Vestaboard unavailable', 'SUCCESS: Vestaboard available', 1, 'Vestaboard connected') GPIO_ERROR_FLIGHT_AWARE_CONNECTION = ( 23, 'ERROR: FlightAware not available', 'SUCCESS: FlightAware available', 2, 'FlightAware connected') GPIO_ERROR_ARDUINO_SERVO_CONNECTION = ( 24, 'ERROR: Servos not running or lost connection', 'SUCCESS: Handshake with servo Arduino received', 3, 'Hemisphere connected') GPIO_ERROR_ARDUINO_REMOTE_CONNECTION = ( 25, 'ERROR: Remote not running or lost connection', 'SUCCESS: Handshake with remote Arduino received', 4, 'Remote connected') GPIO_ERROR_BATTERY_CHARGE = ( 26, 'ERROR: Remote battery is low', 'SUCCESS: Remote battery recharged', 5, 'Remote charged') GPIO_FAN = ( 5, 'ERROR: RPi above %dC degrees' % TEMP_FAN_TURN_ON_CELSIUS, 'SUCCESS: RPi below %dC degrees' % TEMP_FAN_TURN_OFF_CELSIUS, 7, 'Thermal condition') # for future expansion GPIO_UNUSED_1 = ( 27, 'Undefined condition set to true', 'Undefined condition set to false', 6) GPIO_UNUSED_2 = ( 6, 'Undefined condition set to true', 'Undefined condition set to false', 8) # GPIO pushbutton connections - (GPIO pin switch in; GPIO pin LED out) GPIO_SOFT_RESET = (20, 21) #if running on raspberry, then need to prepend path to file names if RASPBERRY_PI: PICKLE_FLIGHTS = MESSAGEBOARD_PATH + PICKLE_FLIGHTS PICKLE_DASHBOARD = MESSAGEBOARD_PATH + PICKLE_DASHBOARD LOGFILE = MESSAGEBOARD_PATH + LOGFILE PICKLE_DUMP_JSON_FILE = MESSAGEBOARD_PATH + PICKLE_DUMP_JSON_FILE PICKLE_FA_JSON_FILE = MESSAGEBOARD_PATH + PICKLE_FA_JSON_FILE CODE_REPOSITORY = MESSAGEBOARD_PATH HISTOGRAM_CONFIG_FILE = WEBSERVER_PATH + HISTOGRAM_CONFIG_FILE <----SKIPPED LINES----> # flight_number flight_number = aircraft.get('flight') if flight_number: flight_number = flight_number.strip() # squawk squawk = aircraft.get('squawk') if squawk: squawk = squawk.strip() identifier = (flight_number, squawk) # merge any duplicate flights: since the id for nearby_aircraft & persistent_path is # the 2-tuple (flight_number, squawk), it's possible for a flight to add or drop # one of those two elements over time as the radio signal comes in / falls out. # Let's keep the identifier as the non-null values as soon as one is seen. id_to_use, ids_to_merge = MergedIdentifier(identifier, persistent_path.keys()) # Now we need to rename any flight paths with that partial identifier to have # the correct new merged_identifier; bu if ids_to_merge: persistent_path = MergePersistentPath(id_to_use, ids_to_merge, persistent_path) if 'lat' in aircraft and 'lon' in aircraft: lat = aircraft['lat'] lon = aircraft['lon'] if isinstance(lat, numbers.Number) and isinstance(lon, numbers.Number): simplified_aircraft['lat'] = lat simplified_aircraft['lon'] = lon altitude = aircraft.get('altitude', aircraft.get('alt_baro')) if isinstance(altitude, numbers.Number): simplified_aircraft['altitude'] = altitude speed = aircraft.get('speed', aircraft.get('gs')) if speed is not None: simplified_aircraft['speed'] = speed vert_rate = aircraft.get('vert_rate', aircraft.get('baro_rate')) if vert_rate is not None: simplified_aircraft['vert_rate'] = vert_rate track = aircraft.get('track') if isinstance(track, numbers.Number): min_meters = MinMetersToHome((lat, lon), track) simplified_aircraft['track'] = track simplified_aircraft['min_feet'] = min_meters * FEET_IN_METER if HaversineDistanceMeters(HOME, (lat, lon)) < MIN_METERS: nearby_aircraft[id_to_use] = simplified_aircraft if flight_number: nearby_aircraft[id_to_use]['flight_number'] = flight_number if squawk: nearby_aircraft[id_to_use]['squawk'] = squawk # aircraft classification: # https://github.com/wiedehopf/adsb-wiki/wiki/ADS-B-aircraft-categories category = aircraft.get('category') if category is not None: simplified_aircraft['category'] = category # keep all that track info - once we start reporting on a nearby flight, it will # become part of the flight's persistent record. Also, note that as we are # building a list of tracks for each flight, and we are later assigning the # flight dictionary to point to the list, we just simply need to continue # updating this list to keep the dictionary up to date (i.e.: we don't need # to directly touch the flights dictionary in main). (last_seen, current_path) = persistent_path.get(id_to_use, (None, [])) if ( # flight position has been updated with this radio signal not current_path or simplified_aircraft.get('lat') != current_path[-1].get('lat') or simplified_aircraft.get('lon') != current_path[-1].get('lon')): current_path.append(simplified_aircraft) persistent_path[id_to_use] = (now, current_path) # if the flight was last seen too far in the past, remove the track info for f in list(persistent_path.keys()): (last_seen, current_path) = persistent_path[f] if last_seen < now - PERSISTENCE_SECONDS: persistent_path.pop(f) <----SKIPPED LINES----> Log('Process (%s) for %s died; restarting' % (str(p), str(start_function))) args[2].value = 0 # (re)set shutdown flag to allow function to run p = multiprocessing.Process(target=start_function, args=args) p.daemon = True # has been set to True #TODO p.start() return p def EnqueueArduinos(flights, json_desc_dict, configuration, to_servo_q, to_remote_q): """Send latest data to arduinos via their shared-memory queues""" 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 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: Log('Message queues to Arduinos full - trigger shutdown') global SHUTDOWN_SIGNAL SHUTDOWN_SIGNAL = True <----SKIPPED LINES----> def CheckTemperature(): """Turn on fan if temperature exceeds threshold.""" if RASPBERRY_PI: temperature = gpiozero.CPUTemperature().temperature if temperature > TEMP_FAN_TURN_ON_CELSIUS: UpdateStatusLight(GPIO_FAN, True) elif temperature < TEMP_FAN_TURN_OFF_CELSIUS: UpdateStatusLight(GPIO_FAN, False) pin_values = {} # caches last set value def SetPinMode(): """Initialize output GPIO pins for output on Raspberry Pi.""" global pin_values if RASPBERRY_PI: RPi.GPIO.setmode(RPi.GPIO.BCM) for pin in ( GPIO_ERROR_VESTABOARD_CONNECTION, GPIO_ERROR_FLIGHT_AWARE_CONNECTION, GPIO_ERROR_ARDUINO_SERVO_CONNECTION, GPIO_ERROR_ARDUINO_REMOTE_CONNECTION, GPIO_ERROR_BATTERY_CHARGE, GPIO_FAN, GPIO_UNUSED_1, GPIO_UNUSED_2): # Initialize some pins to start in error condition if pin in ( GPIO_ERROR_ARDUINO_SERVO_CONNECTION, GPIO_ERROR_ARDUINO_REMOTE_CONNECTION, GPIO_UNUSED_1, GPIO_UNUSED_2): pin_values[pin[0]] = True else: pin_values[pin[0]] = False if RASPBERRY_PI: RPi.GPIO.setup(pin[0], RPi.GPIO.OUT) RPi.GPIO.output(pin[0], pin_values[pin[0]]) UpdateDashboard(pin_values[pin[0]], pin) if RASPBERRY_PI: # configure soft reset button RPi.GPIO.setup(GPIO_SOFT_RESET[0], RPi.GPIO.IN, pull_up_down=RPi.GPIO.PUD_DOWN) RPi.GPIO.setup(GPIO_SOFT_RESET[1], RPi.GPIO.OUT) RPi.GPIO.output(GPIO_SOFT_RESET[1], True) RPi.GPIO.add_event_detect(GPIO_SOFT_RESET[0], RPi.GPIO.RISING) RPi.GPIO.add_event_callback(GPIO_SOFT_RESET[0], InterruptRebootFromButton) def UpdateStatusLight(pin, value): """Sets the Raspberry Pi GPIO pin high (True) or low (False) based on value.""" global pin_values if value: msg = pin[1] else: msg = pin[2] if RASPBERRY_PI: RPi.GPIO.output(pin[0], value) if value: pin_setting = 'HIGH' relay_light_value = 'OFF' else: pin_setting = 'LOW' relay_light_value = 'ON' msg += '; RPi GPIO pin %d set to %s; relay light #%d should now be %s' % ( pin[0], pin_setting, pin[3], relay_light_value) if pin_values[pin[0]] != value: Log(msg) # log pin_values[pin[0]] = value # update cache UpdateDashboard(value, pin) def UpdateDashboard(value, subsystem=0): versions = (VERSION_MESSAGEBOARD, VERSION_ARDUINO) if subsystem: subsystem = subsystem[0] PickleObjectToFile((time.time(), subsystem, value, versions), PICKLE_DASHBOARD, True) def RemoveFile(file): """Removes a file if it exists, returning a boolean indicating if it had existed.""" if os.path.exists(file): os.remove(file) return True return False def ConfirmNewFlight(flight, flights): <----SKIPPED LINES----> Log(message) args = (PICKLE_FLIGHTS, not SIMULATION, max_days) saved_flights = UnpickleObjectFromFile(*args)[:-1] files_to_overwrite = UnpickleObjectFromFile(*args, filenames=True) for file in files_to_overwrite: os.remove(file) for f in saved_flights: PickleObjectToFile(f, PICKLE_FLIGHTS, not SIMULATION) return False def HeartbeatRestart(): if SIMULATION: return 0 UpdateDashboard(True) # Indicates that this wasn't running a moment before, ... UpdateDashboard(False) # ... and now it is running! return time.time() def Heartbeat(last_heartbeat_time): if SIMULATION: return last_heartbeat_time now = time.time() if now - last_heartbeat_time > HEARTBEAT_SECONDS: UpdateDashboard(False) last_heartbeat_time = now return last_heartbeat_time def VersionControl(): global VERSION_MESSAGEBOARD global VERSION_ARDUINO def MakeCopy(python_prefix): file_extension = '.py' live_name = python_prefix + '.py' live_path = os.path.join(CODE_REPOSITORY, live_name) <----SKIPPED LINES----> |
01234567890123456789012345678901234567890123456789012345678901234567890123456789
171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496 49904991499249934994499549964997499849995000500150025003500450055006500750085009 50105011501250135014501550165017501850195020502150225023502450255026502750285029 52465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274 52755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330 53935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433 | <----SKIPPED LINES----> FLAG_INSIGHT_FIRST_ORIGIN = 7 FLAG_INSIGHT_FIRST_AIRLINE = 8 FLAG_INSIGHT_FIRST_AIRCRAFT = 9 FLAG_INSIGHT_LONGEST_DELAY = 10 FLAG_INSIGHT_FLIGHT_DELAY_FREQUENCY = 11 FLAG_INSIGHT_FLIGHT_DELAY_TIME = 12 FLAG_INSIGHT_AIRLINE_DELAY_FREQUENCY = 13 FLAG_INSIGHT_AIRLINE_DELAY_TIME = 14 FLAG_INSIGHT_DESTINATION_DELAY_FREQUENCY = 15 FLAG_INSIGHT_DESTINATION_DELAY_TIME = 16 FLAG_INSIGHT_HOUR_DELAY_FREQUENCY = 17 FLAG_INSIGHT_HOUR_DELAY_TIME = 18 FLAG_INSIGHT_DATE_DELAY_FREQUENCY = 19 FLAG_INSIGHT_DATE_DELAY_TIME = 20 INSIGHT_TYPES = 21 TEMP_FAN_TURN_ON_CELSIUS = 65 TEMP_FAN_TURN_OFF_CELSIUS = 55 # GPIO relay connections # format: (GPIO pin, true message, false message, relay number, description, initial_state) GPIO_ERROR_VESTABOARD_CONNECTION = ( 22, 'ERROR: Vestaboard unavailable', 'SUCCESS: Vestaboard available', 1, 'Vestaboard connected', False) GPIO_ERROR_FLIGHT_AWARE_CONNECTION = ( 23, 'ERROR: FlightAware not available', 'SUCCESS: FlightAware available', 2, 'FlightAware connected', False) GPIO_ERROR_ARDUINO_SERVO_CONNECTION = ( 24, 'ERROR: Servos not running or lost connection', 'SUCCESS: Handshake with servo Arduino received', 3, 'Hemisphere connected', True) GPIO_ERROR_ARDUINO_REMOTE_CONNECTION = ( 25, 'ERROR: Remote not running or lost connection', 'SUCCESS: Handshake with remote Arduino received', 4, 'Remote connected', True) GPIO_ERROR_BATTERY_CHARGE = ( 26, 'ERROR: Remote battery is low', 'SUCCESS: Remote battery recharged', 5, 'Remote charged', False) GPIO_FAN = ( 5, 'ERROR: RPi above %dC degrees' % TEMP_FAN_TURN_ON_CELSIUS, 'SUCCESS: RPi below %dC degrees' % TEMP_FAN_TURN_OFF_CELSIUS, 7, 'Thermal condition', False) # for future expansion GPIO_UNUSED_1 = ( 27, 'Undefined condition set to true', 'Undefined condition set to false', 6) GPIO_UNUSED_2 = ( 6, 'Undefined condition set to true', 'Undefined condition set to false', 8) # GPIO pushbutton connections - (GPIO pin switch in; GPIO pin LED out) GPIO_SOFT_RESET = (20, 21) #if running on raspberry, then need to prepend path to file names if RASPBERRY_PI: PICKLE_FLIGHTS = MESSAGEBOARD_PATH + PICKLE_FLIGHTS PICKLE_DASHBOARD = MESSAGEBOARD_PATH + PICKLE_DASHBOARD LOGFILE = MESSAGEBOARD_PATH + LOGFILE PICKLE_DUMP_JSON_FILE = MESSAGEBOARD_PATH + PICKLE_DUMP_JSON_FILE PICKLE_FA_JSON_FILE = MESSAGEBOARD_PATH + PICKLE_FA_JSON_FILE CODE_REPOSITORY = MESSAGEBOARD_PATH HISTOGRAM_CONFIG_FILE = WEBSERVER_PATH + HISTOGRAM_CONFIG_FILE <----SKIPPED LINES----> # flight_number flight_number = aircraft.get('flight') if flight_number: flight_number = flight_number.strip() # squawk squawk = aircraft.get('squawk') if squawk: squawk = squawk.strip() identifier = (flight_number, squawk) # merge any duplicate flights: since the id for nearby_aircraft & persistent_path is # the 2-tuple (flight_number, squawk), it's possible for a flight to add or drop # one of those two elements over time as the radio signal comes in / falls out. # Let's keep the identifier as the non-null values as soon as one is seen. id_to_use, ids_to_merge = MergedIdentifier(identifier, persistent_path.keys()) # Now we need to rename any flight paths with that partial identifier to have # the correct new merged_identifier if ids_to_merge: persistent_path = MergePersistentPath(id_to_use, ids_to_merge, persistent_path) if 'lat' in aircraft and 'lon' in aircraft: lat = aircraft['lat'] lon = aircraft['lon'] if isinstance(lat, numbers.Number) and isinstance(lon, numbers.Number): simplified_aircraft['lat'] = lat simplified_aircraft['lon'] = lon altitude = aircraft.get('altitude', aircraft.get('alt_baro')) if isinstance(altitude, numbers.Number): simplified_aircraft['altitude'] = altitude speed = aircraft.get('speed', aircraft.get('gs')) if speed is not None: simplified_aircraft['speed'] = speed vert_rate = aircraft.get('vert_rate', aircraft.get('baro_rate')) if vert_rate is not None: simplified_aircraft['vert_rate'] = vert_rate track = aircraft.get('track') if isinstance(track, numbers.Number): min_meters = MinMetersToHome((lat, lon), track) simplified_aircraft['track'] = track simplified_aircraft['min_feet'] = min_meters * FEET_IN_METER # TODO: describe why we want to base this off haversine distance (i.e.: # the actual distance from home) vs. MinMetersToHome (i.e.: forecasted min # distance from home); it seems like the latter would give us more time # to respond? - maybe because there might be other closer flights even though # a far away flight might look like it's going to come nearby? haversine_distance_meters = HaversineDistanceMeters(HOME, (lat, lon)) simplified_aircraft['distance'] = haversine_distance_meters if haversine_distance_meters < MIN_METERS: #nearby_aircraft[id_to_use]['distance'] = haversine_distance_meters nearby_aircraft[id_to_use] = simplified_aircraft if flight_number: nearby_aircraft[id_to_use]['flight_number'] = flight_number if squawk: nearby_aircraft[id_to_use]['squawk'] = squawk # aircraft classification: # https://github.com/wiedehopf/adsb-wiki/wiki/ADS-B-aircraft-categories category = aircraft.get('category') if category is not None: nearby_aircraft[id_to_use]['category'] = category # keep all that track info - once we start reporting on a nearby flight, it will # become part of the flight's persistent record. Also, note that as we are # building a list of tracks for each flight, and we are later assigning the # flight dictionary to point to the list, we just simply need to continue # updating this list to keep the dictionary up to date (i.e.: we don't need # to directly touch the flights dictionary in main). (last_seen, current_path) = persistent_path.get(id_to_use, (None, [])) if ( # flight position has been updated with this radio signal not current_path or simplified_aircraft.get('lat') != current_path[-1].get('lat') or simplified_aircraft.get('lon') != current_path[-1].get('lon')): current_path.append(simplified_aircraft) persistent_path[id_to_use] = (now, current_path) # if the flight was last seen too far in the past, remove the track info for f in list(persistent_path.keys()): (last_seen, current_path) = persistent_path[f] if last_seen < now - PERSISTENCE_SECONDS: persistent_path.pop(f) <----SKIPPED LINES----> Log('Process (%s) for %s died; restarting' % (str(p), str(start_function))) args[2].value = 0 # (re)set shutdown flag to allow function to run p = multiprocessing.Process(target=start_function, args=args) p.daemon = True # has been set to True #TODO p.start() return p def EnqueueArduinos(flights, json_desc_dict, configuration, to_servo_q, to_remote_q): """Send latest data to arduinos via their shared-memory queues""" 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 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: Log('Message queues to Arduinos full - trigger shutdown') global SHUTDOWN_SIGNAL SHUTDOWN_SIGNAL = True <----SKIPPED LINES----> def CheckTemperature(): """Turn on fan if temperature exceeds threshold.""" if RASPBERRY_PI: temperature = gpiozero.CPUTemperature().temperature if temperature > TEMP_FAN_TURN_ON_CELSIUS: UpdateStatusLight(GPIO_FAN, True) elif temperature < TEMP_FAN_TURN_OFF_CELSIUS: UpdateStatusLight(GPIO_FAN, False) pin_values = {} # caches last set value def SetPinMode(): """Initialize output GPIO pins for output on Raspberry Pi.""" global pin_values if RASPBERRY_PI: RPi.GPIO.setmode(RPi.GPIO.BCM) pins = ( GPIO_ERROR_VESTABOARD_CONNECTION, GPIO_ERROR_FLIGHT_AWARE_CONNECTION, GPIO_ERROR_ARDUINO_SERVO_CONNECTION, GPIO_ERROR_ARDUINO_REMOTE_CONNECTION, GPIO_ERROR_BATTERY_CHARGE, GPIO_FAN, GPIO_UNUSED_1, GPIO_UNUSED_2) for pin in pins: initial_state = pin[5] pin_values[pin[0]] = initial_state # Initialize state of pins UpdateDashboard(initial_state, pin) if RASPBERRY_PI: RPi.GPIO.setup(pin[0], RPi.GPIO.OUT) RPi.GPIO.output(pin[0], pin_values[pin[0]]) UpdateDashboard(pin_values[pin[0]], pin) if RASPBERRY_PI: # configure soft reset button RPi.GPIO.setup(GPIO_SOFT_RESET[0], RPi.GPIO.IN, pull_up_down=RPi.GPIO.PUD_DOWN) RPi.GPIO.setup(GPIO_SOFT_RESET[1], RPi.GPIO.OUT) RPi.GPIO.output(GPIO_SOFT_RESET[1], True) RPi.GPIO.add_event_detect(GPIO_SOFT_RESET[0], RPi.GPIO.RISING) RPi.GPIO.add_event_callback(GPIO_SOFT_RESET[0], InterruptRebootFromButton) def UpdateStatusLight(pin, value): """Sets the Raspberry Pi GPIO pin high (True) or low (False) based on value.""" global pin_values if value: msg = pin[1] else: msg = pin[2] if RASPBERRY_PI: RPi.GPIO.output(pin[0], value) if value: pin_setting = 'HIGH' relay_light_value = 'OFF' else: pin_setting = 'LOW' relay_light_value = 'ON' msg += '; RPi GPIO pin %d set to %s; relay light #%d should now be %s' % ( pin[0], pin_setting, pin[3], relay_light_value) if pin_values[pin[0]] != value: if VERBOSE: Log(msg) # log pin_values[pin[0]] = value # update cache UpdateDashboard(value, pin) def UpdateDashboard(value, subsystem=0): versions = (VERSION_MESSAGEBOARD, VERSION_ARDUINO) if subsystem: subsystem = subsystem[0] PickleObjectToFile((time.time(), subsystem, value, versions), PICKLE_DASHBOARD, True) def RemoveFile(file): """Removes a file if it exists, returning a boolean indicating if it had existed.""" if os.path.exists(file): os.remove(file) return True return False def ConfirmNewFlight(flight, flights): <----SKIPPED LINES----> Log(message) args = (PICKLE_FLIGHTS, not SIMULATION, max_days) saved_flights = UnpickleObjectFromFile(*args)[:-1] files_to_overwrite = UnpickleObjectFromFile(*args, filenames=True) for file in files_to_overwrite: os.remove(file) for f in saved_flights: PickleObjectToFile(f, PICKLE_FLIGHTS, not SIMULATION) return False def HeartbeatRestart(): if SIMULATION: return 0 UpdateDashboard(True) # Indicates that this wasn't running a moment before, ... UpdateDashboard(False) # ... and now it is running! return time.time() def Heartbeat(last_heartbeat_time): if SIMULATION: return last_heartbeat_time now = time.time() if now - last_heartbeat_time > HEARTBEAT_SECONDS: UpdateDashboard(False) last_heartbeat_time = now return last_heartbeat_time def VersionControl(): global VERSION_MESSAGEBOARD global VERSION_ARDUINO def MakeCopy(python_prefix): file_extension = '.py' live_name = python_prefix + '.py' live_path = os.path.join(CODE_REPOSITORY, live_name) <----SKIPPED LINES----> |