Trasporti AMAT di Palermo? C’è un Telegram per Te!

DATI

Trasporti AMAT di Palermo? C’è un Telegram per Te!

Post pubblicato originariamente su giovanni.pirrotta.it.

In questi ultimi tempi in rete si fa un gran parlare di BOT (abbreviazione di robot), ovvero quei programmi che fanno credere all’utente di parlare con una persona reale ma che di fatto sono risponditori automatici utili per fornire servizi vari come ad esempio il meteo, news, quiz, sondaggi, giochi, etc.

Il motivo di tutto questo proliferare di BOT è dovuto principalmente all’apertura di Telegram, nella sua versione 3, al mondo degli sviluppatori. Attraverso l’utilizzo di API ufficiali, infatti, è ora possibile creare, gestire e interagire con programmi BOT, personalizzandoli secondo le proprie esigenze.

Ho sempre visto un alto potenziale nell’uso di questo tipo di applicazioni e la scelta di Telegram potrebbe rivelarsi particolarmente azzeccata in questo senso.

Esattamente due anni fa anch’io ho iniziato a interessarmi di BOT, ad immaginarmi il mio smartphone come un telecomando da pigiare per ottenere specifici servizi: informazioni sui programmi televisivi, previsioni meteo, eventi serali della mia città, orari di apertura degli uffici pubblici, etc. Ho sviluppato quindi un BOT su Twitter grazie al quale, con un semplice tweet e una microgrammatica, riuscivo ad inviare richieste ad un’applicazione per ottenere informazioni sui programmi televisivi della serata. Descrivo nel dettaglio l’implementazione del progetto, che si chiama per l’appunto cosaceintv, in questo post; il sito del progetto è cosaceintv.it.

Tuttavia Twitter non consente di creare BOT in modo nativo per cui, per raggiungere lo scopo, sono dovuto scendere a compromessi, chiamateli workaround.

Vero è che l’app non è diffusa come WhatsApp, l’attuale killer application nel settore dell’instant messaging, (molti si aspettavano dei segnali di apertura API da WhatsApp in occasione dell’ultima conferenza F8 di Facebook, ma invece nisba) ma è anche vero che Telegram sta guadagnando sempre più terreno grazie soprattutto a scelte aziendali che si stanno rivelando strategicamente vincenti, come ad esempio

  • il rilascio del sorgente in opensource,
  • l’alta attenzione nei confronti della sicurezza e della privacy degli utenti,
  • la possibilità di creare chat segrete e autodistruggenti dopo un tempo prestabilito,
  • un design pulito e gradevole,
  • la totale gratuita,
  • l’assenza di pubblicità
  • ed infine, non meno importante, l’ultima feature aggiunta cioè la possibilità di creare BOT per la gestione di servizi personalizzati e l’interazione in modo programmatico attraverso API.

Più che una semplice app di messaggistica Telegram è di fatto una vera e propria piattaforma e in rete si trovano già applicazioni BOT di qualsiasi tipo; le più popolari si possono trovare al seguente link.

Ma anche in Italia cominciano a vedersi progetti interessanti.

A Prato Matteo Tempestini ha sviluppato il BOT Emergenze Prato per essere aggiornati in tempo reale su condizioni meteo, possibili allerte e segnalazioni. A Lecce, utilizzando gli opendata del comune e non solo, Pier Paolo Paolicelli (piersoft) ha sviluppato OpenDataLecceBot con il quale è possibile ottenere informazioni su meteo, temperatura, qualità dell’aria, orari delle scuole, tariffe aree ZTL, eventi culturali, etc. Il servizio trasporti bus TPER fornisce informazioni aggiornate sui bus di Bologna usando i servizi informativi e gli opendata. (tperbot.)

Incuriosito quindi da tutto questo fermento mi è venuta voglia di rimettermi in gioco anch’io con i BOT e smanettare un pò con questa piattaforma. Ho accolto, quindi, il suggerimento di piersoft  che consigliava di replicare il servizio offerto dalla TPER di Bologna sui trasporti anche per la città di Palermo, dato che i dati sui trasporti palermitani sono rilasciati dall’ azienda AMAT in formato GTFS con licenza OpenData.

La specifica GTFS (General Transit Feed Specification) è stata sviluppata da Google e definisce un formato comune per rappresentare informazioni orarie di un sistema di trasporti (bus, metro, treno, etc) associandole ad informazioni geografiche.

