示例#1
0
 def test_single(self):
     """
     Test single and multi line messages
     """
     single = b"!AIVDM,1,1,,B,91b55wi;hbOS@OdQAC062Ch2089h,0*30"
     assert NMEAMessage(single).is_single
     assert not NMEAMessage(single).is_multi
示例#2
0
    def test_msg_type_17(self):
        msg = NMEAMessage.assemble_from_iterable(messages=[
            NMEAMessage(
                b"!AIVDM,2,1,5,A,A02VqLPA4I6C07h5Ed1h<OrsuBTTwS?r:C?w`?la<gno1RTRwSP9:BcurA8a,0*3A"
            ),
            NMEAMessage(b"!AIVDM,2,2,5,A,:Oko02TSwu8<:Jbb,0*11")
        ]).decode()
        n = 0x7c0556c07031febbf52924fe33fa2933ffa0fd2932fdb7062922fe3809292afde9122929fcf7002923ffd20c29aaaa
        assert msg['type'] == 17
        assert msg['repeat'] == 0
        assert msg['mmsi'] == "002734450"
        assert msg['lon'] == 17478
        assert msg['lat'] == 35992
        assert msg['data'] == n

        msg = NMEAMessage(
            b"!AIVDM,1,1,,A,A0476BQ>J8`<h2JpH:4P0?j@2mTEw8`=DP1DEnqvj0,0*79"
        ).decode()
        assert msg['type'] == 17
        assert msg['repeat'] == 0
        assert msg['mmsi'] == "004310602"
        assert msg['lat'] == 20582
        assert msg['lon'] == 80290
        assert msg[
            'data'] == 14486955885545814640451754168044205828166539334830080
示例#3
0
    def test_from_str(self):
        old = NMEAMessage(b"!AIVDM,1,1,,B,15M67FC000G?ufbE`FepT@3n00Sa,0*5C"
                          ).decode().content
        new = NMEAMessage.from_string(
            "!AIVDM,1,1,,B,15M67FC000G?ufbE`FepT@3n00Sa,0*5C").decode().content

        assert old == new
示例#4
0
    def _assemble_messages(self):
        queue = []

        for line in self._iter_messages():
            # Try to parse the message
            try:
                msg = NMEAMessage(line)
            except Exception as e:
                raise ValueError(f'Failed to parse line "{line}"') from e

            # Be gentle and just skip invalid messages
            if not msg.is_valid:
                continue

            if msg.is_single:
                yield msg

            # Assemble multiline messages
            elif msg.is_multi:
                queue.append(msg)

                if msg.index == msg.count:
                    yield msg.assemble_from_iterable(queue)
                    queue.clear()
            else:
                raise ValueError("Messages are out of order!")
示例#5
0
    def test_dict(self):
        msg = b"!AIVDM,1,1,,A,15Mj23P000G?q7fK>g:o7@1:0L3S,0*1B"
        msg = NMEAMessage(msg)

        def serializable(o: object):
            if isinstance(o, bytes):
                return o.decode('utf-8')
            elif isinstance(o, bitarray):
                return o.to01()
            return o

        expected = dict([(slot, serializable(getattr(msg, slot)))
                         for slot in NMEAMessage.__slots__])

        actual = msg.asdict()
        pprint(actual)
        self.assertEqual(expected, actual)
        self.assertEqual(1, actual["ais_id"])
        self.assertEqual("!AIVDM,1,1,,A,15Mj23P000G?q7fK>g:o7@1:0L3S,0*1B",
                         actual["raw"])
        self.assertEqual("AI", actual["talker"])
        self.assertEqual("VDM", actual["type"])
        self.assertEqual(1, actual["message_fragments"])
        self.assertEqual(1, actual["fragment_number"])
        self.assertEqual(None, actual["message_id"])
        self.assertEqual("A", actual["channel"])
        self.assertEqual("15Mj23P000G?q7fK>g:o7@1:0L3S", actual["payload"])
        self.assertEqual(0, actual["fill_bits"])
        self.assertEqual(0x1b, actual["checksum"])
