def camera_thread(configuration: Configuration, start_time: float): """Start the camera and log the video""" try: logging.info("Starting video capture") runtime_limit = configuration.get("runtime_limit") output_directory = configuration.get("output_directory") camera = picamera.PiCamera(framerate=90) camera.start_recording( os.path.join(output_directory, f"video_{int(start_time)}.h264")) camera.wait_recording(runtime_limit) camera.stop_recording() logging.info("Video capture complete") except Exception as ex: # pylint: disable=broad-except handle_exception("Video capture failure", ex)
def sensor_log_writing_loop(configuration: Configuration, start_time: float, data_queue: Queue): """Loop through clearing the data queue until RUNTIME_LIMIT has passed""" try: logging.info("Starting sensor log writing loop") runtime_limit = configuration.get("runtime_limit") output_directory = configuration.get("output_directory") with open( os.path.join(output_directory, f"sensor_log_{int(start_time)}.csv"), "w") as outfile: write_sensor_log(start_time, runtime_limit, outfile, data_queue) logging.info("Telemetry log writing loop complete") except Exception as ex: # pylint: disable=broad-except handle_exception("Telemetry log line writing failure", ex)
def __init__(self, configuration: Configuration, sql_file: str = "sessionstore.sqlite3"): """Create a new session store""" self.buffer = SafeBuffer() self.current_session = AtomicValue() self.output_dir = configuration.get("output_directory") self.sql_file = sql_file self.connection = None self.cursor = None
def telemetry_dashboard_server(configuration: Configuration, buffer_session_store: BufferSessionStore): """Serve the static parts of the dashboard visualization""" try: logging.info("Starting telemetry dashboard server") buffer_session_store.initialize() klass = ground_http_class_factory(buffer_session_store) httpd = HTTPServer(("0.0.0.0", configuration.get("http_server_port")), klass) httpd.serve_forever() except Exception as ex: # pylint: disable=broad-except logging.error("Telemetry dashboard server failure: %s", str(ex)) logging.exception(ex)
def camera_thread( configuration: Configuration, start_time: float, continue_running: AtomicValue, continue_logging: AtomicValue, ): """Start the camera and log the video""" try: logging.info("Starting video capture") output_directory = configuration.get("output_directory") camera = picamera.PiCamera(framerate=90) camera.start_recording( os.path.join(output_directory, f"video_{int(start_time)}.h264") ) while continue_running.get_value() and continue_logging.get_value(): time.sleep(5) camera.stop_recording() logging.info("Video capture complete") except Exception as ex: # pylint: disable=broad-except handle_exception("Video capture failure", ex)
def sensor_log_writing_loop( configuration: Configuration, start_time: float, data_queue: Queue, continue_running: AtomicValue, continue_logging: AtomicValue, ): """Loop through clearing the data queue until cancelled""" try: logging.info("Starting sensor log writing loop") output_directory = configuration.get("output_directory") with open( os.path.join(output_directory, f"sensor_log_{int(start_time)}.csv"), "w", encoding="utf8", ) as outfile: write_sensor_log( start_time, outfile, data_queue, continue_running, continue_logging ) logging.info("Telemetry log writing loop complete") except Exception as ex: # pylint: disable=broad-except handle_exception("Telemetry log line writing failure", ex)
def telemetry_streaming_server(configuration: Configuration, buffer_session_store: BufferSessionStore): """Serve the active buffer over websocket""" async def data_stream(websocket, _): """Handle a connection on a websocket""" try: logging.info("Client connected to streaming server") last_index = 0 while True: if websocket.closed: return end_index = buffer_session_store.buffer.size() if end_index > last_index: await websocket.send( json.dumps( buffer_session_store.buffer.get_range( last_index, end_index))) last_index = end_index await asyncio.sleep(1) except websockets.exceptions.ConnectionClosed: logging.info("Client disconnected from streaming server") except Exception as ex: # pylint: disable=broad-except logging.error("Telemetry streaming server failure: %s", str(ex)) logging.exception(ex) try: logging.info("Starting telemetry streaming server") loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) start_server = websockets.serve( data_stream, "0.0.0.0", configuration.get("streaming_server_port")) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever() except websockets.exceptions.ConnectionClosed: logging.info("Client disconnected from streaming server") except Exception as ex: # pylint: disable=broad-except logging.error("Telemetry streaming server failure: %s", str(ex)) logging.exception(ex)
def main(): """Inboard data capture and transmission script""" # Load up the system configuration configuration = Configuration(os.getenv("AIR_CONFIG_FILE", None), Configuration.default_air_configuration) # Queue to manage data synchronization between sensor reading, transmission, and data logging data_queue = Queue(1000) # Timestamp to use for log files and log saving cutoff start_time = time.time() # Thread safe place to store altitude reading current_readings = AtomicBuffer(50) # Holds the most recent GPS data gps_value = AtomicValue((0.0, 0.0, 0.0, 0.0)) # pcnt counter to runtime limit pcnt_to_limit = AtomicValue(0.0) # Thread safe place to store continue value continue_running = AtomicValue(True) # Thread safe place to store continue value continue_logging = AtomicValue(True) # Setup listener for reset button init_reset_button(configuration, continue_running) gps_thread = create_gps_thread(configuration, gps_value, continue_running) gps_thread.start() write_thread = Thread( target=sensor_log_writing_loop, args=( configuration, start_time, data_queue, continue_running, continue_logging, ), daemon=True, ) write_thread.start() camera_thread_handle = Thread( target=camera_thread, args=(configuration, start_time, continue_running, continue_logging), daemon=True, ) camera_thread_handle.start() transmitter_thread_handle = Thread( target=transmitter_thread, args=( configuration, start_time, current_readings, pcnt_to_limit, continue_running, ), daemon=True, ) transmitter_thread_handle.start() sensor_reading_thread = Thread( target=sensor_reading_loop, args=( configuration, start_time, data_queue, current_readings, gps_value, continue_running, ), daemon=True, ) sensor_reading_thread.start() runtime_limit = configuration.get("runtime_limit") while continue_running.get_value( ) and time.time() - start_time <= runtime_limit: pcnt_to_limit.update((time.time() - start_time) / runtime_limit) time.sleep(1) logging.info("Stopping write activities") continue_logging.update(False) write_thread.join() camera_thread_handle.join() pcnt_to_limit.update(1) logging.info("Write activities ended") gps_thread.join() transmitter_thread_handle.join() sensor_reading_thread.join()