La specifica struttura i dati organizzandoli in un insieme di file CSV.

I più importanti sono i seguenti:

  • agency – informazioni inerenti l’azienda che gestisce i trasporti;
  • routes – informazioni sulle linee dei trasporti;
  • trips – informazioni inerenti le corse per ciascuna linea;
  • stops – le fermate geolocalizzate;
  • stop_times – l’orario di arrivo e partenza e la sequenza per ogni corsa in ciascuna fermata;
  • calendar – periodo del servizio trasporti su base settimanale;
  • calendar_dates – date in cui vi sono delle eccezioni rispetto a quanto descritto incalendar (ad. es. feste)

Per la specifica completa si rimanda alla pagina ufficiale GTFS

Quindi mettiamoci al lavoro e scarichiamo i dati dal sito AMAT di Palermo.

Per prima cosa scarico il file zippato GTFS dalla pagina OpenData del Comune di Palermo.

Decido di caricare tutti i file CSV all’interno di un dabatase Mysql, per cui inizio a cercare in rete degli statement DDL in modo da risparmiarmi il creare tutto a manina. Uno potrebbe pensare che, essendo GTFS un formato ben definito, uno schema DDL vale l’altro.

Errore!!!

Quelli che seguono sono alcuni consigli che vi potrebbero farvi risparmiare tempo e mal di testa quando decidete di creare uno schema GTFS trovato in rete.

REGOLE D’ORO

  1. Analizzare sempre e bene la qualità dei dati da importare prima di importarli
  2. GOTO 1 ;–)

La maggior parte dei campi id degli schemi che ho trovano in rete è in formato intero mentre nella maggior parte dei record dei dati GTFS AMAT il campo idcontiene anche valori alfanumerici, ergo trasformate tutti gli id da int a varchar.

Per importare i dati automaticamente ho usato uno script in python scaricato da github. Trovate un fork sul mio repository github in quanto lo script conteneva un bug relativo al caricamento di codici alfanumerici contenenti il carattere E. Lo script erroneamente parsava i codici contenenti il carattere E come formato esadecimale considerandoli interi invece di stringa. Trovate la versione fixata nel mio repo.

A questo punto iniziamo a scrivere un pò di codice. La documentazione di riferimento per creare BOT con Telegram è fatta benissimo e la trovate al seguente link. Per lo sviluppo del codice ho usato questa libreria PHP a sua volta descritta in modo molto chiaro qui. La libreria è stata sviluppata per il framework PHP Laravel ma può essere utilizzata anche in modalità standalone.

La prima cosa da fare è creare il bot. Per fare questo bisogna aggiungere sul proprio client Telegram l’utente @BotFather e inviargli il seguente comando /newbot. Dopo aver risposto ad alcune domande, ad esempio nome ed username del BOT, viene generato un TOKEN che rappresenta il ponte di collegamento tra il nostro software e Telegram. Per maggiori dettagli sulla creazione dei bot fate riferimento alla documentazione ufficiale.

Per poter interagire con Telegram scriviamo quindi:

$telegram = new Api('BOT TOKEN');
$response = $telegram->getMe();

Nella response troveremo informazioni sul bot creato. Per poter inviare messaggi all’utente bisognerà indicare, oltre al messaggio, anche l’ID della chat in modo che solo l’utente che ha fatto la richiesta possa ricevere il messaggio di ritorno.

$response = $telegram->sendMessage('CHAT_ID', 'Hello World');

Oltre a messaggi di testo il nostro BOT può rispondere anche con immagini, audio, video, allegati, etc.:

$response = $telegram->sendPhoto('CHAT_ID', 'path/to/photo.jpg', 'Some caption');

Ma come fa l’utente a chiedere le informazioni al BOT? Inviando dei comandi.

Per creare un comando, usando la libreria PHP, è necessario estendere la classe Command e implementare il metodo handle. Creare un comando è un’operazione veramente banale, è infatti necessario inizializzare semplicemente la variabile namecon il nome del comando che si vuole creare. Nell’esempio si sta creando il comando /start.

Nell’esempio che segue, digitando da Telegram il comando /start il BOT risponderà con Hello World!

<?php   

use Telegram\Bot\Commands\Command;

class StartCommand extends Command 
{
   protected $name = "start";
   protected $description = "Start Command to get you started";
   
