Archivio

Posts Tagged ‘Open Data’

Open Pronto Soccorsi: aggiornamento con nuovi dati


In seguito alla pubblicazione del primo post su Open Pronto Soccorsi ho ricevuto alcune indicazioni su ulteriori dati disponibili.

Mi ci è voluto un po di tempo ma ora sono in grado di pubblicare un aggiornamento dei dati tra cui, la quota maggiore, tutti quelli della Regione Lombardia (e colgo l’occasione per ringraziare Daniele Crespi per la segnalazione).

La nuova distribuzione su base nazionale è quindi la seguente

Quindi, con l’aggiunta dei dati lombardi (che si aggiunge a quella del Veneto e del Friuli Venezia Giulia), possiamo dire che è disponibile una continuità territoriale quasi dell’intero nord est della penisola italiana.

L’elenco completo dei Comuni per i quali sono stati recuperati i dati dei Pronto Soccorsi sul loro territorio è il seguente

Abano Terme Cittadella Magenta San Daniele del Friuli
Abbiategrasso Cittiglio Malcesine San Dona’ di Piave
Acquapendente Cividale del Friuli Manduria San Donato Milanese
Adria Civita Castellana Manerbio San Fermo Della Battaglia
Agordo Civitavecchia Manfredonia San Gavino Monreale
Alatri Cles Mantova San Giovanni Bianco
Albano Laziale Colleferro Martina Franca San Giovanni in Persiceto
Alghero Como Melzo San Marcello Pistoiese
Altamura Conegliano Menaggio San Severo di Puglia
Alto Reno Terme Copertino Merate San Vito al Tagliamento
Alzano Lombardo Corato Mestre Sanremo
Ancona Crema Milano Santorso
Andria Cremona Mirano Saronno
Angera Cuggiono Molfetta Sassari
Anzio Desenzano del Garda Monfalcone Scorrano
Arco Desio Monopoli Segrate
Arzignano Dolo Monselice Seriate
Asiago Edolo Monserrato Sesto San Giovanni
Asola Erba Montagnana Sondalo
Bagno a Ripoli Esine Montebelluna Sondrio
Bari Feltre Monterotondo Sora
Barletta Figline e Incisa Valdarno Montichiari Sorgono
Bassano del Grappa Firenze Monza Stradella
Belluno Foggia Mortara Subiaco
Bentivoglio Fondi Muravera Suzzara
Bergamo Formia Negrar Taranto
Bibione Francavilla Fontana Noventa Vicentina Tarquinia
Bisceglie Frascati Nuoro Tempio Pausania
Bologna Frosinone Oderzo Terlizzi
Bordighera Galatina Olbia Terracina
Borgo San Lorenzo Gallarate Ome Teviglio
Borgo Valsugana Gallipoli Oristano Tione di Trento
Bosa Garbagnate Milanese Osio Sotto Tivoli
Bovolone Gardone Val Trompia Ostuni Tolmezzo
Bracciano Gavardo Ozieri Torino
Brescia Gemona del Friuli Paderno Dugnano Tradate
Brindisi Genova Padova Trani
Budrio Ghilarza Palermo Trecenta
Bussolengo Gorizia Palestrina Trento
Busto Arsizio Grado Palmanova Treviso
Cagliari Gravedona Pavia Trieste
Camposampiero Iglesias Peschiera del Garda Triggiano
Canosa di Puglia Imperia Pescia Udine
Caorle Iseo Piario Valdagno
Carate Brianza Isili Pieve di Cadore Valsamoggia
Carbonia Isola della Scala Pieve di Coriano Varese
Casalmaggiore Jesolo Piove di Sacco Varzi
Casarano La Maddalena Pistoia Velletri
Caserta Lanusei Ponte San Pietro Venezia
Cassino Latina Pordenone Vergato
Castelfranco Veneto Latisana Portogruaro Verona
Castellaneta Lavagna Prato Vicenza
Castellanza Lecce Putignano Vigevano
Castiglione delle Stiviere Lecco Rho Villafranca di Verona
Cavalese Legnago Rieti Vimercate
Cerignola Legnano Roma Viterbo
Cernusco sul Naviglio Lodi Romano di Lomardia Vittorio Veneto
Chiari Lonigo Rovereto Vizzolo Predabissi
Chiavenna Lovere Rovigo Voghera
Chioggia Lucera Rozzano
Cinisello Balsamo Luino San Bonifacio

