Exemple #1
0
 def test_nmea_multipart_sentence_reassembly(self):
     """
     test the ability to recieve multiple NMEA 0183 sentences and join
     them together into one AIS message
     """
     expected = ('000101000011000111100001100010000000000'
                 '10000001001001111000100100011001'
                 '1010100001001100000111011010010000010000'
                 '000011000100100010000010100110'
                 '0001001001111100000100000100000100000100000'
                 '10000010000010000010000010000010000010000010'
                 '00000101100100101000000001100000111100001000'
                 '010011100010011100000001001111000010000001010'
                 '010010010000101001001010010001111100000100000'
                 '100000100000100000100000100000100000100000100'
                 '0001000001000000000')
     testsentences = [('!AIVDM,2,1,2,B,537QR042Ci8kD9PsB20HT'
                       '@DhTv2222222222221I:0H?24pW0ChPDTQB,0*49'),
                      '!AIVDM,2,2,2,B,DSp888888888880,2*7A']
     testtracker = nmea.NMEAtracker()
     for sentence in testsentences:
         processed = testtracker.process_sentence(sentence)
         if processed:
             binarypayload = binary.ais_sentence_payload_binary(processed)
     self.assertEqual(expected, binarypayload)
Exemple #2
0
 def __init__(self):
     tkinter.Tk.__init__(self)
     self.nmeatracker = nmea.NMEAtracker()
     self.aistracker = ais.AISTracker()
     self.messagelog = allmessages.AISMessageLog()
     self.protocol("WM_DELETE_WINDOW", self.quit)
     self.title('PY AIS NMEA - ' + version.VERSION)
     self.statuslabel = tkinter.Label(self, text='', bg='light grey')
     self.statuslabel.pack(fill=tkinter.X)
     self.tabcontrol = TabControl(self)
     self.tabcontrol.pack(expand=1, fill='both')
     self.top_menu()
     self.mpq = multiprocessing.Queue()
     self.updateguithread = None
     self.refreshguithread = None
     self.serverprocess = None
     self.serverrunning = False
     self.stopevent = threading.Event()
     self.forwardsentences = tkinter.BooleanVar()
     self.forwardsentences.set(0)
     self.kmzlivemap = tkinter.BooleanVar()
     self.kmzlivemap.set(0)
     self.livemap = None
     self.timingsources = []
     self.currentupdatethreadid = None
     self.currentrefreshthreadid = None
Exemple #3
0
 def test_nmea_stats(self):
     """
     feed in NMEA sentences and check that stats are computed correctly
     """
     testsentences = [
         '!AIVDM,1,1,,A,13P6>F002lwce04NvkaT<CPGH<02,0*69',
         '!AIVDM,1,1,,A,13P6>F002jwceJDNvk1T<SPcH8Og,0*2F',
         '!AIVDM,1,1,,A,13P6>F002kwcf6dNvj0T=kQ?H@3Q,0*27',
         ('!AIVDM,2,1,5,A,53P6>F42;si4mPhOJ208Dr0mV0<Q8DF22222'
          '220t41H;==8cN<R1FDj0,0*39'),
         '!AIVDM,2,2,5,A,CH8888888888880,2*2A',
         '!AIVDM,1,1,,A,13P6>F002lwcfRPNviF4;CQUH8:s,0*72',
         '!AIVDM,1,1,,B,33P6>F002lwcfgDNvi4T>SQgH50S,0*40',
         '!AIVDM,1,1,,B,13P6>F002lwcg8`NvhLT>kP;HL02,0*3C'
     ]
     testtracker = nmea.NMEAtracker()
     for sentence in testsentences:
         testtracker.process_sentence(sentence)
     teststats = testtracker.nmea_stats()
     expectedstats = {
         'Total Sentences Processed': 8,
         'Multipart Messages Reassembled': 1,
         'Messages Recieved on Channel': {
             'A': 6,
             'B': 2
         }
     }
     self.assertDictEqual(teststats, expectedstats)