    public function handle($arguments)  {
       $this->replyWithMessage('Hello World!');
   }  
}

 

Non mi soffermerò oltre su questa libreria perchè, come già detto, è presente una documentazione completa ed esaustiva.

Vediamo adesso le feature più importanti che dovrà avere il nostro BOT. Verranno descritte le più importanti scelte adottate per la logica applicativa. Si tratta essenzialmente di recuperare informazioni dal database e di formattare l’output, ci soffermeremo quindi solo sulle query SQL più importanti.

La prima versione di amatPABot, questo il nome del BOT, implementa due funzionalità:

  • Orario Linee
  • Fermata più vicina

Orario Linee

Le informazioni sono tutte presenti nel db per cui all’interno del metodo handleviene gestita la logica per estrarre le informazioni relative alle linee AMAT di Palermo.

La query SQL utilizzata per mostrare le linee:

 

SELECT route_id, route_long_name 
FROM routes 
ORDER BY route_id asc

 

A questo punto viene mostrato l’elenco delle linee AMAT. L’utente può scegliere la linea di cui vuole sapere gli orari. Una volta scelta la linea un nuovo comando recupererà il nome delle fermate della linea (Andata e ritorno) e gli orari relativi.

Per recuperare gli orari delle corse uso la seguente query SQL, passandogli l’id della linea e l’id del servizio, cioè del periodo di riferimento nel calendario.

SELECT * from stop_times, trips
WHERE stop_times.trip_id = trips.trip_id 
      and trips.route_id = :route_id 
      and service_id = :service_id
GROUP BY stop_times.trip_id

A questo punto l’output ottenuto è il seguente:

Passiamo adesso all’altra funzionalità.

Fermata più vicina

Per ottenere informazioni sulla fermata più vicina dobbiamo per prima cosa cliccare sulla graffetta e inviare la nostra posizione geografica

Fatto ciò un comando calcolerà le 5 fermate più vicine recuperandole dalla tabellastops eseguendo la seguente query:

SELECT stop_id, stop_name, stop_lat, stop_lon, 
(6371 * acos( cos( radians(:latitude)) *  cos( radians( stop_lat )) *  cos( radians( :longitude ) -  radians(stop_lon)) +  sin( radians(:latitude))  * sin(radians(stop_lat)))) AS distance 
FROM stops 
HAVING distance < 250000 
ORDER BY distance limit 5"

Il valore 6371 è la lunghezza del raggio della terra. La formula utilizzata calcola la distanza in KM tra due punti espressi in latitudine e longitudine. Per maggiori informazioni fate riferimento qui e qui.

Per ogni fermata recupero anche il nome delle linee passanti.

SELECT route_id  
FROM stops, stop_times, trips  
WHERE stops.stop_id=stop_times.stop_id 
AND stop_times.trip_id = trips.trip_id 
AND stops.stop_id = :stop_id 
GROUP BY route_id

 

Vengono mostrate a video le 5 fermate più vicine con le relative linee passanti. La prima fermata viene visualizzata su una mappa (si lo so, è Google Maps e non OpenStreetMap; nativamente Telegram usa le mappe di Google per inviare al client le posizioni geografiche; per usare OSM si potrebbero, ad esempio, creare al volo immagini statiche e inviarle all’utente per la posizione delle fermate).

Per il deploy del BOT ho usato Cloudflare per avere una connessione SSL, condizione necessaria per poter utilizzare il WebHook in Telegram, invece del metodo manuale getUpdates.

Ricapitolando

  • Il BOT è funzionante con i dati aggiornati al 2015;
  • Sulla correttezza e consistenza dei dati non garantisco. Non prendetevela con me per eventuali inesattezze e/o sbagli :–)
  • Il BOT sviluppato è ancora una demo. E’ possibile aggiungere altre funzionalità, il limite è la fantasia.

Per interagire con il bot dovete aggiungere al vostro client Telegram il contatto: @amatPABot.

Il codice sorgente lo trovate qui.

Attenzione, è’ una versione ancora poco stabile, non pronta per andare in produzione.

Se questo lavoro vi è piaciuto un pò, potreste contribuire a farlo conoscere in giro sui social, grazie.

Twittami

 

 

Idee, critiche e suggerimenti sono benvenuti.

That’s all folks! Stay tuned!