Ricordo che i riferimenti utili per consultare i dati sono i seguenti:

  • un servizio “machine readable per interrogare i dati per comune e distanza: http://www.cesaregerbino.it/OpenProntoSoccorsi/API/getProntoSoccorsoDetailsByMunicipality.php?municipality=Torino&distance=0 dove è possibile modificare il nome del comune e in cui il parametro distance indica, se valorizzato a zero, che la ricerca viene svolta per i pronto soccorsi che si trovano all’interno del territorio comunale del comune indicato, altrimenti permette di fare una ricerca nell’intorno del comune stesso, ad esempio distance=10000 indica una ricerca nell’intorno di 10 km dal comune indicato.
  • una semplice web application che, immettendo il nome del comune di interesse ed un raggio di ricerca nel suo intorno restituisce l’elenco dei pronto soccorsi con relative info sui numeri e tempi di attese per tipologia (rif. http://www.cesaregerbino.it/OpenProntoSoccorsi/WebApp/OpenProntoSoccorsiForm.php )
  • un’applicazione di web mapping che permette di visualizzare la distribuzione sul territorio italiano dei pronto soccorsi di cui si è riusciti ad individuare la pubblicazione dei dati sui numeri e tempi di attese per tipologia, e di interrogare interattivamente i dati del singolo pronto soccorso (rif. http://www.cesaregerbino.it/OpenProntoSoccorsi/WebMapping/OpenProntoSoccorsi.php )
  • un bot telegram (OpenProntoSoccorsiBot), in cui è possibile indicare il nome del comune di interesse ed un raggio di ricerca nel suo intorno e che restituisce l’elenco dei pronto soccorsi con relative info sui numeri e tempi di attese per tipologia. E’ anche possibile indicare la posizione, ed un raggio di ricerca nel suo intorno, ed ottenere il medesimo risultato: in questo caso il bot permette anche di avere l’informazione del percorso per raggiungere il pronto soccorso di interesse tra quelli proposti.

Buona consultazione !!

Quattro milioni di verbali (open …) su una mappa


Tra i vari canali social che seguo ho trovato in questi giorni questo bel riferimento, il progetto Infrazioni  ….

infrazioni

… che usando dati i open delle infrazioni stradali della città di Torino ha realizzato una bella web gis application interattiva con cui si possono visualizzare ed interrogare i dati (potete divertirvi a cercare i luoghi, e i periodi, ove si registrano il maggiore o minore numero di infrazioni per tipologia ….diciamo che chi è di Torino intuisce rapidamente la natura dei due grossi cerchi in alto a sinistra ed in basso a destra della mappa …. 🙂 ).

Al netto dell’interfaccia  (realizzata con MapBox …), che è sicuramente curata, con buone prestazioni e di facile utilizzo, il grosso valore aggiunto è il riuso di dati aperti messi a disposizione da parte di una P.A., rappresentando una bella sinergia, un approccio “win-win” che sempre di più si spera di vedere.

I dati delle infrazioni infatti sono disponibili open data sul portale degli open data del Comune di Torino (e disponibili per più anni, dal 2011 al 2015 …), ma questo non è l’unico dataset utilizzato, in quanto i dati sono stati relazionati sul territorio utilizzando i dati della toponomastica comunale, anch’essi disponibili sul medesimo portale (a tale proposito, come elemento di miglioramento, si potrebbe suggerire al Comune di Torino di integrare già dalla fonte, vale a dire dalle generazione del dato delle infrazioni, la relazione spaziale, diretta o indiretta, con ìl numero civico o l’incrocio corrispondente usando la propria toponomatica al fine di rendere  così i dati relazionati strettamente ed in modo tra loro coerente. Credo che questo avrebbe fatto risparmiare parecchio tempo ai realizzatori del progetto …. se poi proprio volessimo esagerare, avere i medesimi dati disponibili come open services …. male non farebbe …).

E’ comunque un esempio “virtuoso” di collaborazione tra P.A e “privati /cittadini” che vale la pena di segnalare ed applaudire …. bravi tutti!

OpenDistributoriCarburantiBot: risparmiare sul pieno di carburante con Telegram

28 febbraio 2016 15 commenti

In questi ultimi tempi, su più fronti si sente parlare molto spesso di Telegram, non solo e non tanto come app di messaggistica (per certi versi in alternativa o in opposizione / concorrenza a WhatsApp), quanto per la possibilità offerta di poter realizzare delle chat automatiche (denominati “bot”), il cui scopo è quello di rispondere alle nostre domande, alle nostre richieste, e facilitare in generale operazioni varie.

Si và da esempi molto semplici, piccoli giochi, sino a cose più serie ed articolate. Riporto ad esempio:

  • @webcamstravelbot che fornisce l’elenco delle webcam intorno ad un punto di interesse
  • @escilaricettaBot che permette di ricercare ricette dato un certo ingrediente di interesse
  • @emergenzeprato_bot per le segnalazioni meteo a di rischio dell’area del comune di Prato
  • @divinacommediabot che permette di ricercare versi della Divina Commedia di Dante
  • @gttorari_bot con cui la compagnia dei trasporti pubblici di Torino informa i propri utenti dei passaggi degli autobus

…. sino ad arrivare, notizia proprio degli ultimi giorni, al canale @pgpompei attraverso il quale Papa Francesco fà arrivare giornalmente il Vangelo del giorno!!! Quindi davvero dal “sacro” al “profano” …..

Non mi dilungo qui a spiegare più nel dettaglio: su internet si trovano abbondanti informazioni sia sulla piattaforma sia su cosa sono questi bot, per cui rimando a queste fonti tutti coloro che fossero interessati ad approfondire.

Più che lo strumento di messagistica in sè, con le sue dichiarate caratteristiche peculiari di maggior sicurezza e rispetto della privacy (nel bene e nel male ….), rispetto ai suoi concorrenti, mi ha incuriosito la possibilità di realizzare queste chat automatiche e quindi, volendone approfondire l’argomento, ho deciso a provare a realizzarne una.

Mi mancava un caso d’uso che non fosse un classico “Hello World!” e che, ovviamente, avesse anche una sua componente “spaziale”.

Dopo qualche riflessione ed ipotesi mi sono ricordato di un bel lavoro fatto tempo fà da Stefano Sabatini (@__sabas) sui distributori di carburanti in Italia che mi sembrava fosse adatto allo scopo: dati “reali”, dati open, liberamente utilizzabili (licenza iodl 2.0), aggiornati giornalmente, con coordinate e quindi facilmente trasformabili in un dato spaziale per poi essere utilizzabili anche con funzionalità spaziali.

E’ così che è nata l’ipotesi, pian piano concretizzatasi, di OpenDistributoriCarburantiBot.

Questo bot permette di sapere, dato un comune italiano, quali sono i distributori di carburante che vi ricadono o, data una posizione georiferita, quali sono i distributori di carburante che ricadono nel suo intorno per una certa distanza (scelta tra 500, 1000, 2000 e 3000 metri).

I dati sono aggiornati giornalmente a partire dalle 08.30 attingendo direttamente dagli open del Ministero dello Sviluppo Economico (MISE).

E’ possibile selezionare il carburante di proprio interesse ed i risultati sono ordinati sulla base del prezzo: è quindi possibile individuare quelli più convenienti per le nostre esigenze.

A seconda del tipo di ricerca effettuata, e se si è fornita o meno la posizione georiferita, è possibile:

  • visualizzare su mappa OpenStreetMap la localizzazione del distributore
  • visualizzare la descrizione del percorso per raggiungere il distributore dalla posizione corrente
  • visualizzare, su mappa 2D, il percorso per raggiungere il distributore dalla posizione corrente
  • visualizzare, su mappa 3D, il percorso per raggiungere il distributore dalla posizione corrente. Per questa ultima funzionalità è necessario disporre di un web browser di ultima generazione che supporti webGL (le ultime versioni di Mozilla Firefox e Chrome sono già abilitate)

Il suo utilizzo è molto semplice: nel seguito vi illustro una sequenza di passi per il suo utilizzo e anche una breve sessione utente registrata in video.

Occorre ovviamente avere installato Telegram sul proprio smartphone, tablet o desktop (nota: la versione desktop è un pò limitata per le funzonalità supportate, ad esempio non è possibile fornire la propria posizione, o almeno io non ci sono riuscito): fatto questo è sufficiente ricercare “OpenDistributoriCarburantiBot” come illustrato

01

All’avvio viene visualizzato un messaggio di benvenuto con una una breve sintesi sulle sue caratteristiche.

02

Occorre avviare il bot se si intende utilizzarlo

04

In qualunque momento questo messaggio è nuovamente visualizzabile scrivendo il comando /start.

Sono disponibili anche altri due comandi, rispettivamente /info (per avere informazioni di dettagli tecnico)…

05

…. e /credits (per i doverosi e necessari ringraziamenti) ….

06

E possibile scrivere il nome di un comune italiano: il nome può essere scritto minuscolo o maiuscolo in modo indifferente. Sono trattati anche nomi di comuni con spazi ed apostrofi.

07

Per i comuni il cui nome contiene lettere accentate è necessario utilizzare gli apici

08

A questo punto occorre selezionare, dal menù visualizzato, il tipo di carburante e attendere il risultato della ricerca

09

Se la ricerca produce risultati questi sono ordinati per prezzo crescente e, per ogni risultato, è possibile visualizzare su una mappa OpenStreetMap la localizzazione del relativo distributore

10

11

L’indicazione del comune non è l’unica modalità di ricerca: è infatti possibile indicare le propria posizione corrente o di interesse cliccando sull’icona della graffetta che in queste videate compare in basso a destra e poi selezionare l’opzione ‘Posizione

12

13

A questo punto è necessario selezionare, dal menù visualizzato, il raggio di ricerca

14

A questo punto occorre selezionare, dal menù visualizzato, il tipo di carburante

15

In questo caso, se la ricerca produce risultati questi sono ordinati per prezzo crescente e, per ogni risultato, è possibile:

  • visualizzare su una mappa OpenStreetMap la localizzazione del relativo distributore
  • visualizzare la descrizione del percorso per raggiungere il distributore di interesse a partire dal punto di ricerca
  • visualizzare il percorso per raggiungere il distributore di interesse a partire dal punto di ricerca su una mappa OpenStreetMap bidimensionale
  • visualizzare il percorso per raggiungere il distributore di interesse a partire dal punto di ricerca su una mappa OpenStreetMap tridimensionale (OSM Buildings)

16

17

18

19

20

Ed ecco ora in video come avviene dal vivo una sessione utente immaginandone la fruizione durante una gita nel territorio Albese:

Come detto in precedenza i dati sono giornalmente tratti direttamente dal Ministero dello Sviluppo Economico (MISE) a cui è demandato il livello di completezza e aggiornamento rispetto alle diverse realtà locali: devo dire che ho notato, almeno nelle zone che conosco, che, da quando ho iniziato a fare questo piccolo esperimento, aggiornamento e completezza sono in crescita.

Per concludere devo ringraziare tutti coloro da cui ho tratto spunti ed ispirazione, nonchè supporto diretto in varie forme, e quindi, sperando di non dimenticare nessuno direi:

  • Stefano Sabatini (@__sabas), per il suo lavoro iniziale da cui ho tratto spunto per l’idea
  • Matteo Tempestini (@il_tempe), Francesco “Piersoft” Paolicelli (@Piersoft) e Gabriele Grillo da cui ho tratto il codice inziale e per il loro supporto via mail
  • Alessandro Furieri, per il suo grandissimo lavoro su Spatialite, data base open source che ho usato come tool per memorizzare i dati georiferiti, e per il suo paziente supporto online
    Fabrizio Massara per la pazienza ed il suo supporto a 360° nonchè, per la condivisione del server su cui stà girando il codice del bot in produzione
  • mia moglie, per il tempo che le ho rubato per fare tutto ciò

Un ringraziamento particolare, perchè si è dimostrato un vero “signore” (merce rara …), lo devo a @Piersoft per la sua disponibilità a rinunciare a pubblicare un lavoro analogo in buona parte realizzato, pur di non “bruciarmi” la news ….. grazie mille!!!!

Per chi fosse interessato a maggiori dettagli tecnici per sapere “come è fatto dentro” rimando ad un altro post

A questo punto non resta quindi che iniziare a provare ad usare di OpenDistributoriCarburantiBot e vedere di iniziare a risparmiare facendo il pieno nei distributori più convenienti!

OpenDistributoriCarburantiBot: come è fatto “dentro”

28 febbraio 2016 4 commenti

In questo post vedo di fornire qualche dettaglio su quelle che sono le caratteristiche e soluzioni tecniche che stanno alla base di OpenDistributoriCarburantiBot.

Non mi dilungo qui a spiegare nel dettaglio la piattaforma Telegram e la basi dei bot: rimando coloro che fossero interessati ad approfondire ad attingere dalle innumerevoli fonti presenti in rete.

Schematicamente l’architettura della soluzione è la seguente:

OpenDistributoriCarburantiBot

Nel diagramma sono citati i vari componenti del sistema che:

Si tratta di una soluzione che utilizza tutti software open source e attinge da servizi disponibili in rete.

Per una soluzione più scalabile è possibile passare ad utilizzare POSTGRESQL con la sua estensione POSTGIS, non cambiando la logica di funzionamento.

Nel diagramma sono anche illustrati i passi delle diverse operazioni coinvolte e precisamente:

  • giornalmente il sistema scarica dal MISE (0a) i dati e li memorizza sul db (0b)
    l’utente invia una richiesta dal proprio client (1)
  • il sistema recupera le richieste con un’operazione di getUpdates (2)
  • effettua le ricerche su DB (3)
  • nell’elaborazione della risposta invoca i servizi di Google Shortlink per abbreviare le url (4)
  • con un’operazione di sendMessage risponde (5)
  • Telegram inoltra la risposta al client (6)
  • l’utente può fruire dei diversi link contenuti nella risposta (7, 7a, 7b e 7c)

Il “cuore” del sistema sono i dati: questi sono tratti giornalmente dagli open del Ministero dello Sviluppo Economico (MISE).

I dati sono forniti nella forma di due file .csv che riportano le anagrafiche dei distributori ed i prezzi dei carburanti. Tra i dati delle anagrafiche dei distributori, informazione importante, sono disponibili anche le coordinate, espresse in latitudine e longitudine.

NOTA: negli esempi si suppone che il sw sia installato in /var/www/html/Telegram per cui la variabile <base_path> = /var/www/html/Telegram

Tutte le mattine, con un crontab schedulato, i dati sono prelevati via wget,

wget -U "Opera" -O <base_path>/OpenDistributoriCarburantiBot/Dati/prezzo_alle_8.csv http://www.sviluppoeconomico.gov.it/images/exportCSV/prezzo_alle_8.csv

wget -U "Opera" -O <base_path>/OpenDistributoriCarburantiBot/Dati/anagrafica_impianti_attivi.csv http://www.sviluppoeconomico.gov.it/images/exportCSV/anagrafica_impianti_attivi.csv

Si provvede ad eliminare la prima riga dei files

sed '1d' <base_path>/OpenDistributoriCarburantiBot/Dati/anagrafica_impianti_attivi.csv > <base_path>/OpenDistributoriCarburantiBot/Dati/anagrafica-temp.csv

sed '1d' <base_path>/OpenDistributoriCarburantiBot/Dati/prezzo_alle_8.csv > <base_path>/OpenDistributoriCarburantiBot/Dati/prezzo.csv

Nel file delle anagrafiche è necessario eliminare il carattere “doppi apici” che influisce negativamente nell’import in Spatialite

sed 's/"//g' <base_path>/OpenDistributoriCarburantiBot/Dati/anagrafica-temp.csv > <base_path>/OpenDistributoriCarburantiBot/Dati/anagrafica.csv

A questo punto è possibile creare il data base Spatialite ….

/usr/local/bin/spatialite <base_path>/OpenDistributoriCarburantiBot/Dati/PrezziCarburanti < <base_path>/OpenDistributoriCarburantiBot/Dati/CreaPrezziCarburanti.txt

….. con i seguenti dettagli …

CREATE TABLE anagrafica_impianti_attivi( idImpianto TEXT,
Gestore TEXT,
Bandiera TEXT,
Tipo Impianto TEXT,
Nome Impianto TEXT,
Indirizzo TEXT,
Comune TEXT,
Provincia TEXT,
Latitudine DOUBLE,
Longitudine DOUBLE );
CREATE TABLE prezzo_alle_8( idImpianto TEXT,
descCarburante TEXT,
prezzo TEXT,
isSelf TEXT,
dtComu TEXT );
.mode csv

.separator ;

.import <BASE_PATH>/OpenDistributoriCarburantiBot/Dati/anagrafica.csv anagrafica_impianti_attivi

SELECT AddGeometryColumn('anagrafica_impianti_attivi','geometry',4326,'POINT',2); UPDATE anagrafica_impianti_attivi SET geometry = GeomFromText('POINT('||"Longitudine"||' '||"Latitudine"||')',4326);

.import <BASE_PATH>/OpenDistributoriCarburantiBot/Dati/prezzo.csv prezzo_alle_8

.quit

La logica di business è stata implementata in php sebbene questa non sia una scelta esclusiva od obbligata. E’ possibile scegliere linguaggi di programmazione diversi: nel mio caso è stata una scelta di opportunità visto che in PHP avevo la possibilità di trovare maggiore esempi e supporto.

Di potenziale interesse riporto come sono implementate le ricerche, ad esempio quella per i distributori di un comune

SELECT distr.Comune, distr.Gestore, distr.Indirizzo, distr.Bandiera, distr.Latitudine, distr.Longitudine, prz.descCarburante, prz.prezzo, prz.dtComu FROM anagrafica_impianti_attivi as distr JOIN prezzo_alle_8 as prz ON (prz.idImpianto = distr.IdImpianto) WHERE distr.Comune = :Comune ORDER BY prz.prezzo ASC

dove ovviamente il parametro :Comune sarà poi valorizzato dal nome del comune corrente indicato dall’utente.

Analogamente, una ricerca spaziale che individua i distributori di un certo carburante, nell’intorno di una certa distanza da un punto, caratterizzato da una determinata coppia di coordinate, sarà

SELECT distr.Comune, distr.Gestore, distr.Indirizzo, distr.Bandiera, distr.Latitudine, distr.Longitudine, prz.descCarburante, prz.prezzo, prz.dtComu, ST_Distance(distr.geometry, MakePoint('.$lon.', '.$lat.', 4326), 1) AS dist FROM anagrafica_impianti_attivi as distr JOIN prezzo_alle_8 as prz ON (prz.idImpianto = distr.IdImpianto) WHERE dist <= '.$dist.' AND prz.descCarburante = \''.$carburante.'\' ORDER BY prz.prezzo ASC, dist ASC

Ovviamente i risultati delle query sono poi parsificati opportunamente per andare a costruire il messaggio finale che arriverà sul dispositivo dell’utente finale.

Ecco come …..

try {
$stmt = $db->prepare($q);
$results = $stmt->execute();
$count = 0;
while (($row = $results->fetchArray(SQLITE3_ASSOC)) AND ($count < $limit_search)){
$data .= "Marca: ".$row['Bandiera'];
$data .= "\n";
$data .= "Carburante: ".$row['descCarburante'];
$data .= "\n";
$data .= "Prezzo: ".$row['prezzo'];
$data .= "\n";
$data .= "Data: ".$row['dtComu'];
$data .= "\n";

$longUrl = "http://www.openstreetmap.org/?mlat=".$row['Latitudine']."&mlon=".$row['Longitudine']."&zoom=18";
$shortUrl = CompactUrl($longUrl);
$data .= "Mappa: ".$shortUrl;
$data .= "\n";

$longUrl = $base_url."/Telegram/DistributoriCarburanti/RenderRoute.php?lat_from=".$lat."&lon_from=".$lon."&lat_to=".$row['Latitudine']."&lon_to=".$row['Longitudine']."&map_type=0";
$shortUrl = CompactUrl($longUrl);
$data .= "Descrizione Percorso: ".$shortUrl;
$data .= "\n";

$longUrl = $base_url."/Telegram/DistributoriCarburanti/RenderRoute.php?lat_from=".$lat."&lon_from=".$lon."&lat_to=".$row['Latitudine']."&lon_to=".$row['Longitudine']."&map_type=2";
$shortUrl = CompactUrl($longUrl);
$data .= "Percorso su mappa 2D: ".$shortUrl;
$data .= "\n";

$longUrl = $base_url."/Telegram/DistributoriCarburanti/RenderRoute.php?lat_from=".$lat."&lon_from=".$lon."&lat_to=".$row['Latitudine']."&lon_to=".$row['Longitudine']."&map_type=3";
$shortUrl = CompactUrl($longUrl);
$data .= "Percorso su mappa 3D: ".$shortUrl;
$data .= "\n";

$data .= "\n";
$count = $count + 1;
}
if ($count >= $limit_search){
$data .= "La ricerca ha prodotto troppi risultati !!! Si presentano solo i primi ".$limit_search.". Per maggiori dettagli provare a cambiare comune, tipo di carburante, posizione o raggio di ricerca";
$data .= "\n";
}
return $data;
}
catch(PDOException $e) {
print "Something went wrong or Connection to database failed! ".$e->getMessage();
}
}
}