示例#6
0
    def test_msg_type_1(self):
        msg = NMEAMessage(b"!AIVDM,1,1,,B,15M67FC000G?ufbE`FepT@3n00Sa,0*5C").decode()
        assert msg.content == {'type': 1, 'repeat': 0, 'mmsi': "366053209",
                               'status': NavigationStatus.RestrictedManoeuverability, 'turn': 0,
                               'speed': 0,
                               'accuracy': 0,
                               'lon': -122.34161833333333, 'lat': 37.80211833333333, 'course': 219.3,
                               'heading': 1,
                               'second': 59, 'maneuver': ManeuverIndicator.NotAvailable, 'raim': False,
                               'radio': 2281}

        msg = NMEAMessage(b"!AIVDM,1,1,,A,15NPOOPP00o?b=bE`UNv4?w428D;,0*24").decode()
        assert msg['type'] == 1
        assert msg['mmsi'] == "367533950"
        assert msg['repeat'] == 0
        assert msg['status'] == NavigationStatus.UnderWayUsingEngine
        assert msg['turn'] == -128
        assert msg['speed'] == 0
        assert msg['accuracy'] == 1
        assert round(msg['lat'], 4) == 37.8084
        assert round(msg['lon'], 4) == -122.4082
        assert msg['course'] == 360
        assert msg['heading'] == 511
        assert msg['second'] == 34
        assert msg['maneuver'] == ManeuverIndicator.NotAvailable
        assert msg['raim']
示例#7
0
    def test_msg_type_21(self):
        msg = NMEAMessage.assemble_from_iterable(messages=[
            NMEAMessage(
                b"!AIVDM,2,1,7,B,E4eHJhPR37q0000000000000000KUOSc=rq4h00000a,0*4A"
            ),
            NMEAMessage(b"!AIVDM,2,2,7,B,@20,4*54")
        ]).decode()
        assert msg['type'] == 21
        assert msg['mmsi'] == "316021442"
        assert msg['aid_type'] == NavAid.REFERENCE_POINT
        assert msg['name'] == "DFO2"
        assert msg['accuracy'] == 1
        assert round(msg['lat'], 2) == 48.65
        assert round(msg['lon'], 2) == -123.43
        assert not msg['to_bow']
        assert not msg['to_stern']
        assert not msg['to_port']
        assert not msg['to_starboard']

        assert msg['off_position']
        assert msg['regional'] == 0
        assert msg['raim']
        assert msg['virtual_aid'] == 0
        assert msg['assigned'] == 0
        assert msg['name_extension'] == ""
示例#8
0
    def test_validity(self):
        msg = b"!AIVDM,1,1,,A,85Mwp`1Kf3aCnsNvBWLi=wQuNhA5t43N`5nCuI=p<IBfVqnMgPGs,0*47"
        assert NMEAMessage(msg).is_valid

        msg = b"!AIVDM,1,1,,A,85Mwp`1Kf3aCnsNvBWLi=wQuNhA5t43N`5nCuI=p<IBfVqnMgPGt,0*47"
        with self.assertRaises(InvalidChecksumException):
            NMEAMessage(msg)
示例#9
0
 def test_talker(self):
     """
     Test talker extraction
     """
     msg = b"!AIVDM,1,1,,B,91b55wi;hbOS@OdQAC062Ch2089h,0*30"
     assert NMEAMessage(msg).talker == "AI"
     msg = b"!AIVDM,1,1,,A,8@30oni?1j020@00,0*23"
     assert NMEAMessage(msg).talker == "AI"
示例#10
0
 def test_message_assembling(self):
     multi = NMEAMessage.assemble_from_iterable(messages=[
         NMEAMessage(b"!AIVDM,2,1,4,A,55O0W7`00001L@gCWGA2uItLth@DqtL5@F22220j1h742t0Ht0000000,0*08"),
         NMEAMessage(b"!AIVDM,2,2,4,A,000000000000000,2*20")
     ])
     assert not multi.is_single
     assert multi.is_multi
     assert multi.is_valid
示例#11
0
 def test_type(self):
     """
     Test value type
     """
     msg = b"!AIVDM,1,1,,B,91b55wi;hbOS@OdQAC062Ch2089h,0*30"
     assert NMEAMessage(msg).msg_type == "VDM"
     msg = b"!AIVDM,1,1,,A,8@30oni?1j020@00,0*23"
     assert NMEAMessage(msg).msg_type == "VDM"
示例#12
0
    def test_fail_silently(self):
        # this tests combines testing for an UnknownMessageException and the silent param at once
        msg = b"!AIVDM,1,1,,A,U31<0OOP000CshrMdl600?wP00SL,0*43"
        nmea = NMEAMessage(msg)

        with self.assertRaises(UnknownMessageException):
            nmea.decode(silent=False)

        # by default errors are ignored and None is returned
        assert nmea.decode() is None
