jueves, 11 de febrero de 2016

Incorporar la previsión del tiempo a tu web (I)

En los últimos días, en la construcción de MyFamilyServer V2, he estado trabajando para tener un calendario mensual, semana y diario y se me ocurrió que podía incorporar algunos datos del mundo exterior al calendario en MyFamilyServer.

He realizado este documento para explicar como incorporar los datos del tiempo a MyFamilyServer, lo voy a explicar muy despacio, con ejemplos en php y html para que tú puedas incorporarlos a tu propia web. He buscado un conjunto de información gratuito (como todo en MyFamilyServer) que tú puedes incorporar de forma gratuita también en tu web (cumpliendo el acuerdo que propone el proveedor de la información del tiempo).
Con un poco (muy poco) de desarrollo podrás presentar en tu web el tiempo actual y la previsión de tiempo para los próximos días. El proveedor de estos datos es http://openweathermap.org/ 

Hay que agradecer a openweathermap.org que nos entregue los datos del tiempo actualizados y la previsión para los próximos días, así como una api para poder acceder desde tus programas e incorporarlos a tú web.

Es muy sencillo vamos manos a la obra.

Un pre-requisito necesario es registrarse en openweathermap para conseguir un identificador de acceso, este se obtiene de forma gratuita al registrarse.

Vale, el proceso consiste en hacer una llamada a la api, con un conjunto de parámetros y la api te contesta con un fichero (en diversos formatos) con un conjunto de información bien identificada. Una vez dispones de la información, la tratas y extraes los parámetros que mas te convienen.

Primero vamos a conocer el tiempo ahora.

La llamada a la api se realiza a esta url:

http://api.openweathermap.org/data/2.5/weather

y se le añaden los parámetros que necesites, es totalmente necesario indicar tu identificador (que obtuviste al registrarte) y definir donde (ciudad por ejemplo).
El parámetro para tu identificador es APPID=xxxxxx 
(xxxxxx debes sustituirlo por el identificador que obtienes al registrarte)
El parámetro para tu cuidad es id=yyyyyy
Con estos dos parámetros ya puedes realizar una llamada. Ejemplo:

http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxx&id=yyyyyy

El identificador para la cuidad de Madrid, España es '6359304'. Prueba a realizar la llamada directamente en tu navegador con tu identificador (en ved de los caracteres xxxxxx y el identificador de Madrid en ved de yyyyyy)

El resultado (lo veras directamente en tu navegador) es algo como esto:

{"coord":{"lon":-3.68,"lat":40.49},
"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10n"}],
"base":"cmc stations",
"main":{"temp":285.491,"pressure":954.83,"humidity":93,"temp_min":285.491,"temp_max":285.491,"sea_level":1027.23,"grnd_level":954.83},
"wind":{"speed":7.89,"deg":252.5},
"rain":{"3h":0.3825},
"clouds":{"all":88},
"dt":1455126919,
"sys":{"message":0.0036,"country":"ES","sunrise":1455088467,"sunset":1455126239},
"id":6359304,
"name":"Madrid",
"cod":200}

Esto que ves es un fichero en formato JSON con el tiempo de Madrid  en el momento que yo hice el request.