I messaggi di Telegram non possono superare i 4096 caratteri e dovendo fornire le url per la visualizzazione dei dettagli del percorso o della sua rappresentazione su mappa, ho dovuto “restringere” le url stesse avvalendomi del servizio di Google URL Shortener.

Il tutto avviene invocando un’apposita funzione …

function CompactUrl($longUrl)
{
$apiKey = API;

$postData = array('longUrl' => $longUrl);
$jsonData = json_encode($postData);

$curlObj = curl_init();

curl_setopt($curlObj, CURLOPT_URL, 'https://www.googleapis.com/urlshortener/v1/url?key='.$apiKey.'&fields=id');
curl_setopt($curlObj, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curlObj, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curlObj, CURLOPT_HEADER, 0);
curl_setopt($curlObj, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
curl_setopt($curlObj, CURLOPT_POST, 1);
curl_setopt($curlObj, CURLOPT_POSTFIELDS, $jsonData);

$response = curl_exec($curlObj);

// Change the response json string to object
$json = json_decode($response);

curl_close($curlObj);
$shortLink = get_object_vars($json);

return $shortLink['id'];
}

Siccome tutte le comunicazioni sono “stateless”, mentre per alcuni passaggi necessitavo di mantenere traccia delle opzioni selezionate ai passi precedenti, ho implementato una piccola gestione di sessione sul db SQLite 3.

In questo modo aggiorno i dati quando necessario …

try {
$base_path = BASE_PATH;
//## Preparo di dati di sessione da memorizzare nel data base per il'id di chat ...
$session_data = array(
array('Chat_id' => $chat_id,
'Comune' => $comune,
'My_Lat' => $lat,
'My_Lon' => $lon,
'Search_Distance' => $search_distance
)
);
//## Accedo al db di sessione per memorizzare i dati per il'id di chat ...
$db_data_sessions = new SQLite3($base_path.'/DistributoriCarburanti/DataSessionsDB');
//## Accedo al db di sessione per eliminare i dati di sessione per di interesse per l'id di chat ...
$q="DELETE FROM data_sessions WHERE Chat_id = :Chat_id";
try {
$stmt = $db_data_sessions->prepare($q);
$stmt->bindvalue(':Chat_id', $chat_id, SQLITE3_TEXT);
$results = $stmt->execute();
}
catch(PDOException $e) {
print "Something went wrong or Connection to database failed! ".$e->getMessage();
}

//## Prepare INSERT statement to SQLite3 file db ...
$insert = "INSERT INTO data_sessions (Chat_id, Comune, My_Lat, My_Lon, Search_Distance) VALUES (:Chat_id, :Comune, :My_Lat, :My_Lon, :Search_Distance)";
$stmt = $db_data_sessions->prepare($insert);

//## Bind parameters to statement variables ...
$stmt->bindParam(':Chat_id', $Chat_id);
$stmt->bindParam(':Comune', $Comune);
$stmt->bindParam(':My_Lat', $My_Lat);
$stmt->bindParam(':My_Lon', $My_Lon);
$stmt->bindParam(':Search_Distance', $Search_Distance);

//## Loop thru all messages and execute prepared insert statement ...
foreach ($session_data as $data) {
//## Set values to bound variables ...
$Chat_id = $data['Chat_id'];
$Comune = $data['Comune'];
$My_Lat = $data['My_Lat'];
$My_Lon = $data['My_Lon'];
$Search_Distance = $data['Search_Distance'];

//## Execute statement ...
$stmt->execute();

$db_data_sessions = null;
}

}
catch(PDOException $e) {
print "Something went wrong or Connection to database failed! ".$e->getMessage();
}

ed in questo modo recupero i dati quando necessario ….

$db_data_sessions = new SQLite3($base_path.’/DistributoriCarburanti/DataSessionsDB’);
$q="SELECT ds.Chat_id, ds.Comune, ds.My_Lat, ds.My_Lon, ds.Search_Distance
FROM data_sessions as ds
WHERE ds.Chat_id = :Chat_id";
try {
$stmt = $db_data_sessions->prepare($q);
$stmt->bindvalue(':Chat_id', $chat_id, SQLITE3_TEXT);
$results = $stmt->execute();
while ($row = $results->fetchArray(SQLITE3_ASSOC)){
$comune = $row['Comune'];
$my_lat = $row['My_Lat'];
$my_lon = $row['My_Lon'];
$search_distance = $row['Search_Distance'];
}
}
catch(PDOException $e) {
print "Something went wrong or Connection to database failed! ".$e->getMessage();
}

Per il calcolo dei percorsi utilizzo il servizio di routing di MapQuest (rif. https://developer.mapquest.com/products/directions): tale servizio, gratuito sino a 15.000 chiamate al giorno (non credo di superare tali limite …. ne sarei piacevolmente stupito ….), si basa sui dati di OpenStreetMap e permette di ritornare sia la semplice descrizione testuale del percorso, sia i suoi dettagli geografici in formato JSON.

Ecco un esempio di chiamata ….

http://www.mapquestapi.com/directions/v2/route?key=YOUR_KEY_HERE&from=Lancaster,PA&to=York,PA&callback=renderNarrative

Il richiamo del servizio avviene via CURL

$url = 'http://open.mapquestapi.com/directions/v2/route?key=&outFormat=json&routeType=fastest&timeType=1&narrativeType=html&enhancedNarrative=true&shapeFormat=raw&generalize=0&locale=it_IT&unit=k&from='.$lat_from.','.$lon_from.'&to='.$lat_to.','.$lon_to.'&drivingStyle=2&highwayEfficiency=21.0';

//#Set CURL parameters
$ch = curl_init();
curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_PROXY, '');
$data = curl_exec($ch);
curl_close($ch);

//#Convert to string (json) the route ...
$json = json_decode($data);

ed ecco come aggiungere il json del percorso sulla mappa Leaflet …..

var json_route = <?php echo json_encode($json); ?>;

//# Calculate the new map center based on the route bounding box ...
lng_ul = json_route.route.boundingBox.ul.lng;
lat_ul = json_route.route.boundingBox.ul.lat;
lng_lr = json_route.route.boundingBox.lr.lng;
lat_lr = json_route.route.boundingBox.lr.lat;
lng_center = (lng_lr - lng_ul)/2 + lng_ul;
lat_center = (lat_ul - lat_lr)/2 + lat_lr;


var map = L.map('map').setView([lat_center, lng_center], 15);

L.tileLayer('https://api.tiles.mapbox.com/v4/{id}
/{z}/{x}/{y}.png?access_token=’, {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: 'mapbox.light'
}).addTo(map);


the_coords = '';

for (i = 0; i < json_route.route.shape.shapePoints.length;
i++) {

if (i == 0) {
the_coords = the_coords + '[' + json_route.route.shape.shapePoints[i+1] + ',' + json_route.route.shape.shapePoints[i] + ']';
}
else {
if ((i % 2) == 0) {
the_coords = the_coords + ',[' + json_route.route.shape.shapePoints[i+1] + ',' + json_route.route.shape.shapePoints[i] + ']';
}
}
}

//# Create the lineString json (text) of the route ...
var my_lineString = '{\"type\": \"Feature\", \"properties\": {
}, \”geometry\”: {\”type\”: \”LineString\”, \”coordinates\”: [‘ + the_coords + ‘]}}’;