示例#13
0
    def test_msg_type_26(self):
        msg = NMEAMessage(b"!AIVDM,1,1,,A,JB3R0GO7p>vQL8tjw0b5hqpd0706kh9d3lR2vbl0400,2*40").decode()
        assert msg['type'] == 26
        assert msg['addressed']
        assert msg['structured']
        assert msg['dest_mmsi'] == "838351848"

        msg = NMEAMessage(b"!AIVDM,1,1,,A,J0@00@370>t0Lh3P0000200H:2rN92,4*14").decode()
        assert msg['type'] == 26
        assert not msg['addressed']
        assert not msg['structured']
示例#14
0
    def test_message_eq_method(self):
        msg = b"!AIVDM,1,1,,B,F030p:j2N2P5aJR0r;6f3rj10000,0*11"

        first_obj = NMEAMessage(msg)
        second_obj = NMEAMessage(msg)

        # make sure they are not the same object
        assert not id(first_obj) == id(second_obj)

        # but make sure they equal
        assert first_obj == second_obj
示例#15
0
 def test_msg_type_5(self):
     msg = NMEAMessage.assemble_from_iterable(messages=[
         NMEAMessage(b"!AIVDM,2,1,1,A,55?MbV02;H;s<HtKR20EHE:0@T4@Dn2222222216L961O5Gf0NSQEp6ClRp8,0*1C"),
         NMEAMessage(b"!AIVDM,2,2,1,A,88888888880,2*25")
     ]).decode()
     assert msg['callsign'] == "3FOF8"
     assert msg['shipname'] == "EVER DIADEM"
     assert msg['shiptype'] == ShipType.Cargo
     assert msg['to_bow'] == 225
     assert msg['to_stern'] == 70
     assert msg['to_port'] == 1
     assert msg['to_starboard'] == 31
     assert msg['draught'] == 12.2
     assert msg['destination'] == "NEW YORK"
示例#16
0
    def test_values(self):
        """
        Test value count
        """
        a = b"!AIVDM,,A,91b77=h3h00nHt0Q3r@@07000<0b,0*69"
        b = b"!AIVDM,1,1,,A,91b77=h3h00nHt0Q3r@@07000<0b,0*69,0,3"

        with self.assertRaises(InvalidNMEAMessageException):
            NMEAMessage(a)

        with self.assertRaises(InvalidNMEAMessageException):
            NMEAMessage(b)

        c = b"!AIVDM,1,1,,B,91b55wi;hbOS@OdQAC062Ch2089h,0*30"
        assert NMEAMessage(c).is_valid
示例#17
0
    def test_msg_type(self):
        """
        Test if msg type is correct
        """
        nmea = NMEAMessage(b"!AIVDM,1,1,,B,15M67FC000G?ufbE`FepT@3n00Sa,0*5C")
        assert nmea.decode().msg_type == AISType.POS_CLASS_A1

        nmea = NMEAMessage(b"!AIVDM,1,1,,B,15NG6V0P01G?cFhE`R2IU?wn28R>,0*05")
        assert nmea.decode().msg_type == AISType.POS_CLASS_A1

        nmea = NMEAMessage.assemble_from_iterable(messages=[
            NMEAMessage(b"!AIVDM,2,1,4,A,55O0W7`00001L@gCWGA2uItLth@DqtL5@F22220j1h742t0Ht0000000,0*08"),
            NMEAMessage(b"!AIVDM,2,2,4,A,000000000000000,2*20")
        ])
        assert nmea.decode().msg_type == AISType.STATIC_AND_VOYAGE
示例#18
0
    def test_msg_type_25(self):
        msg = NMEAMessage(b"!AIVDM,1,1,,A,I6SWo?8P00a3PKpEKEVj0?vNP<65,0*73").decode()

        assert msg['type'] == 25
        assert msg['addressed']
        assert not msg['structured']
        assert msg['dest_mmsi'] == "134218384"
示例#19
0
    def test_deprecated(self):
        msg = NMEAMessage(b"!AIVDM,1,1,,A,15Mj23P000G?q7fK>g:o7@1:0L3S,0*1B")

        self.assertEqual(msg.count, msg.fragment_count)
        self.assertEqual(msg.index, msg.fragment_number)
        self.assertEqual(msg.seq_id, msg.message_id)
        self.assertEqual(msg.data, msg.payload)
