2014-12-20 17 views
5

Ho usato per decodificare i messaggi AIS con il pacchetto theis (Python) https://github.com/schwehr/noaadata/tree/master/ais fino a quando non ho iniziato a ottenere un nuovo formato dei messaggi. Come forse saprai, i messaggi AIS sono principalmente di due tipi. una parte (un messaggio) o due parti (multi messaggio). Il messaggio n. 5 è sempre disponibile in due parti. Esempio:Creazione di decodificatore messaggi AIS

!AIVDM,2,1,1,A,55?MbV02;H;s<HtKR20EHE:[email protected]@Dn2222222216L961O5Gf0NSQEp6ClRp8,0*1C 
!AIVDM,2,2,1,A,88888888880,2*25 

ho utilizzato per decodificare questo bene utilizzando il seguente pezzo di codice:

nmeamsg = fields.split(',') 
    if nmeamsg[0] != '!AIVDM': 
    return 
    total = eval(nmeamsg[1]) 
    part = eval(nmeamsg[2]) 
    aismsg = nmeamsg[5] 
    nmeastring = string.join(nmeamsg[0:-1],',') 


    bv = binary.ais6tobitvec(aismsg) 
    msgnum = int(bv[0:6]) 

-

elif (total>1): 
    # Multi Slot Messages: 5,6,8,12,14,17,19,20?,21,24,26 
    global multimsg 
    if total==2: 
     if msgnum==5: 
     if nmeastring.count('!AIVDM')==2 and len(nmeamsg)==13: # make sure there are two parts concatenated together 
      aismsg = nmeamsg[5]+nmeamsg[11] 
      bv = binary.ais6tobitvec(aismsg)  

      msg5 = ais_msg_5.decode(bv) 
      print "message5 :",msg5 
      return msg5 

Ora sto ottenendo un nuovo formato dei messaggi :

!SAVDM,2,1,7,A,[email protected]`[email protected]:[email protected]@Dp,0*2A,1410825672 
!SAVDM,2,2,7,A,4hC`[email protected]`40,2*76,1410825672,1410825673 

Nota. il numero all'ultimo indice è l'ora in formato epoca

Ho provato a modificare il mio codice per decodificare questo nuovo formato. Riusco a decodificare i messaggi con una parte. Il mio problema è di tipo multi-messaggio.

nmeamsg = fields.split(',') 
    if nmeamsg[0] != '!AIVDM' and nmeamsg[0] != '!SAVDM': 
    return 
    total = eval(nmeamsg[1]) 
    part = eval(nmeamsg[2]) 
    aismsg = nmeamsg[5] 
    nmeastring = string.join(nmeamsg[0:-1],',') 
    dbtimestring = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(nmeamsg[7]))) 

    bv = binary.ais6tobitvec(aismsg) 
    msgnum = int(bv[0:6]) 

Il decodificatore non può portare le due linee come una. Quindi la decodifica fallisce perché il messaggio # 5 dovrebbe contenere due stringhe non una. L'errore che ottengo è in queste righe:

if nmeastring.count('!SAVDM')==2 and len(nmeamsg)==13: 
aismsg = nmeamsg[5]+nmeamsg[11] 

Dove len(nmeamsg) è sempre 8 (seconda riga) e nmeastring.count('!SAVDM') è sempre 1

Spero ho spiegato chiaramente in modo che qualcuno può farmi sapere quello che sto manca qui.

UPDATE

Va bene Credo di aver trovato la ragione. Passo messaggio file script riga per riga:

for line in file: 
    i=i+1 

    try: 
     doais(line) 

Dove messaggio # 5 dovrebbe essere passato come due linee. Qualche idea su come posso farlo?

UPDATE

ho fatto modificando il codice un po ':

for line in file: 
    i=i+1 

try: 
     nmeamsg = line.split(',') 
     aismsg = nmeamsg[5] 
     bv = binary.ais6tobitvec(aismsg) 
     msgnum = int(bv[0:6]) 
     print msgnum 
     if nmeamsg[0] != '!AIVDM' and nmeamsg[0] != '!SAVDM': 
     print "wrong format" 
     total = eval(nmeamsg[1]) 
     if total == 1: 
     dbtimestring = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(nmeamsg[8]))) 
     doais(line,msgnum,dbtimestring,aismsg) 
     if total == 2: #Multi-line messages 
     lines= line+file.next() 
     nmeamsg = lines.split(',') 
     dbtimestring = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(nmeamsg[15]))) 
     aismsg = nmeamsg[5]+nmeamsg[12] 
     doais(lines,msgnum,dbtimestring,aismsg) 
+2

per lino, riga enumerate (aperto ('log.ais'): è più tipico per python –

risposta

2

essere consapevoli del fatto che noaadata è il mio codice di ricerca vecchio. libais è la mia libreria di produzione che è in uso per ERMA e WhaleAlert di NOAA.

Generalmente faccio una decodifica in due passaggi. Per prima cosa unisciti ai messaggi multilinea. Mi riferisco a questo come normalizzazione (ais_normalize.py). Hai diversi problemi in questo passaggio. Innanzitutto le due linee componenti hanno timestamp diversi a destra della seconda stringa. Secondo il vecchio standard dei metadati USCG, l'ultimo è importante. Quindi il mio codice supporrà che queste due linee non siano correlate. In secondo luogo, non hai il campo ID stazione richiesto.

Da dove viene la SA in SAVDM? Quale dispositivo ("talker" nel vocabolario NMEA) sta ricevendo questi messaggi?

+0

Grazie per aver indirizzato la nuova libreria !! Vedo che è passato da Python a C++. Posso chiedere perché? – Shad

+0

Purtroppo non ho idea della risorsa dati, ottengo questi dati in un file di registro, sono riuscito ad associare le due linee come una sola e generare i messaggi a più righe, ho aggiornato il mio post e aggiunto il codice. è – Shad

+0

noaadata + bitvector è molto lento, sì, è flessibile e ottimo per la ricerca e il debugging, tuttavia, libais con il suo core C++ e il sottile wrapper python è probabilmente 2 ordini di grandezza più veloce e il lato C++ può essere incorporato in java, C++ e app c oggettive (ad es. app per android e ios). –

0

Se sei in Ruby, posso consigliare lo NMEA and AIS decoder ruby gem che ho scritto, available on github. Si basa su the unofficial AIS spec at catb.org che è gestito da uno dei colleghi di Kurt.

Gestisce la combinazione di messaggi multipart, letture da flussi e supporta un gran numero di messaggi NMEA e AIS. La decodifica dei 50 sottotipi binari dei messaggi AIS 6 e 8 è attualmente in fase di sviluppo.

per gestire le linee non standard hai postato:

!SAVDM,2,1,7,A,[email protected]`[email protected]:[email protected]@Dp,0*2A,1410825672 
!SAVDM,2,2,7,A,4hC`[email protected]`40,2*76,1410825672,1410825673 

Sarebbe necessario aggiungere una nuova regola di analisi che accetta campi dopo il checksum, ma a parte che dovrebbe andare senza problemi. In altre parole, si sarebbe copiare the parser line here:

| BANG DATA CSUM { result = NMEAPlus::AISMessageFactory.create(val[0], val[1], val[2]) } 

e avere qualcosa di simile

| BANG DATA CSUM COMMA DATA { result = NMEAPlus::AISMessageFactory.create(val[0], val[1], val[2], val[4]) } 

Cosa fai con quelli timestamp in più (s)? Sembra quasi che siano stati aggiunti da qualunque software stia facendo il logging, piuttosto che far parte del messaggio reale.