|
20 | 20 | from pysquared.nvm.counter import Counter |
21 | 21 | from pysquared.nvm.flag import Flag |
22 | 22 | from pysquared.protos.imu import IMUProto |
| 23 | +from pysquared.protos.magnetometer import MagnetometerProto |
23 | 24 | from pysquared.protos.power_monitor import PowerMonitorProto |
24 | 25 | from pysquared.protos.radio import RadioProto |
25 | 26 | from pysquared.protos.temperature_sensor import TemperatureSensorProto |
26 | 27 | from pysquared.sensor_reading.acceleration import Acceleration |
27 | 28 | from pysquared.sensor_reading.angular_velocity import AngularVelocity |
28 | 29 | from pysquared.sensor_reading.avg import avg_readings |
29 | 30 | from pysquared.sensor_reading.current import Current |
| 31 | +from pysquared.sensor_reading.magnetic import Magnetic |
30 | 32 | from pysquared.sensor_reading.temperature import Temperature |
31 | 33 | from pysquared.sensor_reading.voltage import Voltage |
32 | 34 |
|
@@ -128,6 +130,14 @@ def get_acceleration(self) -> Acceleration: |
128 | 130 | return Acceleration(5.4, 3.2, 1.0) |
129 | 131 |
|
130 | 132 |
|
| 133 | +class MockMagnetometer(MagnetometerProto): |
| 134 | + """Mocks the MagnetometerProto for testing.""" |
| 135 | + |
| 136 | + def get_magnetic_field(self) -> Magnetic: |
| 137 | + """Mocks the get_magnetic_field method.""" |
| 138 | + return Magnetic(25.5, -12.3, 8.7) |
| 139 | + |
| 140 | + |
131 | 141 | def test_beacon_init(mock_logger, mock_packet_manager): |
132 | 142 | """Tests Beacon initialization. |
133 | 143 |
|
@@ -1041,3 +1051,130 @@ def test_beacon_encode_sensor_dict_with_non_numeric_values(): |
1041 | 1051 | # Verify encoding completed without error |
1042 | 1052 | encoded_data = encoder.to_bytes() |
1043 | 1053 | assert isinstance(encoded_data, bytes) |
| 1054 | + |
| 1055 | + |
| 1056 | +@patch("pysquared.nvm.flag.microcontroller") |
| 1057 | +@patch("pysquared.nvm.counter.microcontroller") |
| 1058 | +def test_beacon_send_with_magnetometer( |
| 1059 | + mock_flag_microcontroller, |
| 1060 | + mock_counter_microcontroller, |
| 1061 | + mock_logger, |
| 1062 | + mock_packet_manager, |
| 1063 | +): |
| 1064 | + """Tests sending a beacon with magnetometer sensor. |
| 1065 | +
|
| 1066 | + Args: |
| 1067 | + mock_flag_microcontroller: Mocked microcontroller for Flag. |
| 1068 | + mock_counter_microcontroller: Mocked microcontroller for Counter. |
| 1069 | + mock_logger: Mocked Logger instance. |
| 1070 | + mock_packet_manager: Mocked PacketManager instance. |
| 1071 | + """ |
| 1072 | + mock_flag_microcontroller.nvm = setup_datastore |
| 1073 | + mock_counter_microcontroller.nvm = setup_datastore |
| 1074 | + |
| 1075 | + magnetometer = MockMagnetometer() |
| 1076 | + |
| 1077 | + beacon = Beacon( |
| 1078 | + mock_logger, |
| 1079 | + "test_beacon", |
| 1080 | + mock_packet_manager, |
| 1081 | + 0, |
| 1082 | + magnetometer, |
| 1083 | + ) |
| 1084 | + |
| 1085 | + result = beacon.send() |
| 1086 | + |
| 1087 | + # Verify the beacon was sent successfully |
| 1088 | + assert result == mock_packet_manager.send.return_value |
| 1089 | + mock_packet_manager.send.assert_called_once() |
| 1090 | + |
| 1091 | + # Decode the sent data to verify magnetometer data is included |
| 1092 | + sent_data = mock_packet_manager.send.call_args[0][0] |
| 1093 | + decoded_data = Beacon.decode_binary_beacon(sent_data) |
| 1094 | + |
| 1095 | + # Verify magnetometer data is present in the decoded data |
| 1096 | + values = list(decoded_data.values()) |
| 1097 | + |
| 1098 | + # Should contain the magnetic field components (25.5, -12.3, 8.7) |
| 1099 | + # Use approximate comparison for floating point values |
| 1100 | + assert any(abs(v - 25.5) < 0.01 for v in values if isinstance(v, (int, float))) |
| 1101 | + assert any(abs(v - (-12.3)) < 0.01 for v in values if isinstance(v, (int, float))) |
| 1102 | + assert any(abs(v - 8.7) < 0.01 for v in values if isinstance(v, (int, float))) |
| 1103 | + |
| 1104 | + |
| 1105 | +def test_beacon_send_with_magnetometer_error(mock_logger, mock_packet_manager): |
| 1106 | + """Tests sending a beacon when magnetometer sensor fails. |
| 1107 | +
|
| 1108 | + Args: |
| 1109 | + mock_logger: Mocked Logger instance. |
| 1110 | + mock_packet_manager: Mocked PacketManager instance. |
| 1111 | + """ |
| 1112 | + magnetometer = MockMagnetometer() |
| 1113 | + # Mock the get_magnetic_field method to raise an exception |
| 1114 | + magnetometer.get_magnetic_field = MagicMock( |
| 1115 | + side_effect=Exception("Magnetometer sensor failure") |
| 1116 | + ) |
| 1117 | + |
| 1118 | + beacon = Beacon( |
| 1119 | + mock_logger, |
| 1120 | + "test_beacon", |
| 1121 | + mock_packet_manager, |
| 1122 | + 0, |
| 1123 | + magnetometer, |
| 1124 | + ) |
| 1125 | + |
| 1126 | + _ = beacon.send() |
| 1127 | + |
| 1128 | + # Verify the error was logged |
| 1129 | + mock_logger.error.assert_called_with( |
| 1130 | + "Error retrieving magnetic field", |
| 1131 | + magnetometer.get_magnetic_field.side_effect, |
| 1132 | + sensor="MockMagnetometer", |
| 1133 | + index=0, |
| 1134 | + ) |
| 1135 | + |
| 1136 | + # Verify beacon was still sent (despite the error) |
| 1137 | + mock_packet_manager.send.assert_called_once() |
| 1138 | + |
| 1139 | + |
| 1140 | +@patch("pysquared.nvm.flag.microcontroller") |
| 1141 | +@patch("pysquared.nvm.counter.microcontroller") |
| 1142 | +def test_beacon_generate_key_mapping_with_magnetometer( |
| 1143 | + mock_flag_microcontroller, |
| 1144 | + mock_counter_microcontroller, |
| 1145 | + mock_logger, |
| 1146 | + mock_packet_manager, |
| 1147 | +): |
| 1148 | + """Tests the generate_key_mapping method includes magnetometer template data. |
| 1149 | +
|
| 1150 | + Args: |
| 1151 | + mock_flag_microcontroller: Mocked microcontroller for Flag. |
| 1152 | + mock_counter_microcontroller: Mocked microcontroller for Counter. |
| 1153 | + mock_logger: Mocked Logger instance. |
| 1154 | + mock_packet_manager: Mocked PacketManager instance. |
| 1155 | + """ |
| 1156 | + mock_flag_microcontroller.nvm = setup_datastore |
| 1157 | + mock_counter_microcontroller.nvm = setup_datastore |
| 1158 | + |
| 1159 | + magnetometer = MockMagnetometer() |
| 1160 | + |
| 1161 | + beacon = Beacon( |
| 1162 | + mock_logger, |
| 1163 | + "test_beacon", |
| 1164 | + mock_packet_manager, |
| 1165 | + 0, |
| 1166 | + magnetometer, |
| 1167 | + ) |
| 1168 | + |
| 1169 | + key_map = beacon.generate_key_mapping() |
| 1170 | + |
| 1171 | + # Verify comprehensive key mapping is generated |
| 1172 | + assert isinstance(key_map, dict) |
| 1173 | + |
| 1174 | + # Check that magnetometer template keys are present in the mapping |
| 1175 | + # The keys should include magnetometer timestamp and 3D magnetic field components |
| 1176 | + key_names = list(key_map.values()) |
| 1177 | + magnetometer_keys = [key for key in key_names if "magnetic_field" in str(key)] |
| 1178 | + |
| 1179 | + # Should have at least 4 keys: timestamp + 3 components (x, y, z) |
| 1180 | + assert len(magnetometer_keys) >= 4 |
0 commit comments