//# Create le lineString json (object) of the route ...
var lineString = JSON.parse(my_lineString);

//# add the lineString json (object) of the route to the map ...
L.geoJson(lineString).addTo(map);

Per la rappresentazione su mappa 3D l’approccio è del tutto analogo, con una unica eccezione: non essendo possibile sovrapporre alla mappa OSM Buildings un oggetto Linestring il percorso viene trasformato in un oggetto poligonale calcolandone un piccolo buffer di 1 metro. Il calcolo del buffer avviene avvalendosi della libreria Turf.js (rif. http://turfjs.org/).

Ecco come avviene il tutto ….

//# Extract the route coordinates ...
the_coords = '';

for (i = 0; i < json_route.route.shape.shapePoints.length; i++) {
if (i == 0) {
the_coords = the_coords + '[' + json_route.route.shape.shapePoints[i+1] + ',' + json_route.route.shape.shapePoints[i] + ']';
}
else {
if ((i % 2) == 0) {
the_coords = the_coords + ',[' + json_route.route.shape.shapePoints[i+1] + ',' + json_route.route.shape.shapePoints[i] + ']';
}
}
}

//# Create the lineString json (text) of the route ...
var my_lineString = '{\”type\”: \”Feature\”, \”properties\”: {}, \”geometry\”: {\”type\”: \”LineString\”, \”coordinates\”: [‘ + the_coords + ‘]}}’;

//# Create le lineString json (object) of the route ...
var lineString = JSON.parse(my_lineString);

//# Set the unit measure and calculate the buffer using Turf.js ....
var unit = 'meters';
var buffered = turf.buffer(lineString, 1, unit);
var result = turf.featurecollection([buffered]);

//# Convert to string the buffered json ....
var my_json = JSON.parse(JSON.stringify(result));

//# Create an empty Polygon json to put in OSM Building map ....
var geojson_route = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: {
color: '#FF0080',
roofColor: '#ff99cc',
height: 0,
minHeight: 0
},
geometry: {
type: 'Polygon',
coordinates: [
[
]
]
}
}]
};