示例#20
0
    def test_to_json(self):
        json_dump = NMEAMessage(b"!AIVDM,1,1,,A,15NPOOPP00o?b=bE`UNv4?w428D;,0*24").decode().to_json()
        text = """{
    "nmea": {
        "ais_id": 1,
        "raw": "!AIVDM,1,1,,A,15NPOOPP00o?b=bE`UNv4?w428D;,0*24",
        "talker": "AI",
        "msg_type": "VDM",
        "count": 1,
        "index": 1,
        "seq_id": "",
        "channel": "A",
        "data": "15NPOOPP00o?b=bE`UNv4?w428D;",
        "checksum": 36,
        "bit_array": "000001000101011110100000011111011111100000100000000000000000110111001111101010001101101010010101101000100101011110111110000100001111111111000100000010001000010100001011"
    },
    "decoded": {
        "type": 1,
        "repeat": 0,
        "mmsi": "367533950",
        "status": 0,
        "turn": -128,
        "speed": 0.0,
        "accuracy": true,
        "lon": -122.40823166666667,
        "lat": 37.808418333333336,
        "course": 360.0,
        "heading": 511,
        "second": 34,
        "maneuver": 0,
        "raim": true,
        "radio": 34059
    }
}"""
        assert json_dump == text
示例#21
0
 def test_msg_getitem(self):
     """
     Test if one can get items
     """
     msg = NMEAMessage(
         b"!AIVDM,1,1,,B,15NG6V0P01G?cFhE`R2IU?wn28R>,0*05").decode()
     assert msg['repeat'] == 0
示例#22
0
    def test_msg_type_15(self):
        msg = NMEAMessage(b"!AIVDM,1,1,,A,?5OP=l00052HD00,2*5B").decode()
        assert msg['type'] == 15
        assert msg['repeat'] == 0
        assert msg['mmsi'] == "368578000"
        assert msg['offset1_1'] == 0

        msg = NMEAMessage(b"!AIVDM,1,1,,B,?h3Ovn1GP<K0<P@59a0,2*04").decode()
        assert msg['type'] == 15
        assert msg['repeat'] == 3
        assert msg['mmsi'] == "003669720"
        assert msg['mmsi1'] == "367014320"
        assert msg['type1_1'] == 3
        assert msg['type1_2'] == 5
        assert msg['offset1_2'] == 617
        assert msg['offset1_1'] == 516
示例#23
0
 def test_msg_type_14(self):
     msg = NMEAMessage(
         b"!AIVDM,1,1,,A,>5?Per18=HB1U:1@E=B0m<L,2*51").decode()
     assert msg['type'] == 14
     assert msg['repeat'] == 0
     assert msg['mmsi'] == "351809000"
     assert msg['text'] == "RCVD YR TEST MSG"
示例#24
0
 def test_msg_type_6(self):
     msg = NMEAMessage(
         b"!AIVDM,1,1,,B,6B?n;be:cbapalgc;i6?Ow4,2*4A").decode()
     assert msg['seqno'] == 3
     assert msg['dest_mmsi'] == "313240222"
     assert msg['dac'] == 669
     assert msg['fid'] == 11
示例#25
0
    def test_get_item_raises_type_error(self):
        msg = NMEAMessage(b"!AIVDM,1,1,,A,15Mj23P000G?q7fK>g:o7@1:0L3S,0*1B")

        with self.assertRaises(TypeError):
            _ = msg[1]

        with self.assertRaises(TypeError):
            _ = msg[1:3]
示例#26
0
 def test_msg_type_23(self):
     msg = NMEAMessage(b"!AIVDM,1,1,,B,G02:Kn01R`sn@291nj600000900,2*12").decode()
     assert msg['type'] == 23
     assert msg['mmsi'] == "002268120"
     assert msg['ne_lon'] == 157.8
     assert round(msg['ne_lat'], 1) == 3064.2
     assert round(msg['sw_lon'], 1) == 109.6
     assert round(msg['sw_lat'], 1) == 3040.8