Exemple #4
0
 def test_empty_value_for_cog(self):
     """
     this sentence doesn't appear to have a value for course over ground
     the binary module should raise a NoBinaryData exception
     """
     testsentence = '!AIVDM,1,1,,A,3O>soN5MUNBoMdUdlh,0*64'
     nmeatracker = nmea.NMEAtracker()
     testdata = nmeatracker.process_sentence(testsentence)
     testbinarystr = binary.ais_sentence_payload_binary(testdata)
     with self.assertRaises(binary.NoBinaryData):
         binary.decode_sixbit_integer(testbinarystr[116:128]) / 10
Exemple #5
0
 def __init__(self, outputpath, kmzoutput=False):
     self.kmzoutput = kmzoutput
     self.outputpath = outputpath
     self.mpq = multiprocessing.Queue()
     self.serverprocess = None
     if not os.path.exists(outputpath):
         AISLOGGER.info('output path does not exist creating directories')
         os.makedirs(outputpath)
     self.netlinkpath = os.path.join(outputpath, 'open_this.kml')
     self.kmlpath = os.path.join(outputpath, 'livemapdata.kml')
     self.logpath = os.path.join(outputpath, 'nmea-sentence-log.txt')
     self.aistracker = ais.AISTracker()
     self.nmeatracker = nmea.NMEAtracker()
     if kmzoutput:
         self.copy_icons()
def aistracker_from_file(filepath, debug=False, timingsource=None):
    """
    open a file, read all nmea sentences and return an ais.AISTracker object

    Note:
        if debug is set then individual messages are saved into the messagelog

    Args:
        filepath(str): full path to nmea file
        debug(bool): save all message payloads and decoded attributes into
                     messagelog
        timingsource(list): MMSIs of the base stations you wish to use
                           as a time reference, type 4 base station reports
                           from this base station will be used for times.
                           default is None and all base stations will be used
                           for times. list of strings

    Raises:
        NoSuitableMessagesFound: if there are no AIS messages in the file

    Returns:
        aistracker(ais.AISTracker): object that keeps track of all the
                                    ships we have seen
        nmeatracker(nmea.NMEAtracker): object that organises the nmea sentences
        messagelog(allmessages.AISMessageLog): object with all the AIS messages
    """
    messagelog = allmessages.AISMessageLog()
    aistracker = ais.AISTracker()
    aistracker.timingsource = timingsource
    nmeatracker = nmea.NMEAtracker()
    msgnumber = 1
    for line in open_file_generator(filepath):
        try:
            payload = nmeatracker.process_sentence(line)
            if payload:
                msg = aistracker.process_message(payload)
                if debug:
                    messagelog.store(msgnumber, payload, msg)
                msgnumber += 1
        except (nmea.NMEAInvalidSentence, nmea.NMEACheckSumFailed,
                ais.UnknownMessageType, ais.InvalidMMSI, binary.NoBinaryData,
                IndexError) as err:
            AISLOGGER.debug(str(err))
            continue
    if aistracker.messagesprocessed == 0:
        raise NoSuitableMessagesFound('No AIS messages detected in this file')
    return (aistracker, nmeatracker, messagelog)
def extract_time_data_from_file(filepath):
    """
    find the base stations and timing data from NMEA text files

    Args:
        filepath(str): path to the nmea0183 text file

    Returns:
        timingchoices(dict): keys are numbers, values are MMSIs of base stns
        basestntable(list): list of lists, each list is a row for an AIS
                            base stn with its MMSI, flag, total messages, first
                            and last known timestamps

    Raises:
        NoSuitableMessagesFound: if there are no type 4 messages in the file
                                 there is no usable timestamps
    """
    nmeatracker = nmea.NMEAtracker()
    basestntracker = ais.BaseStationTracker()
    for line in open_file_generator(filepath):
        try:
            payload = nmeatracker.process_sentence(line)
            if payload:
                basestntracker.process_message(payload)
        except (nmea.NMEAInvalidSentence, nmea.NMEACheckSumFailed,
                ais.UnknownMessageType, ais.InvalidMMSI, binary.NoBinaryData,
                IndexError) as err:
            AISLOGGER.debug(str(err))
            continue
    if basestntracker.messagesprocessed == 0:
        raise NoSuitableMessagesFound('No AIS Base Stations detected')
    basestnmainheader = [
        'MMSI', 'Flag', 'Total Messages', 'First Known Time', 'Last Known Time'
    ]
    basestnposheader = ['Time']
    basestntable = basestntracker.create_table_data(
        csvheader=basestnmainheader, posheaders=basestnposheader)
    basestntable[0].insert(0, 'Choice')
    timingchoices = {}
    stncount = 1
    for stn in basestntracker.stations:
        timingchoices[str(stncount)] = stn
        basestntable[stncount].insert(0, stncount)
        stncount += 1
    return timingchoices, basestntable
