Inicio > Aplicación, Delphi, OOP, REST > Hablando del tiempo… (OpenWeatherMap) 1/2

Hablando del tiempo… (OpenWeatherMap) 1/2

Viernes, 4 de Diciembre de 2015 Dejar un comentario Ir a comentarios
Share Button

clima_gdeHace 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.

¿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

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:

http://api.openweathermap.org/data/2.5/find?&q=Barcelona,es&lang=es&units=metric&APPID=278857e8dee51f914026df21d0d40c19

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.

respuesta1

(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:

http://api.openweathermap.org/data/2.5/weather?lat=41.390&lon=2.154&APPID=278857e8dee51f914026df21d0d40c19

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.

img_jsonVamos 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:

respuesta_json

(obtener un fichero de texto con la respuesta)

Utilizaremos un código como este:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// 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.

TiempoAtmosferico

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.

Para la siguiente entrada dejo las aplicaciones desarrolladas para plataforma móviles y alguna cosita más.

Como siempre, cualquier comentario o sugerencia será bienvenido.

Share Button
Categories: Aplicación, Delphi, OOP, REST Tags:
  1. Ciro
    Sábado, 5 de Diciembre de 2015 a las 19:38 | #1

    Muchas Felicidades señor neftali, por las grandes iniciativas y guías que nos proporciona.. en lo personal lo admiro.. saludos desde bolivia..

  2. Jose A.
    Domingo, 6 de Diciembre de 2015 a las 10:29 | #2

    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).

  3. Neftalí
    Lunes, 7 de Diciembre de 2015 a las 09:41 | #3

    @Ciro
    Gracias Ciro por el comentario.

  4. Neftalí
    Lunes, 7 de Diciembre de 2015 a las 09:42 | #4

    @Jose A.
    Gracias Jose.
    No conocía esta API que comentas (Weather Underground). y tiene muy buena pinta.

    Un saludo.

  5. Javier P.
    Martes, 8 de Diciembre de 2015 a las 16:13 | #5

    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?

  6. Neftalí
    Miércoles, 9 de Diciembre de 2015 a las 08:45 | #6

    @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.

  7. Casimiro
    Domingo, 13 de Diciembre de 2015 a las 12:09 | #7

    Espectacularmente claro. Se hace sencillísimo gracias a tus explicaciones paso a paso.
    Saludos.

  8. Neftalí
    Lunes, 14 de Diciembre de 2015 a las 09:41 | #8

    @Casimiro
    Gracias Antonio.
    Yo creo que sóis vosotros que lo miráis con buenos ojos…

    ;-DDD

  9. Martes, 5 de Julio de 2016 a las 08:13 | #9

    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.

  10. Neftalí
    Martes, 5 de Julio de 2016 a las 08:17 | #10

    @Shirley
    Si, realente no muchas otras platafromas y entornos deben porder decir lo mismo.

    Gracias por tus comentarios.

  11. Miércoles, 31 de Agosto de 2016 a las 21:54 | #11

    Los links de descarga estan caidos, error 404.

  12. Neftalí
    Domingo, 4 de Septiembre de 2016 a las 15:47 | #12

    @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.

  1. Sin trackbacks aún.
What is 15 + 8 ?
Please leave these two fields as-is:
IMPORTANTE! Para continuar, debes contestar la pregunta anterior (para evitar SPAM) :-)