Jorge Aguilera
Jorge Aguilera | |
@jagedn | Groovy developer |
Speaker MadridGuG, Codemotion | Tutorial Asciidoctor (Amazon) |
Anteriormente una empresa de servicios
Actualmente "marca personal"
Charla práctica, nada académica
Catálogo de datos abiertos de Madrid y otros
Aplicaciones OpenSource, NO comerciales
Sin coste económico (o mínimo) pero con mucho tiempo invertido
Tal vez sean "inspiradoras"
https://puravida-software.gitlab.io/main/opendatamadrid.html
(Basada en Codemotion 2019 https://www.youtube.com/watch?v=7kDOjtZa7lg)
Poquito de teoría
Planteamiento
Catálogo de datos de Madrid (y otros)
Casos de uso
Publicar en canales
Bots
Little Data
Las 5 estrellas de Tim Berners-Lee
Mi planteamiento:
usar OpenSource en la medida de lo posible
consumir OpenData
publicar OpenSource
Mensaje diario a un canal de Telegram, Twitter, Mastodon, etc
Catálogo de datos
Carreras urbanas https://datos.madrid.es/egob/catalogo/300302-10875226-carreras-urbanas.xlsx
Eventos bibliotecas https://datos.madrid.es/egob/catalogo/206717-0-agenda-eventos-bibliotecas.json
Versos al paso https://versosalpaso.madrid.es/ (CSV https://github.com/jagedn/versosalpaso.madrid.es.csv)
Calidad del aire https://aqicn.org/city/madrid/
Usando el scheduler pipeline de Gitlab ejecutamos diariamente un build que envía a los canales los diferentes eventos
Demo
String text = "https://raw.githubusercontent.com/jagedn/versosalpaso.madrid.es.csv/master/versosalpaso.csv".toURL().text
String line = text.split('\n')[ Calendar.instance[Calendar.DAY_OF_YEAR] ]
String[] fields = line.split('\\|',-1)
new File("build/versos_telegram.txt").text = """\"${fields[5]}\"
-${fields[3]}
${fields[6]} ${fields[4]}
#VersosAlPaso #Madrid
https://versosalpaso.madrid.es
"""
xlsx.bytes = 'https://datos.madrid.es/egob/catalogo/300302-10875226-carreras-urbanas.xlsx'.toURL().bytes
Workbook workbook = WorkbookFactory.create(xlsx)
workbook.sheetIterator().each{ sheet ->
sheet.rowIterator().each{ row ->
Cell when = row.getCell(0)
if( when.cellTypeEnum == CellType.NUMERIC ){
eventos.add when:when.dateCellValue.format( 'dd/MM/yyyy' ),
duration: duration.days,
title: row.getCell(2),
distance: row.getCell(3),
where: row.getCell(4)
}
....
Plugin Gradle para enviar mensajes vía Telegram, Twitter, Slack y Mastodon
Páginas web,
Una aplicación para móvil
o algo más molón, un bot de Telegram (especial para backends sin habilidades en el diseño web)
Poder ejecutar código bajo demanda (servidor java, node, serverless, etc) (un http endpoint)
Responder de forma inmediata (un ACK, luego se puede mantener la conversación)
Bot en sí no requiere recursos excesivos. Dependerá de la funcionalidad (obvio)
Heroku, GoogleCloud, Okteto, Netlify
Bot de Telegram
recibe peticiones de calles y devuelve un gif animado con las últimas cámaras
Groovy (java) corriendo en capa gratuita Okteto
catálogo de datos
Namespace gml = new Namespace("http://www.opengis.net/gml", 'gml')
Namespace cite = new Namespace("http://www.opengeospatial.net/cite", 'cite')
String xml = barcelonaUrl.toURL().text
def kml = new XmlParser().parseText(xml)
kml[gml.featureMember].eachWithIndex{ f, idx->
String nombre = f[cite.cameres][cite.carretera].text()
camaras.add new Camara(ciudad: 'barcelona',
id: idx,
nombre: nombre,
url: f[cite.cameres][cite.link].text()
}
Librería Java disponible en Maven Central
https://mvnrepository.com/artifact/com.puravida.gif/gif-generator
Bot de Telegram para conocer el precio de la gasolinera más cercana
Puedes guardar tu favorita y recibir aviso si cambia el precio
Groovy (java) corriendo en capa gratuita de Okteto
Catálogo de datos minetur.gob.es
Sin base de datos
usa un sistema de ficheros persistente para mantener sesion y preferencias (anonimizado)
Un pipeline diario revisa cambio de precios y notifica
url = "https://sedeaplicaciones.minetur.gob.es/ServiciosRESTCarburantes/PreciosCarburantes/EstacionesTerrestres/"
String xml = new InputStreamReader(url.toURL().openStream(), 'UTF-8').text
new XmlParser().parseText(xml).ListaEESSPrecio.EESSPrecio.each { eess ->
estaciones.add new Estacion(
id : node.IDEESS.text(),
direccion : node.Dirección.text() ?: "",
marca : node.Rótulo.text() ?: "",
latitude: node.Latitud.text().replace(',', '.') as float,
longitude: node.Longitud.text().replace(',', '.') as float,
gasolina95 : stringToPrice(node.PrecioGasolina95Protección.text()),
...)
}
float metersTo(float lat1, float lng1, float lat2, float lng2) {
double radioTierra = 6371;
double dLat = Math.toRadians(lat2 - lat1);
double dLng = Math.toRadians(lng2 - lng1);
double sindLat = Math.sin(dLat / 2);
double sindLng = Math.sin(dLng / 2);
double va1 = Math.pow(sindLat, 2) + Math.pow(sindLng, 2) * Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
double va2 = 2 * Math.atan2(Math.sqrt(va1), Math.sqrt(1 - va1));
double meters = radioTierra * va2;
meters as float;
}
Copiado por la cara: https://jambrocio.blogspot.com/2017/02/distancia-entre-dos-puntos-geo.html
@Client('https://api.telegram.org')
interface TelegramClient {
@Post('/bot${telegram.token}/sendMessage')
Single<Message> sendMessage(@Body Message message)
@Post(value='/bot${telegram.token}/sendPhoto', produces = MediaType.MULTIPART_FORM_DATA)
Single<Message> sendPhoto(@Body MultipartBody photo)
@Post(value='/bot${telegram.token}/sendAnimation', produces = MediaType.MULTIPART_FORM_DATA)
Single<Message> sendAnimation(@Body MultipartBody animation)
@Get(value='/bot${telegram.token}/sendLocation')
Single<Message> sendLocation(@QueryValue("chat_id") String chat_id,
@QueryValue("latitude") float latitude,
@QueryValue("longitude") float longitude)
}
Compartir en el canal los libros más leídos en las Bibliotecas de Madrid del mes anterior
Reto: parsear cada mes un CSV con 200K líneas y buscar los TOP en pocos minutos
Solución (entre muchas): usar una bbdd Derby embebida
Plugin Gradle para tratar CSV "pesados" y extraer información mediante SQL
Recolectando en un BigQuery los prestamos desde 2014 para ofrecerlos como dataset publico (en pausa por el COVID19)
Infinidad de datos ahí fuera
OpenData NO es solo tratar ingentes cantidades de datos
Múltiples formas de interactuar
Oportunidad de aprender
Coste "cero" (económico)
Contact | Feedback |
---|---|
@jagedn | |