|
1 |
| -# pylint: disable=missing-function-docstring,missing-module-docstring,invalid-name |
| 1 | +# pylint: disable=missing-function-docstring,missing-module-docstring,invalid-name,protected-access,no-self-use |
2 | 2 |
|
3 | 3 | # SPDX-FileCopyrightText: 2021 Jonas Kittner
|
4 | 4 | #
|
5 | 5 | # SPDX-License-Identifier: MIT
|
| 6 | +import time |
| 7 | +from unittest import mock |
6 | 8 | import pytest
|
7 | 9 |
|
8 | 10 | from adafruit_gps import _parse_degrees
|
|
11 | 13 | from adafruit_gps import _read_degrees
|
12 | 14 | from adafruit_gps import _parse_talker
|
13 | 15 | from adafruit_gps import _parse_data
|
| 16 | +from adafruit_gps import GPS |
14 | 17 |
|
15 | 18 |
|
16 | 19 | @pytest.mark.parametrize(
|
@@ -164,3 +167,201 @@ def test_param_types_does_not_match_data_items():
|
164 | 167 | )
|
165 | 168 | def test_parse_data(st, data, exp_data):
|
166 | 169 | assert pytest.approx(_parse_data(sentence_type=st, data=data)) == exp_data
|
| 170 | + |
| 171 | + |
| 172 | +def test_parse_data_unexpected_parameter_type(): |
| 173 | + with mock.patch("adafruit_gps._SENTENCE_PARAMS", ("xyz",)): |
| 174 | + with pytest.raises(TypeError) as exc_info: |
| 175 | + _parse_data(sentence_type=0, data=["x", "y", "z"]) |
| 176 | + |
| 177 | + assert exc_info.value.args[0] == "GPS: Unexpected parameter type 'x'" |
| 178 | + |
| 179 | + |
| 180 | +class UartMock: |
| 181 | + """mocking the UART connection an its methods""" |
| 182 | + |
| 183 | + def write(self, bytestr): |
| 184 | + print(bytestr, end="") |
| 185 | + |
| 186 | + @property |
| 187 | + def in_waiting(self): |
| 188 | + return 100 |
| 189 | + |
| 190 | + |
| 191 | +def test_read_sentence_too_few_in_waiting(): |
| 192 | + with mock.patch.object(GPS, "readline", return_value="x"): |
| 193 | + |
| 194 | + class UartMockWaiting(UartMock): |
| 195 | + """overwrite the in_waiting property to perform the test""" |
| 196 | + |
| 197 | + @property |
| 198 | + def in_waiting(self): |
| 199 | + return 3 |
| 200 | + |
| 201 | + gps = GPS(uart=UartMockWaiting()) |
| 202 | + assert not gps.update() |
| 203 | + |
| 204 | + |
| 205 | +def test_GPS_update_timestamp_UTC_date_None(): |
| 206 | + gps = GPS(uart=UartMock()) |
| 207 | + exp_struct = time.struct_time((0, 0, 0, 22, 14, 11, 0, 0, -1)) |
| 208 | + gps._update_timestamp_utc(time_utc=221411) |
| 209 | + assert gps.timestamp_utc == exp_struct |
| 210 | + |
| 211 | + |
| 212 | +def test_GPS_update_timestamp_UTC_date_not_None(): |
| 213 | + gps = GPS(uart=UartMock()) |
| 214 | + exp_struct = time.struct_time((2021, 10, 2, 22, 14, 11, 0, 0, -1)) |
| 215 | + gps._update_timestamp_utc(time_utc=221411, date=21021) |
| 216 | + assert gps.timestamp_utc == exp_struct |
| 217 | + |
| 218 | + |
| 219 | +def test_GPS_update_timestamp_timestamp_utc_was_not_none_new_date_none(): |
| 220 | + gps = GPS(uart=UartMock()) |
| 221 | + # set this to a value |
| 222 | + gps.timestamp_utc = time.struct_time((2021, 10, 2, 22, 10, 11, 0, 0, -1)) |
| 223 | + exp_struct = time.struct_time((2021, 10, 2, 22, 14, 11, 0, 0, -1)) |
| 224 | + # update the timestamp |
| 225 | + gps._update_timestamp_utc(time_utc=221411) |
| 226 | + assert gps.timestamp_utc == exp_struct |
| 227 | + |
| 228 | + |
| 229 | +def test_GPS_update_rmc_no_magnetic_variation(): |
| 230 | + r = b"$GPRMC,215032.086,A,1234.5678,N,00123.12345,E,0.45,56.35,021021,,,A*6A\r\n" |
| 231 | + with mock.patch.object(GPS, "readline", return_value=r): |
| 232 | + gps = GPS(uart=UartMock()) |
| 233 | + assert gps.update() |
| 234 | + exp_time = time.struct_time((2021, 10, 2, 21, 50, 32, 0, 0, -1)) |
| 235 | + assert gps.timestamp_utc == exp_time |
| 236 | + assert gps.latitude == pytest.approx(12.57613) |
| 237 | + assert gps.longitude == pytest.approx(1.385391) |
| 238 | + assert gps.fix_quality == 1 |
| 239 | + assert gps.fix_quality_3d == 0 |
| 240 | + assert gps.speed_knots == 0.45 |
| 241 | + assert gps.track_angle_deg == 56.35 |
| 242 | + assert gps._magnetic_variation is None |
| 243 | + assert gps._mode_indicator == "A" |
| 244 | + assert gps.has_fix is True |
| 245 | + assert gps.has_3d_fix is False |
| 246 | + assert gps.datetime == exp_time |
| 247 | + assert ( |
| 248 | + gps._raw_sentence |
| 249 | + == "$GPRMC,215032.086,A,1234.5678,N,00123.12345,E,0.45,56.35,021021,,,A*6A" |
| 250 | + ) |
| 251 | + assert ( |
| 252 | + gps.nmea_sentence |
| 253 | + == "$GPRMC,215032.086,A,1234.5678,N,00123.12345,E,0.45,56.35,021021,,,A*6A" |
| 254 | + ) |
| 255 | + |
| 256 | + |
| 257 | +def test_GPS_update_rmc_fix_is_set(): |
| 258 | + r_valid = ( |
| 259 | + b"$GPRMC,215032.086,A,1234.5678,N,00123.12345,E,0.45,56.35,021021,,,A*6A\r\n" |
| 260 | + ) |
| 261 | + r_invalid = ( |
| 262 | + b"$GPRMC,215032.086,V,1234.5678,N,00123.12345,E,0.45,56.35,021021,,,A*7D\r\n" |
| 263 | + ) |
| 264 | + with mock.patch.object(GPS, "readline", return_value=r_valid): |
| 265 | + gps = GPS(uart=UartMock()) |
| 266 | + assert gps.update() |
| 267 | + assert gps.fix_quality == 1 |
| 268 | + assert gps.has_fix is True |
| 269 | + |
| 270 | + with mock.patch.object(gps, "readline", return_value=r_invalid): |
| 271 | + assert gps.update() |
| 272 | + assert gps.fix_quality == 0 |
| 273 | + assert gps.has_fix is False |
| 274 | + |
| 275 | + |
| 276 | +def test_GPS_update_rmc_fix_is_set_new(): |
| 277 | + r_valid = ( |
| 278 | + b"$GPRMC,215032.086,A,1234.5678,N,00123.12345,E,0.45,56.35,021021,,,A*6A\r\n" |
| 279 | + ) |
| 280 | + r_invalid = b"$GPRMC,215032.086,V,ABC,N,00123.12345,E,0.45,56.35,021021,,,A*1B\r\n" |
| 281 | + with mock.patch.object(GPS, "readline", return_value=r_valid): |
| 282 | + gps = GPS(uart=UartMock()) |
| 283 | + assert gps.update() |
| 284 | + assert gps.fix_quality == 1 |
| 285 | + assert gps.has_fix is True |
| 286 | + # now get an invalid response --> set fix_qualit to 0 |
| 287 | + with mock.patch.object(gps, "readline", return_value=r_invalid): |
| 288 | + assert not gps.update() |
| 289 | + assert gps.fix_quality == 0 |
| 290 | + assert gps.has_fix is False |
| 291 | + |
| 292 | + |
| 293 | +def test_GPS_update_rmc_invalid_checksum(): |
| 294 | + r = b"$GPRMC,215032.086,A,1234.5678,N,00123.12345,E,0.45,56.35,021021,,,A*5C\r\n" |
| 295 | + with mock.patch.object(GPS, "readline", return_value=r): |
| 296 | + gps = GPS(uart=UartMock()) |
| 297 | + assert not gps.update() |
| 298 | + |
| 299 | + |
| 300 | +def test_GPS_update_empty_sentence(): |
| 301 | + with mock.patch.object(GPS, "readline", return_value=b""): |
| 302 | + gps = GPS(uart=UartMock()) |
| 303 | + assert not gps.update() |
| 304 | + |
| 305 | + |
| 306 | +@pytest.mark.parametrize( |
| 307 | + ("r", "exp"), |
| 308 | + ( |
| 309 | + pytest.param( |
| 310 | + b"$GPRMC,215032.086,A,1234.5678,N,00123.12345,E,0.45,56.35,021021,1234.56,W,A*14\r\n", |
| 311 | + -12.576, |
| 312 | + id="W", |
| 313 | + ), |
| 314 | + pytest.param( |
| 315 | + b"$GPRMC,215032.086,A,1234.5678,N,00123.12345,E,0.45,56.35,021021,1234.56,E,A*06\r\n", |
| 316 | + 12.576, |
| 317 | + id="E", |
| 318 | + ), |
| 319 | + ), |
| 320 | +) |
| 321 | +def test_GPS_update_rmc_has_magnetic_variation(r, exp): |
| 322 | + with mock.patch.object(GPS, "readline", return_value=r): |
| 323 | + gps = GPS(uart=UartMock()) |
| 324 | + assert gps.update() |
| 325 | + assert gps._magnetic_variation == pytest.approx(exp) |
| 326 | + |
| 327 | + |
| 328 | +def test_GPS_update_sentence_is_None(): |
| 329 | + with mock.patch.object(GPS, "_parse_sentence", return_value=None): |
| 330 | + gps = GPS(uart=UartMock()) |
| 331 | + assert not gps.update() |
| 332 | + |
| 333 | + |
| 334 | +def test_GPS_update_rmc_debug_shows_sentence(capsys): |
| 335 | + r = b"$GPRMC,215032.086,A,1234.5678,N,00123.12345,E,0.45,56.35,021021,,,A*6A\r\n" |
| 336 | + with mock.patch.object(GPS, "readline", return_value=r): |
| 337 | + gps = GPS(uart=UartMock(), debug=True) |
| 338 | + assert gps.update() |
| 339 | + out, err = capsys.readouterr() |
| 340 | + assert err == "" |
| 341 | + assert ( |
| 342 | + out |
| 343 | + == "('GPRMC', '215032.086,A,1234.5678,N,00123.12345,E,0.45,56.35,021021,,,A')\n" |
| 344 | + ) |
| 345 | + |
| 346 | + |
| 347 | +def test_GPS_update_data_type_too_short(): |
| 348 | + r = ("GPRM", "x,y,z") |
| 349 | + with mock.patch.object(GPS, "_parse_sentence", return_value=r): |
| 350 | + gps = GPS(uart=UartMock(), debug=True) |
| 351 | + assert not gps.update() |
| 352 | + |
| 353 | + |
| 354 | +def test_GPS_send_command_with_checksum(capsys): |
| 355 | + gps = GPS(uart=UartMock()) |
| 356 | + gps.send_command(command=b"$PMTK001,314,3\r\n", add_checksum=True) |
| 357 | + out, err = capsys.readouterr() |
| 358 | + assert err == "" |
| 359 | + assert out == ("b'$'" "b'$PMTK001,314,3\\r\\n'" "b'*'" "b'15'" "b'\\r\\n'") |
| 360 | + |
| 361 | + |
| 362 | +def test_GPS_send_command_without_checksum(capsys): |
| 363 | + gps = GPS(uart=UartMock()) |
| 364 | + gps.send_command(command=b"$PMTK001,314,3\r\n", add_checksum=False) |
| 365 | + out, err = capsys.readouterr() |
| 366 | + assert err == "" |
| 367 | + assert out == ("b'$'" "b'$PMTK001,314,3\\r\\n'" "b'\\r\\n'") |
0 commit comments