AIS: uploadiamo gli spots su aprs.fi…..
Nel precedente articolo sul tema AIS abbiamo visto come si possa realizzare un ricevitore in tecnica SDR in grado di produrre degli “spot” che rappresentano delle tracce di altrettanti natanti presenti nella nostra zona di copertura radio.
L’articolo è stato in realtà il pretesto per cercare di mostrare come oggi si possa fare sperimentazione in ambito radio… anche senza saldare resistenze, condensatori e induttanze, ma viceversa saldando blocchi funzionali di tipo HW e/o SW tra loro usando come mezzo di saldatura anzicchè lo stagno, delle entità virtuali che chiamiamo genericamente interfacce….
In questo articolo vorrei continuare sullo stesso tema facendo un ulteriore passetto: finora abbiamo usato in realtà degli “oggetti” HW e/o SW già preconfezionati e reperiti su internet…. come dire che ci siamo limitati a capire cosa ci poteva servire funzionalmente per fare quello che ci stavamo proponendo di fare, per poi cercare su internet se qualcuno per caso avesse già fatto le stesse cose, ed in caso affermativo vedere come usare le cose fatte da altri, per realizzare il nostro scopo….
Questa modalità operativa è oggi il modo standard di procedere e consente spesso di ottenere dei risultati apparentemente sorprendenti, con uno sforzo di progettazione e realizzazione oggettivamente molto limitato….
Purtroppo la metodica di cui sopra non sempre riesce a sortire i risultati voluti, per cui può succedere che nonostante tutte le ricerche del caso, non si riesca a trovare già fatto quello che si cerca 🙁
Ovviamente è a questo punto che il discorso si fa più interessante per lo sperimentatore 🙂
Preso atto che quello che si cerca non esiste, la prima idea è quella ovviamente di progettare e sviluppare ex novo il tutto…. come dire riscoprire la ruota….
Spesso ci si diverte a riscoprire la ruota…. peccato che alla fine si ottenga nè più nè meno che … una ruota !
Conviene allora evitare di perdere tempo ad inventare cose già inventate, e cercare invece di capire cosa manca alle invenzioni già esistenti, per arrivare a fare la nostra invenzione 🙂
Come dire: cerchiamo innanzitutto di studiare e capire cosa vogliamo fare… una volta capito in dettaglio il tutto, forse scopriremo che quello che ci manca è solo una piccola parte del tutto, per cui “semplicemente” sviluppando quel piccolo “ad-hoc” potremo ottenere il nostro risultato con uno sforzo alla fine molto più limitato se confrontato all’invenzione della ruota…. 🙂
Purtroppo spesso quando si approccia un problema si parte da un assunto del tipo: io sono un esperto di radio ( o equivalente)… per cui … state in mano all’arte !
E’ esattamente la premessa sbagliata per affrontare il problema 🙁
Quando ci si trova di fronte ad un problema conviene sempre affrontarlo con umiltà cercando di capire, prima di tirare conclusioni…. con questo approccio spesso si riesce meglio a centrare il nucleo del problema e trovare il poco o tanto …. che manca alla soluzione del nostro problema….
Nel caso specifico l’obiettivo che ci siamo dati è quello di uploadare gli spot AIS recuperati in qualche modo non meglio precisato sui portali ad hoc esistenti, ed in particolare sul portale aprs.fi.
La funzionalità di upload degli spot su un certo portale è in genere una funzione sempre presente in quasi tutti i programmi di acquisizione e display di AIS disponinibili: molto spesso quest programmi sono tagliati addirittura su u no specifico portale; in certi casi i gestori di uno specifico portale arrivano addiritura a “regalare” a persone disponibili tutto il necessario per ricevere e uploadare degli spot AIS sul loro portale: ovviamente dietro ci sta un evidente interesse econoimico visto che nessuno regala qualcosa senza un qualche piccolo o grande ritorno…..
In genere i siti specializzati lucrano nel rivendere per una quota annua il servizio da loro svolto a soggetti interessati e che possono trarre giovamento dalla conoscenza dei dati recuperati: tipicamente si parla di persone che utilizzano delle imbarcazione o che prestano a loro volta dei servizi derivati dalla conoscenza dei dati presenti sul portale in questione.
Un portale molto interessante per i radioamatori è https://aprs.fi/ : questo portale si distingue dagli altri principalmente per essere senza fini di lucro e soprattutto gestito da radioamatori per i radioamatori e con l’obiettivo principale di svolgere il ruolo di aggregatore per i dati raccolti world-wide dal servizio aprs: per sapere qualcosa in più di questo servizio si può consultare https://it.wikipedia.org/wiki/APRS
Il portale è in grado di raccogliere, in aggiunta ai dati aprs, anche i dati forniti dal servizio AIS che sostanzialmente assomigliano come contenuti e concettualità ai dati standard aprs.
Purtroppo a causa della sua specificità, questo tipo di portale non è particolarmente supportato dai programmi AIS disponibili in giro per l’evidente mancanza di interesse economico…
Come radioamatori che peraltro hanno alle spalle molto spesso anche un background di marittimi attivi, siamo quindi abbastanza motivati a contribuire al progett aprs.fi …..
Nell’imbarcarci (!!!) quindi nel nostro piccolo grande progetto la prima cosa da fare è capire come possa essere possibile effettuare l’upload dei dati AIS sul portale aprs.fi: facendo un poco di ricerca su internet scopriamo che altri ( ovviamente) si sono già posti il nostro stesso problema… scopriamo anche che esiste un bel documento, anche se non aggiornato, di qualche anno fa che specifica esattamente il “protocollo” ( JSON AIS ) reso disponibile dal portale per questa funzione.
Il protocollo JSON_AIS è stato sviluppato qualche anno fa insieme da un OM finlandese di aprs.fi e uno dei principali gestori di siti di aggregazione AIS www.marinetraffic.com
Approfondendo la ricerca scopriamo anche che c’è stato qualcuno che sfruttando questa documentazione ha cercato di realizzare qualcosa a livello di programmazione riuscendo anche ad uploadare con successo degli spot sul portale, anche se il proprio lavoro non è stato poi reso disponibile in maniera usabile “ad occhi chiusi” da parte di altri in quanto i risultati non sono apparsi affidabili.
Il materiale e le info raccolte sono state comunque illuminanti per capire esattamente cosa è necessario fare e come sia possibile procedere; nel seguito riassumiamo sinteticamente il discorso.
Cominciamo dalle richieste del sito aprs.fi: quella che viene resa disponibile è una API (Application Programming Interface) che consente di inviare al sito dei pacchetti di dati ( gli spot AIS) formattati sotto forma di strutture dati di tipo JSON; in effetti JSON è una modalià di rappresentazione dei dati che sfrutta un formato completamente testuale, costituito da una serie di righe del tipo “nome_campo = valore” e raggruppate in modo da poter essere agevolmente trattate con un programma SW, sfruttando delle librerie ( cioè del SW già disponibile) abbastanza diffuse.
Un esempio di “messaggio” JSON_AIS è per esempio il seguente:
Come si può notare nel messaggio esistono due parti ben distinte:
- una componente “path” che cntiene informazioni relative a chi sta originando il messaggio e a chi è destinato
- na componnete “msg” che contiene al suo interno una serie di sottomessaggi ( ognuno compreso tra due parentesi graffe…) ognuno dei quali rappresenta un insiemi di dati dedotti da uno spot AIS; un campo molto importante di ogni zona spot-AIS è il campo “timestamp” che rappresenta in maniera leggermente codificata il tempo relativo allo spot AIS.
Esistono il realtà numerosi tipi di messaggi alo scopo di rappresentare e riportare diverse situazioni.
Esistono diversi modi per trasferire i singoli messaggi verso il server aprs.fi, sfruttando il protocollo HTTP in diversi modi: senza addentrarci nei dettagli è come dire che si sfrutta lo stesso meccanismo utilizzato per la navigazione internet, per far pervenire al server presente sul sito aprs.fi i propri pacchetti di dati.
Capito quindi come vanno formattati i dati e come vanno trasferiti al server presente sul sito, il sucessivo problema è come confezionare i pacchetti AIS in modo da rispettare il formato e le regole della API prima accennata.
Dall’esempio della figura sopra si intuisce che i valori da infilare nei pacchetti sicuramente devono essere estratti dalle sequenze NMEA che provengono dal ricevitore AIS: nella puntata precedente abbiamo già discusso ampiamente queso tema ed abbiamo scoperto che le sentenze NMEA grezze contengono si tutta una serie di dati, ma in maniera codificata….
Quindi evidentemente sarà necessario decodificare le sequenze NMEA grezze ed estrarre tutti i valori richiesti per popolare i campi richiesti dai messaggi AIS da inviare ad aprs.fi…..
Sempre nella puntata scorsa abbiamo anche trovato e provato un bellissimo programma AIS Decoder, che, girando su un PC windows , consente di mettere sotto forma tabellare il contenuto comleto degli spot AIS a partire dalle sequenze NMEA grezze….
Peccato che come tutti i programmi per windows AIS Decoder è molto difficilmente integrabile con altri programmi per poter sfruttare il risultato del suo lavoro….
Un altro problema che avremmo con AIS Decoder è quello di essere costretti ad usare un PC windows per il nostro lavoro… cosa che come già osservavamo è sicuramente uno spreco….
Conviene allora cominciare a pensare ad usare linux … e quindi cominciare a cercare qualcosa di già fatto per decodificare delle sequenze AIS …..
Ci viene in aiuto un bellisimo tool molto diffuso in ambito linux di nome “gpsd”: si tratta di un insieme di programmi pensati per funzionare sotto sistema operativo linux, allo scopo di gestire i dispositivi gps esistenti sul mercato….
Mi direte: cosa centra il gps con noi ?
Siamo fortunati in quanto tutti i GPS in commercio condividono come linguaggio di comunicazione.. il protocollo NMEA !!!!
Quindi siccome le seguenze AIS sono sequenze NMEA, sfruttando i tools di gpsd possiamo proare a decodificare le sequenze grezze AIS. La figura seguente rappresenta l’ingresso e l’uscita del programma gpsdecode:
echo '!AIVDM,1,1,,A,13cmfm0P0011C:6GGdTP0?vL0L0Q,0*46' | gpsdecode { "class":"AIS", "device":"stdin", "type":1, "repeat":0, "mmsi":247295700, "scaled":true, "status":"0", "status_text":"Under way using engine", "turn":"nan", "speed":0.0, "accuracy":false, "lon":14.2649, "lat":40.8425, "course":0.0, "heading":511, "second":14, "maneuver":0, "raim":false, "radio":114721 }
Come potete notare la stringa NMEA grezza è stata decodificata e divisa in una serie di campi del tipo “nome : valore”; come dire che magicamente siamo in grado di decifrare i singoli campi del messaggio AIS… mettere quindi i valori presenti in questo tipo di formato, nel formato richiesto dal protocollo aprs.fi non è un grossissimo lavoro…..
Basta a questo punto tirarsi su le maniche e scrivere un programmino in grado di girare su linux, che ricevendo in ingresso dei dati tipo quelli della figura sopra, li trasformi nel formato JSON_AIS…
Prima però dobbiamo accennare a come far interagire i vari programmi che andiamo ad utilizzare in maniera da cercare di semplificare il nostro lavoro….
Avendo deciso di utilizzare linux, possiamo sfruttare tutta una serie di modi di interfacciamento di diversi programmi…. nel caso specifico siccome già abbiamo trovato fatto il pezzo si SW che fa la decodifica, ci conviene usare la modalità che tale programma utilizza: si chiama modalità “filtro”.
In pratica gpsdecode altro non fa che operare come un scatolotto che inserito in maniera passante su un tubo dell’acqua, provvede a togliere, mettere o modificare qualcosa nel flusso d’acqua entrante, producendo un flusso d’acqua uscente …
Il flusso d’acqua nel nostro caso è un flusso di squenze NMEA grezzi in ingresso, mentre in uscita troveremo delle sequenze in formato JSON corrispondente alle sequenze di ingresso.
Il programma che andremo a scrivere a questo punto potrà operare allo stesso modo accettando in ingresso delle sequenze JSON chiamiamo grezze ( cioè quelle che escono da gpsdecode) e producendo in uscita delle sequenze in formato JSON_AIS come richiesto da aprs.fi.
In realtà il nostro programmino, che chiameremo aprs_prep , dovrà fare una serie di altre cose in quanto il documento che descrive in dettaglio le API aprs.fi richiede una serie di altre cosetto molto sottili senza le quali gli spot AIS non vengono accettati.
Fatto il cuore del nostro sistemino, restano ancora alcune cosettine da sistemare:
- come collegare il nostro catorcio alla sorgente degli spot AIS ?
- come effettuare fisicamente l’upload tramite protocollo HTTP/JSON_AIS sul sito aprs.fi ?
- come estrarre qualche ulteriore informazione dal funzionamento del tutto ?
Vediamo innanzitutto il primo punto: la volta scorsa abbiamo accennato, anche se non abbiamo descritto in dettaglio il funzionamento, ad un tool AIS Dispatcher: si tratta di un piccolo tool disponibile fortunatamente non solo su piattaforma windows, ma anche su piattaforma linux, che consente di fare una serie di cose interessanti:
- ricevere delle sequenze grezze NMEA da una sorgente tramite diverse modalità di interfacciamente, incluse le modalità TCP/IP sia di tipo UDP che di tipo server TCP come descritte nell’articolo precedente.
- inviare le sequenze ricevute ad una o più destinazioni utilizzando il protocollo TCP/IP nella variante UDP.
- inviare le sequenze NMEA di ingresso in uscita dal programma (modalità filtro)
- effettuare delle azioni di riduzione del ritmo di ritrasmissione delle sequenze entranti, allo scopo di non sovraccaricare le destinazioni con un eccessivo ritmo di riporto di spot.
Capite allora che questo tool va perfettamente bene per noi allo scopo di fare le seguenti funzioni:
- ricevere tramite TCP/IP in modalità UDP o TCP le sequenze NMEA grezze prodotte da una o più sorgenti (via UDP)
- affasciare ovvero aggregare sequenze grezze NMEA provenienti da più sorgenti (usando la modalità UDP)
- filtrare ovvero eliminare spot multipli presenti nell’aggregato delle diverse sorgenti
- produrre un unico flusso di spot AIS sostanzialmente sommatoria di tutte le sorgenti collegate.
- fornire in uscita il risultato del suo lavoro in modo da poterlo agevolmente inviare in ingresso agli altri moduli SW.
ll tutto semplicemente programmando opportunamente i parametri con cui invocare il programma.
Per la seconda cosina di cui si parlava sopra conviene scrivere un piccolissimo programma , che chiamiamo ais_send , da far girare periodicamente per ogni 5 secondi e che si occupa di inviare i messaggi JSON_AIS prodotti verso il server aprs.fi, in maniera asincrona rispetto agli altri programmi.
Quindi per quest’ultimo pezzo del lavoro rinunciamo ad usare il meccanismo di comuncazione tramite “filtro” tra programmi e decidiamo di usare una modalità di tipo “lascamente accoppiata”: in futuro tale scelta potrebbe cambiare, ma decidiamo in questa fase sperimentale di scegliere questa modalità principalmente per rendere pù semplice il debug del funzionamento visto che la parte upload è la parte che nelle esperienze di altri ha dato maggiori problemi di stabilità.
In pratica il programmino aprs_prep produrrà dei messaggi in formato JSON_AIS che verranno accumulati in una coda di trasmissione sulla macchina linux, in attesa che il programmino ais_send di invio dei messaggi, prelevi i singoli messaggi e li invii al server aprs.fi. La figura sotto rappresenta un esempio di messaggio che viene accodato:
# cat 2018021101452500
{
“protocol”: “jsonais”,
“encodetime”: “20180211014525”,
“groups”: [
{
“path”: [
{ “name”: “aprs.fi”, “url”: “http://aprs.fi/” },
{ “name”: “I8FUC” }
],
“msgs”: [
{
“msgtype”: “4”,
“mmsi”:2470014,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0″,
“lon”:14.2633,
“lat”:40.8438,
“course”:0,
“heading”:0,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:247042900,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0″,
“lon”:13.9392,
“lat”:40.7452,
“course”:46,
“heading”:155,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:247074100,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0″,
“lon”:14.2648,
“lat”:40.844,
“course”:354.8,
“heading”:511,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “4”,
“mmsi”:2470075,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0″,
“lon”:13.069,
“lat”:41.2304,
“course”:0,
“heading”:0,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:247047300,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0″,
“lon”:14.2612,
“lat”:40.8425,
“course”:216,
“heading”:136,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:247370400,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”20″,
“lon”:13.8286,
“lat”:40.6663,
“course”:121.8,
“heading”:121,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:247376800,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:8,
“speed”:”0″,
“lon”:14.2649,
“lat”:40.8432,
“course”:194.1,
“heading”:175,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:247048600,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0.1″,
“lon”:14.2686,
“lat”:40.842,
“course”:193.5,
“heading”:511,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:247540000,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0″,
“lon”:14.3769,
“lat”:40.6305,
“course”:0,
“heading”:246,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:247074100,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0″,
“lon”:14.2647,
“lat”:40.844,
“course”:356.2,
“heading”:511,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:636017346,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0.2″,
“lon”:14.1738,
“lat”:40.6477,
“course”:268.6,
“heading”:150,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:247047300,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0″,
“lon”:14.2612,
“lat”:40.8425,
“course”:216,
“heading”:136,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “4”,
“mmsi”:2470075,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”0″,
“lon”:13.069,
“lat”:41.2304,
“course”:0,
“heading”:0,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
},
{
“msgtype”: “1”,
“mmsi”:247370400,
“callsign”:””,
“shipname”:””,
“shiptype”:37,
“status”:5,
“speed”:”20″,
“lon”:13.828,
“lat”:40.6666,
“course”:121.8,
“heading”:121,
“length”:12,
“width”:2,
“ref_front”:6,
“ref_left”:1,
“draught”:1,
“rxtime”: “20180211014514”
}]
}
]
Come potrete notare in un unico messaggio sono stati raggruppati tutta una serie di messaggi provenienti da svariate sequenze grezze AIS: il motivo per cui si procede n questo modo ( ovvero raggruppando tanti spot) è perchè il processo di upload tramite protocollo HTTP verso il sito aprs.fi è abbastanza complesso e lento per cui fare tutto il lavoro per ogni singolo spot introdurrebbe un inuti sovraccarico di lavoro e allungamento del tempo di trasferimento a discapito anche della efficienze operativa del server aprs.fi e dell’intero processo .
Siamo finalmente arrivati alla ciliegina sulla torta: atteso che il nostro insieme di programmi vede transitare tutto il flusso dati costituito dalle sequenze NMEA AIS, volendo potremmo divertirci a tenere dei log del funzionamento come ad es. numero e tipo di spot inviati, distanza corrispondente ad ogni spot, statistiche temporali , errrori di comunicazione con il server aprs.fi, etc.
Riepilogando
La fig. sotto riporta l’output del programma che fa il grosso del lavoro
Si può notare sulla prima riga l’unico comando che lancia e collega tra loro i vari pezzi SW descritti in precedenza. Come si può notare per ogni riga viene riportato il sommario dello spot AIS ricevuto, il tempo relativo, il valore del numero MMSI del natante, latitudine, longitudine e distanza tra il natante e l punto di ricezione.
La fig. seguente rappresenta invece l’output del programma send_ais che invia i messaggi JSON_AIS verso aprs.fi
Dalla figura si può notare che l’invio avviene utilizzando la modalità HTTP di tipo “post” usando il protocollo jsonais ; la scritta “received jsonais POST successfully” attesta che il messaggio contenente gli spots è stato ritenuto valido ed accettato dal server.
La figura seguente rappresenta la visualizzazione sul portale aprs.fi degli spots uploadati..
A questo punto qualcuno si sarà chiesto: abbiamo fatto tanto per sganciarci da windows per evitare di tenere un PC bloccato per fare questo lavoro, e ora siamo arrivati alla conclusione che ci server una macchina linux……
Il discorso è corretto se non fosse per un piccolo dettaglio: la macchina linux non è assolutamente dedicata a questo solo lavoro, ma può essere una qualsiasi macchina linux che per accidente già abbiamo operatriva 24/24-7/7…
Nel nostro caso tutti sapete che abbiamo una macchina linux che funge da server per la nostra rete SARIMESH e che in effetti già opera in maniera autonoma 24/24-7/7…. è sufficiente allora aggiungere questo ulteriore “task” ai tanti altri “task” che il server svolge e ci ritroveremo disponibile la funzione senza aggiungere una ulteriore macchina.
Ovviamente nessuno vieta, per es. volendo sperimentare a casa propria, di utilizzare allo scopo una schedina Raspberry RPI o altro mini-schedino da pochi Euro per realizzare la funzione richiesta a costo veramente molto contenuto. Un esempio su questo tema potrebbe essere oggetto di un successivo futuro articolo se ci sta dell’interesse…..
Good way of telling, and pleasant article to take data about my presentation subject,
which i am going to convey in college.