//# Add the coordinates at the Polygon json bringing them from the buffered json ....
for (var i = 0; i < my_json.features[0].features[0].geometry.coordinates[0].length; i++) {
geojson_route.features[0].geometry.coordinates[0][i] = my_json.features[0].features[0].geometry.coordinates[0][i];
}

//# Add the Polygon json to the map ....
osmb.addGeoJSON(geojson_route);

//# Refresh of the map to show the labels ...
map.setPosition(map.getPosition());

Ovviamente per maggiori dettagli mi potete contattare direttamente.

Numeri civici Open Data in Italia: disponibile la release 3.0 della raccolta

27 settembre 2015 17 commenti

A febbraio 2015 ho pubblicato la seconda versione della raccolta di quelli che sono i numeri civici georiferiti open data disponibili nel panorama italiano.

E’ giunta quindi l’ora di un ulteriore aggiornamento, per cui ora è rendo disponibile la release 3.0 della raccolta stessa.

La raccolta è resa disponibile con licenza CC0 1.0 Universal: ovviamente per i singoli dataset restano valide le licenze originali che sono riportate nella raccolta stessa.

Con questo aggiornamento siamo arrivati a 188 dataset diversi : ci sono aree ancora completamente vuote, intere regioni in cui mancano dati, regioni per cui vi sono dati ridondanti, ecc … ma i numeri stanno crescendo

