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---->
|