Puedes añadir algún otro parámetro que es útil como por ejemplo:
El parámetro para definir el idioma es lang=ll (Siendo II el código de idioma, el el momento de publicar este articulo, los idiomas soportados son:  en, ru, it, es (or sp), uk (or ua), de, pt, ro, pl, fi, nl, fr, bg, sv (or se), zh_tw, zh (or zh_cn), tr, hr, ca.
El parámetro para definir unidades de medida es units=zzzzzz (Pudiendo entregarlo en metric o imperial).
El parámetro para definir el formato de salida es mode=xml o bien mode=html, si no especificas formato de salida es json.
El identificador de la ciudad puede ser sustituido por el parámetro q= y en ese caso se identifica la cuidad por nombre (o nombre y país) o puede ser sustituido por latitud y longitud.
A continuación muestro varios ejemplos del estos parámetros

Misma llamada al tiempo actual en Madrid pero en idioma español y utilizando el sistema métrico como unidad de medida:
http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxx&id=6359304&units=metric&lang=es 

Misma llamada al tiempo actual en Madrid pero utilizando el nombre de la cuidad:

http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxx&q=madrid&units=metric&lang=es

Misma llamada para la cuidad de Londres *!!!
http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxx&q=londres&units=metric&lang=es

y para London:
http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxx&q=london&units=metric&lang=es

y por ultimo especificando cuidad y país (París, Francia):
http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxx&q=paris,fr&units=metric&lang=es

(* Cuidado: Como veras en los resultados si pones London o Londres son muy distintos, uno de ellos te entrega datos de Gran Bretaña y el otro de Argentina, por lo tanto utiliza un identificador que sepas que es correcto)
Para obtener el identificador de cualquier cuidad puedes consultar la web de openweathermap (url de descarga de todos los códigos de ciudades: http://bulk.openweathermap.org/sample/)


Todos estos ejemplos los puedes ejecutar directamente en tu navegador para ver como funciona. Eso si, necesitas obtener un identificador registrándote en la web de openweathermap.

Ahora vamos a integrar esto en nuestro programa php en cuatro líneas, superfacil:
El siguiente programa llama a el API del tiempo, recupera los datos de Madrid en español y con unidades en sistema métrico en formato JSON, convierte el fichero JSON a un array en PHP y presenta algunos datos recuperados (para el ejemplo presento solo algunos datos, hay muchos mas disponibles)

<?php

# La url para la invocación:
$url="http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxx&q=madrid,es&units=metric&lang=es";

# Recupero los datos en la variable $json
$json=file_get_contents($url);

# convierto la variable $json en un array php llamado $data
$data=json_decode($json,true);

# Presento en pantalla algunos datos:
echo 'Temperatura: '.$data['main']['temp']."<br>";
echo 'Tiempo actual: '.$data['weather'][0]['main'].', ' . $data['weather'][0]['description']."<br>";
echo 'Nubosidad: '.$data['clouds']['all']." %<br>";
echo 'Velocidad de viento: '.$data['wind']['speed']."<br>";
echo 'Salida del sol: '. date ('H:i:s', $data['sys']['sunrise'])."<br>";
echo 'Puesta de sol: '. date ('H:i:s',$data['sys']['sunset'])."<br>";

?>





Que, ¿Ha sido facil?, superfacil !!.



Ahora te toca a ti investigar un poco mas para decidir que otros datos te interesa presentar.

Este ha sido un ejemplo para presentar el tiempo ahora (son datos en tiempo real del estado del tiempo), a continuación vamos a ver como recuperar el forecast (previsión del tiempo).

El procedimiento es exactamente el mismo, pero llamamos al procedimiento 'forecast' en ved e llamar a 'weather' como hemos hecho hasta ahora.
Puedes probar en tu navegador con las mismas variables, solo tienes que cambiar la palabra 'weather' por 'forecast'.

Ejemplo de llamada:
http://api.openweathermap.org/data/2.5/forecast?APPID=xxxxxx&q=madrid,es&units=metric&lang=es 

Ejemplo de respuesta:
{"city":{"id":3117735,"name":"Madrid","coord":{"lon":-3.70256,"lat":40.4165},"country":"ES","population":0,
"sys":{"population":0}},"cod":"200","message":0.0036,"cnt":40,"list":[{"dt":1455202800,"main":{"temp":14.32,
"temp_min":12.81,"temp_max":14.32,"pressure":953.58,"sea_level":1025.95,"grnd_level":953.58,"humidity":95,
"temp_kf":1.51},"weather":[{"id":500,"main":"Rain","description":"lluvia ligera","icon":"10d"}],"clouds":
{"all":88},"wind":{"speed":5.9,"deg":263.501},"rain":{"3h":0.385},"sys":{"pod":"d"},"dt_txt":"2016-02-11
 15:00:00"},{"dt":1455213600,"main":{"temp":13.61,"temp_min":12.18,"temp_max":13.61,"pressure":954.95,
 
 etcetera etcetera etcetera ...
 


La respuesta, esta vez, es mucho mas larga, con esta invocación obtenemos una previsión del tiempo para 5 días con estimación de tiempo cada tres horas. En información recuperada encontraras la fecha y la hora y la informacion del tiempo previsto.

En el caso de previsión del tiempo también puedes obtener información diaria e indicar el número de días.
Ejemplo de llamada para recuperar una prevision diaria para 10 días (véase el parámetro cnt=10):
http://api.openweathermap.org/data/2.5/forecast/daily?APPID=xxxxxx&q=madrid,es&units=metric&lang=es&cnt=10  

Vamos a incorporar la previsión a nuestro programa para dar la previsión del tiempo en los próximos 10 días:

<?php

# La url para la invocación:
$url = "http://api.openweathermap.org/data/2.5/forecast/daily?APPID=xxxxxx&id=6359304&units=metric&lang=es&cnt=10";

# Recupero los datos en la variable $json
$json=file_get_contents($url);

# convierto la variable $json en un array php llamado $data
$data=json_decode($json,true);

# Presento en pantalla algunos datos:
echo 'Previsión del tiempo en: '.$data['city']['name'].', '.$data['city']['country']."<br>";
echo 'Se muestra la previsión de los próximos '.$data['cnt'].' días: '."<br>";

# Recorro la información de cada día   
foreach ($data['list'] as $dia) {
    echo '<b>Previsión para el día: '.date('d-m-Y', $dia['dt'])."</b><br>";
    echo 'Temperaturas: Max '.$dia['temp']['max'].' mínima: '.$dia['temp']['min']. "<br>";
    echo 'Tiempo previsto: '.$dia['weather'][0]['main'].', '.$dia['weather'][0]['description']. "<br>";
}
       
?>
!! Que facil y que bien funciona !!, Seguro que a vosotros tambien os funciona perfectamente.
La información que se obtiene en el fichero JSON es mucho mas completa, por favor, revisa la documentacion en http://openweathermap.org/api para completar o modificar la información que necesites.

Ahora vamos a realizar otro cambio, no mas funcionalidad, pero mas chula. Vamos a mostrar un icono del tiempo.

Esta misma web del tiempo que estamos utilizando te proporciona información del icono a utilizar. La información se encuentra en el campo 'icon'. (en nuestro ejemplo, podrías añadir    $dia['weather'][0]['icon']    a la linea de tiempo previsto y así ves la codificación del icono a utilizar.

Esta web que estamos utilizando proporciona tambien sus propios iconos (en la siguiente dirección http://openweathermap.org/weather-conditions). Los iconos estan disponibles como recursos en la web, la url para obtener el icono que necesitas se compone con la url del sitio /img/w y el código del icono que quieres recuperar.

Prueba a poner en tu navegador:

http://openweathermap.org/img/w/01d.png

http://openweathermap.org/img/w/01n.png 

http://openweathermap.org/img/w/10d.png 


http://openweathermap.org/img/w/13d.png 

Ya tienes la idea, ahora vamos a ver como lo integramos en el programa que hemos hecho hasta ahora.

<?php

# La url para la invocación:
$url = "http://api.openweathermap.org/data/2.5/forecast/daily?APPID=xxxxxx&id=6359304&units=metric&lang=es&cnt=10";

# Recupero los datos en la variable $json
$json=file_get_contents($url);

# convierto la variable $json en un array php llamado $data
$data=json_decode($json,true);

# Presento en pantalla algunos datos:
echo 'Previsión del tiempo en: '.$data['city']['name'].', '.$data['city']['country']."<br>";
echo 'Se muestra la previsión de los próximos '.$data['cnt'].' días: '."<br>";

# Recorro la informacion de cada dia  
foreach ($data['list'] as $dia) {
    echo '<br><b>Previsión para el día: '.date('d-m-Y', $dia['dt'])."</b><br>";
    echo 'Temperaturas: Max '.$dia['temp']['max'].' mínima: '.$dia['temp']['min']. "<br>";
    echo 'Tiempo previsto: '.$dia['weather'][0]['main'].', '.$dia['weather'][0]['description'];
    $icono = 'http://openweathermap.org/img/w/'.$dia['weather'][0]['icon'].'.png';
    echo '<IMG src='.$icono.'> <br>';
   
}
      
?>


Hemos terminado. Ya tienes un conjunto de ejemplos con resultados sencillos para hacer una llamada y recuperar cualquier dato del tiempo actual o de la previsión del tiempo a tu propia web, incluso incorporar un icono para dar una descripción del tiempo mas visual y en menos espacio.

Como ideas adicionales, estos iconos son bonitos, pero puede que quieras otros con el fondo transparente o mas sencillos, yo he encontrado varias propuestas, de iconos esquemáticos y muy adaptables a tu propia web (ya que en realidad son fuentes y se integran mas con los tamaños que dispongas y el fondo transparente). Mira la propuesta de Erik Flowers, de Alessio Atzeni o Deniz Fuchidzhiev (este ultimo ya te entrega una .css con la misma codificación que el id de openweathermap así no hay que hacer conversiones), son trabajos muy bien realizados. Incorporar estos diferentes iconos te generará mas trabajo ya que la codificación de openweathermap y la que utilizan otros autores no es siempre la misma, y deberás realizar alguna tabla de conversion (lo cual, como puedes imaginar, no esta dentro del ambito de este documento)

En la web de openweathermap encontraras documentación completa y actualizada, acude a esta web para mejorar lo que aquí se presenta o hacer cosas mas chulas. (La documentación es completa y clara yo solo he encontrado un fallito en como realizar la invocación, que ya he reportado a openweathermap, y algún detalle poco documentado de la respuesta, pero cosas menores, en general la documentación es amplia y clara).  

Espero que esta publicación te haya resultado útil y clara.