Ecco quali sono “release notes” di questa versione della raccolta:

  • verificati, per tutti i dataset già esistenti, i link di pubblicazione e download: nel tempo alcuni erano stati cambiati dagli Enti
  • verificate tutte le licenze d’uso: anche qui vi sono casi in cui le licenze sono state modificate
  • aggiunti nuovi dataset, in particolare:
    • Comune di Storo
    • Provincia Autonoma di Bolzano
    • Regione Piemonte
    • Regione Lombardia

La percentuale dei numeri civici resi disponibili come tali, e non “derivati” da altri tematismi,  sale dal 10% al 25 % sul totale delle informazioni raccolte e quindi un buon risultato in termini di crescita  (la prima versione vedeva una percentuale del 5%)

DistribuzioneCivici-V03

Come consueto i dati sono consultabili via web grazie ad un piccolo esempio in web mapping basato su HTML, Javascript e Leaflet.

CiviciItalia2

I dati sono anche resi consultabili, da un punto di vista geografico, usando il software open source QGIS:

A differenza delle versioni precedenti della raccolta, viste le dimensioni raggiunte, non mi è più stato possibile rendere disponibile anche i dati in formato ESRI shapefile insieme al progetto QGIS di consultazione. Resta comunque possibile, per chi interessato, poter scaricare i singoli dataset in formato ESRI shapefile e convertiti un WGS84 utilizzando i link di download resi disponibili all’interno del file della raccolta stessa

