From 02176d55233a9ca96b143da40329a122ccea64d1 Mon Sep 17 00:00:00 2001 From: Leon Morten Richter Date: Mon, 3 Oct 2022 12:13:30 +0200 Subject: [PATCH] ensure that the NMEA sentence length does not exceed 82 characters (#84) --- CHANGELOG.txt | 12 +++++++ pyais/__init__.py | 2 +- pyais/encode.py | 5 +-- tests/test_encode.py | 84 ++++++++++++++++++++++++++++++++------------ 4 files changed, 77 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 1c59948..1b7561a 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,18 @@ ==================== pyais CHANGELOG ==================== +------------------------------------------------------------------------------- + Version 2.2.1 03 Oct 2022 +------------------------------------------------------------------------------- +* Closes https://github.com/M0r13n/pyais/issues/81 + * ensure that the NMEA sentence length does not exceed 82 characters +------------------------------------------------------------------------------- + Version 2.2.0 02 Oct 2022 +------------------------------------------------------------------------------- +* Closes https://github.com/M0r13n/pyais/issues/82 + * introduces optional error_if_checksum_invalid keyword (default=False) + * adds the possibility to raise an exception if the checksum is invalid + ------------------------------------------------------------------------------- Version 2.1.2 14 May 2022 ------------------------------------------------------------------------------- diff --git a/pyais/__init__.py b/pyais/__init__.py index 9620903..6d86925 100644 --- a/pyais/__init__.py +++ b/pyais/__init__.py @@ -4,7 +4,7 @@ from pyais.decode import decode __license__ = 'MIT' -__version__ = '2.2.0' +__version__ = '2.2.1' __author__ = 'Leon Morten Richter' __all__ = ( diff --git a/pyais/encode.py b/pyais/encode.py index 808f619..d4321a8 100644 --- a/pyais/encode.py +++ b/pyais/encode.py @@ -36,7 +36,8 @@ def data_to_payload(ais_type: int, data: DATA_DICT) -> Payload: def ais_to_nmea_0183(payload: str, ais_talker_id: str, radio_channel: str, fill_bits: int) -> AIS_SENTENCES: """ Splits the AIS payload into sentences, ASCII encodes the payload, creates - and sends the relevant NMEA 0183 sentences. + and sends the relevant NMEA 0183 sentences. Messages have a maximum length + of 82 characters, including the $ or ! starting character and the ending . HINT: This method takes care of splitting large payloads (larger than 60 characters) @@ -51,7 +52,7 @@ def ais_to_nmea_0183(payload: str, ais_talker_id: str, radio_channel: str, fill_ @return: A list of relevant AIS sentences. """ messages = [] - max_len = 61 + max_len = 60 frag_cnt = math.ceil(len(payload) / max_len) seq_id = '0' if frag_cnt > 1 else '' diff --git a/tests/test_encode.py b/tests/test_encode.py index 2f0ddad..54c2c74 100644 --- a/tests/test_encode.py +++ b/tests/test_encode.py @@ -654,10 +654,14 @@ def test_encode_type_15(): def test_encode_type_14(): data = {'mmsi': '351809000', 'repeat': 0, 'text': 'RCVD YR TEST MSG', 'type': 14} - encoded = encode_dict(data) - assert encoded[0] == "!AIVDO,3,1,0,A,>5?Per18=HB1U:1@E=B0m5?Per18=HB1U:1@E=B0m1@U@4pT>1@U@40000000000000000000000,0*64" - assert encoded[1] == "!AIVDO,2,2,0,A,0000000000,2*16" + actual = encode_msg(msg) + + expected = [ + '!AIVDO,2,1,0,A,50000Nh000000000001@U@4pT>1@U@4pT>1@U@4000000000000000000000,0*54', + '!AIVDO,2,2,0,A,00000000000,2*26' + ] + + assert actual == expected def test_int_to_bytes(): @@ -1054,3 +1075,20 @@ def test_encode_ascii_6_bit(): bit_arr = decode_into_bit_array(ascii6.encode()) assert bit_arr.to01() == input_val assert decode_bin_as_ascii6(bit_arr) == "HELLO WORLD!" + + +def test_encode_does_not_exceed_nmea_sentence_length_limit(): + data = { + 'type': 5, 'repeat': 0, 'mmsi': '259725000', 'ais_version': 1, + 'imo': 9103128, 'callsign': 'LAXP4', 'shipname': 'STAR HANSA', + 'shiptype': 70, 'to_bow': 177, 'to_stern': 22, 'to_port': 17, + 'to_starboard': 14, 'epfd': 1, 'month': 5, 'day': 20, 'hour': 6, + 'minute': 0, 'draught': 7.4, 'destination': 'US BAL', 'dte': 0 + } + + encoded = encode_dict(data) + encoded = [e + '\r\n' for e in encoded] + + assert len(encoded) == 2 + assert len(encoded[0]) == 82 + assert len(encoded[1]) == 33