Hablando del tiempo… (OpenWeatherMap) 1/2
Hace unos días pensaba en un tema para una nueva entrada del blog.
No tenía ideas, así que como solemos hacer aquí cuando no tenemos de qué hablar, se me ocurrió “hablar del tiempo”… (gracias a Javi desde aquí, que me fue realmente el que me puso en la pista del tema ;-) ).
Pues ya está, decidido, hablemos del tiempo.
Tenía en mente escribir sobre algunas de las novedades de las últimas versiones de RAD Studio y utilizaremos el tema para realizar algunas pruebas y demostrar cómo funcionan. Para ellos y para hablar del tiempo, vamos a utilizar en la entrada OpenWeatherMap.
Contenido
¿Qué es OpenWeatherMap?
Según la web se describe como, “un servicio que provee de datos del tiempo de más de 200.000 ciudades y de todas las ubicaciones geográficas que se encuentra disponible en la web OpenWeatherMap.org y también a través de API. La idea del servicio está inspirada en OpenStreetMap y Wikipedia que ofrecen la información gratuita y disponible para todo el mundo.”
APY Key
OpenWeatherMap es un servicuio gratuito y para poder trabajar con él, deberemos crear una cuenta y así acceder a una API Key, que es obligatoria a la hora de realizar peticiones a la web.
Para esta entrada y los ejemplos de código he dado de alta una cuenta gratuíta y he obtenido la siguiente API Key:
278857e8dee51f914026df21d0d40c19
_________________________________________________________________
NOTA (21/01/2021): Algún usuario del blog ha utilizado esta clave, en lugar de para hacer pruebas, para otros temas, de manera que desde la página de OpenWeatherMap me han informado de un tráfico excesivamente alto y de que se bloqueará esta APIKey cuando lo exceda. Siento que para los que accedéis al blog esta deje de funcionar (a ratos). Si queréis hacer pruebas debréis crear vuestra propia clave.
Desgraciadamente a veces intento facilitar las cosas a los que accedéis a estas entradas, pero hay quien prefiere no seguir las reglas y usar el camino fácil.
_________________________________________________________________
AVISO: Para seguir esta entrada y probar los ejemplos, podéis usar esta clave, pero si váis a programar aplicaciones o vuestros propios ejemplos, os aconsejo que déis de alta vuestra propia cuenta y obtengáis vuestra clave, pues en cualquier momento ésta puede dejar de estar activa.
La explicación completa de cómo utilizar el valor de la «API KEY» lo tenéis en este link.
Acceso a la API
Toda la documentación de la API de OpenWeatherMap está disponible en esta dirección. Muy clara y muy bien documentada y con multitud de ejemplos que muestran cómo se comporta.
Todas o casi todas las opciones y consultas que podamos necesitar están disponibles y la cantidad de datos y detalles acerca del tiempo que podemos obtener es bastante grande.
Podemos consultar en tiempo en una ciudad o ubicación en este preciso momento, a partir de bastantes datos, pero también predicciones futuras a intervalos de horas o días. Es muy sencillo conocer, por ejemplo, el tiempo que nos espera en los próximos 7 días o la cantidad de precipitaciones o temperatura que hará en las próximas horas.
Los datos que se proporcionan incluyen diversidad de parámetros (a parte de los básicos), como pueden ser todos los referentes a lluvias, viento, nubes, nieve,…
Un ejemplo…
Podemos ver el funcionamiento con un ejemplo sencillo.
Una llamada como lo que os muestro a continuación:
Nos devolverá (según los parámetros indicados), el tiempo actual en Barcelona (ES), con los mensajes en castellano (lang=es) y en unidades del sistema métrico (units=metric –la alternativa es el Imprerial utilizado en Estados Unidos principalmente). Por defecto, como no hemos expresado nada, se devolverá en formato JSON, aunque también se puede pedir la respuesta en XML.
(acceder a la respuesta como texto)
Aquí podemos ver el resultado de esta consulta.
Las unidades en que están expresados los datos, así como el formato de cada uno de ellos, podéis consultarlo en la Referencia a la API, de la que ya hemos hablado antes.
Obtener tiempo en una ciudad
Podemos obtener el tiempo actual en una ciudad de una forma similar a la que hemos visto en el ejemplo anterior. También hay otras opciones (interesantes para dispositivos móviles) como por ejemplo, obtener el tiempo en un lugar determinado a partir de las coordenadas GPS.
De esta forma, si obtenemos las coordenadas desde nuestro dispositivo, podemos realizar una llamada similar a esta:
En este caso la llamada se hace utilizando los valores GPS (lat=41.390&lon=2.154) y en la propia respuesta (en la parte final) podemos ver la ciudad/país a la que pertenecen dichas coordenadas.
…
«sys»: {
«message»: 0.0027,
«country»: «ES»,
«sunrise»: 1446531928,
«sunset»: 1446569027
},
«id»: 3128760,
«name»: «Barcelona»,
«cod»: 200
}
Ahora de lo que se trata, es de plasmar esto en una aplicación.
Vamos a empezar de menos a más, así que la primera versión que vamos a ver está compilada con Delphi 7 (sí Delphi 7, no delphi XE 7). Y veremos que salvo la librería de tratamiento de JSON, mucho código -salvo vistas-) es el mismo que posteriormente vamos a compilar para Windows con una versión 10 Seatle y para móviles, tanto Android como iOS. Así, que ciertamente, si programáis con un poco de «vista», el código que generamos en gran parte puede ser reutilizable en las nuevas plataformas.
Para tratamiento de JSON en verisones antiguas, he utilizado la librería ulkJSON (disponible en Sourceforge), de la que ya he hablado otras veces. Funciona muy bien y es una buena opción si posteriormente tenemos que actualizar, porque como veremos en otra entrada, el tratamiento de una respuesta es bastante similar utilizando esta librería, a realizarlo con la unit JSON que encontraremos en las versiones modernas de delphi (así que la migración luego será poco traumática).
Para una respesta como esta, que es la que obtenemos cuando solicitamos los datos sobre una ciudad:
(obtener un fichero de texto con la respuesta)
Utilizaremos un código como este:
// Parsea la respuesta de varias ciudades a una estructura que nos ha devuelto la web function TForm1.ParseTiempoCiudades(AObjResp:TlkJSONobject; var ATiempoObj:TTiempoStruct):Boolean; var i, j, num, index:integer; oCityList, OWList:TlkJSONlist; oCity, oCoord, oMain, oWind, oWeather:TlkJSONobject; begin // ini Result := False; // Si no está asignado salimos.. if not Assigned(AobjResp) then begin Exit; end; // Si hay error no parseamos if IsErrorResponse(AObjResp, errCode, ErrMsg) then begin Exit; end; // proteccion para el parseo try // cod. devuelto (datos principales ATiempoObj.Cod := errCode; num := AObjResp.IndexOfName('count'); if (num <> -1) then begin num := GetAsInteger(AObjResp.Field['count'].Value); end; // si no hay ciudades if (num = 0) then begin MessageDlg('No hay ninguna ciudad que coincida con ese código [nombre,pais].', mtWarning, [mbOK], 0); Exit; end; // Ciudades (Lista) TlkJSONBase(oCityList) := AObjResp.Field['list']; // datos de la primera ciudad TlkJSONBase(oCity) := oCityList.Child[0]; // datos básicos ATiempoObj.id := GetAsInteger(oCity.Field['id'].Value); ATiempoObj.Name := GetAsString(oCity.Field['name'].Value); // Parseo de coordenadas TlkJSONBase(oCoord) := oCity.Field['coord']; ATiempoObj.Coord.Lat := GetAsFloat(oCoord.Field['lat'].Value); ATiempoObj.Coord.Lon := GetAsFloat(oCoord.Field['lon'].Value); // main TlkJSONBase(oMain) := oCity.Field['main']; ATiempoObj.Main.temp := GetAsFloat(oMain.Field['temp'].Value); ATiempoObj.Main.tempmin := GetAsFloat(oMain.Field['temp_min'].Value); ATiempoObj.Main.tempmax := GetAsFloat(oMain.Field['temp_max'].Value); ATiempoObj.Main.pressure := GetAsFloat(oMain.Field['pressure'].Value); ATiempoObj.Main.humidity := GetAsInteger(oMain.Field['humidity'].Value); // Viento TlkJSONBase(oWind) := oCity.Field['wind']; ATiempoObj.Wind.speed := GetAsFloat(owind.Field['speed'].Value); ATiempoObj.Wind.deg := GetAsInteger(oWind.Field['deg'].value); // Weather TlkJSONBase(OWList) := oCity.Field['weather']; // array de elementos SetLength(ATiempoObj.Weather, OWList.Count); // Recorrer la lista de objetos. for j := 0 to (oWList.Count - 1) do begin // Datos weather TlkJSONBase(oWeather) := oWList.Child[j]; ATiempoObj.Weather[j].id := GetAsInteger(oWeather.Field['id'].Value); ATiempoObj.Weather[j].main := GetAsString(oWeather.Field['main'].Value); ATiempoObj.Weather[j].desc := GetAsString(oWeather.Field['description'].Value); ATiempoObj.Weather[j].icon := GetAsString(oWeather.Field['icon'].Value); end; Result := True; except // si hay error, FALSe Result := False; end; end; |
Para probar el acceso al servicio, las peticiones básicas y la librería para «parsear» la respuesta JSON, he realizado una aplicación en Delphi. Debajo podéis ver la compilación en Delphi 7 y Delphi Seatle (en el segundo caso se aplican algunos de los nuevos estilos que vienen para Windows 10). Salvo eso, el resto de código es el mismo para ambas compilaciones.
Os adjunto el video de Youtube con la versión de Delphi Seatle.
Por último os dejo los links de ambos proyectos, de las librerías y de alguna cosa más relacionada.
- Código fuente del proyecto (Delphi 7)
- Ejecutable del proyecto (Delphi 7)
- Código fuente del proyecto (Delphi Seatle)
- Ejecutable del proyecto (Delphi Seatle)
- Librería ulkJson en Sourceforge
- Página web de OpenWeatherMap
Para la siguiente entrada dejo las aplicaciones desarrolladas para plataforma móviles y alguna cosita más.
____________________________________________________________________
UPDATE (13/10/2020): Peter estudiante de «the hydrometeorological institute», me adjunta este link sobre una comporativa de 8 APIs para obtener datos meteorológicos. El artículo está en la página de climacell, y tal y como comentan al principio no son objetivos, ya que una de las APIs comentadas es suya. De todas formas y teniendo esto presente, creo que la información y los links que aporta en su interior puede ser relevante para alguien que esté pensando en realizar un proyecto de este tipo.
Las 8 mejores API’s meteorológicas para 2020
Gracias Peter.
____________________________________________________________________
Como siempre, cualquier comentario o sugerencia será bienvenido.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
Muchas Felicidades señor neftali, por las grandes iniciativas y guías que nos proporciona.. en lo personal lo admiro.. saludos desde bolivia..
Muy buen artículo (como siempre). Con unas pocas modificaciones se puede adaptar fácilmente para la API de Weather Underground (es el que uso yo normalmente), que tiene ademas la posibilidad de acceder en vivo a los datos de muchas estaciones meteorológicas (suelen ser de gente que pone a disponibilidad del público las datos de sus estaciones).
@Ciro
Gracias Ciro por el comentario.
@Jose A.
Gracias Jose.
No conocía esta API que comentas (Weather Underground). y tiene muy buena pinta.
Un saludo.
El análisis de comportamiento del ejecutable con virustotal me dice que hay una inyección de código en dwwin.exe ¿que opinas?
===============
Created processes
C:\WINDOWS\system32\drwtsn32 -p 1496 -e 228 -g (successful)
Code injections in the following processes
dwwin.exe (successful)
=================
Con Windows 8.1 me da un aviso : «el archivo podría dañar mi pc- ¿Está seguro que quiere ejecutarlo?
@Javier P.
Hola Javier.
Ninguno de los 2 ejecutable tiene virus, te lo puedo asegurar.
De todas formas por eso adjunto el código fuente. Para que puedas compilarlo tú mismo.
Aun así, pongo los ejecutable para que gente que no tenga la misma versión pueda probar los ejemplos sin problemas. Si pasas los 2 ejecutables por virustotal verás que los marca como limpios, excepto un fañlso positivo por heurística.
Un saludo.
Espectacularmente claro. Se hace sencillísimo gracias a tus explicaciones paso a paso.
Saludos.
@Casimiro
Gracias Antonio.
Yo creo que sóis vosotros que lo miráis con buenos ojos…
;-DDD
Es interesante ver que el código fuente (con ligeros cambios) sea compatible con Delphi7 y con la penúltima versión Delphi Seatle, y entre ambos haya más de 13 años.
Neftalí, gracias por compartir, tus aportes son fantásticos, sigo tus comentarios desde que egresé de la UAB… y desde entonces hace ya 16 años.
Gracias por todos tus comentarios desde entonces :)
Un cordial saludo.
@Shirley
Si, realente no muchas otras platafromas y entornos deben porder decir lo mismo.
Gracias por tus comentarios.
Los links de descarga estan caidos, error 404.
@Alex Kain
Hola Alex.
Gracias por el aviso.
Ya están corregidos. Últimamente he realizado algunos cambios en el blog y hay enlaces que han quedado mal.
Un saludo.
hola podrias poner el código adaptado a Wunderground, tengo una estación metereológica en casa que usa este sistema, pero no consigo adaptarlo