Ricordo una breve nota tecnica: per rendere operativo lo sfondo OpenStreetMap è necessario che, qualora si operi su una rete locale, si verifichi la corretta configurazione del proxy, e che, nel QGIS utilizzato, sia presente ed attivo il plugin OpenLayers.

I progetti QGIS sono stati realizzati con la versione 2.6.1 (Brigthon).

Segnalazioni di dati mancanti per aggiornare la raccolta sono particolarmente gradite …. grazie sin da ora!

Numeri civici Open Data in Italia: disponibile la release 2.0 della raccolta

4 febbraio 2015 10 commenti

A settembre 2014 ho pubblicato la prima versione della raccolta di quelli che sono i numeri civici georiferiti open data disponibili nel panorama italiano, ripromettendomi di rilasciare un aggiornamento ogni trimestre.

Un po’ in ritardo rispetto alle previsioni ma riesco a mantenere ora la promessa e quindi ecco pronta la release 2.0 della raccolta stessa (il totale di ciò che ho raccolto è reso liberamente disponibile nel rispetto delle licenze d’suo dei dati originali).

Quali sono le aggiunte? Non moltissime in termini di numero di Enti ma direi, discrete in termini di volumi di civici georiferiti aggiunti in quanto vanno ad aggiungersi ben 4 Regioni che hanno reso open data questo livello informativo.

L’elenco completo delle aggiunte di questa release è il seguente:

  • Comune di Rovereto
  • Comune di Verona
  • Regione Toscana
  • Regione Umbria
  • Regione Sicilia
  • Comune di Modena
  • Regione Sardegna
  • Comune di Verona
  • Comune di Biella
  • Provincia di Biella

Alcune di queste fonti informative sono già state oggetto di import nella base dati di OSM (Comune di Biella), per altre (Regione Sardegna), l’attività è, ad oggi, in corso e altre lo potrebbero diventare a seconda della compatibilità della licenza d’uso.

La percentuale dei numeri civici sale dal 5% al 10 % sul totale delle informazioni raccolte e quindi un buon risultato in termini di crescita.

TortaCivici2

I dati sono consultabili via web grazie ad un piccolo esempio in web mapping basato su HTML, Javascript e Leaflet.

DettaglioMappa

Analogamente alla release 1.0 tutti i dati sono anche resi consultabili, da un punto di vista geografico, usando il software open source QGIS, in due modalità:

Ricordo una breve nota tecnica: per rendere operativo lo sfondo OpenStreetMap è necessario che, qualora si operi su una rete locale, si verifichi la corretta configurazione del proxy, e che, nel QGIS utilizzato, sia presente ed attivo il plugin OpenLayers.

I progetti QGIS sono stati realizzati con la versione 2.6.1 (Brigthon).

La mappa nazionale inizia a riempirsi di pallini colorati come vedete sotto, anche se ci sono ancora parecchi buchi e regioni in cui, per il momento, non sono riuscito a rintracciare nulla per cui chiedo, a chiunque interessato, di farmi avere riferimenti utili così che possano essere inclusi nei successivi rilasci.

CiviciItalia2

Una nota doverosa, relativamente a questa release, sono i ringraziamenti a coloro che, in varia forma, mi hanno dato una mano con i loro contributi quindi procedo:

  • Giovanni Allegri (@_giohappy_), per i dati di Regione Toscana
  • Maurizio Napolitano (@napo), per i dati di Regione Umbria
  • Andrea Borruso (@aborruso), per l’ispirazione metodologica che ho utilizzato per i dati di Regione Sicilia
  • Francesco Fiermonte (@ffierm), per il tempo speso a farmi da “tester”

In conclusione una riflessione: questo lavoro mi costa fatica, tempo da dedicarci, ecc …., quindi ci tengo ma al tempo stesso sarei lieto di chiuderlo, definitivamente, nel momento in cui vi fosse la disponibilità dei civici georiferiti open data per come prevista nell’elenco dell’Agenda Digitale 2014: purtroppo al momento le date indicate sono state, più o meno ampiamente, disattese, …… ma resto fiducioso …… 🙂

 

Open data e Open service basati su standard: come ottenere lo shapefile dei Numeri Civici Open Data della Regione Sicilia partendo dai servizi resi disponibili


Tutto è nato da una mail di Andrea Borruso, apparsa sulla lista GFOSS proprio alla vigilia di Natale, in cui si annunciava, da parte della Regione Sicilia e per una serie di comuni, la disponibilità, in modalità WFS, di un dataset dei numeri civici georiferiti.

I servizi sono fruibili direttamente da client diversi, desktop, web, mobile, ecc …. che ovviamente supportino lo standard OGC WFS,  cosa oramai ampiamente diffusa, piuttosto facile da fare e alla portata di un’utenza, seppur tecnica, piuttosto ampia.

Con una chiamata standard è anche possibile avere l’elenco dei comuni per cui sono disponibili i dati dei numeri civici: la chiamata è la seguente:

ogrinfo -ro wfs:"http://map.sitr.regione.sicilia.it/ArcGIS/services/CART_2000/Numeri_Civici/GeoDataServer/WFSServer"

Bello ma, per il mio interesse cioè quello di raccogliere i civici open data disponibili sul panorama nazionale, mancava una visione di insieme che mi fornisse TUTTI i civici a livello regionale.

Ma, essendo tutto basato  su standard, si trattava solo di avere un po di voglia e tempo per fare un interessante (??? 🙂 ) esercizio informatico e “rinfrescare” alcune conoscenze messe un po’ da parte negli ultimi tempi.

Provo a riassumere quanto fatto, primo per mie note personali, ma anche perchè credo / spero possa interessare a chi voglia /debba poter replicare un’esigenza analoga.

Premetto che quello indicato NON è l’unico modo possibile per raggiungere l’obiettivo, ve ne possono essere diversi altri, anche più “eleganti”.

In tutto è organizzato in 3 passi logici.

Step 1: scaricare i dati collegandosi ai servizi

Nota organizzativa: gli eseguibili shell che illustro nel seguito operano nel rispetto di questa organizzazione su file system:

OrganizzazioneCartelle

I servizi sono esposti in WFS e quindi possono essere contattati via chiamata http ottendo in risposta, tra le altre cose, il dato in formato GML.

Purtroppo gli attuali servizi non permettono di ottenere i dati in formati diversi.

