예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
 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
예제 #4
0
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)
예제 #5
0
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)
예제 #6
0
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)
예제 #7
0
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)
예제 #8
0
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()