diff --git a/modules/telemetry/v1/data_block.py b/modules/telemetry/v1/data_block.py index 05009e4..90b536c 100644 --- a/modules/telemetry/v1/data_block.py +++ b/modules/telemetry/v1/data_block.py @@ -104,10 +104,11 @@ def parse(block_subtype: DataBlockSubtype, payload: bytes) -> DataBlock: DataBlockSubtype.ALTITUDE_LAUNCH_LEVEL: AltitudeLaunchLevelDB, DataBlockSubtype.TEMPERATURE: TemperatureDB, DataBlockSubtype.PRESSURE: PressureDB, - DataBlockSubtype.HUMIDITY: HumidityDB, DataBlockSubtype.LIN_ACCEL_REL: RelativeLinearAccelerationDB, DataBlockSubtype.LIN_ACCEL_ABS: AbsoluteLinearAccelerationDB, DataBlockSubtype.ANGULAR_VELOCITY: AngularVelocityDB, + DataBlockSubtype.HUMIDITY: HumidityDB, + DataBlockSubtype.COORDINATES: CoordinatesDB, DataBlockSubtype.VOLTAGE: VoltageDB, } @@ -290,47 +291,6 @@ def __iter__(self): yield "pressure", {"pascals": self.pressure, "psi": pascals_to_psi(self.pressure)} -class HumidityDB(DataBlock): - """Represents a humidity data block.""" - - def __init__(self, mission_time: int, humidity: int) -> None: - """ - Constructs a humidity data block. - - Args: - mission_time: The mission time the humidity was measured at in milliseconds since launch. - humidity: The calculated relative humidity in ten thousandths of a percent. - - """ - super().__init__(mission_time) - self.humidity: int = humidity - - @classmethod - def from_bytes(cls, payload: bytes) -> Self: - """ - Constructs a humidity data block from bytes. - Returns: - A humidity data block. - """ - parts = struct.unpack(" int: - """ - Get the length of a humidity data block in bytes. - Returns: - The length of a humidity data block in bytes, not including the block header. - """ - return 8 - - def __str__(self): - return f"{self.__class__.__name__} -> time: {self.mission_time} ms, humidity: {round(self.humidity / 100)}%" - - def __iter__(self): - yield "mission_time", self.mission_time - yield "percentage", round(self.humidity / 100) - - class LinearAccelerationDB(DataBlock): """Represents a linear acceleration data block""" @@ -439,6 +399,91 @@ def __iter__(self): yield "angular_velocity", {"x": self.x_axis, "y": self.y_axis, "z": self.z_axis, "magnitude": self.magnitude} +class HumidityDB(DataBlock): + """Represents a humidity data block.""" + + def __init__(self, mission_time: int, humidity: int) -> None: + """ + Constructs a humidity data block. + + Args: + mission_time: The mission time the humidity was measured at in milliseconds since launch. + humidity: The calculated relative humidity in ten thousandths of a percent. + + """ + super().__init__(mission_time) + self.humidity: int = humidity + + @classmethod + def from_bytes(cls, payload: bytes) -> Self: + """ + Constructs a humidity data block from bytes. + Returns: + A humidity data block. + """ + parts = struct.unpack(" int: + """ + Get the length of a humidity data block in bytes. + Returns: + The length of a humidity data block in bytes, not including the block header. + """ + return 8 + + def __str__(self): + return f"{self.__class__.__name__} -> time: {self.mission_time} ms, humidity: {round(self.humidity / 100)}%" + + def __iter__(self): + yield "mission_time", self.mission_time + yield "percentage", round(self.humidity / 100) + + +class CoordinatesDB(DataBlock): + """Represents a coordinates data block""" + + def __init__(self, mission_time: int, latitude: int, longitude: int) -> None: + """ + Constructs a coordinates data block. + + Args: + mission_time: The mission time the coordinates were measured in milliseconds since launch. + latitude: The latitude in units of micro-degrees. + longitude: The longitude in units of micro-degrees. + """ + super().__init__(mission_time) + self.latitude: int = latitude + self.longitude: int = longitude + + @classmethod + def from_bytes(cls, payload: bytes) -> Self: + """ + Constructs a coordinates data block from bytes. + Returns: + A coordinates data block. + """ + parts = struct.unpack(" int: + """ + Get the length of a coordinates data block in bytes + Returns: + The length of a coordinates data block in bytes not including the block header. + """ + return 12 + + def __str__(self): + return f"""{self.__class__.__name__} -> time: {self.mission_time} ms, latitude: {(self.latitude / pow(10, 7))}° + , longitude: {(self.longitude / pow(10, 7))}°""" + + def __iter__(self): + yield "mission_time", self.mission_time + yield "latitude", self.latitude + yield "longitude", self.longitude + + class VoltageDB(DataBlock): """Represents a voltage data block""" diff --git a/tests/parsing/test_block_data.py b/tests/parsing/test_block_data.py index ef14072..5ed0a6c 100644 --- a/tests/parsing/test_block_data.py +++ b/tests/parsing/test_block_data.py @@ -7,6 +7,8 @@ TemperatureDB, LinearAccelerationDB, AngularVelocityDB, + HumidityDB, + CoordinatesDB, VoltageDB, ) @@ -60,8 +62,27 @@ def angular_velocity_data_content() -> bytes: @pytest.fixture -# 9b0d00000200ee0c -# DEBUG:modules.telemetry.telemetry_utils:VoltageDB -> time: 3483 ms, id: 2, voltage: 3310 mV +def humidity_data_content() -> bytes: + """ + Returns a humidity sensor reading with the following attributes + mission time: 4121ms + humidity: 44% + """ + return b"\x19\x10\x00\x00\xfe\x10\x00\x00" + + +@pytest.fixture +def coordinates_data_content() -> bytes: + """ + Returns a coordinates sensor reading with the following attributes + mission time: 3340ms + latitude: 0 + longitude: 0 + """ + return b"\x0c\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + + +@pytest.fixture def voltage_data_content() -> bytes: """ Returns a voltage sensor reading with the following attributes @@ -110,6 +131,23 @@ def test_angular_velocity_data_block(angular_velocity_data_content: bytes) -> No assert ang_vel.magnitude == 1.29 +def test_humidity_data_block(humidity_data_content: bytes) -> None: + """Test that the humidity data block is parsed correctly.""" + hdb = HumidityDB.from_bytes(humidity_data_content) + + assert hdb.mission_time == 4121 + assert hdb.humidity == 4350 + + +def test_coordinates_data_block(coordinates_data_content: bytes) -> None: + """Test that the coordinates data block is parsed correctly.""" + cdb = CoordinatesDB.from_bytes(coordinates_data_content) + + assert cdb.mission_time == 3340 + assert cdb.latitude == 0 + assert cdb.longitude == 0 + + def test_voltage_data_block(voltage_data_content: bytes) -> None: """Test that the voltage data block is parsed correctly.""" vdb = VoltageDB.from_bytes(voltage_data_content)