def read_from_file(filepath,
                   outpath,
                   everything=False,
                   filetype='text',
                   orderby='Types',
                   region='A'):
    """
    read AIS NMEA sentences from a text file and save to various output formats

    Note:
        a text file containing stats and a basic summary, a KMZ map,
        JSON + CSV containing details of AIS stations and JSONLINES + CSV of
        all AIS messages are generated by default

    Args:
        filepath(str): full path to the input file containing NMEA sentences
        outpath(str): path to save to excluding file extensions
        everything(bool): whether to output files for every individual station
        filetype(str): what type of file are we reading from
                       options are text, csv or jsonlines
        orderby(str): order KML/KMZ output and Everything station folders by
                      'Types', 'Flags' or 'Class', default is 'Types'
        region(str): IALA region 'A' or 'B', default is 'A'
    """
    if not os.path.exists(outpath):
        AISLOGGER.info('output path does not exist creating directories')
        os.makedirs(outpath)
    AISLOGGER.info('processed output will be saved in %s', outpath)
    AISLOGGER.info('reading nmea sentences from - %s', filepath)
    timesources = []
    try:
        if filetype == 'text':
            try:
                AISLOGGER.info('importing as text file')
                basestnchoices, basestntable = extract_time_data_from_file(
                    filepath)
                AISLOGGER.info('choose timing source')
                choiceconfirmed = False
                while not choiceconfirmed:
                    print_table(basestntable)
                    choice = input('enter timing source choice number: ')
                    try:
                        basestnmmsi = basestnchoices[choice.rstrip()]
                        if basestnmmsi not in timesources:
                            timesources.append(basestnmmsi)
                    except KeyError:
                        AISLOGGER.error('enter a choice no!')
                        continue
                    AISLOGGER.info('use %s as a time reference', basestnmmsi)
                    yesno = input('Y/N: ')
                    if yesno.rstrip() in ('Y', 'y', 'yes', 'YES'):
                        AISLOGGER.info('timing sources to be used - %s',
                                       timesources)
                        yesno2 = input('add another timing source? Y/N: ')
                        if yesno2.rstrip() in ('N', 'n', 'no', 'NO'):
                            basestntimingsource = timesources
                            choiceconfirmed = True
            except NoSuitableMessagesFound as err:
                basestntimingsource = None
                AISLOGGER.error(str(err))
            aistracker, nmeatracker, messagelog = aistracker_from_file(
                filepath, debug=True, timingsource=basestntimingsource)
        elif filetype == 'csv':
            AISLOGGER.info('importing as CSV file')
            aistracker, messagelog = aistracker_from_csv(filepath, debug=True)
        elif filetype == 'jsonlines':
            AISLOGGER.info('importing as JSON lines file')
            aistracker, messagelog = aistracker_from_json(filepath, debug=True)
        if filetype in ('csv', 'jsonlines'):
            nmeatracker = nmea.NMEAtracker()
            nmeatracker.sentencecount = 'N/A'
            nmeatracker.reassembled = 'N/A'
    except (FileNotFoundError, NoSuitableMessagesFound) as err:
        AISLOGGER.info(str(err))
        sys.exit(1)
    export.export_overview(aistracker,
                           nmeatracker,
                           messagelog,
                           outpath,
                           printsummary=True,
                           orderby=orderby,
                           region=region)
    if everything:
        export.export_everything(aistracker,
                                 messagelog,
                                 outpath,
                                 orderby=orderby,
                                 region=region)
    AISLOGGER.info('Finished')