Archivio

Archive for the ‘Web Mapping’ Category

(Più) Open data e (meno) dashboard al tempo del COVID

4 maggio 2020 7 commenti

Da quando è diffusa a livello mondiale la pandemia COVID sono sorte innumerevoli dashboard (con mappa o meno …), utilizzate per comunicare le informazioni e i dati della diffusione del contagio.

A questi strumenti, sicuramente utili e più o meno graficamente gradevoli e/o semplici da usare, non ha fatto seguito, in parallelo, la pubblicazione dei “dati” su cui queste si basano utilizzando una modalità aperta ed interoperabile , basandosi su standard e formati di interoperabilità internazionali ed utilizzando licenze d’uso dei dati (e dei servizi) adeguate.

Ma l’importanza di avere questi dati disponibili, e quindi di “liberarli” per garantire innanzi tutto, da un lato, la massima trasparenza e dall’altro per permettere analisi, approfondimenti e ausilio “data-driven” alle decisioni, è quanto mai impostante: cito alcuni riferimenti:

Su questo fronte, almeno a livello del panorama nazionale, si è in forte carenza e ritardo (tranne alcuni esempi / best practise più felici …).

Anzi in alcuni casi, pur a fronte di richieste della società civile fatte alle diverse Pubbliche Amministrazioni, pur seguendo le regole correnti, c’è stata una forte chiusura arrivando a sospendere il FOIA (esempio https://www.infodata.ilsole24ore.com/2020/03/30/sta-andando-lepidemnia-del-coronavirus-piemonte/)

Tralasciando e non entrando  nelle ragioni “politiche” di questi approcci (che sono out-of-scope del post …), e tornando all’aspetto più “tecnico” …….. ci sono esempi virtuosi, tool e soluzioni, standard che possono essere utilizzati per raggiungere, e bene, l’obiettivo? Provo a portare qualche contributo sperando che sia (ancora), utile.

 

Dipartimento Protezione Civile

Sicuramente i punto di partenza può essere il repository GitHub del Dipartimento della Protezione Civile dedicato al COVID in Italia che è disponibile al seguente url:

https://github.com/pcm-dpc/COVID-19

in cui sono raccolti e forniti, con aggiornamento giornaliero, i dati relativi all’andamento nazionale espressi per Regioni e Province.

I dati sono disponibili con licenza CC-BY-4.0 – Visualizza licenza

La struttura in cui sono raccolti i dati è la seguente:

Tali dati sono resi, ad oggi, disponibili in formato CSV ai seguenti riferimenti:

Sembra esserci una iniziativa (non ancora disponibile …), per pubblicare questi stessi dati anche come API Rest (Json) e GraphQL  (rif. https://github.com/pcm-dpc/COVID-19/commit/c5cfabe8b8b666b93ed6b6ae3103f76e93bda3ca), il che sarebbe sicuramente un gran passo in avanti per l’interoperabilità ed il riuso.

Il dipartimento della Protezione Civile pubblica anche una dashboard che è consultabile qui:

 

Il repository del Dipartimento della Protezione Civile si presenta quindi in sintesi come un importante fonte di dati.

La grossa carenza, ed è un vero peccato, è la mancanza di dati ed informazioni a livello comunale.

 

Regioni

Sul fronte pubblicazione dati le Regioni si stanno muovendo in ordine sparso e disomogeneo.

Regione Lombardia pubblica una dashboard

https://experience.arcgis.com/experience/0a5dfcc103d0468bbb6b14e713ec1e30/

Al momento NON ci sono i dati su base comunale ma c’è stato un momento in cui questi dati erano disponibili come si vede dallo snapshot sotto

e grazie ad una sorta di “data leak” del servizio (accedendo a questi servizi, https://services1.arcgis.com/XannvQVnsM1hoZyv/ArcGIS/rest/services/TA_COVID19_RL/FeatureServer che ora sono stati resi non fruibili ….), i dati sono stati scaricati e sono ancora disponibili qui https://github.com/ondata/covid19italia/blob/master/webservices/regioneLombardia/processing/TA_COVID19_RL.csv e sono stati utilizzati per analisi e report giornalistici come questo https://www.giornaledibrescia.it/storie/coronavirus-il-punto/covid-19-il-profilo-dei-contagiati-bresciani-comune-per-comune-1.3474449

I dati della Lombardia non sono comunque ad oggi disponibili al dettaglio comunale ed in modalità open e interoperabile o machine-learning.

Anche Regione Piemonte pubblica la sua dashboard su mappa

https://www.regione.piemonte.it/web/covid-19-mappa-piemonte

tramite la quale è possibile interrogare i singoli comuni per avere l’informazione di quanti positivi al COVID sono presenti sul territorio comunale.

Anche qui c’è un caso curioso che è quello relativo la fatto che la mappa nella sua versione iniziale, al lancio del servizio, riportasse l’andamento dei contagi per comune, informazione che è poi sparita nelle versioni successive del servizio.

Anche i dati del Piemonte non sono comunque ad oggi disponibili al dettaglio comunale ed in modalità open e interoperabile o machine-learning.

Regione Lazio pubblica la sua dashboard su mappa

https://www.dep.lazio.it/covid/covid_map.php

dove anch’essa permette di interrogare i singoli comuni per avere l’informazione di quanti positivi al COVID sono presenti sul territorio comunale.

Anche i dati del Lazio non sono comunque ad oggi disponibili al dettaglio comunale ed in modalità open e interoperabile o machine-learning, sebbene sia possibile provare ad estrarre i dati in formato CSV, seppur in modo non documentato, con una modalità descritta qui https://github.com/ondata/covid19italia/blob/master/webservices/regioneLazio/README.md

Regione Friuli Venezia Giulia pubblica anch’essa la sua dashboard su mappa

https://covid19map.protezionecivile.fvg.it/

dove è possibile interrogare i singoli comuni per avere l’informazione di quanti positivi al COVID sono presenti sul territorio comunale.

A differenza delle precedenti regioni analizzate, il Friuli Venezia Giulia permette di scaricare i dati in formato CSV: non parliamo ancora di interoperabilità ma è già un passo avanti rispetto alla trasparenza e alla condivisione dei dati.

Come ultimo caso possiamo vedere la Regione Umbria che pubblica anch’essa la sua dashboard su mappa

https://coronavirus.regione.umbria.it/

 

 

Dalla dashboard è anche possibile filtrare per singolo comune e visualizzare, oltre ai dati numerici, anche l’andamento rispetto ad alcuni fattori, come pure fare filtri per data

A differenza delle altre regioni, ed è l’unico caso riscontrato sinora, pubblica anche in open data sul proprio portale degli open data le API di accesso ai dati stessi

https://apistore.regione.umbria.it/store/apis/info?name=COVID-19&version=1.0.0&provider=admin&tag=Agenda%20digitale-group

Quello dell’Umbria è quindi il primo caso, ed unico sinora, di esempio virtuoso di condivisione in modo aperto ed interoperabile dei dati legati alla pandemia di COVID che ho riscontrato sul piano nazionale

Per avere il quadro della situazione nell’insieme delle diverse Regioni italiane, si può fare riferimento ad un articolo (in continuo aggiornamento …), de Il Sole 24 Ore reperibile al seguente indirizzo https://www.infodata.ilsole24ore.com/2020/05/09/dati-coronavirus-regione-va-conto-suo-aiutateci-mappare-condivide-cosa-aggiornato/

 

Società civile ?

Cosa stanno facendo società civile e le comunità attive sul fronte degli open data su questo argomento?

Cito alcune iniziative, non così note ai più ma che necessitano di adeguato risalto.

All’inizio dell’epidemia quando ancora i dati non circolavano e ci si limitava a pubblicare, in modo non ancora strutturato i dati in forma aggregata tipicamente col slide o al più files in formato PDF (!!!!!),  l’associazione OnData (rif. https://ondata.it/), ha provveduto a raccogliere su un repository pubblico (rif. https://github.com/ondata/covid19italia), i dati pubblicati sul sito della Protezione Civile per renderli disponibili in formato machine-readable.

Questa iniziativa, insieme ad una pressione sui social per avere queste informazioni disponibili pubblicamente (rif. http://blog.ondata.it/coronavirus-abbiamo-trasformato-i-dati-ufficiali-in-formato-machine-readable-ma-chiediamo-alle-istituzioni-di-farlo-da-sole/), ha “spinto” il Dipartimento della Protezione Civile, all’apertura del repository GitHub del Dipartimento della Protezione Civile (rif. http://www.protezionecivile.gov.it/media-comunicazione/comunicati-stampa/dettaglio/-/asset_publisher/default/content/coronavirus-da-oggi-on-line-la-mappa-dei-contagi-in-italia), descritto all’inizio del post

 

Sul tale repository, alla data di questo post, i dati, sebbene pubblicati NON sono ancora fruibili in termini di API (sebbene questo sia  stato annunciato .. vedi quanto detto sopra …), e anche qui la società civile si è comunque già mossa in quest’ottica e ha provveduto, da fine marzo, a renderli fruibili in modalità JSON a questo indirizzo

https://openpuglia.org/content/i-dati-ufficiali-sullepidemia-covid-19-attraverso-api-openpuglia

  • Dati Regionali

E’ possibile ottenere gli ultimi dati relativi ad una singola regione attraverso il seguente endpoint:

https://openpuglia.org/api/?q=getdatapccovid-19&reg=puglia

dove reg=nomeregione

Per ottenere la serie storica dei dati giornalieri disponibili, va aggiunto mode=ts 

https://openpuglia.org/api/?q=getdatapccovid-19&reg=puglia&mode=ts

I dati di tutte le regioni possono essere ottenuti omettendo il parametro reg come in questo caso

https://openpuglia.org/api/?q=getdatapccovid-19

  • Dati Nazionali

Per ottenere l’ultimo dato nazionale disponibile:

https://openpuglia.org/api/?q=getsummarydatacovid-19&lang=it

Mentre per ottenere la serie storica, anche in questo caso va aggiunto mode=ts

https://openpuglia.org/api/?q=getsummarydatacovid-19&mode=ts&lang=it

La comunità OpenDataSicilia ha raccolto qui https://opendatasicilia.github.io/COVID-19_Sicilia/ alcune visualizzazioni di base sulla COVID-19 per la Sicilia, mettendo insieme  i dati dei comunicati stampa della Regione Siciliana (dopo averli trasformati in tabella CSV), ed i dati già machine readable pubblicati dal Dipartimento della Protezione Civile.

Il risultato di questo lavoro è consultabile nelle seguenti modalità:

Infine, la stessa associazione OnData insieme a insieme a Transparency International Italia, Scienzainrete.it, The Good Lobby Italia, Cittadini Reattivi  … hanno scritto una lettere aperta (rif.  http://blog.ondata.it/covid-19-lettera-aperta-ai-presidenti-di-regione/), ai Presidenti delle Regioni italiane in cui si richiede di rendere aperti i dati relativi al COVID in loro possesso.

 

Standard ?

Abbiamo visto che sia il Dipartimento della Protezione Civile sia le Regioni adottano modalità diverse per la pubblicazione dei dati, tipicamente, tranne il caso di Regione Umbria che ha delle API pubbliche di consultazione dei dati, tramite delle dashboard.

Nasce quindi i problema di come mettere insieme queste informazioni per una visione complessiva.

Esistono a tal proposito degli standard a cui provare ad attenersi per descrivere in modo completo e condiviso questi dati?

La risposta è SI …..  ad esempio:

  • standard JSON based
    •  CovidJSON (rif https://covidjson.org/)
      • un geoJson data model per lo scambio di informazioni che si basa sui concetti dello standard OGC/ISO Observations & measurements Standard (OGC O&MISO 19156
      • è stato creato per raccogliere e scambiare dati sull’infezione SARS-CoV-2 ma è sufficientemente generale per applicarsi anche ad altre tipologie di infezione
    • The COVID Tracking Project propone, sullo scenario statunitense, questo https://covidtracking.com/api
  • standard ontologie

 

Dashboard open source ?

Anche su fronte dashboard esiste una forte eterogeneità: ogni Regione si è mossa in autonomia e questo ha voluto dire sforzi (e costi …), paralleli per ottenere risultati “funzionalmente” ampiamente sovrapposti. Forse una maggiore sinergia avrebbe permesso di unire le forze e ridurre i costi sostenuti nell’insieme.

Esistono dashboard open source da cui attingere? Anche qui la risposta è SI !!

La più interessante, per una serie di ragioni che riporto tra breve è la seguente (rif. https://www.geosolutionsgroup.com/blog/health-sdi-covid-map/)

Le ragioni per cui la segnalo sono le seguenti:

  • si basa su un concetto di Health Spatial Data Infrastructure di cui esiste un recente white paper Health Spatial Data Infrastructure: Application Areas, Recommendations, and Architecture  dell’Open Geospatial Consortium (OGC)
    • l’avere un “catalogo” dati e una “infrastruttura” è condizione fondamentale
    • …..  What is critical from the workflow is the catalog, which is the heart of an SDI. If you don’t know what data is available you can’t put it together in a fast manner and it requires phone calls, emails, searching, scraping websites, etc., wasting precious time ….”
    • …. Organizations harvesting information from different sources to create dashboards mostly rely on personal communications and getting the data from official web reports available at government/intergovernmental websites. Then, they create “machine readable formats” such as JSON or CSV that are ingested in the web clients. The “manual process” of getting the data requires a lot of human power, and fortunately for this crisis there are a lot of people willing to help. This is not the ideal. Government and other official sources should be making data available via open standards following the recommendation in the report…..
  • NON costruisce questo catalogo ma si basa su:
  • il client NON ha un suo database ma si basa solo ed esclusivamente sull’utilizzo delle API
    • questo permette di installarlo anche su un qualunque cloud provider
  • è rilasciato in modalità open source con licenza BSD
  • è anche un pò italiano e ciò, a maggior ragione in questo momento, non guasta!

In conclusione …. più dati, più standard, più interoperabilità e meno dashboard!!!!

P.S

Segnalazioni di altre realtà / esempi virtuosi sono ben accette e provvederò ad integrarle nel post

 

 

Street Image Compare: how to compare Google Street View and Mapillary in the same web page

7 agosto 2017 6 commenti

If you ask to a crowd of people if they use Google Street View, probably you’ll have a positive answer.

If you ask, to the same crowd of people if they use Mapillary, probably the positive answers will be much less.

Despite the fact Mapillary, with lower means and possibilities, is proposed as a “crowd” alternative to the BigG service, its diffusion is not yet widespread, although there are places on the Earth whose geo referred images are available on Mapillary platform and are not available on Google Street platform.

The question is: is it possible to know, for a specific place, if geo referred images are available in one of these platforms or in both and, in that case, compare them?

I became aware about this problem after seeing an email in an Italian forum on Geographic Free and Open Source software (Gfoss.it); I’ve searched on the web but not successful.

So, starting from the OSM Map Compare idea, I’ve decide to build something by myself and in this way Street Image Compare was created.

The application is very simple to use: for the same place you can compare Google Street View and Mapillary images (if they are both available) and “surf” on the streets having Google Maps and OpenStreetMap as reference.

The user can select the place in three different ways:

  • typing the place name
  • typing an address
  • typing the coordinates couple

The application use Google Maps geocoder as geocoding engine.

When you open the app on the web page with the two maps, Google Street View and Mapillary, you can navigate on the images using the little arrows that are shown on the images: on the maps you’ll see a marker that show your current position.

On the both maps, and using the right buttons, is also possible to click on a specific point where you want to positionate yourself.

It’s quite easy to show the availability of Google Street View images (you can move the pegman on the map and immediately are shown some blue lines that show where the Google Street View images are present or not …) ….

…. for Mapillary is available a button “ON/OFF Mapillary sequences” on OpenStreetMap that draws some blue lines which show where the Mapillary images are present or not.

So, now with Street Image Compare you can compare Google Street View and Mapillary for every place in the world !!!

Here you’re a user session little video

 

On a technical point of view these are the data / services used:

Beyond the mere comparison between two similar services (or, in any case with strong analogies …), that could be a coding exercise the application has some pratical use.

The pictures above are about Amatrice in Italy where last year, on August 24, 2016, there was a great earthquake: in this case you can compare places before and after the earthquake because after this event someone has captured and published the images on Mapillary platform.

You can move along Amatrice streets and the effect in really shocking !!

Starting from this example you can understand as, in case of natural events with big impacts, Mapillary, for its “crowd” nature, can be useful to capture images after the events and with Street Image Compare, you can immediately compare places before and after event. Very useful!

The application code is open source, available on GitHub, with MIT license.

Here you have some examples:

Note: thanks to Mariana Cristina Da Silva for the help on this post! 🙂

Street Image Compare: confrontare Google Street View e Mapillary nella stessa pagina web

6 agosto 2017 4 commenti

Se ad una platea di persone si chiedesse di alzare la mano a chi conosce Google Street View, e lo abbia usato almeno una volta, sicuramente si noterebbero moltissime mani alzate.

Se, alla stessa platea, si chiedesse di alzare la mano a chi conosce Mapillary, e lo abbia usato almeno una volta, le mani alzate sarebbero sicuramente molte di meno.

Nonostante Mapillary si ponga, pur con mezzi e possibilità inferiori, come alternativa “crowd” al servizio di BigG, la sua diffusione non è ancora infatti così ampia e capillare sebbene vi siano
zone della Terra le cui immmagini georiferite risultano essere state catturate e disponibili sulla piattaforma offerta da Mapillary e non su quella offerta da Google Street View.

Ma …… esiste la possibilità di sapere se, per una determinata zona, entrambe le piattaforme, o una sola di loro, dispone di immagini e, nel caso, di poterle confrontare ?

Mi sono posto questa domanda dopo aver visto una mail, sulla lista di GFOSS.it: ho cercato sulla rete e non ho trovato nulla adatto allo scopo (sebbene se la cosa mi paresse strana … ).

Sfruttando l’idea di OSM Map Compare, ho deciso di provare a farlo io e da questa idea è nato Street Image Compare.

L’applicazione dovrebbe piuttosto semplice ed intuitiva: permette di confrontare, per la medesima zona, le immagini (se disponibili …), sia di Google Street View sia di Mapillary e, di navigare i percorsi avendo come riferimenti territoriali sia la mappa di Google Maps sia la mappa di OpenStreetMap.

L’utente può selezionare, a partire da una semplice pagina web, l’area di interesse in tre diverse modalità:

  • scrivendo il nome di una località
  • scrivendo un indirizzo
  • scrivendo una coppia di coordinate

Per la geocodifica è utilizzato il geocoder di Google Maps.

Una volta ottenuta la pagina web con le due mappe, Google Street View e Mapillary, l’utente può navigare le immagini usando le frecce che trova disponibili sulle immagini stesse: sulle mappe saranno riportati i marker che indicano la corrispondente posizione corrente sul territorio.

E’ anche possibile, su entrambe le mappe e con appositi bottoni, cliccare in un punto per posizionarsi direttamente in una zone ben precisa.

Mentre è piuttosto facile individuare la disponibilità su mappa di Google Street View (basta spostare l'”omino” sulla mappa e appaiono delle righe blu che evidenziano dove è presente o meno Google Street View … ), ….

…. per Mapillary è disponibile un apposito bottone “ON/OFF Mapillary sequences” che permette di evidenziare sulla mappa Open Street Map dove Mapillary sia presente o meno.

Quindi ora con Street Image Compare, per ogni posto del mondo, è possibile confrontare Google Street View e Mapillary!!

E’ comunque disponibile un filmato di una sessione si utilizzo

 

Da un punto di vista tecnico i dati e servizi utilizzati sono:

Dalla mail citata in precedenza, che ha dato origine all’idea, e come evidenziato dalle immagini sopra riportate, emerge un utilizzo pratico dello strumento che và al di là del mero confronto tra due servizi analoghi o comunque con forti analogie (che di per sè potrebbe essere un esercizio informatico più o meno interessante ….): sfruttando il fatto che in aree quali quelle colpite dell’evento del terremoto del 24/08/2017 in centro Italia, a ridosso dell’evento, sono state catturate delle immagini con Mapillary, è quindi possibile utilizzare Street Image Compare per un confronto che illustra con “crudezza” la potenza distruttiva dell’evento naturale.

E’ possibile spostarsi lungo le strade e poter vedere le medesime zone prima e dopo l’evento e l’effetto è di sicuro impattante.

Partendo da questo esempio già in essere si comprende come, in caso di eventi naturali che abbiano grossi impatti sul territorio, Mapillary, proprio per la sua natura “crowd”, possa essere utilizzato da attori diversi sia “istituzionali” sia abitanti gli stessi dei luoghi interessati per raccogliere le immagini post evento per poi, con uno strumento come Street Image Compare, avere immediatamente disponibile un confronto delle zone pre e post evento.

Mapillary, tra l’altro, permette anche di poter “filtrare” le immagini per data di rilevamento: questa funzionalità NON è presente nell’attuale versione di Street Image Compare ma, una volta implementata, potrebbe permettere, eseguendo opportune campagne di “rilevamento” di avere un monitoraggio attivo e pubblico dell’evolversi delle attività di ricostruzione.

Il codice dell’applicazione è liberamente disponibile con licenza MIT.

Ecco alcuni riferimenti di interesse:

 

Realizzare automaticamente storytelling usando Mapillary? Ci si può provare …

2 ottobre 2016 4 commenti

Mapillary è un servizio per condividere foto georeferenziate sviluppato da una startup, con sede a Malmö, Svezia. I suoi ideatori vogliono rappresentare il mondo intero (non solo le strade) con delle foto. Ritengono che per coprire tutti i posti interessanti nel mondo siano necessari un progetto crowd-sourced indipendente e un approccio sistematico alla copertura di aree interessanti.

Si pongono quindi, fatte le debite proporzioni, in alternativa a Google Street View.

Contribuire è facilissimo: chiunque può scaricare l’app di Mapillary sul proprio smartphone / tablet ed iniziare a scattare foto muovendosi a piedi, in bici o in auto, effettuare poi l’upload sulla piattaforma, e dopo pochissimo tempo rendere disponibile il frutto del proprio “lavoro” al resto della community di Mapillary.

Tempo fa ho usato questo approccio per mappare l’intero mio comune.

Di chi sono le immagini caricate sul sistema e come si possono usare? Le immagini su Mapillary possono essere usate da chiunque secondo la licenza internazionale Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA).

Un permesso speciale è concesso per derivare dati dalle foto per contribuire ad OpenStreetMap.

Le tracce GPX possono essere usate senza restrizioni.

Sino a non molti mesi fà queste immagini erano consultabili solo attraverso il sito di Mapillary: interessante ma un po’ “chiusa” come possibilità.

A Febbraio 2016 però Mapillary se n’è uscita con Mapillary JS,  che è quanto segue (citando esattamente quanto pubblicato … )

“…MapillaryJS is a tool used for displaying street level photos anywhere on the internet. Today we are putting it into your hands. It enables you to add street level photos to your blog, website or even into your professional mapping applications. …”

E’ quindi ora possibile utilizzare le immagini di Mapillary all’interno di una qualunque applicazione web usando un’interfaccia Javascript che ne facilità la fruizione.

Tra gli esempi forniti con Mapillary JS, ha colpito la mia curiosità quello relativo allo storytelling.

Da qui ho iniziato a pensare se fosse possibile, per produrre il codice della pagina di esempio, automatizzare le scelta delle immagini e delle relative sequenze partendo da un percorso che l’utente poteva disegnare su una mappa.

Il risultato ora c’è ed è … SAMBA !!!  (il nome deriva dall’influenza del periodo olimpico che ha coinciso con lo sviluppo dell’applicativo??? 🙂 ….  comunque l’acronimo stà per Storytelling Author Mapillary BAsed).

samba

L’applicativo permette di scegliere una qualunque area del mondo, per nome o indirizzo, visualizzare su una mappa quelle che sono le tracce delle sequenze di immagini di Mapillary che sono disponibili per quell’area e, sulla base di queste, interattivamente, di impostare quelli che sono i punti di interesse per cui si vuole che il nostro percorso passi (sino ad un massimo di 25 punti …. ).

L’applicativo calcolerà il percorso ed individuerà quelle che sono le immagini di Mapillary più vicine ai punti del percorso stesso (nel verso della percorrenza … ), e proverà a proporre una prima versione dello storytelling di cui l’utente può fare il preview in una sorta di “filmato”.

Se il preview è giudicato soddisfacente l’utente può scaricare il codice sorgente HTML / Javascript per una sua esecuzione autonoma o per poter essere incluso nella pagina web del proprio sito.

Qualora nel preview vi siano immagini non corrette o che generano problemi nell’esecuzione del “filmato” stesso (situazione piuttosto comune …), o qualora l’utente desideri inserire dei piccoli commenti testuali in corrispondenza di alcune delle immagini, è possibile effettuare un raffinamento, deselezionando le immagini da escludere dalla restituzione e/o editando il testo.

Nuovamente sarà possibile effettuare un preview e/o scaricare il codice sorgente HTML / Javascript: il processo di raffinamento può essere eseguito più volte sino ad arrivare alla configurazione di gradimento.

Ogni passo è corredato da un help ed un filmato di esempio di utilizzo.

Riporto qui i filmati per completezza di informazione (nel loro insieme rappresentano una sessione di utilizzo completa).

Step 1

Step 2

Step 3

Step 4

Step 5

I vincoli per l’utilizzo sono i seguenti:

  • utilizzo di un browser di recente generazione e che supporti WebGL: l’applicazione è stata testata su Chrome e Firefox
  • numero massimo punti per il calcolo percorso: 25
  • non si possono usare lettere o caratteri speciali nel testo descrittivo che viene aggiunto all’immagine. Non è possibile usare tag HTML (es. per mettere link)

L’applicazione non è fruibile da smartphone / tablet in quanto risulta comunque difficoltosa l’interazione sulla mappa nel momento in cui si disegnano i punti di interesse o, peggio ancora quando li si desidera riposizionare / trascinare sulla mappa stessa.

Sono comunque fruibili da smartphone / tablet gli storytelling generati.

Esistono problemi noti, che sono:

  • il servizio di routing di MapBox ha un piccolo bug per cui, a volte, non riporta nel percorso l’ultimo punto (destinazione). Ho cercato di aprire una richiesta su StackExchange,  ma ad oggi non ho ancora avuto risposte, nemmeno da MapBox stessa. Il bug non è comunque bloccante anche se fastidioso

Ecco alcuni esempi di storytelling prodotti con SAMBA:

Il codice dell’applicazione e’ disponibile su GitHub con licenza Licenza MIT Copyright (c) [2014].

Ora non vi resta che provare … enjoy!

 

Storytelling Author Mapillary BAsed (SAMBA): come è fatto “dentro”


In questo post vedo di fornire qualche dettaglio su quelle che sono le caratteristiche e soluzioni tecniche che stanno alla base di SAMBA, Storytelling Author Mapillary BAsed.

Schematicamente l’architettura della soluzione è la seguente:

architecture

L’applicazione è una tipica web mapping application realizzata in HTML / Javascript avvalendosi di una componente PHP 5 ospitata su web server Apache.

Per implementare le sue funzionalità utilizza una serie di librerie Javascript e di alcuni servizi e precisamente:

  • mapbox-gl-draw.js: fornisce il supporto per disegnare ed editare features su mappe basate su MapBox GL JS
  • Mapillary API: le API di accesso alle immagini e sequenze di Mapillary
  • MapBox Directions API: le API MapBox per il calcolo dei percorsi
  • MapBox GL Geocoder: il Geocoder per mappe basate su MapBox GL JS
  • Turf.JS: libreria Javascript realizzata da MapBox per il calcolo di funzioni geospaziali direttamente sul browser
  • il servizio (vector tiles), delle sequenze di Mapillary  pubblkicato su http://d25uarhxywzl1j.cloudfront.net/v0.1/{z}/{x}/{y}.mvt

Il codice dell’applicazione e’ disponibile su GitHub con licenza Licenza MIT Copyright (c) [2014].

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.

Test automation su web gis application “OpenLayers based” usando Selenium Web Driver


Per ragioni lavorative mi sono occupato di valutare l’utilizzo della suite Selenium HQ per il test automation di web application.

Tale suite risulta essere uno dei principali prodotti open source di test automation per web application: sostanzialmente è caratterizzato da due tool, Selenium IDE e Selenium Web Driver (ve ne sono poi altri due, Selenium Grid e Selenium Remote Control che non ho analizzato).

Selenium IDE è un plugin per Firefox (non esiste omologo per altri browser), che permette di catturare una sessione utente di una web application (comprese le azioni di imputazione di dati ….), produrre automaticamente uno script che può poi essere rieseguito come tale o modificato.

Il tool è adatto per test semplici (sostanzialmente adatto per l’entry level …), non richiede alcuna conoscenza tecnica pregressa (sebbene un profilo tecnico, tipo programmatore, probabilmente riesce ad ottenere il meglio dallo strumento ….), ed è molto facile da utilizzare: ha tuttavia dei limiti che, anche con le personalizzazioni degli script ottenuti automaticamente, difficilmente possono essere superati.

La maggior parte della comunità che utilizza la suite Selenium utilizza per i propri scopi Selenium Web Driver.

Selenium Web Driver permette di creare delle vere e proprie suite di test programmando i test cases nei principali linguaggi di programmazione (Java, Ruby, Python, ecc …): nel mio caso ho utilizzato Java ma questa non è la scelta esclusiva anche se è quella per cui forse si trovano maggiori esempi, documentazione e supporto.

Sostanzialmente Web Driver “emula” una sessione browser ma lo fà server-side.

La sua installazione (è necessario usare Eclipse …), è molto semplice e ben documentata (nel senso adatta anche a chi non ha grosse conoscenza tecniche, si tratta di un tutorial veramente descritto “passo – passo” ….), sul sito di Selenium o in vari altri blog.

A differenza di Selenium IDE è quindi rivolto ad una utenza decisamente più tecnica, diciamo figure professionali con profili da programmatore (e la cosa si evidenzia andando a vedere il supporto che si ottiene on-line sui vari StackExchange, StackOverflow, ecc …, nel senso che chi risponde sono tutte figure di questo genere, lo si intende dal livello di risposte fornite).

Fatta questa esperienza professionale ho deciso di provare a vedere come il tool si comportava con web gis application che sono tipicamente caratterizzate da un abbondante uso di librerie javascript, anche “verticali” quali OpenLayers o Leaflet, e un livello di interattività (intendo quello sulla mappa ….), decisamente superiore ad una tipica web application gestionale.

Ho quindi provato a vedere cosa succedeva ad utilizzare Web Driver inizialmente con alcuni degli esempi consultabili sul sito di OpenLayers 2.13, ed infine con una web gis application “vera” Java based ed utilizzante OpenLayers ed ExtJS (non ho provato per ragioni di tempo con Leaflet ma credo che, rispetto alle conclusioni che se ne possono trarre, la cosa sia piuttosto invariante).

I .jar che vi potete scaricare dovrebbero essere eseguibili direttamente dando il seguente comando:

java -jar <nome_esempio>.jar

e richiedono come minimo la jdk 1.6.

Vi condivido comunque il codice sorgente in modo che, chi interessato, una volta installato e configurato Eclipse con le diverse librerie che servono per Web Driver (per l’installazione e configurazione vi rimando alla documentazione ufficiale …).

In merito al codice sorgente solo una nota: il codice è puramente a scopo didattico e pensato per poter essere compilato ed eseguito nel maggior numero di situazioni, non và preso come codice di “produzione”, per cui i “puristi” o i programmatori veri (cosa che io oramai non sono più ….), non me ne vogliano per le diverse System.out che troveranno nel codice, sò da me che avrei dovuto usare, come deve essere fatto correttamente, Log4J e compilare di conseguenza, ma lascio il tutto a coloro che vorranno poi scrivere dei test cases veri.

Altra cosa è che i test case NON analizzano come trattare eventuali situazioni di errore: il loro focus è provare se si riesce a simulare una sessione utente che comprenda le principali interazioni con la mappa. Trattandosi di test case realizzati in modalità “programmatica” la gestione dell’errore viene lasciata alla modalità organizzativa ritenuta più efficace dall’organizzazione: raccogliere i dati su un database, scatenare eventi, inviare messaggi, tracciare su file di log, ecc … Ovviamente tutto questo era, al momento, out-of-scope di queste prove.

Vediamo allora il primo test case sull’esempio base di OpenLayers effettuando uno zoom in interattivo sulla mappa

Il codice sorgente che implementa questo test è il seguente:

package myTests;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.firefox.internal.ProfilesIni;
import org.openqa.selenium.interactions.Actions;

public class interactiveZoomInOpenLayerstest_01 {

private static WebDriver driver = null;

public static void main(String[] args) throws InterruptedException {

//Create a new profile and load my Firefox default profile
System.out.println("Creo un nuovo profilo e vi carico il profilo di default di Firefox ...");
Thread.sleep(3000L);
ProfilesIni profile = new ProfilesIni();
FirefoxProfile ffProfile = profile.getProfile("default");

// Create a new instance of the Firefox driver using my new Firefox profile
System.out.println("Creo una nuova sessione del browser Firefox ...");
Thread.sleep(3000L);
driver = new FirefoxDriver(ffProfile);

//Put a Implicit wait, this means that any search for elements on the page could take the time the implicit wait is set for before throwing exception
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

// It is always advisable to Maximize the window before performing DragNDrop action
System.out.println("Massimizzo la finestra del browser ...");
Thread.sleep(3000L);
driver.manage().window().maximize();

//Launch the OpenLayers 2.x sample
System.out.println("Mi collego all'esempio di OpenLayers 2.x ...");
Thread.sleep(3000L);
driver.get("http://dev.openlayers.org/releases/OpenLayers-2.13.1/examples/example.html");

// Find the viewport inside in witch there is the map
System.out.println("Individuo il viewport al cui interno c'è la mappa ...");
Thread.sleep(3000L);
WebElement el = driver.findElement(By.id("OpenLayers_Map_2_OpenLayers_ViewPort"));

// Create a new Action instance
System.out.println("Creo un oggetto di tipo \"Action\" ...");
Actions act = new Actions(driver);

// Moves to 2nd location
System.out.println("Moves to 1st location: 200, 50 ...");
Thread.sleep(3000L);

// Draw rectangle and execute zoom in
System.out.println("Moves to 1st location: 300, 150 ...");
act.moveToElement(el,200,50).click().keyDown(Keys.SHIFT).clickAndHold().moveToElement(el, 300, 150).click().release().keyUp(Keys.SHIFT).build().perform();

// Print TEST = OK!!
System.out.println("TEST = OK !!");
//driver.quit();

}

}

Il codice sorgente è liberamente scaricabile.

E’ possibile anche scaricare lo zip dell’eseguibile Java: una volta decompresso posizionarsi in

InterActiveZoomInTest\InterActiveZoomIn\jar

e poi riprodurlo in locale con il seguente comando

java -jar InterActiveZoomIn.jar

Vediamo ora il  secondo test case sull’esempio del calcolo della misura di un’area disegnata interattivamente di OpenLayers

Per brevità non si riporta il codice sorgente che comunque liberamente scaricabile.

E’ possibile anche scaricare lo zip dell’eseguibile Java: una volta decompresso posizionarsi in

MeasureAreaOpenTest\MeasureAreaOpenLayers\jar

e poi riprodurlo in locale con il seguente comando

java -jar MeasureAreaOpenLayers.jar

Vediamo ora il  terzo test case sull’esempio di OpenLayers dell’interrogazione interattiva di un marker presente sulla mappa

Per brevità non si riporta il codice sorgente che comunque liberamente scaricabile.

E’ possibile anche scaricare lo zip dell’eseguibile Java: una volta decompresso posizionarsi in

IdentifyOpenLayersTest\IdentifyOpenLayers\jar

e poi riprodurlo in locale con il seguente comando

java -jar IdentifyOpenLayers.jar

Vediamo ora il quarto test case sull’esempio di OpenLayers dell’interrogazione interattiva di geometrie di un servizio WMS presente sulla mappa

Per brevità non si riporta il codice sorgente che comunque liberamente scaricabile.

E’ possibile anche scaricare lo zip dell’eseguibile Java: una volta decompresso posizionarsi in

GetFeatureInfoWMSTest\GetFeatureInfoWMSTest\jar

e poi riprodurlo in locale con il seguente comando

java -jar GetFeatureInfoWMSTest.jar

Vediamo ora il  quinto test case sull’esempio di OpenLayers dell’editing interattivo su mappa 

Per brevità non si riporta il codice sorgente che comunque liberamente scaricabile.

E’ possibile anche scaricare lo zip dell’eseguibile Java: una volta decompresso posizionarsi in

EditingOpenLayersTest\EditingOpenLayers\jar

e poi riprodurlo in locale con il seguente comando

java -jar EditingOpenLayers.jar

Ma il tutto è applicabile anche a progetti reali? La risposta è sì: ho provato a costruire una navigazione interattiva su un progetto di web mapping reale di Regione Piemonte ad accesso libero realizzato con MapStore (prodotto open source realizzato partendo da GeoExplorer e quindi basato su ExtJS e OpenLayers).

Per brevità non si riporta il codice sorgente che comunque liberamente scaricabile.

E’ possibile anche scaricare lo zip dell’eseguibile Java: una volta decompresso posizionarsi in

AeraTest\AeraProject\jar

e poi riprodurlo in locale con il seguente comando

java -jar AeraProject.jar

Occorre precisare che la realizzazione di test suite richiede l’impegno di risorse con un profilo tecnico (programmatori) medio-alto, e non è banale per cui anche i tempi di realizzazione non sono bassi: non è quindi ammortizzabile, in termini di costi, per progetti “piccoli”, mentre per progetti medio – grandi, in particolare se critici o sensibili per aspetti diversi, sicuramente, una volta redatti ed automatizzati i test, si ha la possibilità di eseguirli automaticamente in tempi molto rapidi e tutte le volte he lo si ritiene necessario.

Essendo in questo caso le suite di test “codice”, le si possono (anzi le si devono ….), trattare come tali e quindi possono (devono), essere mantenuti su repository da cui, con tools di software automation, agganciare a processi di building automatici che permettano di eseguire i test automaticamente ad ogni rilascio significativo del codice di business dell’applicazione.

Non occorre però scordare due aspetti fondamentale che esulano dall’automazione: il codice delle suite di test deve essere manutenuto allo stesso modo del codice di business applicativo e, altro aspetto fondamentale, anche la base dati su cui si eseguono i test deve essere mantenuta (o replicata), coerente.

Concludendo quindi si può dire che per l’automazione di test di web mapping application si possono usare senza problemi i medesimi tools che si utilizzano per le web application gestionale e che quindi, in questo caso …. “spatial is not special” !!!

GeoNews 29/01/2014


GeoNews di personale interesse apparse in questi giorni:

  • L’Ordinance Survey ipotizza di usare dati di OpenStreetMap nei suoi prodotti futuri? (fonte @oobr)

OrdinanceSurvey-OSM

  • OpenStreetMap riporta già gli impianti olimpici di Sochi 2014 … gli “altri” no … 🙂 (fonte @_alastair)

Sochi

  • Gereida è una città in Sudan che si trova solo su OpenStreetMap ! (fonte @1jour1carte)

Gereida

  • Il governo statunitense ha lanciato il progetto MapGive un sito per promuovere l’uso di OpenStreetMap facendo leva sull’importanza di dati accurati ed aggiornati in caso di necessità umanitarie di emergenza (fonte Gfoss Mailing List – Maurizio Napolitano)
  • Routing: un’altra soluzione open source java based che permette di calcolare percorsi usando coem dati quelli di OpenStreetMap: GraphHopper ! (fonte Gfoss Mailing List – Maurizio Napolitano)