Example #1
0
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.

    HINT:
        This method takes care of splitting large payloads (larger than 60 characters)
        into multiple sentences. With a total of 80 maximum chars excluding end of line
        per sentence, and 20 chars head + tail in the nmea 0183 carrier protocol, 60
        chars remain for the actual payload.

    @param payload:         Armored AIs payload.
    @param ais_talker_id:   AIS talker ID (AIVDO or AIVDM)
    @param radio_channel:   Radio channel (either A or B)
    @param fill_bits:       The number of fill bits requires to pad the data payload to a 6 bit boundary.
    @return:                A list of relevant AIS sentences.
    """
    messages = []
    max_len = 61
    seq_id = ''
    frag_cnt = math.ceil(len(payload) / max_len)

    if len(ais_talker_id) != 5:
        raise ValueError(
            "AIS talker is must have exactly 6 characters. E.g. AIVDO")

    if len(radio_channel) != 1:
        raise ValueError("Radio channel must be a single character")

    for frag_num, chunk in enumerate(chunks(payload, max_len), start=1):
        tpl = "!{},{},{},{},{},{},{}*{:02X}"
        dummy_message = tpl.format(ais_talker_id, frag_cnt, frag_num, seq_id,
                                   radio_channel, chunk, fill_bits, 0)
        checksum = compute_checksum(dummy_message)
        msg = tpl.format(ais_talker_id, frag_cnt, frag_num, seq_id,
                         radio_channel, chunk, fill_bits, checksum)
        messages.append(msg)

    return messages
Example #2
0
 def is_valid(self) -> bool:
     return self.checksum == compute_checksum(self.raw)