def altimeter_reading_loop(configuration: Configuration, altimeter_value: AtomicValue): """Continually read the altimeter and set it to the atomic var""" try: bmp = init_altimeter(configuration) while bmp: try: altimeter_value.update(bmp._read()) # pylint: disable=protected-access except Exception as ex: # pylint: disable=broad-except handle_exception("Altimeter reading failure", ex) except Exception as ex: # pylint: disable=broad-except handle_exception("Altimeter setup failure", ex)
class BufferSessionStore: """Data capture session storage engine""" 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 initialize(self): """Initialize the store. (Pins the SQLite connection to the calling thread)""" self.connection = sqlite3.connect( path.join(self.output_dir, self.sql_file)) self.cursor = self.connection.cursor() self.cursor.execute( "CREATE TABLE IF NOT EXISTS sessions (timestamp NUMBER UNIQUE NOT NULL)" ) self.connection.commit() self.create_new_session() def get_sessions(self) -> List[float]: """Get a list of saved sessions""" self.cursor.execute( "SELECT timestamp FROM sessions WHERE timestamp != ? ORDER BY timestamp DESC", (self.current_session.get_value(), ), ) return [row[0] for row in self.cursor.fetchall()] def create_new_session(self) -> float: """Create and save a new session""" timestamp = int(time.time()) self.current_session.update(timestamp) self.cursor.execute("INSERT INTO sessions (timestamp) VALUES (?)", (timestamp, )) self.connection.commit() self.buffer.purge() return timestamp def load_session(self, session) -> List[List[float]]: """Load data from a given session""" with open(self.data_path_for_session(session), "r") as csvfile: reader = csv.reader(csvfile) return [[float(v) for v in r] for r in reader] def data_path_for_session(self, session=None) -> str: """Get the path to the given session's data""" if not session: session = self.current_session.get_value() return path.join(self.output_dir, f"telemetry_log_{session}.csv")
def take_gps_reading(sio, gps_value: AtomicValue) -> bool: """Grab the most recent data from GPS feed""" line = sio.readline() if line[0:6] == "$GPGGA": gps = pynmea2.parse(line) gps_value.update(( gps.latitude if gps else 0.0, gps.longitude if gps else 0.0, gps.gps_qual if gps else 0.0, float(gps.num_sats) if gps else 0.0, )) return True return False
def magnetometer_accelerometer_reading_loop( configuration: Configuration, magnetometer_accelerometer_value: AtomicValue): """Continually read the accelerometer/magnetometer and set it to the atomic var""" try: mag, accel = init_magnetometer_accelerometer(configuration) while mag and accel: try: magnetometer_accelerometer_value.update( (*accel.acceleration, *mag.magnetic)) except Exception as ex: # pylint: disable=broad-except handle_exception("Magnetometer/Accelerometer reading failure", ex) except Exception as ex: # pylint: disable=broad-except handle_exception("Magnetometer/Accelerometer setup failure", ex)
def take_gps_reading(sio, gps_value: AtomicValue) -> bool: """Grab the most recent data from GPS feed""" line = sio.readline() gps = pynmea2.parse(line) if isinstance(gps, pynmea2.types.talker.GGA): gps_value.update( ( gps.latitude if gps else 0.0, gps.longitude if gps else 0.0, float(gps.gps_qual) if gps else 0.0, float(gps.num_sats) if gps else 0.0, ) ) return True return False
def test_write_sensor_log(): start_time = time.time() outfile = io.StringIO("") data_queue = Queue() while data_queue.qsize() < 100: data_queue.put((random.random(), random.random(), random.random())) continue_running = AtomicValue(True) thread = Thread( target=write_sensor_log, args=(start_time, outfile, data_queue, continue_running, continue_running), ) thread.start() time.sleep(5) continue_running.update(False) thread.join() contents = outfile.getvalue() assert contents assert len(contents.split("\n")) > 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()
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() # Timestamp to use for log files and log saving cutoff start_time = time.time() # Thread safe place to store altitude reading current_reading = AtomicValue() # Holds the most recent GPS data gps_value = AtomicValue((0.0, 0.0, 0.0, 0.0)) altimeter_value = AtomicValue() altimeter_value.update((0.0, 0.0)) magnetometer_accelerometer_value = AtomicValue() magnetometer_accelerometer_value.update((0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) gps_thread = create_gps_thread(configuration, gps_value) gps_thread.start() write_thread = Thread( target=sensor_log_writing_loop, args=(configuration, start_time, data_queue), daemon=True, ) write_thread.start() camera_thread_handle = Thread( target=camera_thread, args=(configuration, start_time), daemon=True, ) camera_thread_handle.start() transmitter_thread_handle = Thread( target=transmitter_thread, args=( configuration, start_time, current_reading, ), daemon=True, ) transmitter_thread_handle.start() altimeter_thread = Thread( target=altimeter_reading_loop, args=(configuration, altimeter_value) ) altimeter_thread.start() magnetometer_accelerometer_thread = Thread( target=magnetometer_accelerometer_reading_loop, args=(configuration, magnetometer_accelerometer_value), ) magnetometer_accelerometer_thread.start() sensor_reading_loop( start_time, data_queue, current_reading, gps_value, altimeter_value, magnetometer_accelerometer_value, )
def test_atomic_value(): raw_value = random.random() value = AtomicValue(raw_value) assert raw_value == value.get_value() value.update(random.random()) assert raw_value != value.get_value()