From 28418db46c7db28217c8524fde6ddde9a85e9485 Mon Sep 17 00:00:00 2001 From: pwoods25443 Date: Tue, 16 Apr 2024 23:59:01 -0400 Subject: [PATCH 1/4] fix for type 5 messages with bad padding value --- ais_tools/ais.py | 2 ++ ais_tools/ais5.py | 10 ++++++++++ tests/test_aivdm.py | 10 ++++++++++ 3 files changed, 22 insertions(+) create mode 100644 ais_tools/ais5.py diff --git a/ais_tools/ais.py b/ais_tools/ais.py index 5d8ed3b..7cd5853 100644 --- a/ais_tools/ais.py +++ b/ais_tools/ais.py @@ -1,5 +1,6 @@ from ais_tools.transcode import DecodeError from ais_tools.transcode import ASCII8toAIS6 +from ais_tools import ais5 from ais_tools import ais8 from ais_tools import ais9 from ais_tools import ais18 @@ -18,6 +19,7 @@ } decode_fn = { + 5: ais5.ais5_decode, 8: ais8.ais8_decode, 9: ais9.ais9_decode, 18: ais18.ais18_decode, diff --git a/ais_tools/ais5.py b/ais_tools/ais5.py new file mode 100644 index 0000000..bfa2cb5 --- /dev/null +++ b/ais_tools/ais5.py @@ -0,0 +1,10 @@ +import ais as libais +from ais import DecodeError + + +def ais5_decode(body, pad): + try: + return libais.decode(body, 2) + except DecodeError as e: + raise DecodeError(f'TYPE 5 LIBAIS ERR: {str(e)}') + diff --git a/tests/test_aivdm.py b/tests/test_aivdm.py index 4de0da2..3ea6bbd 100644 --- a/tests/test_aivdm.py +++ b/tests/test_aivdm.py @@ -89,3 +89,13 @@ def test_missing_part(): msg = decoder.safe_decode(nmea=nmea, best_effort=True) assert msg['error'] == 'Expected 2 message parts to decode but found 1' assert msg['tagblock_timestamp'] == 1668472438 + + +@pytest.mark.parametrize("nmea", [ + ('\\c:1711942361,s:terrestrial,t:spire*4B\\!AIVDM,1,1,,A,56:=31`000008QaF220QD60`T4pN3N2222222216>pN5@50e0ES2@C`6EC`1hCQp8888880,0*60'), + ('\\c:1711952914,s:terrestrial,t:spire*42\\!AIVDM,1,1,,A,56:Ib8P0000000000008DV09F1L4r1TTr374000j1p5320C=02U2ADj0CP000000000000:,0*03'), +]) +def test_type_5_bad_padding(nmea): + decoder = AIVDM() + msg = decoder.safe_decode(nmea=nmea, best_effort=True) + assert 'error' not in msg From 598c155af08ef05eaa8b202a2fc617f1c83865fc Mon Sep 17 00:00:00 2001 From: pwoods25443 Date: Wed, 17 Apr 2024 00:06:55 -0400 Subject: [PATCH 2/4] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c079965..1a32c63 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" name = "ais-tools" description = "Tools for managing AIS messages" readme = "README.md" -version = "v0.1.6.dev9" +version = "v0.1.6.dev10 " license = {file = "LICENSE"} authors = [ {name = "Paul Woods", email = "paul@globalfishingwatch.org"}, From 7a11a7857b390029f92a296ecd92d8cb07251322 Mon Sep 17 00:00:00 2001 From: pwoods25443 Date: Wed, 17 Apr 2024 11:11:42 -0400 Subject: [PATCH 3/4] change version for release --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1a32c63..bf060ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" name = "ais-tools" description = "Tools for managing AIS messages" readme = "README.md" -version = "v0.1.6.dev10 " +version = "v0.1.7" license = {file = "LICENSE"} authors = [ {name = "Paul Woods", email = "paul@globalfishingwatch.org"}, From 2e71c44f3f8f598deddb5a12a32c40f49d7f7bb7 Mon Sep 17 00:00:00 2001 From: pwoods25443 Date: Wed, 17 Apr 2024 12:20:09 -0400 Subject: [PATCH 4/4] better unit tests for type 5 --- tests/test_ais.py | 24 ++++++++++++++++++++++++ tests/test_aivdm.py | 10 ---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/tests/test_ais.py b/tests/test_ais.py index 34a35be..e36627d 100644 --- a/tests/test_ais.py +++ b/tests/test_ais.py @@ -81,6 +81,30 @@ def test_ais8_wrong_pad(): assert ('83am8S@jpN5@50e0ES2@C`6EC`1hCQp8888880', 0, + {'name': 'HUA JIANG 7 '}), + # correct padding + ('56:=31`000008QaF220QD60`T4pN3N2222222216>pN5@50e0ES2@C`6EC`1hCQp8888880', 2, + {'name': 'HUA JIANG 7 '}) + ]) +def test_ais5(body, pad, expected): + msg = AISMessageTranscoder.decode_nmea(body, pad) + actual = {k: v for k, v in msg.items() if k in expected} + assert actual == expected + + +@pytest.mark.parametrize("body,pad,expected", [ + # incorrect padding + ('56:=31`000008QaF220QD60`T4pN3N2222222216>pN5@50e0ES2@C`6EC`1hCQp88888809999', 0, + 'TYPE 5 LIBAIS ERR: Ais5: AIS_ERR_BAD_BIT_COUNT'), +]) +def test_ais5_fail(body, pad, expected): + with pytest.raises(DecodeError, match=expected): + _ = AISMessageTranscoder.decode_nmea(body, pad) + + @pytest.mark.parametrize("body,pad,expected", [ ('9001?BP=h:qJ9vb;:f7EN1h240Rb', 0, {'mmsi': 20298, 'alt': 55, 'sog': 10}), ('90009C3dRIM1QSsjSPAa1;h200T4', 0, {'mmsi': 2380, 'alt': 946, 'alt_sensor': 0}), diff --git a/tests/test_aivdm.py b/tests/test_aivdm.py index 3ea6bbd..4de0da2 100644 --- a/tests/test_aivdm.py +++ b/tests/test_aivdm.py @@ -89,13 +89,3 @@ def test_missing_part(): msg = decoder.safe_decode(nmea=nmea, best_effort=True) assert msg['error'] == 'Expected 2 message parts to decode but found 1' assert msg['tagblock_timestamp'] == 1668472438 - - -@pytest.mark.parametrize("nmea", [ - ('\\c:1711942361,s:terrestrial,t:spire*4B\\!AIVDM,1,1,,A,56:=31`000008QaF220QD60`T4pN3N2222222216>pN5@50e0ES2@C`6EC`1hCQp8888880,0*60'), - ('\\c:1711952914,s:terrestrial,t:spire*42\\!AIVDM,1,1,,A,56:Ib8P0000000000008DV09F1L4r1TTr374000j1p5320C=02U2ADj0CP000000000000:,0*03'), -]) -def test_type_5_bad_padding(nmea): - decoder = AIVDM() - msg = decoder.safe_decode(nmea=nmea, best_effort=True) - assert 'error' not in msg