In questo caso, essendo 376 i comuni da scaricare, e quindi le chiamate da fare, ho creato un piccolo eseguibile shell, lanciabile da linea di comando, che, usando il comando CURL disponibile in ambiente Linux e/o Windows a seconda delle installazioni (nel mio caso ho utilizzato CygWin …), scaricherà, completamente, tutti i singoli GML, uno per ogni comune.

La chiamata, per un singolo comune è la seguente …

curl "http://map.sitr.regione.sicilia.it/ArcGIS/services/CART_2000/Numeri_Civici/GeoDataServer/WFSServer?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=CART_2000:NumeriCivici_81008_Erice&SRSNAME=EPSG:4326" -o CiviciComuniSicilia/GML/81008_Erice_4326.gml

Visto che i comuni erano molti ho realizzato un programmino shell, denominato DownloadCiviciByCurl.sh, reso parametrico ….

echo "Download civici $1 ......"
curl "http://map.sitr.regione.sicilia.it/ArcGIS/services/CART_2000/Numeri_Civici/GeoDataServer/WFSServer?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=CART_2000:NumeriCivici_$1&SRSNAME=EPSG:4326" -o CiviciComuniSicilia/GML/$1_4326.gml
echo "Sleeping for 30 sec: don't load too much the server ...."
sleep 30

il quale è poi richiamabile da un programmino di lancio denominato LauncherDownloadCiviciByCurl.sh

echo "Starting download civici Sicilia ......"
sleep 5
./DownloadCiviciByCurl.sh 81008_Erice
./DownloadCiviciByCurl.sh 83040_Limina
./DownloadCiviciByCurl.sh 87001_Aci_Bonaccorsi
......
......

da completare con l’elenco dei comuni ricavato dall’istruzione ogrinfo mostrata in precedenza.

I files .sh sono mantenuti nella cartella “Work”.

Ecco uno snapshot dell’esecuzione di questo primo passo …

DownloadCiviciSicilia

Step 2: convertire i dati in formato ESRI shapefile

Il mio obiettivo finale era quello di avere un unico file con tutti gli indirizzi georiferiti disponibili per la Regione Sicilia, e quindi dovevo in un qualche modo unire tra loro, geograficamente, i singoli files GML scaricati.

L’aggregazione geografica di più files GML non sembra sia possibile (dopo una veloce ricerca sul web …), e quindi ho deciso di convertire ogni singolo file GML in uno shapefile per poi unificali tra loro in uno step successivo.

Per eseguire l’operazione di cui sopra ovviamente il tool che meglio si adatta sono ancora le librerie GDAL con il seguente comando ogr2ogr

ogr2ogr -f "ESRI Shapefile" 81008_Erice_4326 CiviciComuniSicilia/GML/81008_Erice_4326.gml

Nel preparare questa trasformazione mi sono accorto che lo shapefile prodotto risultava privo del file di proiezione (.prj), e quindi, con una seconda operazione ogr2ogr ho provveduto ad aggiungere allo shapefile prodotto, il file .prj relativo al sistema di riferimento che volevo utilizzare (EPSG: 4326)

ogr2ogr -a_srs EPSG:4326 CiviciComuniSicilia/Shapefile/NumeriCivici_81008_Erice.shp 81008_Erice_4326/NumeriCivici_81008_Erice.shp

Anche in questo caso  ho poi realizzato un programmino shell, denominato ConvertShapefile.sh, reso parametrico ….

echo Convert $1 civici GML into ESRI shapefile .....
ogr2ogr -f "ESRI Shapefile" $1_4326 CiviciComuniSicilia/GML/$1_4326.gml
echo Adding .prj to $1 civici shapefile .....
ogr2ogr -a_srs EPSG:4326 CiviciComuniSicilia/Shapefile/NumeriCivici_%1.shp $1_4326/NumeriCivici_$1.shp
echo Delete temporary files .....
rm -R $1_4326

il quale è poi richiamabile da un programmino di lancio denominato LauncherConvertShapefile.sh …

echo "Starting converting civici Sicilia in shapefiles ......"
./ConvertShapefile.bat 81008_Erice
./ConvertShapefile.bat 83040_Limina
./ConvertShapefile.bat 87001_Aci_Bonaccorsi
......
......

I files .sh sono mantenuti nella cartella “Work”.

Ecco lo snapshot dell’esecuzione di questo secondo passo …

ConvertShapefile

Step 3: creare un unico shapefile di dati

A questo punto non restava che “fondere” insieme i vari shapefile dei singoli comuni in un unico shapefile a livello regionale.

Anche qui viene in aiuto la libreria GDAL con le ogr2ogr che permettono di effettuare questa operazione eseguendo un semplice ciclo: anche in questo caso ho racchiuso il tutto in un programmino shell che ho nominato UnionShapefileComuni.sh

#!/bin/bash
for f in `ls *.shp`
do
echo "Append shapefile " $f " ....."
ogr2ogr -update -append civici_sicilia.shp $f -f "ESRI Shapefile" -nln civici_sicilia
done

Il file .sh è mantenuto nella cartella “Shapefile”.

Ecco uno snapshot dell’esecuzione di questo terzo passo …

Append

Ed ecco che il gioco è fatto, replicabile e, volendo,  completamente automatizzabile mettendo i vari passi in un unico shell.

Il risultato è il seguente:

Sicilia1

Sicilia2

L’intero dataset è scaricabile e disponibile nel rispetto delle licenze originali dei dati di partenza (CC-BY SA).

Come detto in precedenza quello descritto non è l’unico metodo ma ve ne possono essere molti altri, anche più eleganti: ne cito uno, illustrato da Andrea Borruso, che mi sembra di particolare interesse e che si basa sul fatto che i servizi della Regione Sicilia sono contattabili anche via REST, e quindi, partedo da questo,  si potrebbe replicare l’esperienza fatta da Maurizio Napolitano nel caso di Regione Umbria.

Un primo utilizzo delle informazioni che ho aggreato? Per visualizzare i dati delle mia raccolta degli indirizzi georiferiti open data in Italia (di cui stò preparando la nuova release … stay tuned!!!): portando i dati su un db POSTGIS e poi usando TileMill ho prodotto i tiles che permettono di visualizzare rapidamente l’intero dataset insieme a tutti gli altri raccolti a livello nazionale.

Spero che queste info possano essere utili.