示例#27
0
    def test_fail_silently(self):
        # this tests combines testing for an UnknownMessageException and the silent param at once
        msg = b"!AIVDM,1,1,,A,U31<0OOP000CshrMdl600?wP00SL,0*43"
        nmea = NMEAMessage(msg)

        with self.assertRaises(UnknownMessageException):
            nmea.decode(silent=False)

        # by default errors are ignored and an empty AIS message is returned
        assert nmea.decode() is not None
        assert isinstance(nmea.decode(), AISMessage)
        text = """{
    "nmea": {
        "ais_id": 37,
        "raw": "!AIVDM,1,1,,A,U31<0OOP000CshrMdl600?wP00SL,0*43",
        "talker": "AI",
        "type": "VDM",
        "message_fragments": 1,
        "fragment_number": 1,
        "message_id": null,
        "channel": "A",
        "payload": "U31<0OOP000CshrMdl600?wP00SL",
        "fill_bits": 0,
        "checksum": 67,
        "bit_array": "100101000011000001001100000000011111011111100000000000000000000000010011111011110000111010011101101100110100000110000000000000001111111111100000000000000000100011011100"
    },
    "decoded": {}
}"""
        self.assertEqual(nmea.decode().to_json(), text)
示例#28
0
    def test_msg_type_12(self):
        msg = NMEAMessage(b"!AIVDM,1,1,,A,<5?SIj1;GbD07??4,0*38").decode()
        assert msg['type'] == 12
        assert msg['repeat'] == 0
        assert msg['mmsi'] == "351853000"
        assert msg['seqno'] == 0
        assert msg['dest_mmsi'] == "316123456"
        assert msg['retransmit'] == 0
        assert msg['text'] == "GOOD"

        msg = NMEAMessage(b"!AIVDM,1,1,,A,<42Lati0W:Ov=C7P6B?=Pjoihhjhqq0,2*2B").decode()
        assert msg['type'] == 12
        assert msg['repeat'] == 0
        assert msg['mmsi'] == "271002099"
        assert msg['seqno'] == 0
        assert msg['dest_mmsi'] == "271002111"
        assert msg['retransmit'] == 1
        assert msg['text'] == "MSG FROM 271002099"
示例#29
0
    def test_decode_pos_1_2_3(self):
        # weired message of type 0 as part of issue #4
        msg: NMEAMessage = NMEAMessage(b"!AIVDM,1,1,,B,0S9edj0P03PecbBN`ja@0?w42cFC,0*7C")

        assert msg.is_valid
        content: AISMessage = msg.decode(silent=False)
        assert msg

        assert content['repeat'] == 2
        assert content['mmsi'] == "211512520"
        assert content['turn'] == -128
        assert content['speed'] == 0.3
        assert round(content['lat'], 4) == 53.5427
        assert round(content['lon'], 4) == 9.9794
        assert round(content['course'], 1) == 0.0

        msg: NMEAMessage = NMEAMessage(b"!AIVDM,1,1,,B,0S9edj0P03PecbBN`ja@0?w42cFC,0*7C")
        assert msg.decode().to_json()
示例#30
0
    def test_msg_type_22(self):
        # Broadcast
        msg = NMEAMessage(
            b"!AIVDM,1,1,,B,F030p:j2N2P5aJR0r;6f3rj10000,0*11").decode()
        assert msg['type'] == 22
        assert msg['mmsi'] == "003160107"
        assert msg['channel_a'] == 2087
        assert msg['channel_b'] == 2088
        assert msg['power'] == 0

        assert msg['ne_lon'] == -7710.0
        assert msg['ne_lat'] == 3300.0
        assert msg['sw_lon'] == -8020.0
        assert msg['sw_lat'] == 3210

        assert msg['band_a'] == 0
        assert msg['band_b'] == 0
        assert msg['zonesize'] == 2

        assert 'dest1' not in msg.content.keys()
        assert 'dest2' not in msg.content.keys()

        # Addressed
        msg = NMEAMessage(
            b"!AIVDM,1,1,,A,F@@W>gOP00PH=JrN9l000?wB2HH;,0*44").decode()
        assert msg['type'] == 22
        assert msg['mmsi'] == "017419965"
        assert msg['channel_a'] == 3584
        assert msg['channel_b'] == 8
        assert msg['power'] == 1
        assert msg['addressed'] == 1

        assert msg['dest1'] == "028144881"
        assert msg['dest2'] == "268435519"

        assert msg['band_a'] == 0
        assert msg['band_b'] == 0
        assert msg['zonesize'] == 4

        assert 'ne_lon' not in msg.content.keys()
        assert 'ne_lat' not in msg.content.keys()
        assert 'sw_lon' not in msg.content.keys()
        assert 'sw_lat' not in msg.content.keys()